在 Kubernetes(简称 K8s)中,Secret(秘密) 是一种用于存储和管理敏感信息(如密码、OAuth 令牌和 SSH 密钥等)的资源对象。与 ConfigMap 类似,Secret 也是一种配置资源,但专门设计用于处理敏感数据,以确保这些数据在集群中传输和存储时的安全性。
Secret 的基本概念
在 Kubernetes 中,Secret 是一种 API 对象,用于存储小规模的敏感数据。通过 Secret,用户可以将敏感信息从 Pod 的定义中分离出来,避免将敏感数据硬编码到容器镜像或配置文件中。
为什么使用 Secret?
- 安全性:避免将敏感信息暴露在代码库或配置文件中。
- 灵活性:可以在运行时动态更新敏感信息,而无需重建容器镜像。
- 集成性:与 Kubernetes 的其他资源(如 Pod、Deployment、ServiceAccount 等)无缝集成。
Secret 的类型
Kubernetes 支持多种类型的 Secret,每种类型适用于不同的场景:
- Opaque(不透明类型) :最常用的类型,用于存储任意类型的键值对。
- kubernetes.io/dockerconfigjson:用于存储 Docker 镜像仓库的认证信息,通常用于拉取私有镜像。
- kubernetes.io/service-account-token:自动为每个 ServiceAccount 创建的 Secret,包含访问 Kubernetes API 的令牌。
- kubernetes.io/basic-auth:用于存储基本认证的用户名和密码。
- kubernetes.io/ssh-auth:用于存储 SSH 密钥。
- 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 中:
- 作为环境变量:
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
- 作为卷(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
- 作为 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 的安全性,需要考虑以下几点:
- 访问控制:利用 Kubernetes 的 RBAC(基于角色的访问控制)机制,限制对 Secret 的访问权限,确保只有授权的用户和服务账户能够访问敏感信息。
- 加密存储:启用 Kubernetes 的数据加密功能,确保存储在 etcd 中的 Secret 数据是加密的。
- 避免日志泄露:确保应用程序不会将 Secret 数据输出到日志中,防止敏感信息泄露。
- 定期轮换:定期更新和轮换 Secret,降低密钥泄露带来的风险。
加密存储
默认情况下,Kubernetes 将 Secret 存储在 etcd 中,未经加密。如果需要增强安全性,可以启用 Kubernetes 的数据加密功能,使用 AES-CBC 或其他加密算法对 Secret 数据进行加密。以下是配置加密存储的基本步骤:
- 创建加密配置文件(例如
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: {}
- 更新 API Server 配置,指定加密配置文件:
bash
复制代码
--encryption-provider-config=/path/to/encryption-config.yaml
- 重启 API Server 以应用更改。
注意:加密配置需要在集群创建时设置,后续更改可能需要额外的步骤来加密现有的 Secret。
管理 Secret 的最佳实践
- 最小权限原则:仅授予应用程序和用户访问所需 Secret 的权限,避免过度授权。
- 使用命名空间隔离:将 Secret 限定在特定命名空间中,防止跨命名空间的访问。
- 避免在代码中硬编码:永远不要将 Secret 硬编码在应用程序代码或配置文件中。
- 定期审计和轮换:定期检查 Secret 的使用情况,并定期更新和轮换密钥和密码。
- 使用外部秘密管理系统:考虑集成外部的秘密管理解决方案(如 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_USERNAME 和 DB_PASSWORD 访问数据库凭证。
通过合理使用 Kubernetes 的 Secret 资源,可以有效地管理和保护集群中的敏感信息,提高应用程序的安全性和可维护性。