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

一、身份认证与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 |
。

三、网络策略与流量控制
默认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 | 基本支持 | 无扩展 |
生产环境推荐Calico或Cilium。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: {}
关键配置解释:
-
1runAsNonRoot: true
:禁止以root运行容器
-
1allowPrivilegeEscalation: false
:禁止子进程获取更多权限
-
1readOnlyRootFilesystem: true
:只读根文件系统,防止恶意写入
-
1capabilities.drop: ALL
:移除所有Linux capabilities
-
1seccompProfile: RuntimeDefault
:启用默认系统调用过滤
1 | readOnlyRootFilesystem |
常导致应用启动失败,因为很多应用需要写入
1 | /tmp |
或日志目录。解决方案是用
1 | emptyDir |
挂载一个临时卷。

五、密钥管理与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 运行时安全检测
推荐部署Falco或Tetragon进行运行时安全监控:
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安全不是一蹴而就的,而是一个持续的过程。核心原则可以总结为三条:最小权限、默认拒绝、深度防御。每一层防护都可能有漏洞,但多层防护的组合使得攻击成本指数级增长。
从实践角度看,建议按以下顺序推进加固工作:
- 首先加固API Server和RBAC(阻断入口)
- 然后配置NetworkPolicy(遏制横向移动)
- 接着部署Pod安全标准(限制容器能力)
- 再处理密钥管理(保护敏感数据)
- 最后部署审计和运行时监控(感知威胁)
安全加固是一个对抗性博弈的过程——攻击者在进化,你的防御也必须持续迭代。定期Review集群配置、跟踪CVE、更新策略,才能让Kubernetes集群在云原生时代保持安全。
汤不热吧