Aller au contenu
CI/CD & Automatisation medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Flux CD — Multi-tenancy et isolation par équipe

11 min de lecture

Flux CD est conçu nativement pour le multi-tenancy : chaque équipe peut avoir son propre dépôt Git, ses propres namespaces et ses propres droits dans le cluster, sans accès aux ressources des autres équipes. Ce guide explique comment mettre en place cette isolation en utilisant les ServiceAccount Flux et les permissions RBAC Kubernetes standards.

  • Comprendre le modèle de tenant de Flux (pas de CRD custom — juste du K8s)
  • Créer un namespace dédié avec un ServiceAccount Flux pour chaque équipe
  • Configurer une Kustomization pour s’exécuter sous le compte d’une équipe
  • Restreindre les dépôts Git autorisés par équipe
  • Appliquer la politique de no-cross-namespace pour les sources
  • Structurer un dépôt multi-tenant en pratique
  • Flux bootstrappé et fonctionnel
  • Connaissance des bases RBAC Kubernetes (Role, ClusterRole, RoleBinding)
  • Au moins deux équipes ou applications à isoler

Contrairement à ArgoCD qui utilise les AppProject pour l’isolation, Flux utilise le RBAC Kubernetes natif. L’isolation repose sur deux mécanismes :

  1. ServiceAccount par équipe — Chaque Kustomization ou HelmRelease peut s’exécuter sous l’identité d’un ServiceAccount dédié avec des droits limités à son namespace.

  2. Politiques de sources cross-namespace — Par défaut, une ressource Flux dans le namespace team-a ne peut pas référencer une GitRepository dans le namespace flux-system (ou tout autre namespace). Vous devez autoriser explicitement ce partage.

flux-system namespace
└── kustomize-controller (droits cluster-admin)
└── Kustomization: team-a → déploie dans team-a
└── Kustomization: team-b → déploie dans team-b

Dans ce modèle, le contrôleur Flux s’exécute avec des droits cluster-admin. Une Kustomization de l’équipe A peut potentiellement créer des ClusterRole ou modifier le namespace team-b.

flux-system namespace
└── kustomize-controller
└── Kustomization: team-a → ServiceAccount: team-a-flux (droits: team-a seulement)
└── Kustomization: team-b → ServiceAccount: team-b-flux (droits: team-b seulement)

Chaque Kustomization s’exécute avec les droits du ServiceAccount de l’équipe. Le kustomize-controller se comporte juste comme un intermédiaire qui impersonne le ServiceAccount désigné.

Voici la procédure complète pour créer un tenant pour l’équipe frontend.

  1. Créer le namespace et le ServiceAccount
tenants/frontend/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: frontend
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flux-tenant
namespace: frontend
  1. Créer les droits RBAC du ServiceAccount

Le tenant peut créer et gérer des ressources dans son namespace, mais pas créer de ClusterRole ou accéder aux autres namespaces :

tenants/frontend/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: flux-tenant
namespace: frontend
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin # Droits admin dans ce namespace seulement
subjects:
- kind: ServiceAccount
name: flux-tenant
namespace: frontend
  1. Créer la Source GitRepository pour le tenant
tenants/frontend/gitrepository.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: frontend-config
namespace: frontend # Dans le namespace du tenant, pas flux-system
spec:
interval: 1m
url: https://github.com/my-org/frontend-config
ref:
branch: main
secretRef:
name: frontend-git-credentials
  1. Créer la Kustomization avec serviceAccountName
tenants/frontend/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: frontend-apps
namespace: frontend # Dans le namespace du tenant
spec:
interval: 5m
path: ./apps
prune: true
sourceRef:
kind: GitRepository
name: frontend-config
namespace: frontend # Même namespace que la Kustomization
serviceAccountName: flux-tenant # Impersonation du ServiceAccount tenant
targetNamespace: frontend
  1. Ajouter le tenant à la Kustomization racine

Dans clusters/my-cluster/, créez ou éditez la Kustomization qui gère les tenants :

clusters/my-cluster/tenants.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: tenants
namespace: flux-system
spec:
interval: 5m
path: ./tenants
prune: true
sourceRef:
kind: GitRepository
name: flux-system
  1. Poussez dans Git et vérifiez :
Fenêtre de terminal
git add tenants/
git commit -m "feat: add frontend tenant"
git push origin main
flux reconcile kustomization tenants
flux get kustomizations

Par défaut depuis Flux v0.27, les Kustomization et HelmRelease ne peuvent pas référencer des sources dans d’autres namespaces sans autorisation explicite.

Pour permettre à la Kustomization du namespace frontend de partager la GitRepository de flux-system, créez un CrossNamespaceObjectReference ou, plus simplement, placez la GitRepository dans le même namespace que la Kustomization.

Si vous voulez partager une source depuis flux-system, ajoutez une annotation sur la source :

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: shared-infra
namespace: flux-system
labels:
app.kubernetes.io/component: source
# Pas d'annotation nécessaire côté source, mais la Kustomization
# doit utiliser spec.crossNamespaceSelector ou pointer vers son namespace

La pratique la plus simple et la mieux isolée : chaque tenant a sa propre GitRepository dans son namespace.

Interdire les ressources cross-namespace (sécurité renforcée)

Section intitulée « Interdire les ressources cross-namespace (sécurité renforcée) »

Pour bloquer complètement les références cross-namespace, activez la politique au niveau du contrôleur :

# Dans gotk-components.yaml ou votre configuration Flux
# Ajoutez --no-cross-namespace-refs dans args du kustomize-controller
spec:
template:
spec:
containers:
- name: manager
args:
- --no-cross-namespace-refs=true

Avec cette option, toute Kustomization qui tente de référencer une source dans un namespace différent sera immédiatement rejetée avec une erreur.

Voici une structure recommandée pour gérer plusieurs tenants depuis le même dépôt d’administration :

fleet-infra/
├── clusters/
│ └── my-cluster/
│ ├── flux-system/ ← Flux se gère lui-même
│ └── tenants.yaml ← Kustomization qui charge ./tenants
├── tenants/
│ ├── frontend/
│ │ ├── namespace.yaml
│ │ ├── rbac.yaml
│ │ ├── gitrepository.yaml
│ │ └── kustomization.yaml
│ ├── backend/
│ │ └── ...
│ └── data-team/
│ └── ...
└── infrastructure/
└── ... ← Ressources cluster-wide administrées par l'équipe plateforme

L’équipe plateforme gère fleet-infra (les tenants + l’infrastructure). Chaque équipe applicative gère son propre frontend-config ou backend-config.

Pour une isolation encore plus fine, créez un Role custom qui liste précisément les ressources qu’un tenant peut créer :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: flux-tenant-role
namespace: frontend
rules:
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["*"]
- apiGroups: [""]
resources: ["services", "configmaps", "serviceaccounts"]
verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["*"]
# Interdire explicitement la création de RBAC
# (en ne listant pas ces ressources)

Ce Role empêche le tenant de créer des ClusterRole, des NetworkPolicy global, ou d’accéder aux Secrets des autres namespaces.

Fenêtre de terminal
# Lister les Kustomizations par namespace
kubectl get kustomizations -A
# NAMESPACE NAME READY SUSPENDED
# flux-system flux-system True False
# flux-system tenants True False
# frontend frontend-apps True False
# Vérifier le ServiceAccount utilisé
kubectl describe kustomization frontend-apps -n frontend
# Spec:
# Service Account Name: flux-tenant
# Tester que le tenant NE peut pas modifier le namespace flux-system
kubectl auth can-i create deployments -n flux-system \
--as=system:serviceaccount:frontend:flux-tenant
# no
  • Flux utilise le RBAC Kubernetes natif pour l’isolation — pas de CRD d’isolation spécifique.
  • Chaque tenant a son propre ServiceAccount avec des RoleBinding limités à son namespace.
  • Le champ serviceAccountName dans une Kustomization délègue l’exécution au compte du tenant.
  • Placer la GitRepository dans le même namespace que la Kustomization évite les problèmes de références cross-namespace.
  • --no-cross-namespace-refs renforce l’isolation en interdisant tout partage de sources entre namespaces.
  • L’équipe plateforme gère le dépôt d’admin (tenants + infra) ; chaque équipe gère son propre dépôt applicatif.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn