Kubernetes Secret 介绍与使用 – wiki大全

Kubernetes Secret 介绍与使用

在云原生应用部署中,敏感信息的管理一直是一个核心且具有挑战性的问题。密码、API 密钥、OAuth 令牌、SSH 密钥和证书等数据,如果处理不当,极易导致安全漏洞。Kubernetes Secret 提供了一种安全有效的方式来存储和管理这些敏感数据,避免将其直接硬编码到应用程序代码或 Pod 配置文件中。

什么是 Kubernetes Secret?

Kubernetes Secret 是一种用于存储和管理敏感信息(例如密码、OAuth 令牌、SSH 密钥和证书)的 Kubernetes 对象。它类似于 ConfigMap,但专为处理机密数据而设计,而 ConfigMap 则用于存储非敏感的配置信息。通过将敏感信息从应用程序中解耦,Secret 提高了应用的安全性、可移植性和可管理性。

为什么使用 Secret?

  1. 安全性提升: 避免将敏感数据直接暴露在 Pod 定义、容器镜像或版本控制系统中,降低意外泄露的风险。
  2. 职责分离: 允许开发者专注于应用程序逻辑,而运维人员则负责敏感数据的安全管理。
  3. 灵活部署: 应用程序可以在不修改代码的情况下,轻松地在不同环境中使用不同的敏感数据。
  4. 动态更新: Secret 的数据可以在不重启 Pod 的情况下进行更新(对于挂载为 Volume 的情况),提高了运维效率。

Secret 的类型

Kubernetes 提供了多种内置的 Secret 类型,以适应不同的使用场景:

  • Opaque (默认): 这是最常见的类型,用于存储用户定义的任意数据。数据以 Base64 编码格式存储。需要强调的是,Base64 编码并非加密,它只是一种编码方式,可以轻易解码获取原始数据。因此,尽管 Secret 提供了存储敏感信息的位置,其在 etcd 中的存储加密(即静态加密)至关重要。
    yaml
    apiVersion: v1
    kind: Secret
    metadata:
    name: my-opaque-secret
    type: Opaque
    data:
    username: YWRtaW4= # "admin" 的 Base64 编码
    password: c2VjcmV0 # "secret" 的 Base64 编码
  • kubernetes.io/dockerconfigjson: 用于存储私有 Docker 镜像仓库的认证信息,以便 kubelet 从私有仓库拉取镜像。
  • kubernetes.io/service-account-token: 用于 ServiceAccount 访问 Kubernetes API 的令牌凭据。Kubernetes 在创建 ServiceAccount 时会自动创建并挂载相应的 Secret。
  • kubernetes.io/basic-auth: 用于存储基本认证所需的凭据,包含 usernamepassword 字段。
  • kubernetes.io/ssh-auth: 用于存储 SSH 认证所需的凭据。
  • kubernetes.io/tls: 用于存储 TLS 客户端或服务器端的证书和私钥数据。

如何创建 Secret?

主要有两种方式创建 Secret:

1. 使用 kubectl 命令

  • 从字面值创建:
    bash
    kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=secret
  • 从文件创建:
    假设你有一个 username.txt 文件内容为 admin,一个 password.txt 文件内容为 secret
    bash
    kubectl create secret generic my-secret --from-file=username=username.txt --from-file=password=password.txt

2. 通过 YAML 文件定义

创建 Secret 的 YAML 定义文件时,data 字段的值必须是 Base64 编码的字符串。你可以使用 echo -n "your_value" | base64 来进行编码。

“`yaml

my-secret.yaml

apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: YWRtaW4= # “admin” 的 Base64 编码
password: c2VjcmV0 # “secret” 的 Base64 编码


base64 -w 0 <<< “admin”

base64 -w 0 <<< “secret”

然后应用该文件:bash
kubectl apply -f my-secret.yaml
“`

如何使用 Secret?

在 Pod 中使用 Secret 主要有以下几种方式:

1. 作为 Volume 挂载

将 Secret 作为数据卷挂载到 Pod 中的容器。Secret 中的数据将以文件的形式出现在指定的挂载路径下。
* 挂载为 Volume 的 Secret 数据存储在节点上的 tmpfs (内存文件系统) 中,不会写入磁盘,并在 Pod 删除后自动清除。
* Secret 更新后,挂载的 Volume 中的数据会最终保持一致并更新。

yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- name: secret-volume
mountPath: "/etc/secrets"
readOnly: true # 建议设置为只读
volumes:
- name: secret-volume
secret:
secretName: my-secret
items: # 可选:指定要挂载的 Secret 中的特定键
- key: username
path: db_username
- key: password
path: db_password

在容器内部,你可以在 /etc/secrets/db_username/etc/secrets/db_password 路径下找到相应的值。

2. 作为环境变量

将 Secret 中的数据作为环境变量注入到容器中。
* 需要注意的是,通过环境变量注入的 Secret 数据在 Secret 更新后不会自动更新。如果 Secret 更新,需要重启 Pod 才能使环境变量生效。

yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod-env
spec:
containers:
- name: my-container-env
image: alpine
command: ["sh", "-c", "echo Username: $DB_USERNAME && echo Password: $DB_PASSWORD"]
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password
restartPolicy: Never

3. 作为 Image Pull Secret

用于 kubelet 从私有镜像仓库拉取镜像时进行认证。
首先创建一个 docker-registry 类型的 Secret:
bash
kubectl create secret docker-registry my-registry-secret \
--docker-server=your-registry.example.com \
--docker-username=your-username \
--docker-password=your-password \
[email protected]

然后,在 Pod 或 Deployment 的 spec 中引用它:
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod-private-image
spec:
containers:
- name: my-container
image: your-registry.example.com/my-private-image:latest
imagePullSecrets:
- name: my-registry-secret

最佳实践

为了安全有效地使用 Kubernetes Secret,建议遵循以下最佳实践:

  1. 启用静态加密 (Encryption at Rest): 默认情况下,Secret 在 etcd 中是以未加密的形式存储的。强烈建议为 etcd 启用静态加密,以保护存储在其中的 Secret 数据。这是防止攻击者直接访问 etcd 数据时获取敏感信息的最关键措施。
  2. 最小权限访问 (Least Privilege Access):
    • 通过 RBAC (Role-Based Access Control) 严格限制对 Secret 的访问权限。仅向有需要的用户和 ServiceAccount 授予访问 Secret 的权限。
    • 仅向最高权限的系统组件授予 watchlist Secret 的权限,并且仅在必要时授予 get Secret 的权限。
    • 请注意,任何有权创建使用 Secret 的 Pod 的用户,都可以间接读取该 Secret 的值。
    • 使用独立的命名空间来隔离对 Secret 的访问,进一步限制其作用域。
  3. 传输中安全 (In-transit Security): Kubernetes 用户与 API 服务器之间以及 API 服务器与 kubelet 之间的所有通信都通过 SSL/TLS 保护,确保 Secret 在传输过程中的安全。
  4. 生命周期管理:
    • 使用生命周期较短的 Secret,定期轮换敏感信息。
    • 实施审计规则,对可疑的 Secret 访问行为发出警报。
  5. 节点存储的安全性: Secret 仅在 Pod 需要时才会被发送到相应的节点。在节点上,它们存储在内存文件系统 (tmpfs) 中,不会写入磁盘,并在 Pod 删除后自动从节点本地副本中删除。这有效防止了敏感信息在节点磁盘上留下痕迹。
  6. 隔离性: 一个 Pod 无法访问另一个 Pod 的 Secret。在同一个 Pod 内,每个容器也必须通过 volumeMountsenv 明确请求 Secret 才能访问。
  7. 考虑外部 Secret 管理: 对于更高的安全要求或跨集群/多云环境,可以考虑使用外部 Secret 管理解决方案,如 HashiCorp Vault、AWS Secrets Manager、Azure Key Vault 或 GCP Secret Manager。这些工具提供了更高级的加密、审计、轮换和访问控制功能。
  8. 避免硬编码: 绝不应将敏感信息硬编码在 Pod 定义或容器镜像中。始终通过 Secret 或其他秘密管理机制来注入。

总结

Kubernetes Secret 是管理敏感数据的强大工具,它将敏感配置与应用程序代码分离,显著提高了安全性、灵活性和可维护性。然而,为了充分利用其优势并确保环境安全,理解其工作原理并遵循最佳实践至关重要。结合静态加密、最小权限原则和恰当的生命周期管理,Secret 将成为您云原生应用部署中不可或缺的安全基石。

滚动至顶部