Skip to content

Secret

概述

Secret 是 Kubernetes 中用于存储和管理敏感信息的对象,如密码、OAuth 令牌、SSH 密钥等。它提供了一种安全的方式来处理敏感数据,避免将这些信息硬编码在应用程序或容器镜像中。

关键点内容
核心作用安全存储和管理敏感信息
数据编码Base64 编码存储
访问控制基于 RBAC 的访问控制
使用方式环境变量、文件挂载、镜像拉取凭证

Secret 的本质

设计理念

  • 安全隔离:将敏感数据与应用程序代码分离
  • 访问控制:通过 RBAC 控制对敏感数据的访问
  • 灵活使用:支持多种方式将敏感数据注入到 Pod 中
  • 版本管理:支持敏感数据的版本控制和更新

工作原理

敏感数据 → Base64编码 → Secret对象 → etcd存储 → Pod使用
    ↓           ↓          ↓         ↓        ↓
  明文数据    编码存储    API对象   加密存储   解码使用

Secret vs ConfigMap

特性SecretConfigMap
数据类型敏感数据配置数据
存储方式Base64 编码明文存储
安全性高(可加密)低(明文)
使用场景密码、证书、密钥配置文件、环境变量
大小限制1MB1MB

Secret 类型

内置类型

类型用途数据字段
Opaque通用类型,用户定义数据任意键值对
kubernetes.io/service-account-tokenServiceAccount 令牌token, ca.crt, namespace
kubernetes.io/dockercfgDocker 配置文件.dockercfg
kubernetes.io/dockerconfigjsonDocker 配置 JSON.dockerconfigjson
kubernetes.io/basic-auth基本认证username, password
kubernetes.io/ssh-authSSH 认证ssh-privatekey
kubernetes.io/tlsTLS 证书tls.crt, tls.key
bootstrap.kubernetes.io/tokenBootstrap 令牌token-id, token-secret

基本配置

1. Opaque Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=  # admin 的 base64 编码
  password: MWYyZDFlMmU2N2Rm  # 1f2d1e2e67df 的 base64 编码

使用 stringData(推荐)

yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
  username: admin
  password: 1f2d1e2e67df

2. Docker Registry Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: regcred
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJteXVzZXIiLCJwYXNzd29yZCI6Im15cGFzcyIsImVtYWlsIjoibXllbWFpbEBleGFtcGxlLmNvbSIsImF1dGgiOiJiWGwxYzJWeU9tMTVjR0Z6Y3c9PSJ9fX0=

使用命令创建

bash
kubectl create secret docker-registry regcred \
  --docker-server=https://index.docker.io/v1/ \
  --docker-username=myuser \
  --docker-password=mypass \
  --docker-email=myemail@example.com

3. TLS Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTi... # base64 编码的证书
  tls.key: LS0tLS1CRUdJTi... # base64 编码的私钥

使用命令创建

bash
kubectl create secret tls tls-secret \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key

4. Basic Auth Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin
  password: secretpassword

5. SSH Auth Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: ssh-key-secret
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: LS0tLS1CRUdJTi... # base64 编码的私钥

使用 Secret

1. 作为环境变量

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
    - name: SECRET_USERNAME
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: username
    - name: SECRET_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password
  restartPolicy: Never

批量导入环境变量

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-envfrom-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    envFrom:
    - secretRef:
        name: mysecret
  restartPolicy: Never

2. 作为文件挂载

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    volumeMounts:
    - name: secret-volume
      mountPath: "/etc/secret-volume"
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: mysecret
  restartPolicy: Never

指定文件权限

yaml
volumes:
- name: secret-volume
  secret:
    secretName: mysecret
    defaultMode: 0400  # 只读权限
    items:
    - key: username
      path: my-group/my-username
      mode: 0777

3. 作为镜像拉取凭证

yaml
apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: myregistry.com/myapp:latest
  imagePullSecrets:
  - name: regcred

在 ServiceAccount 中配置

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
imagePullSecrets:
- name: regcred

---
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-sa
spec:
  serviceAccountName: my-service-account
  containers:
  - name: mycontainer
    image: myregistry.com/myapp:latest

高级配置

1. 多个 Secret 组合使用

yaml
apiVersion: v1
kind: Pod
metadata:
  name: multi-secret-pod
spec:
  containers:
  - name: mycontainer
    image: nginx
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    - name: API_KEY
      valueFrom:
        secretKeyRef:
          name: api-secret
          key: key
    volumeMounts:
    - name: ssl-certs
      mountPath: "/etc/ssl/certs"
      readOnly: true
    - name: ssh-keys
      mountPath: "/root/.ssh"
      readOnly: true
  volumes:
  - name: ssl-certs
    secret:
      secretName: tls-secret
  - name: ssh-keys
    secret:
      secretName: ssh-key-secret
      defaultMode: 0600

2. Secret 的投影卷

yaml
apiVersion: v1
kind: Pod
metadata:
  name: projected-secret-pod
spec:
  containers:
  - name: mycontainer
    image: nginx
    volumeMounts:
    - name: projected-volume
      mountPath: "/etc/config"
      readOnly: true
  volumes:
  - name: projected-volume
    projected:
      sources:
      - secret:
          name: mysecret
          items:
          - key: username
            path: db-username
      - secret:
          name: api-secret
          items:
          - key: key
            path: api-key
      - configMap:
          name: myconfig
          items:
          - key: config.yaml
            path: app-config.yaml

3. 不可变 Secret

yaml
apiVersion: v1
kind: Secret
metadata:
  name: immutable-secret
type: Opaque
immutable: true  # 设置为不可变
stringData:
  username: admin
  password: secretpassword

4. Secret 的子路径挂载

yaml
apiVersion: v1
kind: Pod
metadata:
  name: subpath-secret-pod
spec:
  containers:
  - name: mycontainer
    image: nginx
    volumeMounts:
    - name: secret-volume
      mountPath: "/etc/nginx/ssl/tls.crt"
      subPath: tls.crt
      readOnly: true
    - name: secret-volume
      mountPath: "/etc/nginx/ssl/tls.key"
      subPath: tls.key
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: tls-secret

命令行操作

创建 Secret

bash
# 从字面值创建
kubectl create secret generic mysecret \
  --from-literal=username=admin \
  --from-literal=password=secretpassword

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

# 从目录创建
kubectl create secret generic mysecret \
  --from-file=path/to/secret/dir/

# 创建 Docker Registry Secret
kubectl create secret docker-registry regcred \
  --docker-server=myregistry.com \
  --docker-username=myuser \
  --docker-password=mypass \
  --docker-email=myemail@example.com

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

查看和管理 Secret

bash
# 查看 Secret 列表
kubectl get secrets

# 查看 Secret 详细信息
kubectl describe secret mysecret

# 查看 Secret 内容(base64 编码)
kubectl get secret mysecret -o yaml

# 解码 Secret 内容
kubectl get secret mysecret -o jsonpath='{.data.username}' | base64 --decode

# 编辑 Secret
kubectl edit secret mysecret

# 删除 Secret
kubectl delete secret mysecret

更新 Secret

bash
# 使用 kubectl patch 更新
kubectl patch secret mysecret -p '{"stringData":{"password":"newpassword"}}'

# 使用 kubectl apply 更新
kubectl apply -f updated-secret.yaml

# 替换整个 Secret
kubectl replace -f new-secret.yaml

安全最佳实践

1. 访问控制

yaml
# RBAC 配置示例
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]
  resourceNames: ["mysecret"]  # 限制特定 Secret

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-secrets
  namespace: default
subjects:
- kind: ServiceAccount
  name: secret-reader-sa
  namespace: default
roleRef:
  kind: Role
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

2. 加密存储

yaml
# EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <32-byte base64 encoded key>
  - identity: {}

3. 网络策略

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-secret-access
spec:
  podSelector:
    matchLabels:
      access-secrets: "false"
  policyTypes:
  - Ingress
  - Egress

4. Pod 安全策略

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: mycontainer
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL
    volumeMounts:
    - name: secret-volume
      mountPath: "/etc/secret"
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: mysecret
      defaultMode: 0400

监控和审计

1. Secret 使用监控

yaml
# ServiceMonitor for Prometheus
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: secret-usage-monitor
spec:
  selector:
    matchLabels:
      app: secret-monitor
  endpoints:
  - port: metrics
    path: /metrics
    interval: 30s

2. 审计策略

yaml
# Audit Policy
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets"]
  verbs: ["get", "list", "create", "update", "patch", "delete"]

3. 告警规则

yaml
# Prometheus Alert Rules
groups:
- name: secret-alerts
  rules:
  - alert: SecretAccessFailure
    expr: increase(apiserver_audit_total{verb="get",objectRef_resource="secrets",verb="get",code!~"2.."}[5m]) > 0
    for: 0m
    labels:
      severity: warning
    annotations:
      summary: "Secret access failure detected"
      description: "Failed attempts to access secrets detected"
  
  - alert: UnauthorizedSecretAccess
    expr: increase(apiserver_audit_total{verb="get",objectRef_resource="secrets",user_username!~"system:.*"}[5m]) > 10
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "Unusual secret access pattern"
      description: "High number of secret access attempts by non-system users"

故障排查

常见问题

问题可能原因解决方案
Secret 无法挂载权限不足或 Secret 不存在检查 RBAC 和 Secret 存在性
环境变量为空Secret key 不存在检查 Secret 的 key 名称
文件权限错误defaultMode 设置不当调整 defaultMode 或 mode 设置
Base64 解码错误编码格式问题检查 base64 编码是否正确
Pod 启动失败Secret 引用错误检查 Secret 名称和命名空间

诊断步骤

  1. 检查 Secret 存在性
bash
kubectl get secret mysecret
kubectl describe secret mysecret
  1. 验证 Secret 内容
bash
kubectl get secret mysecret -o yaml
echo "<base64-string>" | base64 --decode
  1. 检查 Pod 配置
bash
kubectl describe pod mypod
kubectl get pod mypod -o yaml
  1. 查看 Pod 日志
bash
kubectl logs mypod
kubectl describe pod mypod
  1. 测试 Secret 访问
bash
# 进入 Pod 检查
kubectl exec -it mypod -- /bin/sh
ls -la /etc/secret-volume/
echo $SECRET_USERNAME

性能优化

1. Secret 大小优化

yaml
# 避免大型 Secret,考虑拆分
apiVersion: v1
kind: Secret
metadata:
  name: large-secret
type: Opaque
stringData:
  # 避免存储大文件,考虑使用外部存储
  config: |
    # 保持配置简洁
    key1: value1
    key2: value2

2. 缓存优化

yaml
# 使用 projected volumes 减少 API 调用
volumes:
- name: combined-volume
  projected:
    sources:
    - secret:
        name: secret1
    - secret:
        name: secret2
    - configMap:
        name: config1

3. 更新策略

yaml
# 使用不可变 Secret 提高性能
apiVersion: v1
kind: Secret
metadata:
  name: immutable-secret
type: Opaque
immutable: true
stringData:
  key: value

外部 Secret 管理

1. External Secrets Operator

yaml
# SecretStore 配置
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "example-role"

---
# ExternalSecret 配置
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: vault-secret
spec:
  refreshInterval: 15s
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: example-secret
    creationPolicy: Owner
  data:
  - secretKey: password
    remoteRef:
      key: secret/data/database
      property: password

2. Sealed Secrets

yaml
# SealedSecret 配置
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: mysecret
spec:
  encryptedData:
    username: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEQAx...
    password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEQAx...
  template:
    metadata:
      name: mysecret
    type: Opaque

总结

Secret 是 Kubernetes 中管理敏感信息的核心组件,提供了安全、灵活的敏感数据管理能力。通过合理配置 Secret 类型、访问控制和使用方式,可以构建安全可靠的应用程序。

关键要点

  • 选择合适的 Secret 类型和存储方式
  • 实施严格的访问控制和 RBAC 策略
  • 使用加密存储保护静态数据
  • 建立监控和审计机制
  • 遵循安全最佳实践
  • 考虑使用外部 Secret 管理系统
  • 优化 Secret 的大小和更新策略