テナント境界とアプリ工場を作る
目標
AppProjectでテナントの境界を宣言し、ApplicationSetの2種類でApplicationを作り出すマニフェストを作成したうえで、その境界に対応する実際のネームスペースとResourceQuotaを、クラスターに載せます。
なぜ重要なのか
マルチテナンシーは、2つの層でできています。上の層は「誰が何を宣言できるか」で、下の層は「その宣言がリソースをどれだけ使えるか」です。AppProjectは、上の層だけを担当します。destinationsでデプロイ先を絞っても、そのネームスペースがノードを使い切ることは防げず、それはResourceQuotaの役目です。逆に、ResourceQuotaだけだと、テナントが他人のリポジトリをソースに指定したり、ClusterRoleBindingを作ったりすることを防げません。2つの層を一緒に立ててみてはじめて、各ツールの射程が身につきます。
ステップ
/root/capa-project/ディレクトリを作成し、appproject.yamlに、kindがAppProject、metadata.nameがcapa-tenants、metadata.namespaceがargocdのリソースを書いてください。spec.sourceReposにhttps://gitea.homelab.internal/platform/*を、spec.destinations[0]に、serverとしてhttps://kubernetes.default.svc、namespaceとしてcapa-team-*を入れてください。- 同じファイルの
spec.clusterResourceWhitelistに、groupが""、kindがNamespaceの項目を入れ、spec.namespaceResourceBlacklistには、groupが""のResourceQuotaとLimitRangeの2種類を入れてください。 spec.roles[0]に、nameがdeployerのロールを置き、policiesにp, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allowを含め、groupsにcapa-platformを入れてください。spec.syncWindowsに、kindがdeny、scheduleが0 0 * * 0,6、durationが24h、applicationsが*の項目を1つ作成してください。/root/capa-project/appset-list.yamlに、kindがApplicationSet、metadata.nameがcapa-tenants-listのリソースを書き、spec.goTemplateをtrueにしてください。spec.generators[0].list.elementsに、tenantキーの値がそれぞれalpha、bravo、charlieの項目を3つ入れ、spec.template.spec.projectをcapa-tenantsに指定してください。/root/capa-project/appset-matrix.yamlに、kindがApplicationSet、metadata.nameがcapa-tenants-matrixのリソースを書き、spec.goTemplateをtrueにしてください。spec.generators[0].matrix.generatorsにちょうど2つを入れ、1つはrepoURLがhttps://gitea.homelab.internal/platform/tenants.gitで、directories[0].pathがapps/*のgitジェネレーター、もう1つは要素が1つ以上のlistジェネレーターにしてください。- クラスターに、ネームスペース
capa-team-alpha、capa-team-bravo、capa-team-charlieの3つを実際に作成し、それぞれにラベルcapa.io/tenantの値を、alpha、bravo、charlieとして付けてください。 - 3つのネームスペースそれぞれに、名前が
tenant-quotaのResourceQuotaを実際に作成してください。spec.hard.podsは10、spec.hard["requests.cpu"]は2です。
参考
kubectl create quota tenant-quota --hard=pods=10,requests.cpu=2 -n <네임스페이스>(プレースホルダーはネームスペース名です)で、素早く作成できます。- マニフェストの検証は、
yq '.spec.clusterResourceWhitelist' /root/capa-project/appproject.yamlのように、フィールドだけを取り出して見てください。 - よくある間違い1: 許可リスト(clusterResourceWhitelist)と拒否リスト(namespaceResourceBlacklist)に、同じ種類を入れることです。2つのフィールドは、スコープが違います。
- よくある間違い2: matrixの下にジェネレーターを1つしか入れないことです。直積は、2つのときだけ成り立ちます。
AppProjectの許可するソースとデプロイ先
/root/capa-project/ディレクトリを作成し、appproject.yamlに、kindがAppProject、metadata.nameがcapa-tenants、metadata.namespaceがargocdのリソースを書いてください。spec.sourceReposにhttps://gitea.homelab.internal/platform/*を、spec.destinations[0]に、serverとしてhttps://kubernetes.default.svc、namespaceとしてcapa-team-*を入れてください。
sourceReposとdestinationsは、どちらも許可リストです。destinationsのnamespaceフィールドには、ワイルドカードを使えます。
許可リストと拒否リスト
同じファイルのspec.clusterResourceWhitelistに、groupが""、kindがNamespaceの項目を入れ、spec.namespaceResourceBlacklistには、groupが""のResourceQuotaとLimitRangeの2種類を入れてください。
クラスタースコープは、デフォルトが全面禁止なので、開けるべきものを書き、ネームスペーススコープは、デフォルトが全面許可なので、閉じるべきものを書きます。方向が逆だという点さえ押さえれば大丈夫です。
プロジェクトのロールとグループのマッピング
spec.roles[0]に、nameがdeployerのロールを置き、policiesにp, proj:capa-tenants:deployer, applications, sync, capa-tenants/*, allowを含め、groupsにcapa-platformを入れてください。
ポリシーの文字列は、p, SUBJECT, RESOURCE, ACTION, OBJECT, EFFECTの6つの欄です。プロジェクトのロールの主体は、proj:プロジェクト名:ロール名の形を使います。
週末は同期を止める
spec.syncWindowsに、kindがdeny、scheduleが0 0 * * 0,6、durationが24h、applicationsが*の項目を1つ作成してください。
syncWindowsの項目は、kind、schedule、duration、applicationsでできています。scheduleはウィンドウが開く時刻を指すcronで、durationがウィンドウの長さです。
listジェネレーターとgoTemplate
/root/capa-project/appset-list.yamlに、kindがApplicationSet、metadata.nameがcapa-tenants-listのリソースを書き、spec.goTemplateをtrueにしてください。spec.generators[0].list.elementsに、tenantキーの値がそれぞれalpha、bravo、charlieの項目を3つ入れ、spec.template.spec.projectをcapa-tenantsに指定してください。
listジェネレーターのelementsは、任意のキーを持つマップの配列です。条件や繰り返しを使うには、specの直下に、テンプレートエンジンを切り替えるブール値を1つ有効にする必要があります。
matrixジェネレーターで直積を作る
/root/capa-project/appset-matrix.yamlに、kindがApplicationSet、metadata.nameがcapa-tenants-matrixのリソースを書き、spec.goTemplateをtrueにしてください。spec.generators[0].matrix.generatorsにちょうど2つを入れ、1つはrepoURLがhttps://gitea.homelab.internal/platform/tenants.gitで、directories[0].pathがapps/*のgitジェネレーター、もう1つは要素が1つ以上のlistジェネレーターにしてください。
matrixの下のgeneratorsは、ちょうど2つであってはじめて直積になります。gitジェネレーターは、directoriesでディレクトリをスキャンして、各ディレクトリごとにパラメーターを1つずつ出します。
テナントのネームスペースを3つ作る
クラスターに、ネームスペースcapa-team-alpha、capa-team-bravo、capa-team-charlieの3つを実際に作成し、それぞれにラベルcapa.io/tenantの値を、alpha、bravo、charlieとして付けてください。
ここからは、実際のクラスターです。名前とラベルの値が、互いに対応するように作成してください。繰り返しの作業なので、シェルのループを使ってもよいです。
リソースの境界を立てるResourceQuota
3つのネームスペースそれぞれに、名前がtenant-quotaのResourceQuotaを実際に作成してください。spec.hard.podsは10、spec.hard["requests.cpu"]は2です。
ResourceQuotaのspec.hardはマップで、キーにドットが入ります。AppProjectが描いたものは、文法上の境界にすぎないという点を思い出せば、このステップの意味がはっきりします。