安全与多租户
Kubernetes 安全不是单一开关,而是身份、权限、工作负载隔离、网络、Secret、镜像供应链和审计共同形成的边界。
认证、鉴权和准入
API 请求依次经过三个阶段:
| 阶段 | 回答的问题 | 常见机制 |
|---|---|---|
| Authentication | 请求者是谁 | 客户端证书、OIDC、ServiceAccount Token |
| Authorization | 是否允许该操作 | RBAC、Webhook Authorizer |
| Admission Control | 对象是否允许进入集群 | Pod Security Admission、ValidatingAdmissionPolicy、Webhook |
认证成功不代表拥有操作权限,RBAC 通过 Role/ClusterRole 描述权限,通过 RoleBinding/ClusterRoleBinding 绑定主体。
RBAC 最小权限
Role 只在命名空间内生效:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: app
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader
namespace: app
subjects:
- kind: Group
name: app-readers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io检查权限:
bash
kubectl auth can-i get pods -n app
kubectl auth can-i --list -n app
kubectl auth can-i get secrets --as=system:serviceaccount:app:web -n app避免给业务 ServiceAccount 绑定 cluster-admin,也不要随意授予对 Secret、Pod exec、节点代理或 RBAC 对象的写权限。
ServiceAccount
每个 Pod 都关联一个 ServiceAccount。业务不访问 Kubernetes API 时,应禁用自动挂载 Token:
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: web
automountServiceAccountToken: false需要访问 API 时使用专用 ServiceAccount 和最小 RBAC。Kubernetes 1.24 起不再默认创建长期 Secret Token;交互调试可创建短期 Token:
bash
kubectl create token web -n app --duration=10mPod Security Admission
Pod Security Admission 根据命名空间标签应用 Pod Security Standards:
bash
kubectl label namespace app \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted现有命名空间不应直接从无策略切换到 restricted。先使用 warn 和 audit 观察,再逐步启用 enforce。
SecurityContext
一个较严格的 Pod 基线:
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: nginx:1.27
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: cache
mountPath: /var/cache/nginx
volumes:
- name: cache
emptyDir: {}具体镜像可能还需要可写的临时目录和指定 UID,应在镜像构建阶段验证,不能机械复制字段。
Secret 安全
Base64 不是加密。Secret 的保护至少包含:
- API Server 启用 encryption at rest,并制定密钥轮换流程。
- RBAC 限制
get/list/watch secrets。 - 优先通过 Volume 使用 Secret,谨慎使用可能进入日志和进程环境的环境变量。
- 使用短期凭据,并接入外部密钥管理和轮换系统。
- etcd 备份按敏感数据保护,限制访问并加密存储。
网络隔离
NetworkPolicy 只有在 CNI 实现支持时才生效。可先为命名空间设置默认拒绝,再按需开放:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: app
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress启用默认拒绝后需要显式允许 DNS、依赖服务、监控和必要的外部访问,避免把业务全部阻断。
镜像与供应链
- 使用不可变 tag 或 digest,避免
latest。 - 扫描镜像漏洞和错误配置,保留 SBOM。
- 对镜像签名并在准入阶段验证来源。
- 限制可用仓库、特权容器、hostPath、hostNetwork 和危险 capability。
- 定期更新基础镜像和运行时,不只更新业务依赖。
审计与节点安全
- 为 API Server 配置审计策略,并把日志发送到受保护的集中存储。
- 限制 kubelet API、容器运行时 socket 和节点 SSH 权限。
- 为控制平面和 etcd 使用独立网络边界。
- 定期轮换证书和凭据,检查匿名访问与未授权端点。
- 对高权限 debug、exec、port-forward 和临时容器操作保留审计记录。