Skip to content

kubernetes-reflector 学习实验

这个组件是干什么的

kubernetes-reflector 用来把 Secret 和 ConfigMap 从一个命名空间同步到另一个命名空间。

它常见的用途有两类:

  • 把共享配置同步给多个业务命名空间
  • 把 TLS 证书、镜像拉取凭据这类共享密钥同步给多个命名空间

先记住这 4 条

  1. 只有 Secret 和 ConfigMap 能被它处理。
  2. 源对象必须显式声明“允许被反射”。
  3. 手动镜像是“你先建目标对象,再让它指向源对象”。
  4. 自动镜像是“源对象一声明,Reflector 自动去目标命名空间创建同名对象”。

关键注解

  • reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
  • 允许这个源对象被反射
  • reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "ns1,ns2"
  • 只允许这些命名空间接收镜像
  • reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces-selector: "team=demo"
  • 按命名空间标签选择允许接收镜像的命名空间
  • reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
  • 开启自动镜像
  • reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "ns1,ns2"
  • 自动镜像到这些命名空间
  • reflector.v1.k8s.emberstack.com/reflection-auto-namespaces-selector: "team=demo"
  • 按命名空间标签自动创建镜像
  • reflector.v1.k8s.emberstack.com/reflects: "源命名空间/源对象名"
  • 手动镜像时,目标对象用它指向源对象

安装

前提条件:

  • Kubernetes 版本不低于 1.22
  • Helm 版本不低于 3.8

安装命令:

helm upgrade --install reflector oci://ghcr.io/emberstack/helm-charts/reflector -n kube-system --create-namespace
kubectl -n kube-system get pods

如果想看控制器日志:

kubectl -n kube-system logs deploy/reflector

实验 1:手动镜像 ConfigMap

目标:理解 reflects 是怎么工作的。

应用实验文件:

#01-manual-configmap.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: reflector-source
---
apiVersion: v1
kind: Namespace
metadata:
  name: app-a
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: reflector-source
  annotations:
    reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
    reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "app-a"
data:
  color: red
  version: v1
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-copy
  namespace: app-a
  annotations:
    reflector.v1.k8s.emberstack.com/reflects: "reflector-source/app-config"
data: {}
kubectl apply -f 01-manual-configmap.yaml
kubectl -n app-a get configmap app-config-copy -o yaml

会看到:

  • 源对象在 reflector-source/app-config
  • 目标对象在 app-a/app-config-copy
  • 目标对象的数据会和源对象保持一致

继续做同步实验:

  1. 打开 01-manual-configmap.yaml
  2. 把源 ConfigMap 里的 color: red 改成 color: blue
  3. 把 version: v1 改成 version: v2
  4. 再次执行:
kubectl apply -f 01-manual-configmap.yaml
kubectl -n app-a get configmap app-config-copy -o yaml

学习点:

  • 手动镜像时,目标对象名字可以和源对象不同
  • 真正的同步入口是目标对象上的 reflects

实验 2:自动镜像 Secret

目标:理解自动创建同名镜像的方式。

应用实验文件:

#02-auto-secret.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: shared-secrets
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-a
---
apiVersion: v1
kind: Namespace
metadata:
  name: team-b
---
apiVersion: v1
kind: Secret
metadata:
  name: shared-login
  namespace: shared-secrets
  annotations:
    reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
    reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "team-a,team-b"
    reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
    reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "team-a,team-b"
type: Opaque
stringData:
  username: demo
  password: p1
kubectl apply -f 02-auto-secret.yaml
kubectl -n team-a get secret shared-login -o yaml
kubectl -n team-b get secret shared-login -o yaml

会看到:

  • 源对象在 shared-secrets/shared-login
  • team-a 和 team-b 会自动出现同名 Secret

继续做同步实验:

  1. 打开02-auto-secret.yaml
  2. 把源 Secret 里的 password: p1 改成 password: p2
  3. 再次执行:
kubectl apply -f 02-auto-secret.yaml
kubectl -n team-a get secret shared-login -o yaml
kubectl -n team-b get secret shared-login -o yaml

学习点:

  • 自动镜像要求源对象开启 reflection-auto-enabled
  • 自动镜像创建出来的目标对象默认与源对象同名
  • 自动镜像的目标命名空间必须同时满足“允许反射”和“自动反射”的约束

实验 3:按命名空间标签自动分发

目标:理解选择器模式,避免手写很多命名空间名。

应用实验文件:

#3-selector-configmap.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: selector-source
---
apiVersion: v1
kind: Namespace
metadata:
  name: blue-team
  labels:
    shared-config: "true"
    team: demo
    color: blue
---
apiVersion: v1
kind: Namespace
metadata:
  name: green-team
  labels:
    shared-config: "true"
    team: demo
    color: green
---
apiVersion: v1
kind: Namespace
metadata:
  name: other-team
  labels:
    shared-config: "false"
    team: other
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: shared-banner
  namespace: selector-source
  annotations:
    reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
    reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces-selector: "shared-config=true"
    reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
    reflector.v1.k8s.emberstack.com/reflection-auto-namespaces-selector: "shared-config=true"
data:
  title: 统一公告
  owner: 平台团队
kubectl apply -f 03-selector-configmap.yaml
kubectl -n blue-team get configmap shared-banner -o yaml
kubectl -n green-team get configmap shared-banner -o yaml
kubectl -n other-team get configmap shared-banner -o yaml

会看到:

  • blue-team 和 green-team 能拿到镜像
  • other-team 拿不到,因为它的标签不匹配

学习点:

  • 选择器语法遵循 Kubernetes 官方标签选择器规则
  • 这比手写一长串命名空间更适合规模化管理
  • 官方说明里,命名空间列表和选择器是“或”的关系

建议再做一个扩展实验

目标:观察自动镜像遇到同名资源冲突时的行为。

步骤:

  1. 先在 team-a 手动创建一个名字也叫 shared-login 的 Secret
  2. 再应用 02-auto-secret.yaml
  3. 查看日志:
kubectl -n kube-system logs deploy/reflector

理解:

  • 自动镜像不会强制覆盖已有同名对象
  • 生产环境里要先规划好共享资源命名

生产环境使用建议

  • 对 Secret 一定要缩小允许同步的命名空间范围
  • 尽量优先用标签选择器,而不是人工维护很长的命名空间名单
  • 如果是多租户集群,先验证租户边界,再决定是否允许跨命名空间复制密钥

官方来源

  • 官方仓库:https://github.com/emberstack/kubernetes-reflector
  • 官方 README:https://raw.githubusercontent.com/emberstack/kubernetes-reflector/master/README.md
  • 官方 Helm 发布页:https://artifacthub.io/packages/helm/emberstack/reflector
  • Kubernetes 官方标签选择器文档:https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/