欢迎光临

Kubernetes集群安全加固实战:从RBAC到网络策略的全链路防护指南

Kubernetes已成为云原生时代的事实标准编排平台,但默认配置的K8s集群存在大量安全风险。从容器逃逸到权限提升,从未授权访问到数据泄露,每一个环节都可能成为攻击者的突破口。本文将从身份认证、RBAC授权、网络策略、Pod安全、密钥管理、审计日志六大维度,带你完成Kubernetes集群的全面安全加固。

Kubernetes Security

一、身份认证与API Server加固

API Server是Kubernetes的入口,所有操作都经过它。默认情况下,如果API Server暴露在公网且未配置认证,任何人都可以控制你的集群。这是最基础也是最关键的安全防线。

1.1 禁用匿名访问

Kubernetes默认允许匿名请求。在生产环境中,你必须关闭这一行为。编辑API Server的启动参数:


1
2
3
4
5
6
7
8
9
10
11
12
# /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kube-apiserver
spec:
  containers:
  - command:
    - kube-apiserver
    - --anonymous-auth=false
    - --enable-bootstrap-token-auth=false
    - --insecure-port=0

关键参数说明:

  • 1
    --anonymous-auth=false

    :拒绝所有未认证的请求

  • 1
    --insecure-port=0

    :关闭非安全端口(8080),只保留HTTPS

  • 1
    --enable-bootstrap-token-auth=false

    :如非必要,关闭bootstrap token认证

1.2 配置强认证方式

推荐使用OIDC(OpenID Connect)集成企业SSO,而非静态token文件:


1
2
3
4
5
6
# API Server OIDC配置
- --oidc-issuer-url=https://auth.example.com/realms/master
- --oidc-client-id=kubernetes
- --oidc-username-claim=preferred_username
- --oidc-groups-claim=groups
- --oidc-ca-file=/etc/kubernetes/ssl/oidc-ca.pem

这样开发者通过SSO登录后,K8s会自动映射其用户名和组信息,配合RBAC实现精细化权限控制。

1.3 证书轮换与轮转

Kubernetes集群证书默认有效期1年。过期未更新会导致整个集群不可用。务必启用自动证书轮换:


1
2
3
4
5
# kubelet配置自动证书轮换
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
rotateCertificates: true
serverTLSBootstrap: true

同时配置ClusterRoleBinding允许kubelet申请新证书:


1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubeadm:node-autoapprove-certificate-rotation
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:certificates.k8s.io:certificatesigningrequests:selfnoderequester
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:nodes

二、RBAC最小权限原则

RBAC(基于角色的访问控制)是Kubernetes授权的核心机制。错误配置的RBAC规则比没有RBAC更危险——它给你一种安全的假象。

2.1 审计现有RBAC规则

首先检查是否存在过度授权的绑定:


1
2
3
4
5
6
7
8
9
# 查找绑定到cluster-admin的超权角色
kubectl get clusterrolebindings -o json | \
  jq -r '.items[] | select(.roleRef.name=="cluster-admin") |
  .subjects[]?.name // .subjects[]?.name'

# 查找通配符权限
kubectl get clusterroles -o json | \
  jq -r '.items[] | select(.rules[]?.resources[]? == "*" or
  .rules[]?.verbs[]? == "*") | .metadata.name'

以下角色必须严格审查:

角色 风险 建议
cluster-admin 完全控制集群 仅保留给运维负责人
system:master 绕过RBAC 仅通过证书组使用
自定义通配符角色 可能拥有unintended权限 逐一审计rules

2.2 创建精细化角色

为不同团队创建最小权限角色。例如,开发团队只需查看Pod日志和进入容器调试:


1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: production
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

注意pods/exec需要create权限而非get,因为exec是子资源操作。这是新手常犯的错误。

2.3 ServiceAccount权限隔离

每个应用应使用独立的ServiceAccount,而非default:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: production
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: myapp-sa-binding
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: myapp-role
subjects:
- kind: ServiceAccount
  name: myapp-sa
1
automountServiceAccountToken: false

非常关键——如果应用不需要访问K8s API,就不应该挂载token。攻击者进入容器后第一件事就是读取

1
/var/run/secrets/kubernetes.io/serviceaccount/token

RBAC Access Control

三、网络策略与流量控制

默认Kubernetes集群中,所有Pod之间可以自由通信。这在生产环境中是不可接受的——一个被入侵的Pod可以扫描整个集群。

3.1 默认拒绝所有流量

首先在每个Namespace中创建默认拒绝策略:


1
2
3
4
5
6
7
8
9
10
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

然后按需开放白名单。这种”默认拒绝、按需开放”的模式是零信任网络的基础。

3.2 微分段网络策略

以一个典型的三层Web应用为例——前端、后端、数据库——定义严格的流量规则:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 前端只接受外部HTTP流量,只能访问后端
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 8080
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

数据库的Egress为空——数据库Pod不需要访问任何外部服务。同时别忘了为所有策略放行DNS(UDP 53端口),否则Pod无法解析服务名。

3.3 CNI选择

NetworkPolicy需要CNI插件支持。主流选择:

CNI NetworkPolicy支持 扩展策略
Calico 完整支持 GlobalNetworkPolicy(跨命名空间)
Cilium 完整支持 CiliumNetworkPolicy(L7策略)
Flannel 不支持 需搭配Calico
Weave 基本支持 无扩展

生产环境推荐CalicoCilium。Cilium基于eBPF,支持七层策略(如”只允许GET请求到/api路径”),适合对安全要求极高的场景。

四、Pod安全标准与准入控制

Pod安全是容器运行时的第一道防线。Kubernetes 1.25+已移除PodSecurityPolicy,替代方案是Pod Security Standards(PSS)配合Pod Security Admission(PSA)

4.1 三级安全标准

Kubernetes定义了三个安全级别:

  • Privileged:不限制,适用于系统组件
  • Baseline:最小限制,禁止已知的明显提权路径
  • Restricted:严格限制,遵循最佳安全实践

推荐为不同Namespace配置不同级别:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 生产环境Namespace使用restricted
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
# 基础设施Namespace使用baseline
apiVersion: v1
kind: Namespace
metadata:
  name: infra
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

4.2 Security Context配置

Restricted标准要求每个Pod配置安全上下文。以下是一个符合restricted标准的Pod配置:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:1.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      runAsUser: 1000
      runAsGroup: 1000
      capabilities:
        drop:
        - ALL
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

关键配置解释:

  • 1
    runAsNonRoot: true

    :禁止以root运行容器

  • 1
    allowPrivilegeEscalation: false

    :禁止子进程获取更多权限

  • 1
    readOnlyRootFilesystem: true

    :只读根文件系统,防止恶意写入

  • 1
    capabilities.drop: ALL

    :移除所有Linux capabilities

  • 1
    seccompProfile: RuntimeDefault

    :启用默认系统调用过滤

1
readOnlyRootFilesystem

常导致应用启动失败,因为很多应用需要写入

1
/tmp

或日志目录。解决方案是用

1
emptyDir

挂载一个临时卷。

Container Security

五、密钥管理与Secrets安全

Kubernetes的Secret本质上只是Base64编码,不是加密。etcd中的Secret明文可读,任何有etcd访问权限的人都能获取。这是K8s安全中最常被忽视的问题。

5.1 启用etcd加密

首先配置etcd加密存储:


1
2
3
4
5
6
7
8
9
10
11
12
# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <BASE64_ENCODED_32BYTE_KEY>
  - identity: {}

然后在API Server中引用:


1
2
# kube-apiserver启动参数
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml

加密密钥需要定期轮换。创建新密钥后,将新密钥放在keys列表第一位,旧密钥保留用于解密,然后执行:


1
2
# 强制重写所有Secret以使用新密钥加密
kubectl get secrets --all-namespaces -o json | kubectl replace -f -

5.2 使用外部密钥管理

对于生产环境,推荐使用外部Secret管理工具:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用External Secrets Operator集成Vault
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: db-credentials
  data:
  - secretKey: password
    remoteRef:
      key: secret/data/db
      property: password

External Secrets Operator支持Vault、AWS Secrets Manager、GCP Secret Manager、Azure Key Vault等后端,将外部密钥同步为K8s Secret,同时保持密钥在外部系统的生命周期管理。

5.3 Sealed Secrets方案

如果需要将Secret存储在Git中(GitOps流程),使用Sealed Secrets:


1
2
3
4
5
6
7
# 安装controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml

# 加密Secret
kubectl create secret generic mysecret \
  --from-literal=password=s3cret --dry-run=client -o json | \
  kubeseal -o yaml > sealed-secret.yaml

Sealed Secrets使用集群controller的私钥解密,加密后的数据只能在目标集群中还原。即使泄露到公网也无法解密。

六、审计日志与入侵检测

没有审计,安全就无从谈起。你需要知道谁在什么时候做了什么操作。

6.1 配置审计策略


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets"]
  verbs: ["get", "list", "create", "update", "delete"]
- level: RequestResponse
  resources:
  - group: "rbac.authorization.k8s.io"
    resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
  verbs: ["create", "update", "patch", "delete"]
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods/exec", "pods/attach"]
- level: None
  users: ["system:kube-scheduler", "system:kube-proxy"]
  verbs: ["get", "list", "watch"]
- level: Metadata
  omitStages:
  - RequestReceived

审计日志级别从低到高:

级别 记录内容 存储开销
None 不记录
Metadata 请求元数据(谁、何时、做什么)
Request Metadata + 请求体
RequestResponse Metadata + 请求体 + 响应体

建议对Secret和RBAC操作使用RequestResponse级别,日常操作使用Metadata级别以控制存储量。

6.2 日志后端集成


1
2
3
4
5
6
7
# API Server审计日志配置
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/kubernetes/audit.log
- --audit-log-maxage=30
- --audit-log-maxbackup=10
- --audit-log-maxsize=200
- --audit-log-format=json

将审计日志发送到SIEM系统(如ELK、Splunk)进行实时分析。以下是一个检测可疑行为的Falco规则示例:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Falco规则:检测容器内执行Shell
- rule: Terminal Shell in Container
  desc: A shell was spawned in a container
  condition: >
    spawned_process and container and
    proc.name in (bash, zsh, sh, ash) and
    not proc.pname in (docker-entrypoint)
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
     shell=%proc.name parent=%proc.pname
     cmdline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell]

6.3 运行时安全检测

推荐部署FalcoTetragon进行运行时安全监控:


1
2
3
4
5
6
7
# 使用Helm安装Falco
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
  --namespace falco --create-namespace \
  --set falco.driver.enabled=true \
  --set falco.driver.kind=module \
  --set falco.metrics.enabled=true

Falco基于内核模块或eBPF,能检测到传统安全工具无法发现的行为,如:

  • 容器内读取敏感文件(
    1
    /etc/shadow

    、ServiceAccount token)

  • 意外进程启动(容器内出现curl、wget、nc)
  • 网络连接异常(反向Shell、数据外传)
  • 权限提升(setuid、capset系统调用)

七、安全加固检查清单

将以上内容整理为可执行的检查清单,用于集群上线前的安全Review:

# 检查项 命令/方法 优先级
1 关闭匿名访问 检查–anonymous-auth=false P0
2 关闭非安全端口 检查–insecure-port=0 P0
3 RBAC无通配符权限 kubectl get clusterroles审查 P0
4 Pod Security Standards启用 检查Namespace labels P0
5 etcd加密存储 检查–encryption-provider-config P1
6 NetworkPolicy默认拒绝 检查每个Namespace P1
7 审计日志启用 检查–audit-policy-file P1
8 ServiceAccount最小权限 检查default SA的绑定 P1
9 证书自动轮换 检查rotateCertificates P2
10 运行时安全监控 Falco/Tetragon部署 P2

此外,推荐使用kube-bench(CIS Kubernetes Benchmark自动化检查工具)定期扫描集群:


1
2
3
4
# 运行CIS Benchmark检查
docker run --pid=host -v /etc:/etc:ro \
  -v /var:/var:ro aquasec/kube-bench:latest \
  run --targets master,node

总结

Kubernetes安全不是一蹴而就的,而是一个持续的过程。核心原则可以总结为三条:最小权限、默认拒绝、深度防御。每一层防护都可能有漏洞,但多层防护的组合使得攻击成本指数级增长。

从实践角度看,建议按以下顺序推进加固工作:

  1. 首先加固API Server和RBAC(阻断入口)
  2. 然后配置NetworkPolicy(遏制横向移动)
  3. 接着部署Pod安全标准(限制容器能力)
  4. 再处理密钥管理(保护敏感数据)
  5. 最后部署审计和运行时监控(感知威胁)

安全加固是一个对抗性博弈的过程——攻击者在进化,你的防御也必须持续迭代。定期Review集群配置、跟踪CVE、更新策略,才能让Kubernetes集群在云原生时代保持安全。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Kubernetes集群安全加固实战:从RBAC到网络策略的全链路防护指南
分享到: 更多 (0)