kubernetes 核心技术-Secret

183 阅读5分钟

在 Kubernetes(简称 K8s)中,Secret(秘密) 是一种用于存储和管理敏感信息(如密码、OAuth 令牌和 SSH 密钥等)的资源对象。与 ConfigMap 类似,Secret 也是一种配置资源,但专门设计用于处理敏感数据,以确保这些数据在集群中传输和存储时的安全性。

Secret 的基本概念

在 Kubernetes 中,Secret 是一种 API 对象,用于存储小规模的敏感数据。通过 Secret,用户可以将敏感信息从 Pod 的定义中分离出来,避免将敏感数据硬编码到容器镜像或配置文件中。

为什么使用 Secret?

  • 安全性:避免将敏感信息暴露在代码库或配置文件中。
  • 灵活性:可以在运行时动态更新敏感信息,而无需重建容器镜像。
  • 集成性:与 Kubernetes 的其他资源(如 Pod、Deployment、ServiceAccount 等)无缝集成。

Secret 的类型

Kubernetes 支持多种类型的 Secret,每种类型适用于不同的场景:

  1. Opaque(不透明类型) :最常用的类型,用于存储任意类型的键值对。
  2. kubernetes.io/dockerconfigjson:用于存储 Docker 镜像仓库的认证信息,通常用于拉取私有镜像。
  3. kubernetes.io/service-account-token:自动为每个 ServiceAccount 创建的 Secret,包含访问 Kubernetes API 的令牌。
  4. kubernetes.io/basic-auth:用于存储基本认证的用户名和密码。
  5. kubernetes.io/ssh-auth:用于存储 SSH 密钥。
  6. kubernetes.io/tls:用于存储 TLS 证书和私钥。

创建和使用 Secret

创建 Secret

可以通过多种方式创建 Secret,包括 YAML 文件、kubectl 命令以及 API 请求。以下是通过 YAML 文件创建一个 Opaque 类型的 Secret 的示例:

yaml
复制代码
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4=   # base64 编码后的 'admin'
  password: MWYyZDFlMmU2N2Rm   # base64 编码后的 '1f2d1e2e67df'

注意:Secret 数据需要以 base64 编码存储。

可以使用 kubectl 命令创建 Secret:

bash
复制代码
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=1f2d1e2e67df

使用 Secret

Secret 可以通过以下几种方式挂载到 Pod 中:

  1. 作为环境变量
yaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
    - name: app
      image: myapp:latest
      env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: password
  1. 作为卷(Volume)
yaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-pod
spec:
  containers:
    - name: app
      image: myapp:latest
      volumeMounts:
        - name: secret-volume
          mountPath: "/etc/secret"
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: my-secret
  1. 作为 Docker 镜像拉取凭证
yaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: private-reg-pod
spec:
  containers:
    - name: app
      image: myprivateregistry.com/myapp:latest
  imagePullSecrets:
    - name: my-reg-secret

Secret 的安全性考虑

尽管 Secret 提供了一定程度的安全性,但默认情况下,Secret 数据是以 base64 编码存储的,这并不提供加密保护。因此,为了增强 Secret 的安全性,需要考虑以下几点:

  1. 访问控制:利用 Kubernetes 的 RBAC(基于角色的访问控制)机制,限制对 Secret 的访问权限,确保只有授权的用户和服务账户能够访问敏感信息。
  2. 加密存储:启用 Kubernetes 的数据加密功能,确保存储在 etcd 中的 Secret 数据是加密的。
  3. 避免日志泄露:确保应用程序不会将 Secret 数据输出到日志中,防止敏感信息泄露。
  4. 定期轮换:定期更新和轮换 Secret,降低密钥泄露带来的风险。

加密存储

默认情况下,Kubernetes 将 Secret 存储在 etcd 中,未经加密。如果需要增强安全性,可以启用 Kubernetes 的数据加密功能,使用 AES-CBC 或其他加密算法对 Secret 数据进行加密。以下是配置加密存储的基本步骤:

  1. 创建加密配置文件(例如 encryption-config.yaml):
yaml
复制代码
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}
  1. 更新 API Server 配置,指定加密配置文件:
bash
复制代码
--encryption-provider-config=/path/to/encryption-config.yaml
  1. 重启 API Server 以应用更改。

注意:加密配置需要在集群创建时设置,后续更改可能需要额外的步骤来加密现有的 Secret。

管理 Secret 的最佳实践

  1. 最小权限原则:仅授予应用程序和用户访问所需 Secret 的权限,避免过度授权。
  2. 使用命名空间隔离:将 Secret 限定在特定命名空间中,防止跨命名空间的访问。
  3. 避免在代码中硬编码:永远不要将 Secret 硬编码在应用程序代码或配置文件中。
  4. 定期审计和轮换:定期检查 Secret 的使用情况,并定期更新和轮换密钥和密码。
  5. 使用外部秘密管理系统:考虑集成外部的秘密管理解决方案(如 HashiCorp Vault、AWS Secrets Manager、Azure Key Vault 等)以增强 Secret 的管理和安全性。

示例

以下是一个完整的示例,展示如何创建一个包含数据库凭证的 Secret,并将其作为环境变量挂载到 Pod 中。

创建 Secret

yaml
复制代码
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: ZGJ1c2Vy  # base64 编码 'dbuser'
  password: cGFzc3dvcmQ=  # base64 编码 'password'

使用 kubectl 创建:

bash
复制代码
kubectl apply -f db-secret.yaml

使用 Secret 的 Pod 定义

yaml
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: db-app-pod
spec:
  containers:
    - name: db-app
      image: mydbapp:latest
      env:
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: password

应用 Pod 配置:

bash
复制代码
kubectl apply -f db-app-pod.yaml

在应用程序中,可以通过环境变量 DB_USERNAMEDB_PASSWORD 访问数据库凭证。


通过合理使用 Kubernetes 的 Secret 资源,可以有效地管理和保护集群中的敏感信息,提高应用程序的安全性和可维护性。