在多 namespace 的 Kubernetes 集群里,TLS Secret、镜像拉取凭据、配置文件等资源经常需要在多个 namespace 里保持相同的内容。Secret 不能直接跨 namespace 引用,传统做法是手动 kubectl 复制,或者写脚本定时同步——两种方式都有维护成本和容易遗漏的问题。
Kubernetes Reflector 是一个轻量级的 controller,专门解决这个问题:在源资源(Secret 或 ConfigMap)上添加几个注解,它就会自动把资源同步到指定的 namespace,并在源资源更新时同步更新所有副本。
典型使用场景
TLS 通配符证书跨 namespace 分发
cert-manager 只在一个 namespace 签发证书,但多个 namespace 的 Ingress 都需要引用同一份 TLS Secret。
default/wiloon-tls-secret ──Reflector──▶ argocd/wiloon-tls-secret
──▶ nexus/wiloon-tls-secret
──▶ rssx/wiloon-tls-secret
──▶ ...
镜像拉取凭据(ImagePullSecret)
私有镜像仓库的登录凭据需要在所有运行业务 Pod 的 namespace 里都存在。
安装
helm repo add emberstack https://emberstack.github.io/helm-charts
helm repo update
helm upgrade --install reflector emberstack/reflector \
--namespace kube-system
或者用 ArgoCD Application 管理:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: reflector
namespace: argocd
spec:
project: default
source:
repoURL: https://emberstack.github.io/helm-charts
chart: reflector
targetRevision: "8.x"
destination:
server: https://kubernetes.default.svc
namespace: kube-system
syncPolicy:
automated:
prune: true
selfHeal: true
注解说明
在源 Secret / ConfigMap 上添加注解来控制同步行为:
metadata:
annotations:
# 允许被反射(必填)
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
# 允许同步到哪些 namespace(逗号分隔,支持正则)
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "argocd,nexus,rssx"
# 自动在目标 namespace 创建(无需目标 namespace 显式声明接收)
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
# 自动同步到哪些 namespace(留空则同步到 reflection-allowed-namespaces)
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "argocd,nexus"
reflection-auto-enabled: "true" 时,Reflector 主动推送——目标 namespace 不需要做任何操作,Secret 自动出现。这是最省事的模式,适合通配符 TLS 证书这类"所有 namespace 都需要"的场景。
与 cert-manager 结合使用
在 default namespace 签发通配符证书,通过 Reflector 同步到其他 namespace:
# Certificate(default namespace)
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-cert
namespace: default
spec:
secretName: wiloon-tls-secret
commonName: "*.wiloon.lab"
dnsNames:
- "*.wiloon.lab"
duration: 8760h
renewBefore: 720h
issuerRef:
kind: ClusterIssuer
name: ca-issuer
cert-manager 签发后,Secret wiloon-tls-secret 会自动创建。推荐在 Certificate CR 的 secretTemplate 里预先定义注解,这样 cert-manager 在创建 Secret 时就带上注解,完全声明式,适合 ArgoCD 管理:
spec:
secretTemplate:
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "argocd,nexus,rssx,enx"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
如果 Secret 已经存在(如从旧版迁移),也可以用 kubectl annotate 补打:
# 补打注解(已有 Secret 的迁移场景)
kubectl annotate secret wiloon-tls-secret -n default \
reflector.v1.k8s.emberstack.com/reflection-allowed=true \
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces="argocd,nexus,rssx,enx" \
reflector.v1.k8s.emberstack.com/reflection-auto-enabled=true
验证同步结果:
kubectl get secret wiloon-tls-secret -A
新增 namespace 的处理
开启 reflection-auto-enabled 后,新建 namespace 里也会自动出现 Secret,无需任何额外操作。
如果不想用 auto 模式,而是由目标 namespace 主动声明"我要接收这个 Secret",可以在目标端创建一个同名的 Secret 并打上注解:
apiVersion: v1
kind: Secret
metadata:
name: wiloon-tls-secret
namespace: new-namespace
annotations:
reflector.v1.k8s.emberstack.com/reflects: "default/wiloon-tls-secret"
这种方式更安全,能精确控制哪些 namespace 可以接收。
注意事项
- Reflector 异常时,已同步的 Secret 不会消失,只是不再自动更新;服务短期内不受影响
- 源 Secret 删除时,Reflector 会同步删除所有反射副本,需注意不要误删
reflection-allowed-namespaces支持正则表达式,如".*"表示所有 namespace(谨慎使用)- cert-manager 续期后会更新源 Secret,Reflector 会自动把新证书同步到各 namespace
与 per-namespace Certificate CR 方案对比
| per-namespace Certificate | Reflector | |
|---|---|---|
| 原理 | cert-manager 在每个 namespace 各自签发 | 只签发一次,controller 自动同步 |
| 新增 namespace | 需在 manifests 里加 certificate.yaml |
auto 模式下零操作 |
| 额外依赖 | 无 | 需部署 Reflector controller |
| 证书续期 | cert-manager 各自续期,相互独立 | 源续期后 Reflector 同步 |
| GitOps 可见性 | 每个 namespace 的证书状态都在 git 里 | 副本由 Reflector 管理,不在 git 里 |
两种方案都是合理的选择。namespace 数量少、变动少时,per-namespace CR 更透明;namespace 数量多或经常新增时,Reflector 更省事。