1. 概述
在 Kubernetes 中,**Secret** 是一种用于存储敏感信息(如 API 密钥、证书、密码等)的资源对象。通过 Secret 来传递敏感信息,可以有效控制访问权限,提高安全性。然而,Secret 的作用域是命名空间级别的,也就是说,一个 Secret 只能在它被创建的 namespace 中使用,无法直接在其他 namespace 中引用。
本文将介绍 Kubernetes 中 Secret 的基本使用方式,并探讨几种在多个 namespace 之间共享 Secret 的方法。
2. 跨命名空间使用 Secret 的问题
为了说明 Secret 无法跨 namespace 使用的问题,我们先创建一个 Secret,然后尝试在另一个 namespace 中引用它。
示例 Secret 定义
# app-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
secret_api_key: YWRtaW4=
上面这个 Secret 存储了一个 Base64 编码的字符串 admin
,键为 secret_api_key
。
创建 Secret
kubectl create namespace production
kubectl apply -n production -f app-secret.yaml
在另一个 namespace 中引用 Secret
# deployment.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: alpine:latest
command: ['sh', '-c', 'env | grep SECRET_API_KEY']
env:
- name: SECRET_API_KEY
valueFrom:
secretKeyRef:
name: app-secret
key: secret_api_key
尝试在 staging
命名空间中部署这个 Pod:
kubectl apply -n staging -f deployment.yaml
查看 Pod 状态
kubectl get pods -n staging
输出:
NAME READY STATUS RESTARTS AGE
myapp 0/1 CreateContainerConfigError 0 68s
使用 kubectl describe
查看具体错误:
kubectl describe -n staging pod myapp
输出中会包含类似如下信息:
Warning Failed ... kubelet Error: secret "app-secret" not found
这说明,Secret 是 namespace 限定的,无法跨 namespace 使用。
3. 方法一:在多个命名空间中复制 Secret
最直接的方式是在每个需要使用的 namespace 中分别创建相同的 Secret。这种方式实现简单,无需额外组件。
手动复制
kubectl apply -f app-secret.yaml
kubectl apply -f app-secret.yaml -n staging
kubectl apply -f app-secret.yaml -n production
自动复制已有 Secret
可以使用 kubectl get
+ jq
命令将某个 namespace 中的 Secret 复制到另一个 namespace:
kubectl get secrets app-secret -n default -o json \
| jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid","annotations"])' \
| kubectl apply -n gateway -f -
✅ 优点:无需引入额外组件,操作简单
❌ 缺点:Secret 更新后需手动同步多个 namespace,维护成本高
4. 方法二:使用 kubernetes-reflector 扩展自动同步
kubernetes-reflector 是一个 Kubernetes 自定义控制器,可以自动将某个 namespace 中的资源(如 Secret)复制并同步到其他 namespace。
4.1 安装
kubectl apply -f https://github.com/emberstack/kubernetes-reflector/releases/latest/download/reflector.yaml
检查部署状态:
kubectl get deployments
输出:
NAME READY UP-TO-DATE AVAILABLE AGE
reflector 1/1 1 1 3m6s
4.2 启用 Secret 复制
在目标 Secret 上添加如下注解:
# app-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
type: Opaque
stringData:
db_host: vendor-database.org
data:
secret_api_key: YWRtaW4=
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
✅ 启用复制reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
✅ 自动同步
部署 Secret:
kubectl apply -f app-secret.yaml
创建一个新 namespace,Secret 会自动复制过去:
kubectl create namespace test
kubectl get secrets -n test
输出:
NAME TYPE DATA AGE
app-secret Opaque 2 4s
4.3 限制复制的目标命名空间
可以通过注解指定只复制到特定的 namespace:
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "test,staging"
✅ 优点:自动同步,适合频繁变更的 Secret(如短期证书)
❌ 缺点:需引入额外组件,增加集群维护复杂度
5. 总结
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
手动复制 Secret | 简单直接,无需组件 | 更新需手动同步 | Secret 不常变 |
使用 kubernetes-reflector | 自动同步,维护方便 | 引入新组件,增加复杂度 | Secret 频繁更新 |
✅ 建议:
- 如果 Secret 不常变,推荐使用手动复制方式,简单可控
- 如果 Secret 需要频繁更新,或需同步到多个 namespace,建议使用
kubernetes-reflector
自动同步
⚠️ 注意:无论使用哪种方式,都应确保 Secret 的权限管理得当,避免敏感信息泄露。