使用 Flux 设置多租户
为每个团队提供各自的命名空间和仓库,并通过 Kubernetes RBAC 强制隔离。
当多个团队共享一个集群时,你希望每个团队都能部署自己的应用,而无法触碰他人的应用。Flux 在 Kubernetes 原语之上构建了这一点:每个租户获得一个命名空间、一个 service account 和一个 role binding,Flux 在模拟该 service account 的身份下应用租户的清单。隔离由 Kubernetes RBAC 强制执行,不需要单独的策略引擎。本指南设置一个名为 dev-team 的租户。
两种角色
- 平台管理员拥有集群和 Flux 安装。他们创建租户,并决定每个租户可以访问什么。
- 租户拥有他们自己的应用。他们把清单提交到自己的仓库,Flux 仅在租户的命名空间内应用它们。
创建租户
CLI 会为你生成命名空间、service account 和 RBAC。在平台仓库的克隆中运行:
mkdir -p tenants/base/dev-team
flux create tenant dev-team \
--with-namespace=apps \
--export > tenants/base/dev-team/rbac.yaml
生成的 YAML 包含一个名为 apps 的 Namespace、一个名为 dev-team 的 ServiceAccount,以及一个 RoleBinding,它授予该 service account 仅在 apps 命名空间内的 cluster-admin 角色。它无法在该命名空间之外做任何事情。
连接租户的仓库
在租户的命名空间中,为租户自己的仓库创建一个 source 和 Kustomization:
flux create source git dev-team \
--namespace=apps \
--url=https://github.com/your-org/dev-team-apps \
--branch=main \
--export > tenants/base/dev-team/sync.yaml
flux create kustomization dev-team \
--namespace=apps \
--service-account=dev-team \
--source=GitRepository/dev-team \
--path="./" \
--prune=true --interval=5m \
--export >> tenants/base/dev-team/sync.yaml
重要的一行是 Kustomization 上的 serviceAccountName: dev-team。它让 kustomize-controller 以该 service account 的身份应用租户的清单,因此任何试图在 apps 之外创建资源、或创建 ClusterRole 之类集群范围资源的尝试,都会被 Kubernetes API 拒绝。HelmRelease 上也有同样的字段。
在 tenants/base/dev-team/ 中添加一个列出 rbac.yaml 和 sync.yaml 的 kustomization.yaml,并从集群的文件夹中引用该租户,例如通过 clusters/production/tenants.yaml 中 path: ./tenants/production 的 Flux Kustomization。提交并推送。Flux 会创建命名空间、RBAC 和租户的同步,随后由团队自己的仓库接管。
对于私有的租户仓库,请在租户的命名空间中创建凭据,这样只有该租户的对象会引用它们:
flux create secret git dev-team-auth \
--namespace=apps \
--url=https://github.com/your-org/dev-team-apps \
--username=git --password=<token>
然后在 source 中添加 --secret-ref=dev-team-auth。
锁定控制器
只有当租户无法绕过 service account 时,它们才有意义。请通过修补 clusters/<env>/flux-system/kustomization.yaml 中的 Flux 安装,配置控制器来强制执行这些规则:
patches:
- patch: |
- op: add
path: /spec/template/spec/containers/0/args/-
value: --no-cross-namespace-refs=true
- op: add
path: /spec/template/spec/containers/0/args/-
value: --default-service-account=default
target:
kind: Deployment
name: "(kustomize-controller|helm-controller)"
- patch: |
- op: add
path: /spec/template/spec/containers/0/args/-
value: --no-cross-namespace-refs=true
target:
kind: Deployment
name: "(notification-controller|image-reflector-controller|image-automation-controller)"
这些参数的作用:
--no-cross-namespace-refs=true阻止租户的 Kustomization 引用另一个命名空间中的 source,所以租户无法使用彼此的仓库或凭据。--default-service-account=default使控制器在对象没有设置 service account 时,模拟该对象所在命名空间中的defaultservice account。忘记设置serviceAccountName的租户只会得到几乎没有任何权限的身份,而不是 Flux 的 cluster-admin 身份。
将这些补丁提交到 bootstrap 在该文件夹中生成的 kustomization.yaml 里。重新运行 bootstrap 会保留你添加到该文件中的自定义内容。请查看当前的 Flux 多租户文档,了解适用于你版本的确切补丁。
限制租户能做什么
在命名空间边界之外,考虑额外的控制:
- 命名空间范围的 RBAC。 如果租户不应当创建例如 Role 或 NetworkPolicy,请用更窄的角色替换生成的
cluster-admin角色绑定。 - 准入策略。 使用 Kyverno 或 ValidatingAdmissionPolicy 来强制镜像仓库、资源限制,或禁止特权 Pod。
- 配额。 在 RBAC 之外,为租户命名空间添加
ResourceQuota和LimitRange。 - 网络隔离。 添加默认拒绝的
NetworkPolicy对象,使租户命名空间之间无法互相通信。
验证隔离
向租户的仓库添加一个会在租户命名空间之外创建东西的清单,比如一个 ClusterRole,然后推送。接着检查:
flux get kustomizations -n apps
kubectl describe kustomization dev-team -n apps
Kustomization 会以一个指明 service account 的 forbidden 错误失败,这正是你想要的。移除有问题的清单后,Flux 会自行恢复。
与基于项目的租户模型的比较
有些工具将租户建模为带有各自策略对象的项目。Flux 没有这样的概念。租户只是一个命名空间加上一个 Flux 所模拟的 service account,这意味着 Kubernetes API 服务器是唯一强制执行权限的地方。
热门指南
-
推送与拉取:Flux 如何向 Kubernetes 交付 为什么基于拉取、由 Git 驱动的交付会改变你部署、保障安全和恢复集群的方式。 -
使用 GitRepository 与 Kustomization 部署你的第一个应用 通过 Kustomization 资源将 Flux 指向 Git 中的清单,并观察同步。 -
控制同步行为:间隔、Prune、漂移修正与回滚 决定 Flux 何时应用变更、删除什么、如何暂停它,以及如何撤销一次有问题的部署。 -
使用 Flux 镜像自动化实现镜像更新自动化 让 Flux 检测新的容器镜像标签,并将其提交回 Git。 -
使用 Flux 配置多集群 从一个仓库管理多个集群,包含共享基础设施和每个集群各自的差异。 -
Flux CD 与 Argo CD:如何选择 GitOps 工具 比较架构、UI、Helm、密钥、租户和镜像自动化,以选出合适的工具。