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 的权限管理得当,避免敏感信息泄露。


原始标题:Sharing Secrets Across Namespaces in Kubernetes