16.7.7 安全基线与最佳实践
安全基线强调“最小权限、最小暴露、可审计、可恢复”。本节给出一套可落地的 Kubernetes 安全基线清单与执行范式,覆盖控制面与节点加固、运行时安全、镜像与供应链、网络隔离、密钥治理、审计与合规、资源防滥用,并通过准入与流水线实现自动化。
原理草图(安全基线落地路径):
基线清单与关键落地示例#
1) 集群与节点加固(控制面访问与组件安全)#
示例:限制 kube-apiserver 访问来源(防止公网滥用)
# 查看 apiserver 监听地址与端口
ss -lntp | grep kube-apiserver
# 建议在节点防火墙限制控制面端口(示例:仅允许办公网段访问)
# 以 iptables 为例
iptables -A INPUT -p tcp --dport 6443 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6443 -j DROP
# 验证:从非允许网段访问应失败
curl -k https://<apiserver_ip>:6443/healthz
排错要点:
- 若集群管理工具无法连接,检查防火墙规则与 apiserver 证书 SAN 是否包含访问地址。
- kubectl get --raw /healthz 失败时确认 apiserver 端口与负载均衡策略。
2) 最小权限(RBAC + ServiceAccount)#
示例:创建只读命名空间角色并绑定到专用 SA
# 文件:rbac-readonly.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-readonly
namespace: dev
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dev-readonly
namespace: dev
rules:
- apiGroups: [""]
resources: ["pods","services","configmaps"]
verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-readonly-bind
namespace: dev
subjects:
- kind: ServiceAccount
name: sa-readonly
namespace: dev
roleRef:
kind: Role
name: dev-readonly
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac-readonly.yaml
# 验证:使用 SA 访问
kubectl -n dev auth can-i list pods --as=system:serviceaccount:dev:sa-readonly
kubectl -n dev auth can-i delete pods --as=system:serviceaccount:dev:sa-readonly
排错要点:
- can-i 为 no:确认 Role/RoleBinding 命名空间一致。
- 误授权:使用 kubectl get rolebinding -n dev -o yaml 检查是否绑定了 ClusterRole。
3) 运行时安全(非 root、只读、禁特权)#
示例:Pod 安全基线(非 root + 只读根文件系统)
# 文件:pod-secure.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-secure
namespace: dev
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
containers:
- name: web
image: nginx:1.25
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
ports:
- containerPort: 80
kubectl apply -f pod-secure.yaml
kubectl -n dev get pod web-secure
排错要点:
- 容器启动失败:检查镜像是否需要写入根文件系统(可挂载空目录到 /tmp)。
- 如果应用必须以 root 运行,评估是否可通过 init 容器做权限修复。
4) 镜像与供应链安全(扫描与固定版本)#
示例:固定镜像标签与拉取策略
# 文件:deployment-image.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: dev
spec:
replicas: 2
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:1.4.2
imagePullPolicy: IfNotPresent
命令解释与验证:
kubectl -n dev rollout status deploy/api
kubectl -n dev get pods -o wide
# 验证镜像是否固定版本,避免 latest 漂移
排错要点:
- 拉取失败:检查 Secret、仓库可达性与证书。
- 镜像频繁变更:禁用 latest 并在流水线中强制版本号。
5) 网络安全(NetworkPolicy 白名单)#
示例:仅允许同命名空间的特定应用访问
# 文件:np-allow.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api
namespace: dev
spec:
podSelector:
matchLabels:
app: api
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
kubectl apply -f np-allow.yaml
# 验证:仅 app=web 可访问 api:8080
排错要点:
- 未生效:确认 CNI 是否支持 NetworkPolicy(如 Calico)。
- 访问被拒:检查默认拒绝策略是否启用。
6) 配置与密钥管理(Secrets + 权限)#
示例:使用 Secret 挂载数据库密码
kubectl -n dev create secret generic db-pass --from-literal=password='S3cr3t!'
# 文件:pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-secret
namespace: dev
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh","-c","echo $DB_PASS && sleep 3600"]
env:
- name: DB_PASS
valueFrom:
secretKeyRef:
name: db-pass
key: password
kubectl apply -f pod-secret.yaml
kubectl -n dev logs app-secret
排错要点:
- 环境变量为空:检查 Secret 名称与 key 是否一致。
- 安全性:RBAC 限制对 Secret 的 get/list/watch 权限。
7) 审计与可追溯(审计日志启用示例)#
示例:启用简化审计策略(需修改 apiserver 配置)
# 文件:/etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets","configmaps","pods"]
- level: RequestResponse
verbs: ["create","update","patch","delete"]
apiserver 追加参数(示意):
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
排错要点:
- 无日志:检查 apiserver 是否加载参数、日志路径权限。
- 日志过大:降低审计等级或启用轮转。
8) 资源与防滥用(Quota/LimitRange)#
示例:命名空间资源配额与默认限制
# 文件:quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "2"
requests.memory: "4Gi"
limits.cpu: "4"
limits.memory: "8Gi"
---
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: dev
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "200m"
memory: "256Mi"
kubectl apply -f quota.yaml
kubectl -n dev describe quota dev-quota
排错要点:
- Pod 无法创建:检查是否超出配额或未设置 requests/limits。
准入与流水线固化(示例)#
示例:启用 Pod Security Admission(PSA)
# 文件:psa-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
pod-security.kubernetes.io/enforce: "baseline"
pod-security.kubernetes.io/audit: "restricted"
pod-security.kubernetes.io/warn: "restricted"
示例:CI/CD 里镜像扫描(伪示例流程)
# 1) 构建镜像
docker build -t registry.example.com/api:1.4.2 .
# 2) 扫描漏洞(示例:trivy)
trivy image --exit-code 1 --severity HIGH,CRITICAL registry.example.com/api:1.4.2
# 3) 通过后推送
docker push registry.example.com/api:1.4.2
常见故障排查清单#
- 访问被拒:
kubectl auth can-i检查 RBAC。 - Pod 被拒绝创建:检查 PSA/OPA 拦截日志。
- 网络不通:确认 NetworkPolicy 生效与 CNI 支持。
- 密钥泄露风险:排查是否误给了
cluster-admin或对 Secret 过度授权。
练习#
- 为命名空间
test创建只读 SA,并验证禁止删除 Pod。 - 编写一个非 root 的 Pod,并证明其无法写入根文件系统。
- 配置 NetworkPolicy,仅允许
app=web访问app=api。 - 启用 ResourceQuota,验证超配时 Pod 创建被拒。
- 在 CI 流水线中加入镜像扫描步骤并设置高危漏洞阻断。