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 过度授权。

练习#

  1. 为命名空间 test 创建只读 SA,并验证禁止删除 Pod。
  2. 编写一个非 root 的 Pod,并证明其无法写入根文件系统。
  3. 配置 NetworkPolicy,仅允许 app=web 访问 app=api
  4. 启用 ResourceQuota,验证超配时 Pod 创建被拒。
  5. 在 CI 流水线中加入镜像扫描步骤并设置高危漏洞阻断。