Kubernetes 安全加固是云原生环境防护的核心内容,本文从 RBAC 权限控制、ServiceAccount 管理、Pod 安全标准、网络策略隔离与 etcd 加密五个层面,提供一套可直接落地的 Kubernetes 集群安全加固配置方案,并附上每条加固项的验证命令,帮助团队降低集群被攻陷与横向扩散的风险。
适用场景
- Kubernetes 集群上线前或等保整改时的安全基线配置
- 多团队共享集群,需要隔离权限与资源边界
- 审计发现存在 cluster-admin 滥用、特权容器等风险
- 容器化业务需要满足 Pod 安全标准与网络策略合规要求
前置条件
- 已部署 Kubernetes 集群(本教程以 Kubernetes 1.28+ 为例)
- 具备集群管理员权限(kubeconfig 指向 admin 上下文)
- 已安装 kubectl 命令行工具
原理说明
Kubernetes 的安全纵深可分为四层:认证与授权(谁有权限调用 API)、Pod 运行安全(容器以什么身份、什么能力运行)、网络隔离(工作负载之间能否互访)、数据加密(etcd 中存储的敏感信息是否落盘加密)。多数真实入侵事件中,攻击者通过供应链或应用漏洞进入 Pod 后,利用过度授权的 ServiceAccount 调用 kubelet/API Server 实现集群级接管。因此 RBAC 最小权限与禁止特权容器是最优先的两项加固。
操作步骤
1. 审计并收敛 RBAC 权限
# 查看所有绑定 cluster-admin 的账号(应立即收敛)
kubectl get clusterrolebindings -o custom-columns=NAME:.metadata.name,SUBJECTS:.subjects[*].name | grep -B1 -i admin
# 查看默认 ServiceAccount 是否有高危权限
kubectl get clusterrolebindings -o json | jq '.items[] | select(.subjects[]?.kind=="Group" and .subjects[]?.name=="system:serviceaccounts")'
为业务创建最小权限的 Role 与 RoleBinding(限定命名空间):
# 创建只读角色
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app-dev
name: app-readonly
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
EOF
# 绑定到指定用户
kubectl create rolebinding app-readonly-binding --role=app-readonly --user=alice@example.com --namespace=app-dev
2. 收紧 ServiceAccount 与自动挂载
# 禁止默认 ServiceAccount 自动挂载 API 凭证
kubectl patch serviceaccount default -n app-dev -p '{"automountServiceAccountToken": false}'
# 每个工作负载显式指定专用 SA
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: app-dev
automountServiceAccountToken: false
EOF
在 Deployment 的 spec 中指定 serviceAccountName: app-sa,只有真正需要调用 Kubernetes API 的组件(如 Operator)才单独授权并挂载凭证。
3. 启用 Pod Security 标准
使用 Pod Security Admission(PSA)强制 Pod 遵循基线/受限标准:
# 对 app-dev 命名空间启用 restricted(最严格)标准,先 warn 观察
kubectl label --overwrite ns app-dev pod-security.kubernetes.io/enforce=restricted
kubectl label --overwrite ns app-dev pod-security.kubernetes.io/audit=restricted
kubectl label --overwrite ns app-dev pod-security.kubernetes.io/warn=restricted
工作负载补充安全上下文(restricted 要求):
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile:
type: RuntimeDefault
capabilities:
drop: ["ALL"]
allowPrivilegeEscalation: false
4. 配置 NetworkPolicy 默认拒绝
# 默认拒绝所有入站/出站流量
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: app-dev
spec:
podSelector: {}
policyTypes: ["Ingress", "Egress"]
EOF
# 只允许前端访问后端 8080 端口
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: app-dev
spec:
podSelector:
matchLabels: { app: backend }
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector: { matchLabels: { app: frontend } }
ports:
- protocol: TCP
port: 8080
EOF
前提:集群必须安装支持 NetworkPolicy 的 CNI 插件(Calico、Cilium、Weave 等),否则策略不会生效。
5. 开启 etcd 静态加密
在 API Server 启动参数中启用 --encryption-provider-config:
# 生成加密密钥(生产环境建议使用 KMS 提供方)
head -c 32 /dev/urandom | base64
# 创建加密配置文件 encryption-config.yaml
cat > /etc/kubernetes/encryption-config.yaml <<EOF
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources: ["secrets"]
providers:
- aescbc:
keys:
- name: key1
secret: 上一步生成的base64密钥
- identity: {}
EOF
在 kube-apiserver 的 --encryption-provider-config=/etc/kubernetes/encryption-config.yaml 参数后重启 API Server,并执行全量重加密:
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
6. 审计 API Server 关键参数
# 确认已禁用匿名请求、启用 RBAC 鉴权
kubectl get --raw /api/v1/namespaces/kube-system/configmaps/kube-apiserver-leader-elect 2>/dev/null
# 推荐参数(管理平面部署时设置)
# --authorization-mode=RBAC
# --anonymous-auth=false
# --enable-admission-plugins=NodeRestriction,PodSecurity,ServiceAccount
配置验证
# 1. RBAC 生效验证:用只读账号尝试删除 Pod(应被拒绝)
kubectl --as=alice@example.com -n app-dev delete pod nginx-demo
# 输出: Error from server (Forbidden): ... 表示授权生效
# 2. 检查 Pod 实际安全上下文
kubectl get pod -n app-dev -o jsonpath='{.items[*].spec.containers[*].securityContext}'
# 3. 验证 etcd 加密
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key get /registry/secrets/app-dev/mysecret | head -c 200
# 4. NetworkPolicy 生效:从非白名单 Pod 访问后端应超时
kubectl exec -n app-dev frontend-pod -- curl -m 3 http://backend-svc:8080
etcd 中 secret 值以 k8s:enc:aescbc:v1:key1: 前缀开头即说明加密生效。
常见问题
FAQ 1:开启 restricted 标准后现有 Pod 无法调度/报错?
Pod Security 是准入控制,不满足 restricted 的 Pod 会被拒绝。处理步骤:先查看拒绝原因 kubectl describe pod xxx -n app-dev(或 kubectl get events);对照 restricted 要求补齐 securityContext(runAsNonRoot、capabilities drop ALL、seccompProfile、allowPrivilegeEscalation: false);确有特殊需求的 Pod(如需要 NET_ADMIN 的网络插件 DaemonSet)可将其所在命名空间降级为 baseline 或为 Pod 添加 pod-security.kubernetes.io/audit=baseline 注解并评估风险。建议先在 warn/audit 模式下灰度,再切 enforce。
FAQ 2:配置 NetworkPolicy 后服务间访问不通?
NetworkPolicy 默认拒绝策略会阻断所有未显式放行的流量。排查顺序:一是确认 CNI 支持 NetworkPolicy(kubectl get networkpolicies 能列出即基本正常);二是检查 policyTypes 是否只声明了需要的方向(只拦 Ingress 就不要写 Egress);三是确认 selector 标签与实际 Pod 标签完全匹配(kubectl get pods --show-labels 核对);四是跨命名空间访问需用 namespaceSelector 放行,并确认目标端口声明与实际端口一致。加白名单策略时注意策略之间是 OR 关系,新增策略不会覆盖已有放行。
总结
Kubernetes 安全加固遵循最小权限与纵深防御原则:RBAC 收敛管理权限、ServiceAccount 禁用自动挂载、Pod Security 禁止特权容器、NetworkPolicy 默认拒绝、etcd 静态加密。五层措施相互独立又彼此补充,即使某一层被突破,其余层级仍可限制攻击者的横向移动范围。建议将以上配置固化为基础镜像与 Helm 模板,纳入 CI 流水线做策略校验,并定期用 kube-bench 等工具对集群做基线复查,确保持续符合安全要求。