88·安全高级

密钥管理

kubernetessecuritysecretsencryption

密钥管理

学习目标

  1. 理解密钥管理的重要性
  2. 掌握 Secrets 的创建和使用
  3. 了解密钥管理的最佳实践

核心概念

一句话解释

Kubernetes Secrets 用于存储和管理敏感信息,如密码、Token、证书等。

密钥管理挑战

┌─────────────────────────────────────────────────────────────┐
│                    密钥管理挑战                              │
├─────────────────────────────────────────────────────────────┤
│  存储安全                                                   │
│  ├── 明文存储风险                                           │
│  ├── etcd 加密                                             │
│  └── 外部密钥管理 (Vault)                                   │
├─────────────────────────────────────────────────────────────┤
│  访问控制                                                   │
│  ├── RBAC 权限管理                                          │
│  ├── 命名空间隔离                                           │
│  └── Pod 级别访问                                           │
├─────────────────────────────────────────────────────────────┤
│  生命周期                                                   │
│  ├── 密钥轮换                                               │
│  ├── 过期管理                                               │
│  └── 审计追踪                                               │
└─────────────────────────────────────────────────────────────┘

Secret 类型

类型说明用途
Opaque通用 Secret密码、Token
kubernetes.io/tlsTLS 证书HTTPS
kubernetes.io/dockerconfigjsonDocker 镜像仓库认证拉取私有镜像
kubernetes.io/service-account-tokenServiceAccount TokenAPI 访问
kubernetes.io/basic-auth基本认证用户名密码

创建 Secret

# Opaque Secret
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
  namespace: default
type: Opaque
data:
  username: YWRtaW4=        # base64 编码的 "admin"
  password: cEBzc3cwcmQ=    # base64 编码的 "p@ssw0rd"

---
# 字符串数据 (自动 base64 编码)
apiVersion: v1
kind: Secret
metadata:
  name: my-secret-string
  namespace: default
type: Opaque
stringData:
  username: admin
  password: p@ssw0rd
# 命令行创建 Secret
kubectl create secret generic my-secret \
  --from-literal=username=admin \
  --from-literal=password=p@ssw0rd

# 从文件创建 Secret
kubectl create secret generic my-secret \
  --from-file=username.txt \
  --from-file=password.txt

# 创建 TLS Secret
kubectl create secret tls my-tls \
  --cert=tls.crt \
  --key=tls.key

Pod 使用 Secret

# 环境变量方式
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: password

---
# 挂载卷方式
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-pod
spec:
  containers:
  - name: app
    image: my-app:latest
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

Secret 编码

# Base64 编码
echo -n "admin" | base64
# 输出: YWRtaW4=

# Base64 解码
echo "YWRtaW4=" | base64 -d
# 输出: admin

# 创建 Secret
kubectl create secret generic my-secret \
  --from-literal=username=admin \
  --from-literal=password=p@ssw0rd \
  --dry-run=client -o yaml

etcd 加密配置

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-secret>
      - identity: {}
# 检查 etcd 加密状态
kubectl get secrets --all-namespaces -o json | kubectl neat

# 验证加密配置
kubectl get encryptionconfig -n kube-system

External Secrets Operator

# 安装 External Secrets Operator
# helm install external-secrets external-secrets/external-secrets

# SecretStore 配置
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
  namespace: default
spec:
  provider:
    vault:
      server: "http://vault:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "my-role"

---
# ExternalSecret 配置
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-external-secret
  namespace: default
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: my-secret
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: secret/my-app
        property: username
    - secretKey: password
      remoteRef:
        key: secret/my-app
        property: password

HashiCorp Vault 集成

# Vault Agent 注入
apiVersion: v1
kind: Pod
metadata:
  name: vault-agent-pod
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "my-role"
    vault.hashicorp.com/agent-inject-secret-db-creds: "secret/data/my-app"
spec:
  containers:
  - name: app
    image: my-app:latest

密钥轮换

# 使用外部密钥管理实现自动轮换
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: auto-rotating-secret
spec:
  refreshInterval: 1h  # 每小时检查更新
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: my-secret
  data:
    - secretKey: api-key
      remoteRef:
        key: secret/my-app
        property: api-key

密钥管理最佳实践

1. 不要将 Secret 提交到代码仓库
   - 使用 .gitignore
   - 使用 Secret 管理工具

2. 启用 etcd 加密
   - 配置 EncryptionConfiguration
   - 定期轮换加密密钥

3. 使用外部密钥管理
   - HashiCorp Vault
   - AWS Secrets Manager
   - Azure Key Vault

4. 最小权限原则
   - RBAC 限制 Secret 访问
   - Pod 级别访问控制

5. 定期轮换密钥
   - 自动轮换
   - 监控过期时间

实践练习

练习 1:创建和使用 Secret

# 创建 Secret
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: default
type: Opaque
stringData:
  username: admin
  password: securepassword123

---
# Pod 使用 Secret
apiVersion: v1
kind: Pod
metadata:
  name: db-client
spec:
  containers:
  - name: app
    image: postgres:latest
    env:
    - name: POSTGRES_USER
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: username
    - name: POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: password
# 应用配置
kubectl apply -f db-credentials.yaml

# 验证 Secret
kubectl get secret db-credentials -o yaml

练习 2:配置 etcd 加密

# 创建加密配置
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <生成的密钥>
      - identity: {}
# 生成加密密钥
head -c 32 /dev/urandom | base64

# 配置 API Server
# 编辑 /etc/kubernetes/manifests/kube-apiserver.yaml
# 添加 --encryption-provider-config 参数

常见误解

1. Secret 是加密的

事实:Secret 默认只是 base64 编码,不是加密
误解:Secret 自动加密存储
解决:启用 etcd 加密或使用外部密钥管理

2. Secret 可以替代所有密钥管理

事实:Secret 是基本的密钥存储机制
误解:Secret 可以替代专业的密钥管理工具
解决:生产环境使用 Vault 等专业工具

小结

要点说明
Secret存储敏感信息的 Kubernetes 资源
编码方式Base64 编码 (非加密)
安全增强etcd 加密、外部密钥管理
最佳实践不提交代码仓库、启用加密、定期轮换
外部工具HashiCorp Vault、AWS Secrets Manager

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「镜像安全」 以巩固所学知识。