16.7.5 Secrets与配置安全管理

Secrets与配置安全管理#

Kubernetes中配置与密钥管理的核心对象是ConfigMap与Secret。ConfigMap用于保存非敏感配置,Secret用于保存敏感信息(如密码、证书、令牌)。二者以键值对形式存储,可通过环境变量或挂载卷注入到Pod中。核心原则是“配置与镜像解耦”,确保镜像在不同环境复用。

原理与对象关系图#

文章图片

Secret类型与创建方式(含命令解释)#

1) 通用Opaque(命令行创建)

# 创建通用Secret,--from-literal以明文键值生成
kubectl create secret generic app-db \
  --from-literal=username=appuser \
  --from-literal=password='S3cReT!' \
  -n prod
# 预期:生成prod命名空间下的Secret/app-db
kubectl get secret app-db -n prod

2) TLS证书Secret(从文件创建)

# 证书文件放置示例路径
ls /etc/pki/tls/app.crt /etc/pki/tls/app.key

kubectl create secret tls app-tls \
  --cert=/etc/pki/tls/app.crt \
  --key=/etc/pki/tls/app.key \
  -n prod

3) 镜像仓库认证(dockerconfigjson)

kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=ci \
  --docker-password='P@ssw0rd' \
  --docker-email=ci@example.com \
  -n prod

4) YAML声明式创建(stringData避免手工Base64)

# 文件:/opt/k8s/secret-app.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-api
  namespace: prod
type: Opaque
stringData:
  token: "t-123456"
  endpoint: "https://api.example.com"
kubectl apply -f /opt/k8s/secret-app.yaml

挂载与使用模式(示例完整可执行)#

1) 以环境变量注入(适合少量配置)

# 文件:/opt/k8s/pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: env-demo
  namespace: prod
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "env | grep APP_ && sleep 3600"]
    env:
    - name: APP_USER
      valueFrom:
        secretKeyRef:
          name: app-db
          key: username
    - name: APP_PASS
      valueFrom:
        secretKeyRef:
          name: app-db
          key: password
kubectl apply -f /opt/k8s/pod-env.yaml
kubectl logs -n prod env-demo
# 预期:输出APP_USER/APP_PASS环境变量

2) 以卷挂载(推荐,适合证书/配置文件)

# 文件:/opt/k8s/pod-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: vol-demo
  namespace: prod
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "ls /etc/secret && cat /etc/secret/username && sleep 3600"]
    volumeMounts:
    - name: secret-vol
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: secret-vol
    secret:
      secretName: app-db
kubectl apply -f /opt/k8s/pod-vol.yaml
kubectl logs -n prod vol-demo

etcd静态加密(示例与命令解释)#

# 文件:/etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: MjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTA=  # 32字节Base64
      - identity: {}
# 1) 生成32字节密钥并Base64
head -c 32 /dev/urandom | base64

# 2) 修改apiserver静态Pod配置
# 文件:/etc/kubernetes/manifests/kube-apiserver.yaml
# 增加参数:
# --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# 并挂载配置文件

# 3) 验证:重新写入一个Secret以触发加密
kubectl delete secret app-db -n prod
kubectl create secret generic app-db --from-literal=username=appuser --from-literal=password='S3cReT!' -n prod

配置更新与发布策略(触发滚动更新示例)#

# 通过注解触发Deployment滚动重启
kubectl -n prod annotate deploy app \
  kubernetes.io/change-cause="update secret $(date +%F_%T)"

# 或使用rollout restart
kubectl -n prod rollout restart deploy app

故障排查清单(含命令与解释)#

# 1) Secret不存在
kubectl -n prod get secret app-db

# 2) 挂载路径为空(检查Pod事件)
kubectl -n prod describe pod vol-demo | sed -n '/Events/,$p'

# 3) Base64解码异常(检查data字段)
kubectl -n prod get secret app-db -o yaml

# 4) RBAC无权限读取Secret
kubectl -n prod auth can-i get secret/app-db --as system:serviceaccount:prod:default

安全风险与防护要点#

  • Secret默认Base64存储在etcd中,需启用etcd静态加密。
  • 限制RBAC访问,仅授权必要的ServiceAccount。
  • 禁止在镜像或代码中硬编码密码与令牌。
  • 对敏感命名空间配置NetworkPolicy与最小访问原则。

练习#

1) 创建一个TLS Secret并挂载到Pod的/etc/tls目录,验证文件是否存在。
2) 将ConfigMap与Secret分别以环境变量注入同一Pod,比较两者的适用场景。
3) 启用etcd静态加密后,重新创建Secret并验证apiserver正常工作。
4) 使用kubectl auth can-i验证无权限账号无法读取Secret。