Kubernetes 安全配置:RBAC、Pod 安全与网络策略

FreeGuideOnline 最新 2026-07-01

yaml apiVersion: v1 kind: Namespace metadata: name: dev

apiVersion: v1 kind: ServiceAccount metadata: name: dev-reader namespace: dev


**2. 定义只读 Role**

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: dev
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

3. 绑定角色到 ServiceAccount

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-binding
  namespace: dev
subjects:
- kind: ServiceAccount
  name: dev-reader
  namespace: dev
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

此后,在 dev 命名空间中使用该 ServiceAccount 运行的 Pod 即可安全地查询 Pod 信息,无法执行任何修改操作。

RBAC 最佳实践

  • 优先使用 ServiceAccount 而非直接分发 kubeconfig 用户凭证。
  • 为每个应用组件创建独立的 ServiceAccount,避免共用。
  • 禁止使用 * 通配符动词,明确列出所需操作。
  • 定期审计 ClusterRoleBinding,移除不必要的高权限绑定。
  • 利用工具(如 kubectl auth can-i)验证实际权限效果。

Pod 安全

Pod 安全机制限制容器运行时的权限,防止容器逃逸、宿主机资源访问等风险。

Pod 安全标准

Kubernetes 定义了三个内置安全级别:

  • Privileged:无任何限制,允许特权容器、挂载宿主机路径等。仅用于系统级服务。
  • Baseline:阻止已知的提权行为,如容器运行于 hostNetwork、挂载敏感宿主机目录,同时允许部分特权操作。适用于大多数应用。
  • Restricted:严格遵循安全最佳实践,强制非 root 运行、只读根文件系统、禁止特权提升等。推荐用于所有非系统工作负载。

使用 Pod Security Admission (PSA) 实施策略

从 v1.25 起,PSA 取代旧的 PodSecurityPolicy,以命名空间标签进行控制。

# 为 dev 命名空间强制实施 Restricted 标准,违反准入则拒绝
kubectl label namespace dev pod-security.kubernetes.io/enforce=restricted

# 同时开启审计和告警模式,便于观测违规请求
kubectl label namespace dev pod-security.kubernetes.io/audit=restricted
kubectl label namespace dev pod-security.kubernetes.io/warn=restricted

标签组合 enforceauditwarn 可渐进式推行。先使用 auditwarn 收集违规信息,再启用 enforce 硬阻断。

SecurityContext:精确控制容器安全

即使不使用全局 PSA,也可在 Pod/容器级别通过 securityContext 设置安全参数。

核心字段示例:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true      # 必须以非 root 用户运行
    seccompProfile:
      type: RuntimeDefault  # 使用容器运行时的默认 seccomp 规则
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      allowPrivilegeEscalation: false  # 禁止权限提升
      capabilities:
        drop: ["ALL"]                  # 移除所有 Linux capabilities
        add: ["NET_BIND_SERVICE"]      # 仅添加必要的能力
      readOnlyRootFilesystem: true     # 根文件系统只读
      runAsUser: 1000
      runAsGroup: 3000
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

关键字段解释

  • runAsNonRoot: true 要求容器用户非 UID 0,防止获取宿主机 root 权限。
  • capabilities.drop: ["ALL"] 剥夺全部默认能力,再逐一添加必需能力。
  • readOnlyRootFilesystem: true 避免容器内部文件篡改,需要写入的目录需挂载卷。
  • allowPrivilegeEscalation: false 禁止通过 suid 二进制提升权限。

Pod 安全最佳实践

  • 生产环境统一采用 Restricted 标准。
  • 所有容器镜像指定非 root 用户,或通过 Dockerfile USER 指令控制。
  • 避免使用 privileged 容器,除非明确需要(如网络插件)。
  • 启用 RuntimeDefault seccomp 和 AppArmor/SELinux 可选安全模块。
  • 定期扫描镜像漏洞,并确保基础镜像最小化。

网络策略

网络策略类似于为 Pod 组配置的防火墙规则,控制入站(Ingress)和出站(Egress)流量。Kubernetes 默认未隔离 Pod 间通信,需显式创建策略。

前提条件

集群必须安装支持网络策略的网络插件,如 Calico、Cilium、Weave Net 等。Flannel 在不使用 Calico 网络策略引擎时不支持。

工作模型

网络策略通过标签选择器指定目标 Pod,并基于规则限制流量流向。

  • Ingress 规则:定义哪些源可以访问目标 Pod。
  • Egress 规则:定义目标 Pod 可以访问哪些外部资源。

实战:实现命名空间级隔离

场景:frontend 命名空间的 Pod 只能接受来自同一命名空间的请求,并只允许访问后端 API 的 backend 服务。

1. 默认拒绝所有入口流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: frontend
spec:
  podSelector: {}       # 选择所有 Pod
  policyTypes:
  - Ingress
  ingress: []           # 空规则拒绝所有入口流量

这一步骤确保没有预想的 Pod 不被暴露。

2. 允许来自同命名空间的请求

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: frontend
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}   # 允许同一命名空间内任何 Pod

3. 控制 Egress:只允许访问特定后端

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-egress
  namespace: frontend
spec:
  podSelector:
    matchLabels:
      role: web        # 仅对具有 role=web 的 Pod 生效
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: backend      # 仅允许连接到具有标签 name=backend 的命名空间
      podSelector:
        matchLabels:
          role: api          # 且 Pod 标签为 role=api
    ports:
    - protocol: TCP
      port: 8080

4. 允许 DNS 解析

集群 DNS 服务通常位于 kube-system 命名空间,需额外放行 UDP 53 端口,否则 Pod 无法解析服务名称。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: frontend
spec:
  podSelector: {}
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53