16.9.10 安全基线与合规审计
在生产环境中,Kubernetes安全基线应覆盖身份鉴别、授权、网络隔离、镜像供应链、运行时防护与审计可追溯性。建议以“最小权限、默认拒绝、可审计”为核心原则,并与等保/ISO27001/SOC2等合规要求对齐。
原理草图(安全控制面与数据面联动)
安全基线要点与示例
- 身份与访问控制(RBAC最小权限)
```yaml
# 文件: rbac-readonly.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ns-readonly
namespace: prod
rules: - apiGroups: [""]
resources: ["pods","services","configmaps"]
verbs: ["get","list","watch"]
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: bind-readonly
namespace: prod
subjects:
- kind: User
name: dev1
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: ns-readonly
apiGroup: rbac.authorization.k8s.io
bash
kubectl apply -f rbac-readonly.yaml
# 验证权限:预计只能查看,不能创建
kubectl auth can-i create pods -n prod --as=dev1 # 预期: no
kubectl auth can-i list pods -n prod --as=dev1 # 预期: yes
```
-
网络隔离(默认拒绝 + 白名单放行)
yaml # 文件: np-deny-all.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all namespace: prod spec: podSelector: {} policyTypes: ["Ingress","Egress"]
```yaml
# 文件: np-allow-web.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-web
namespace: prod
spec:
podSelector:
matchLabels:
app: web
ingress:- from:
- namespaceSelector:
matchLabels:
name: prod
ports: - protocol: TCP
port: 80
bash
kubectl apply -f np-deny-all.yaml
kubectl apply -f np-allow-web.yaml
# 验证:仅允许同命名空间访问 web 80 端口
```
-
API安全与审计(审计策略)
```yaml
# 文件: /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules: - level: Metadata
resources:- group: ""
resources: ["pods","secrets","configmaps"]
- group: ""
-
level: RequestResponse
resources:- group: "rbac.authorization.k8s.io"
resources: ["clusterroles","clusterrolebindings","roles","rolebindings"]
bash
# kube-apiserver 增加参数(示例)
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30 --audit-log-maxsize=100 --audit-log-maxbackup=10
# 验证:
sudo tail -f /var/log/kubernetes/audit.log
```
- group: "rbac.authorization.k8s.io"
-
镜像与供应链安全(Trivy 扫描 + 准入)
```bash
# 安装 Trivy(示例)
sudo apt-get update && sudo apt-get install -y wget
wget https://github.com/aquasecurity/trivy/releases/download/v0.50.1/trivy_0.50.1_Linux-64bit.deb
sudo dpkg -i trivy_0.50.1_Linux-64bit.deb
# 扫描镜像
trivy image --severity HIGH,CRITICAL nginx:1.25
# 预期:输出漏洞列表与修复建议
```
-
运行时安全(Pod安全标准 + Seccomp)
yaml # 文件: pss-restricted-ns.yaml apiVersion: v1 kind: Namespace metadata: name: prod labels: pod-security.kubernetes.io/enforce: "restricted" pod-security.kubernetes.io/enforce-version: "latest"
```yaml
# 文件: pod-seccomp.yaml
apiVersion: v1
kind: Pod
metadata:
name: safe-nginx
namespace: prod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:- name: nginx
image: nginx:1.25
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
bash
kubectl apply -f pss-restricted-ns.yaml
kubectl apply -f pod-seccomp.yaml
# 预期:PSS限制生效,特权容器将被拒绝
```
- name: nginx
-
密钥与敏感信息(Secret 加密 at-rest)
```yaml
# 文件: /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources: -
resources:
- secrets
providers: - aescbc:
keys:- name: key1
secret: WmF0dGxvY2tLZXlCYXNlNjQ=
- name: key1
- identity: {}
bash
# kube-apiserver 参数
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# 验证:创建 secret 后在 etcd 中应为加密内容
kubectl create secret generic test --from-literal=pass=123 -n prod
```
- secrets
-
节点安全(基线加固)
```bash
# 关闭不必要服务、限制SSH
sudo systemctl disable --now rpcbind
sudo sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart ssh
# 检查开放端口(仅示例)
sudo ss -lntp
```
合规审计流程(工具化落地)
-
基线扫描工具安装(kube-bench)
bash # 使用容器运行 kube-bench(不污染主机) docker run --rm -v /etc:/etc -v /var:/var \ --net=host aquasec/kube-bench:0.7.2 # 预期:输出 CIS 基线评分与失败项 -
持续合规检测(OPA Gatekeeper 安装示例)
bash kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml kubectl get pods -n gatekeeper-system
```yaml
# 文件: constraint-template.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
targets:- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
required := {"owner"}
provided := {label | input.review.object.metadata.labels[label]}
missing := required - provided
count(missing) > 0
msg := sprintf("missing labels: %v", [missing])
}
- target: admission.k8s.gatekeeper.sh
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-owner
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
bash
kubectl apply -f constraint-template.yaml
# 预期:创建无 owner 标签的 Namespace 会被拒绝
```
常见排错清单(含命令)
- RBAC 拒绝:
bash
kubectl auth can-i get pods -n prod --as=dev1
kubectl get rolebinding,clusterrolebinding -A | grep dev1
- NetworkPolicy 误拦截:
bash
kubectl describe networkpolicy -n prod
kubectl exec -n prod -it pod-a -- curl -m 2 http://pod-b:80
- 准入控制拒绝:
bash
kubectl describe pod safe-nginx -n prod
kubectl get events -n prod --sort-by=.lastTimestamp | tail
- 审计日志无输出:
bash
ps -ef | grep kube-apiserver | grep audit
ls -l /var/log/kubernetes/audit.log
练习与验收
1. 建立 prod 命名空间,启用 PSS restricted,创建一个特权容器并观察被拒绝原因。
2. 配置默认拒绝的 NetworkPolicy,验证同命名空间与跨命名空间访问的差异。
3. 运行 kube-bench,列出前三个失败项并给出修复命令。
4. 在 CI 中使用 Trivy 扫描镜像,设置严重级别 HIGH/CRITICAL 失败即阻断。
5. 开启审计日志,进行一次 RoleBinding 变更,查看 audit.log 中的记录。