Skip to main content

Multi-tenancy


Table of Contents​

  1. Concept
  2. Isolation by namespace
  3. Isolation by repository
  4. RBAC and ServiceAccounts
  5. Advanced patterns
  6. Hands-on exercises

1 - Concept​

What is Multi-tenancy?​

Multi-tenancy makes it possible to share a Flux cluster among multiple teams with isolation.

Multi-tenancy models​

ModelDescriptionIsolation
NamespaceTeams in separate namespacesMedium
RepositoryEach team has its own Git repoStrong
ClusterSeparate clustersMaximum

πŸ” Back to table of contents​


2 - Isolation by namespace​

Structure​

clusters/production/
β”œβ”€β”€ flux-system/
β”œβ”€β”€ tenants/
β”‚ β”œβ”€β”€ team-a/
β”‚ β”‚ β”œβ”€β”€ namespace.yaml
β”‚ β”‚ β”œβ”€β”€ rbac.yaml
β”‚ β”‚ └── kustomization.yaml
β”‚ └── team-b/
β”‚ β”œβ”€β”€ namespace.yaml
β”‚ β”œβ”€β”€ rbac.yaml
β”‚ └── kustomization.yaml
└── infrastructure/

Namespace for a tenant​

# tenants/team-a/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: team-a
labels:
toolkit.fluxcd.io/tenant: team-a

Kustomization limited to the namespace​

# tenants/team-a/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: team-a-apps
namespace: team-a
spec:
interval: 5m
path: ./apps
sourceRef:
kind: GitRepository
name: team-a-repo
namespace: team-a
prune: true
targetNamespace: team-a # Force le namespace
serviceAccountName: team-a-flux # ServiceAccount limitΓ©

Restrict the target namespaces​

spec:
targetNamespace: team-a
# OU
patches:
- patch: |
- op: replace
path: /metadata/namespace
value: team-a
target:
kind: '*'

πŸ” Back to table of contents​


3 - Isolation by repository​

# Repo platform-admin (admin seulement)
platform-gitops/
β”œβ”€β”€ clusters/
β”‚ └── production/
β”‚ β”œβ”€β”€ flux-system/
β”‚ └── tenants/
β”‚ β”œβ”€β”€ team-a.yaml # GitRepository + Kustomization
β”‚ └── team-b.yaml

# Repo team-a (Γ©quipe A seulement)
team-a-gitops/
β”œβ”€β”€ apps/
β”‚ β”œβ”€β”€ frontend/
β”‚ └── backend/
└── kustomization.yaml

# Repo team-b (Γ©quipe B seulement)
team-b-gitops/
β”œβ”€β”€ apps/
β”‚ └── api/
└── kustomization.yaml

Reference the team's repo​

# platform-gitops/clusters/production/tenants/team-a.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: team-a-repo
namespace: team-a
spec:
interval: 1m
url: https://github.com/org/team-a-gitops
ref:
branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: team-a
namespace: team-a
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: team-a-repo
path: ./apps
prune: true
serviceAccountName: team-a-flux

πŸ” Back to table of contents​


4 - RBAC and ServiceAccounts​

ServiceAccount for a tenant​

apiVersion: v1
kind: ServiceAccount
metadata:
name: team-a-flux
namespace: team-a

Limited Role​

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: team-a-flux
namespace: team-a
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

RoleBinding​

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-flux
namespace: team-a
subjects:
- kind: ServiceAccount
name: team-a-flux
namespace: team-a
roleRef:
kind: Role
name: team-a-flux
apiGroup: rbac.authorization.k8s.io

Limit the creatable resources​

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: team-a-flux
namespace: team-a
rules:
# Autoriser Deployments, Services, ConfigMaps
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["*"]
- apiGroups: [""]
resources: ["services", "configmaps", "secrets"]
verbs: ["*"]
# Interdire les Ingress (exemple)
# - apiGroups: ["networking.k8s.io"]
# resources: ["ingresses"]
# verbs: ["*"]

πŸ” Back to table of contents​


5 - Advanced patterns​

App-of-apps pattern​

# tenants/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: tenants
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: flux-system
path: ./tenants
prune: true

Network Policies​

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}

Resource Quotas​

apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"

Limit Ranges​

apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
type: Container

πŸ” Back to table of contents​


6 - Hands-on exercises​

Exercise 1: Create a tenant​

# team-demo-tenant.yaml
apiVersion: v1
kind: Namespace
metadata:
name: team-demo
labels:
toolkit.fluxcd.io/tenant: team-demo
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: team-demo-flux
namespace: team-demo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: team-demo-flux
namespace: team-demo
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-demo-flux
namespace: team-demo
subjects:
- kind: ServiceAccount
name: team-demo-flux
namespace: team-demo
roleRef:
kind: Role
name: team-demo-flux
apiGroup: rbac.authorization.k8s.io

Quiz​

Q1. Why use a ServiceAccount per tenant?

Answer

To limit the permissions of the Kustomize Controller to the tenant's namespace only. Without a dedicated ServiceAccount, Flux uses its own permissions (cluster-admin) and can deploy anywhere.

Q2. Which is the best isolation: namespace or repository?

Answer

Isolation by repository is stronger because:

  • Each team only sees its own Git repo
  • No access to other teams' secrets
  • Clear separation of responsibilities

The namespace alone isolates within the cluster but not in Git.

πŸ” Back to table of contents​


Key takeaways​

  • Multi-tenancy = sharing the cluster among teams
  • Isolation by namespace, repository, or cluster
  • Dedicated ServiceAccount per tenant
  • RBAC to limit permissions
  • NetworkPolicies and ResourceQuotas for isolation

← Previous chapter | Next chapter: Best practices β†’