Kubernetes--secret的简介和使用

一、什么是 Secret?

在 Kubernetes 中,Secret 是一种用于存储敏感信息的对象,例如:

  • 密码
  • 令牌(Token)
  • SSH 密钥
  • TLS 证书
  • Docker 镜像仓库认证信息

使用 Secret 可以避免将敏感数据直接写入 Pod 定义或容器镜像中,从而降低泄露风险。

二、为什么需要 Secret?

  • 安全隔离:Secret 独立于 Pod 创建和管理,减少在 Pod 创建、查看、编辑过程中敏感数据暴露的可能性。
  • 灵活分发:通过 Volume 或环境变量将敏感信息注入容器。
  • 访问控制:可结合 RBAC 限制对 Secret 的访问权限。

注意:默认情况下,Secret 在 etcd 中是未加密存储的。任何有 API 访问权限或 etcd 访问权限的人都能读取或修改 Secret。因此,建议启用静态加密、配置最小权限 RBAC 规则,并考虑使用外部 Secret 存储方案。

三、Secret 的类型

Kubernetes 提供了多种内置 Secret 类型,用于常见场景:

类型 用途
Opaque 用户自定义的任意数据(默认类型)
kubernetes.io/service-account-token ServiceAccount 令牌(旧版机制)
kubernetes.io/dockercfg 旧版 Docker 配置文件(~/.dockercfg)
kubernetes.io/dockerconfigjson 新版 Docker 配置文件(~/.docker/config.json)
kubernetes.io/basic-auth 基本认证的用户名/密码
kubernetes.io/ssh-auth SSH 认证的私钥
kubernetes.io/tls TLS 证书和密钥
bootstrap.kubernetes.io/token 节点引导令牌

你可以使用 kubectl create secret 命令或 YAML 文件创建这些类型的 Secret。

四、常用操作示例

1. 查看已有 Secret

bash 复制代码
kubectl get secret

输出示例:

复制代码
NAME                        TYPE                                  DATA   AGE
aliyun-kafka                Opaque                                2       2d
default-token-bzz7p         kubernetes.io/service-account-token   3       8d
model-mongo                 Opaque                                2       2d

2. 查看 Secret 详情(包含数据条目 Key)

bash 复制代码
kubectl describe secret model-mongo

输出示例:

复制代码
Name:         model-mongo
Namespace:    default
Type:         Opaque

Data
====
password:  16 bytes
username:  10 bytes

这里可以看到 passwordusername 两个数据条目,但不显示具体值

3. 查看 Secret 的完整 YAML(包含 Base64 编码的值)

bash 复制代码
kubectl edit secret model-mongo

或者:

bash 复制代码
kubectl get secret model-mongo -o yaml

输出片段:

yaml 复制代码
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
  name: model-mongo
type: Opaque

4. 解码 Secret 的值

Secret 中的 data 字段值是 Base64 编码 的。要查看原始值,可以解码:

bash 复制代码
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode

输出就是原始的密码或用户名。

五、创建 Secret 的方法

方法一:使用 kubectl create secret generic(Opaque 类型)

bash 复制代码
# 从字面值创建
kubectl create secret generic my-secret \
  --from-literal=username=admin \
  --from-literal=password=S3cRet!

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

方法二:使用 YAML 配置文件

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4=      # echo -n 'admin' | base64
  password: UzNjUmV0IQ==  # echo -n 'S3cRet!' | base64

更方便的可读方式(未编码)使用 stringData

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
stringData:
  username: admin
  password: S3cRet!

stringData 字段在写入 etcd 时会自动转为 Base64,且不能与 data 混用相同 key。

方法三:创建 Docker 仓库认证 Secret

bash 复制代码
kubectl create secret docker-registry my-registry-secret \
  --docker-server=https://index.docker.io/v1/ \
  --docker-username=myuser \
  --docker-password=mypassword \
  --docker-email=myemail@example.com

方法四:创建 TLS Secret

bash 复制代码
kubectl create secret tls my-tls-secret \
  --cert=path/to/tls.crt \
  --key=path/to/tls.key

六、在 Pod 中使用 Secret

1. 通过 Volume 挂载(文件形式)

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: nginx
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

每个 key 会变成一个文件,文件内容为解码后的值。

2. 通过环境变量注入

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: nginx
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: password

3. 用于拉取私有镜像

在 Pod 中通过 imagePullSecrets 引用:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myprivaterepo/myimage:latest
  imagePullSecrets:
  - name: my-registry-secret

也可以通过 ServiceAccount 默认挂载 imagePullSecrets

七、更新与不可变 Secret

  • 当 Secret 数据更新时,已挂载到 Pod Volume 中的内容会最终一致 地更新(但以 subPath 方式挂载的不会自动更新)。
  • 环境变量方式注入的 Secret 不会自动更新,需要重启 Pod。

从 Kubernetes v1.21 开始,支持 不可变 Secret

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: immutable-secret
immutable: true
data:
  key: dmFsdWU=

一旦标记为不可变,无法修改数据,也不能改回可变状态。这能提升大规模集群性能并防止意外修改。

八、最佳实践与安全建议

  1. 启用静态加密 :在 API Server 配置中开启 --encryption-provider-config
  2. 最小权限 RBAC :只授予必要的 getlist 权限,避免 watchdelete 范围过大。
  3. 避免将 Secret 放入环境变量(除非必要),环境变量可能被调试工具或日志泄漏。
  4. 使用 short-lived token :对于 ServiceAccount,优先使用 TokenRequest API 获取短期令牌,而不是长期 Secret 令牌。
  5. 限制 Secret 大小:每个 Secret 最大 1MiB,防止 API Server 内存过大。
  6. 审计与监控:定期检查谁访问了哪些 Secret。

九、参考链接


总结:Kubernetes Secret 是一种重要且灵活的资源对象,用于管理敏感信息。结合合理的安全策略和访问控制,可以安全地将凭证注入到 Pod 中,避免硬编码在镜像或配置中。

相关推荐
运维开发故事2 天前
基于 Arthas 的多集群在线诊断系统设计与实现
kubernetes
Patrick_Wilson4 天前
从「改个端口」到 502:Next.js on k8s 的容器端口、Service 映射与 env 覆盖
docker·kubernetes·next.js
阿里云云原生4 天前
AI 开发新常态:当 Cursor、Claude、Codex 并行,如何统一管理散落的 Skill 资产?
云原生·ai编程
探索云原生4 天前
K8s 1.36 这个 GA 特性,把 initContainer 拉模型的 hack 干掉了
ai·云原生·kubernetes
云恒要逆袭4 天前
运行你的第一个Docker容器
后端·docker·容器
Java之美4 天前
从edge-trigger到level-trigger,谈谈 Kubernetes controller 的开发范式
云原生
阿里云云原生5 天前
深度解构:当 Append-only 的 SLS 遇上 Update/Delete,是如何实现设计权衡的?
云原生
Java之美5 天前
一次k8s升级引发的DevicePlugin注册失败
云原生·kubernetes
秋播5 天前
nerdctl推送rancher本地镜像到harbor
云原生