Flux CD Flux CD

Mettre en place la multi-tenance avec Flux

Donnez à chaque équipe son propre namespace et son propre dépôt, et appliquez l'isolation avec le RBAC Kubernetes.

15 min Avancé

Quand plusieurs équipes partagent un cluster, vous voulez que chacune déploie ses propres applications sans pouvoir toucher à celles des autres. Flux construit cela sur des primitives Kubernetes : chaque tenant reçoit un namespace, un service account et un role binding, et Flux applique les manifestes du tenant en se faisant passer pour ce service account. L’isolation est assurée par le RBAC Kubernetes, sans moteur de politiques distinct. Ce guide met en place un tenant appelé dev-team.

Les deux rôles

  • Les administrateurs de la plateforme possèdent le cluster et l’installation de Flux. Ils créent les tenants et décident de ce à quoi chacun peut accéder.
  • Les tenants possèdent leurs applications. Ils committent leurs manifestes dans leur propre dépôt, et Flux les applique uniquement dans le namespace du tenant.

Créer le tenant

La CLI génère pour vous le namespace, le service account et le RBAC. Exécutez-la dans un clone du dépôt de la plateforme :

mkdir -p tenants/base/dev-team
flux create tenant dev-team \
  --with-namespace=apps \
  --export > tenants/base/dev-team/rbac.yaml

Le YAML généré contient un Namespace nommé apps, un ServiceAccount nommé dev-team, et un RoleBinding qui accorde à ce service account le rôle cluster-admin dans le seul namespace apps. Il ne peut rien faire en dehors.

Connecter le dépôt du tenant

Créez une source et une Kustomization pour le dépôt propre au tenant, dans le namespace du tenant :

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

La ligne importante est serviceAccountName: dev-team sur la Kustomization. Elle fait appliquer par kustomize-controller les manifestes du tenant sous l’identité de ce service account, de sorte que toute tentative de créer des ressources en dehors de apps, ou des ressources à l’échelle du cluster comme un ClusterRole, est rejetée par l’API Kubernetes. Le même champ existe sur HelmRelease.

Ajoutez un kustomization.yaml dans tenants/base/dev-team/ listant rbac.yaml et sync.yaml, et référencez le tenant depuis le dossier du cluster, par exemple via une Kustomization Flux dans clusters/production/tenants.yaml avec path: ./tenants/production. Committez et poussez. Flux crée le namespace, le RBAC et la synchronisation du tenant, puis le dépôt propre à l’équipe prend le relais.

Pour un dépôt de tenant privé, créez les identifiants dans le namespace du tenant pour que seuls les objets de ce tenant les référencent :

flux create secret git dev-team-auth \
  --namespace=apps \
  --url=https://github.com/your-org/dev-team-apps \
  --username=git --password=<token>

Ajoutez ensuite --secret-ref=dev-team-auth à la source.

Verrouiller les contrôleurs

Les service accounts ne servent que si les tenants ne peuvent pas les contourner. Configurez les contrôleurs pour appliquer les règles en patchant l’installation de Flux dans clusters/<env>/flux-system/kustomization.yaml :

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)"

Ce que font ces options :

  • --no-cross-namespace-refs=true empêche la Kustomization d’un tenant de référencer une source d’un autre namespace, de sorte que les tenants ne peuvent pas utiliser les dépôts ou les identifiants des autres.
  • --default-service-account=default fait emprunter aux contrôleurs l’identité du service account default dans le namespace de l’objet quand aucun n’est défini. Un tenant qui oublie serviceAccountName obtient presque aucune permission au lieu de l’identité cluster-admin de Flux.

Committez les patches dans le kustomization.yaml généré par le bootstrap dans ce dossier. Relancer le bootstrap conserve les personnalisations que vous ajoutez à ce fichier. Consultez la documentation actuelle de Flux sur la multi-tenance pour le patch exact correspondant à votre version.

Restreindre ce que les tenants peuvent faire

Au-delà de la frontière du namespace, envisagez des contrôles supplémentaires :

  • RBAC limité au namespace. Remplacez le role binding cluster-admin généré par un rôle plus étroit si les tenants ne doivent pas créer, par exemple, des Roles ou des NetworkPolicies.
  • Politique d’admission. Utilisez Kyverno ou une ValidatingAdmissionPolicy pour imposer des registres d’images, des limites de ressources, ou interdire les Pods privilégiés.
  • Quotas. Ajoutez un ResourceQuota et un LimitRange au namespace du tenant, à côté du RBAC.
  • Isolation réseau. Ajoutez des objets NetworkPolicy en refus par défaut pour que les namespaces des tenants ne puissent pas communiquer entre eux.

Vérifier l’isolation

Ajoutez au dépôt du tenant un manifeste qui crée quelque chose en dehors du namespace du tenant, comme un ClusterRole, puis poussez. Vérifiez ensuite :

flux get kustomizations -n apps
kubectl describe kustomization dev-team -n apps

La Kustomization échoue avec une erreur forbidden nommant le service account, ce qui est exactement ce que l’on veut. Retirez le mauvais manifeste et Flux se rétablit de lui-même.

Comparaison avec la multi-tenance basée sur des projets

Certains outils modélisent les tenants comme des projets dotés de leurs propres objets de politique. Flux n’a pas un tel concept. Un tenant est simplement un namespace plus un service account que Flux emprunte, ce qui signifie que l’API server de Kubernetes est le seul endroit où les permissions sont appliquées.

Guides populaires