深色模式
K8s 安全加固与 PodSecurity
摘要:本文用内置的 Pod Security Admission 为命名空间设置 restricted 基线,配合非 root 用户、只读根文件系统、能力裁剪等容器级加固项,把 Pod 权限压到最小。附逐项验证命令。
适用环境
- K8s 1.25+(Pod Security Admission 已 GA;1.22-1.24 需确认特性门控)
- 有命名空间管理权限
- 示例命名空间:
secure-app
操作步骤
一、三种安全标准等级
| 等级 | 定位 | 主要限制 |
|---|---|---|
privileged | 无限制 | 允许特权容器、hostPath 等 |
baseline | 阻止已知提权 | 禁特权、禁 hostNetwork/hostPID、禁大部分能力 |
restricted | 严格加固(推荐生产) | 在 baseline 之上要求 runAsNonRoot、禁提权、禁写根文件系统等 |
二、为命名空间打标签启用 PSA
yaml
apiVersion: v1
kind: Namespace
metadata:
name: secure-app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
三种模式的区别:
enforce:拒绝违规 Pod 创建。audit:允许创建,但在审计日志里记录。warn:允许创建,但给客户端返回警告。
建议
新命名空间直接 enforce: restricted。存量命名空间先只开 warn + audit,观察一段时间确认无业务受阻后,再改成 enforce,避免一刀切导致服务起不来。
三、验证违规被拦截
bash
kubectl run bad --rm -it --restart=Never -n secure-app --image=busybox -- sh
# 会收到警告/拒绝:allowPrivilegeEscalation != false、runAsNonRoot、capabilities 等1
2
2
四、写出符合 restricted 的 Pod
yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
namespace: secure-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:1.27-alpine
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
privileged: false
capabilities:
drop:
- ALL
volumeMounts:
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: cache
emptyDir: {}
- name: run
emptyDir: {}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
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
逐项解释:
| 配置项 | 作用 |
|---|---|
runAsNonRoot: true | 禁止以 root 启动 |
allowPrivilegeEscalation: false | 禁止子进程获得比父进程更多权限 |
readOnlyRootFilesystem: true | 根文件系统只读,防止写入恶意文件 |
capabilities.drop: ALL | 移除所有 Linux 能力,需要时按需加回 |
seccompProfile: RuntimeDefault | 启用默认 seccomp 过滤系统调用 |
readOnlyRootFilesystem: true 后需要写临时文件的目录用 emptyDir 单独挂出来(如上例的 /var/cache/nginx)。
注意
capabilities.drop: ["ALL"] 后,若应用需要绑定 1024 以下端口(如 80),会失败。解决:让应用监听 8080+,或用 Service 的 targetPort 做端口转换,不要为此加回 NET_BIND_SERVICE。
五、其它关键加固项
禁用 ServiceAccount token 自动挂载(应用不需要调 API 时):
yaml
spec:
automountServiceAccountToken: false1
2
2
或针对某个 SA:
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: no-api-access
automountServiceAccountToken: false1
2
3
4
5
2
3
4
5
禁止使用默认 ServiceAccount:
yaml
spec:
serviceAccountName: app-sa # 不要用 default1
2
2
用 NetworkPolicy 限制流量:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: secure-app
spec:
podSelector: {}
policyTypes:
- Ingress1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
先全禁再按需放行,是零信任网络的基本做法。
镜像安全:
yaml
imagePullPolicy: IfNotPresent
# 配合镜像签名校验(sigstore/cosign)与漏洞扫描1
2
2
六、集群级加固检查
bash
# 检查是否有特权 Pod
kubectl get pod -A -o json | jq -r '.items[] | select(.spec.containers[].securityContext.privileged==true) | .metadata.namespace + "/" + .metadata.name'
# 检查 hostNetwork 使用
kubectl get pod -A -o json | jq -r '.items[] | select(.spec.hostNetwork==true) | .metadata.name'
# 检查匿名访问是否关闭
kubectl -n kube-system get cm kube-apiserver -o yaml 2>/dev/null | grep anonymous1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
用 kube-bench 做 CIS 基线扫描:
bash
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs -l app=kube-bench1
2
2
七、从 PSP 迁移
PodSecurityPolicy 在 1.21 弃用、1.25 移除。如果集群里还有 PSP 对象,升级前必须迁移到 PSA,否则升级后策略消失、权限失控。
验证
- [ ]
kubectl get ns secure-app --show-labels能看到 PSA 标签 - [ ] 违规 Pod 被拒绝并给出明确原因
- [ ] 合规 Pod 能正常运行,且
id返回非 root - [ ] 尝试在只读根文件系统上写文件失败:
kubectl exec secure-pod -- touch /x报 Read-only file system
常见坑
- 开启 restricted 后大量服务起不来:镜像本身以 root 运行或需要写根目录,需改 Dockerfile(见 Dockerfile 章节的
USER)。 readOnlyRootFilesystem导致应用日志写不了:把日志输出到 stdout,或挂emptyDir。- 只开 enforce 没做灰度:存量业务直接被拒,应先用 warn/audit 观察。
- 忽略了
runAsUser与文件属主冲突:非 root 用户无法读 root 属主的挂载文件,需配fsGroup或改镜像内属主。 - 以为 PSA 能防住一切:PSA 只管 Pod 安全上下文,不覆盖 RBAC、NetworkPolicy、镜像供应链,需配合其它手段。