LabHub
学习 学习路径 课程

CAPA — Argo 项目认证助理

造出租户边界与应用工厂

在 LabHub 中继续学习

目标

通过 AppProject 声明 tenant 边界,编写使用两种 ApplicationSet 生成 Application 的 manifest,并把与该边界相对应的实际 namespace 和 ResourceQuota 部署到 cluster。

为什么重要

multi-tenancy 由两层组成。上层规定“谁可以声明什么”,下层规定“这些声明能使用多少资源”。AppProject 只负责上层。即使通过 destinations 限制了部署目标,也无法阻止该 namespace 占满 node,这属于 ResourceQuota 的职责。反过来,如果只有 ResourceQuota,就无法阻止 tenant 把别人的仓库作为 source,或创建 ClusterRoleBinding。只有把两层一起建立起来,才能真正理解每种工具的作用范围。

步骤

  1. 创建 /root/capa-project/ 目录,并在 appproject.yaml 中写入 kind AppProjectmetadata.namecapa-tenantsmetadata.namespaceargocd。在 spec.sourceRepos 中加入 https://gitea.homelab.internal/platform/*;在 spec.destinations[0] 中加入 server https://kubernetes.default.svc 与 namespace capa-team-*
  2. 在同一文件的 spec.clusterResourceWhitelist 中加入 group ""、kind Namespace;在 spec.namespaceResourceBlacklist 中加入 group ""ResourceQuotaLimitRange 两种资源。
  3. spec.roles[0] 中设置 name deployer,policies 包含 p, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allow,groups 中加入 capa-platform
  4. spec.syncWindows 中创建一项:kind deny、schedule 0 0 * * 0,6、duration 24h、applications *
  5. /root/capa-project/appset-list.yaml 中写入 kind ApplicationSetmetadata.namecapa-tenants-list,并把 spec.goTemplate 设为 true。在 spec.generators[0].list.elements 中加入 3 项,每项的 tenant 值分别为 alphabravocharlie;把 spec.template.spec.project 指定为 capa-tenants
  6. /root/capa-project/appset-matrix.yaml 中写入 kind ApplicationSetmetadata.namecapa-tenants-matrix,并把 spec.goTemplate 设为 true。在 spec.generators[0].matrix.generators 中恰好放入两个 generator:一个是 repoURL 为 https://gitea.homelab.internal/platform/tenants.gitdirectories[0].pathapps/* 的 git generator;另一个是至少包含一个 element 的 list generator。
  7. 在 cluster 中实际创建 capa-team-alphacapa-team-bravocapa-team-charlie 三个 namespace,并分别把 label capa.io/tenant 的值设为 alphabravocharlie
  8. 在三个 namespace 中分别实际创建名为 tenant-quota 的 ResourceQuota。spec.hard.pods10spec.hard["requests.cpu"]2

参考

配置 AppProject 的允许 source 与部署目标

创建 /root/capa-project/ 目录,并在 appproject.yaml 中写入 kind AppProjectmetadata.namecapa-tenantsmetadata.namespaceargocd。在 spec.sourceRepos 中加入 https://gitea.homelab.internal/platform/*;在 spec.destinations[0] 中加入 server https://kubernetes.default.svc 与 namespace capa-team-*

sourceRepos 与 destinations 都是 allowlist。destinations 的 namespace 字段可以使用 wildcard。

配置 whitelist 与 blacklist

在同一文件的 spec.clusterResourceWhitelist 中加入 group ""、kind Namespace;在 spec.namespaceResourceBlacklist 中加入 group ""ResourceQuotaLimitRange 两种资源。

cluster scope 默认为全部禁止,需要列出允许项;namespace scope 默认为全部允许,需要列出禁止项。记住两者方向相反即可。

映射 project role 与 group

spec.roles[0] 中设置 name deployer,policies 包含 p, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allow,groups 中加入 capa-platform

policy 字符串由 p、SUBJECT、RESOURCE、ACTION、OBJECT、EFFECT 六部分组成。project role 的 subject 使用 proj:项目名:角色名格式。

在周末禁止同步

spec.syncWindows 中创建一项:kind deny、schedule 0 0 * * 0,6、duration 24h、applications *

syncWindows 项由 kind、schedule、duration、applications 组成。schedule 表示窗口开始时间的 cron,duration 表示窗口长度。

配置 list generator 与 goTemplate

/root/capa-project/appset-list.yaml 中写入 kind ApplicationSetmetadata.namecapa-tenants-list,并把 spec.goTemplate 设为 true。在 spec.generators[0].list.elements 中加入 3 项,每项的 tenant 值分别为 alphabravocharlie;把 spec.template.spec.project 指定为 capa-tenants

list generator 的 elements 是由任意 key 组成的 map 数组。若要使用条件或循环,需要在 spec 下启用一个用于切换 template engine 的 boolean。

通过 matrix generator 创建笛卡尔积

/root/capa-project/appset-matrix.yaml 中写入 kind ApplicationSetmetadata.namecapa-tenants-matrix,并把 spec.goTemplate 设为 true。在 spec.generators[0].matrix.generators 中恰好放入两个 generator:一个是 repoURL 为 https://gitea.homelab.internal/platform/tenants.gitdirectories[0].pathapps/* 的 git generator;另一个是至少包含一个 element 的 list generator。

matrix 下必须恰好有两个 generators 才会形成笛卡尔积。git generator 通过 directories 扫描目录,并为每个目录产生一组参数。

创建三个 tenant namespace

在 cluster 中实际创建 capa-team-alphacapa-team-bravocapa-team-charlie 三个 namespace,并分别把 label capa.io/tenant 的值设为 alphabravocharlie

从这里开始操作的是实际 cluster。确保名称与 label 值一一对应;这是重复操作,也可以使用 shell loop。

用 ResourceQuota 建立资源边界

在三个 namespace 中分别实际创建名为 tenant-quota 的 ResourceQuota。spec.hard.pods10spec.hard["requests.cpu"]2

ResourceQuota 的 spec.hard 是 map,key 中包含点号。请记住,AppProject 画出的只是声明层面的边界,这正是本步骤存在的意义。