1. Kubernetes安全工程导论
Kubernetes 安全工程不是给集群“加一层防火墙”这么简单。它要解决的是一个分布式控制平面在持续变更中,如何保证工作负载身份可信、权限最小、数据不被越权读取、运行时行为可约束、异常可发现可追溯。理解这一章,关键是先建立三个判断:保护什么、对手从哪里进来、边界画在哪里。
一、核心目标:CIA 在集群语境下的具体含义
机密性、完整性、可用性在 Kubernetes 中都有非常具体的落点。机密性对应 Secret、etcd 数据、ServiceAccount Token、镜像中的敏感配置;完整性对应 API 对象不被篡改、镜像摘要不被替换、准入策略不被绕过;可用性对应控制平面组件、节点资源、网络插件和关键工作负载不被拒绝服务或误操作打垮。
但仅用 CIA 还不够。Kubernetes 安全工程还要额外关注身份与授权边界和供应链可信。一个 Pod 能做什么,取决于它使用的 ServiceAccount、绑定的 RBAC、所处的命名空间、挂载的卷、可访问的网络端点以及节点上的运行时权限。把这些关系理清,才能把“安全目标”翻译成可配置、可验证的工程项。
二、威胁模型:从攻击面出发,而不是从工具出发
集群的威胁模型可以按“入口—横向—持久化—影响”来拆。常见入口包括:暴露的 kube-apiserver、未授权 Dashboard、弱口令 kubeconfig、CI/CD 流水线凭据泄露、镜像仓库被投毒、供应链依赖漏洞。进入之后,攻击者往往利用过度宽松的 RBAC、默认 ServiceAccount 自动挂载 Token、特权容器、hostPath 挂载、hostNetwork/hostPID 等向节点或其他命名空间横向移动。持久化则可能通过创建 ClusterRoleBinding、部署 DaemonSet、篡改 admission webhook 或写入 etcd 实现。最终影响可能是数据窃取、加密勒索、资源耗尽或整个集群被接管。
威胁模型的价值在于:它决定了你优先加固哪一层。如果集群只在内网、由单一团队运维,外部暴露面小,重点可能是 RBAC 与工作负载隔离;如果多租户、对外提供 API,重点则要前移到认证、准入和网络策略。
三、安全边界:把“信任”切成可管理的层
Kubernetes 的安全边界不是一条线,而是多层嵌套。最外层是集群边界:谁能访问 apiserver、是否启用匿名认证、证书与 Token 如何轮换。往内是命名空间边界:RBAC 作用域、ResourceQuota、NetworkPolicy 默认拒绝。再往内是工作负载边界:Pod 的 SecurityContext、ServiceAccount 权限、卷类型、能力集。最内层是进程与内核边界:容器运行时、seccomp、AppArmor/SELinux、用户命名空间。
工程上要避免“边界穿透”。例如,一个命名空间内的 Pod 如果挂载了 hostPath,它就可能越过工作负载边界读到节点上的 kubelet 凭据;如果 ServiceAccount 绑定了 cluster-admin,它就能越过命名空间边界操作整个集群。因此,边界设计的原则是:每一层都默认拒绝,只显式放行必要能力。
四、工程化防护体系:从策略到可观测
把安全目标落地,需要一套分层的工程体系。下面给出一个可参考的防护矩阵,字段和取值可根据实际集群调整。
| 防护层 | 关键控制 | 示例配置/参数 | 验证方式 |
|---|---|---|---|
| 认证与准入 | 禁用匿名认证、启用 Node 授权、准入 Webhook | --anonymous-auth=false;--authorization-mode=Node,RBAC |
匿名请求返回 401;未授权操作返回 403 |
| RBAC | 最小权限、避免通配符、定期审计绑定 | Role 仅授予 get/list/watch 指定资源 |
kubectl auth can-i --list 检查实际权限 |
| 工作负载 | 非 root、只读根、禁用特权、限制能力 | runAsNonRoot: true;readOnlyRootFilesystem: true;drop: ["ALL"] |
Pod 启动后 id 非 0;写入根目录失败 |
| 网络 | 默认拒绝、按需放行、限制出站 | NetworkPolicy 选择 podSelector: {} 且 policyTypes: [Ingress, Egress] |
未放行流量被拒绝;放行流量可连通 |
| 运行时 | seccomp、AppArmor、镜像签名验证 | securityContext.seccompProfile.type: RuntimeDefault |
审计日志记录被拦截的系统调用 |
| 可观测 | 审计日志、Falco 类运行时检测、指标告警 | 审计策略记录 RequestResponse 级别 |
模拟越权操作后能在日志中定位 |
五、一个可执行的最小加固示例
假设有一个命名空间 prod,其中运行一个无状态 Web 服务。下面给出一个 Pod 安全上下文片段,用于把工作负载边界收紧到可接受程度:
apiVersion: v1
kind: Pod
metadata:
name: web
namespace: prod
spec:
serviceAccountName: web-sa
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.example.com/web@sha256:abc123...
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
这段配置的关键判断点:automountServiceAccountToken: false 避免默认 Token 被挂载;runAsNonRoot 与 runAsUser 确保进程不以 root 运行;readOnlyRootFilesystem 阻止写入容器根文件系统,只保留 /tmp 可写;drop: ["ALL"] 移除所有 Linux 能力;seccompProfile 使用运行时默认 seccomp 配置。验证时,可以进入 Pod 执行 id 确认 UID 为 10001,尝试 touch /test 应失败,尝试 capsh --print 应看到能力集为空。
kubectl auth can-i、kube-score、conftest 或 OPA Gatekeeper 做策略校验。
六、从“知道”到“做到”的判断依据
判断一个集群的安全工程是否到位,可以问四个问题:第一,匿名请求是否被拒绝,未授权操作是否返回 403;第二,是否存在绑定 cluster-admin 的 ServiceAccount,是否存在通配符 RBAC;第三,工作负载是否以非 root 运行、是否禁用特权、是否限制能力;第四,网络是否默认拒绝,审计日志是否能还原一次越权尝试。这四个问题分别对应认证、授权、工作负载和可观测四个层面,任何一个层面失守,其他层面的加固效果都会被打折。