## Introduction La multi-location dans Kubernetes consiste à exécuter des charges de travail de différentes équipes, projets ou clients sur un cluster partagé tout en les isolant les uns des autres. Dans un laboratoire local, vous pouvez expérimenter en toute sécurité les éléments constitutifs de la multi-location : les namespaces, les quotas de ressources, le contrôle d'accès basé sur les rôles (RBAC, Role-Based Access Control) et les politiques réseau. Cet article montre comment mettre en place un tel laboratoire, tester l'isolation, diagnostiquer les défaillances courantes et s'en remettre. Il s'adresse aux développeurs, ingénieurs DevOps et équipes techniques de startups qui souhaitent acquérir une expérience pratique de la multi-location Kubernetes avant de passer en production. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier chaque résultat et documenter comment récupérer si l'état attendu n'est pas atteint. Chaque commande inclut la sortie ou le signal attendu, et chaque modification est limitée et réversible lorsque c'est possible. ## Inventaire des versions et de l'environnement Avant d'appliquer des manifestes, confirmez que votre cluster Kubernetes local est en cours d'exécution et que vous disposez des outils nécessaires. Les exemples de cet article ont été testés avec Kubernetes v1.27, kind v0.20, kubectl v1.27 et un hôte Linux avec 4 CPU et 8 Go de RAM. Vous pouvez utiliser Minikube, Docker Desktop ou tout autre cluster local, mais les commandes peuvent différer légèrement. Tout d'abord, vérifiez la version du cluster et l'état des nœuds : ```bash kubectl version --short kubectl get nodes -o wide ``` La sortie attendue montre un seul nœud avec le statut `Ready` et la version de Kubernetes correspondant à votre configuration. Si le nœud est `NotReady`, attendez un moment puis réexécutez la commande. Pour kind, vous pouvez vérifier l'état du conteneur avec `docker ps`. Ensuite, vérifiez que les modules complémentaires de base nécessaires à la multi-location sont disponibles. La plupart des distributions incluent RBAC et les quotas de ressources par défaut. Les politiques réseau nécessitent un plugin CNI qui les prend en charge, comme Calico, Cilium ou Antrea. Dans un cluster kind, le CNI par défaut n'applique pas les politiques réseau ; vous devez en installer un. Par exemple, pour installer Calico sur kind : ```bash kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/kind/main/site/content/docs/user/calico.yaml ``` Attendez que les pods Calico soient prêts : ```bash kubectl get pods -n kube-system | grep calico ``` La sortie attendue montre des pods calico-node avec le statut `Running` et `1/1` prêt. S'ils ne sont pas prêts, vérifiez les journaux avec `kubectl logs -n kube-system `. Enfin, notez les versions exactes dans un carnet de laboratoire ou un fichier, car le comportement peut changer entre les versions. Cet inventaire vous aidera à comparer les résultats avec vos collègues ou lors du signalement de bogues. ## Chemin de configuration sûr Un cluster multi-tenant commence par les namespaces. Créez deux namespaces pour représenter deux locataires : `tenant-a` et `tenant-b`. ```bash kubectl create namespace tenant-a kubectl create namespace tenant-b ``` Sortie attendue : `namespace/tenant-a created` et `namespace/tenant-b created`. Ensuite, appliquez des quotas de ressources pour limiter la consommation de ressources par namespace. Enregistrez le YAML suivant sous `quota-tenant-a.yaml` : ```yaml apiVersion: v1 kind: ResourceQuota metadata: name: tenant-a-quota namespace: tenant-a spec: hard: requests.cpu: "2" requests.memory: "4Gi" limits.cpu: "4" limits.memory: "8Gi" persistentvolumeclaims: "5" ``` Appliquez-le : ```bash kubectl apply -f quota-tenant-a.yaml ``` Vérifiez que le quota est actif : ```bash kubectl describe resourcequota tenant-a-quota -n tenant-a ``` La sortie doit montrer les limites strictes et l'utilisation actuelle (tous à zéro). Créez un quota similaire pour `tenant-b` avec des valeurs différentes, par exemple une limite CPU de 2, pour tester l'isolation. Restreignez maintenant l'accès avec RBAC. Créez un rôle qui permet de gérer uniquement les pods dans le namespace. Enregistrez sous `role-pod-manager.yaml` : ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: tenant-a name: pod-manager rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "create", "update", "delete"] ``` Appliquez-le puis créez une liaison de rôle pour un utilisateur de test. Dans un vrai cluster, vous intégreriez un fournisseur d'identité, mais pour un laboratoire, vous pouvez utiliser un compte de service pour simuler un utilisateur locataire. Créez un compte de service : ```bash kubectl create serviceaccount tenant-a-user -n tenant-a ``` Créez une liaison de rôle : ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tenant-a-user-pod-manager namespace: tenant-a subjects: - kind: ServiceAccount name: tenant-a-user namespace: tenant-a roleRef: kind: Role name: pod-manager apiGroup: rbac.authorization.k8s.io ``` Appliquez-le. Testez ensuite que le compte de service peut créer des pods mais ne peut pas lister les services. Obtenez le jeton du compte de service : ```bash TOKEN=$(kubectl create token tenant-a-user -n tenant-a) ``` Utilisez le jeton avec kubectl : ```bash kubectl --token=$TOKEN --namespace=tenant-a get pods kubectl --token=$TOKEN --namespace=tenant-a get services ``` La première commande doit réussir (liste vide), et la seconde doit renvoyer `Error from server (Forbidden): services is forbidden: User "system:serviceaccount:tenant-a:tenant-a-user" cannot list resource "services" in API group "" in the namespace "tenant-a"`. Enfin, appliquez l'isolation réseau entre locataires. La NetworkPolicy suivante refuse tout trafic entrant vers les pods de `tenant-a` sauf depuis des pods du même namespace. Enregistrez sous `default-deny-ingress.yaml` : ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress namespace: tenant-a spec: podSelector: {} policyTypes: - Ingress ``` Appliquez-la et testez la connectivité plus tard après avoir déployé des pods. Ces étapes suivent le principe du plus petit changement justifié : chaque manifeste est appliqué indépendamment, vérifié, et facile à annuler en supprimant l'objet. ## Vérification et diagnostic Déployez maintenant une charge de travail simple dans chaque namespace pour tester les limites de ressources, RBAC et les politiques réseau. Créez un déploiement avec un pod nginx dans `tenant-a` : ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: tenant-a spec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginx:1.23 resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi" ``` Appliquez et vérifiez le statut du déploiement : ```bash kubectl apply -f web-deployment.yaml kubectl rollout status deployment/web -n tenant-a ``` Attendu : `deployment "web" successfully rolled out`. Vérifiez que le quota de ressources est consommé : ```bash kubectl describe resourcequota tenant-a-quota -n tenant-a ``` Vous devriez voir `requests.cpu: 100m/2` et `requests.memory: 128Mi/4Gi` dans la section Used. Testez la connectivité réseau. Comme nous avons appliqué une politique de refus d'entrée par défaut dans `tenant-a`, un pod dans `tenant-b` ne devrait pas pouvoir atteindre le pod nginx. Tout d'abord, créez un pod de test dans `tenant-b` : ```bash kubectl run test-pod --image=busybox:1.35 --restart=Never --namespace=tenant-b -- sleep 3600 ``` Attendez qu'il soit en cours d'exécution : ```bash kubectl get pods test-pod -n tenant-b ``` Ensuite, obtenez l'adresse IP du pod nginx dans `tenant-a` : ```bash NGINX_IP=$(kubectl get pod -n tenant-a -l app=web -o jsonpath='{.items[0].status.podIP}') echo $NGINX_IP ``` Depuis le pod de test, tentez de faire un curl vers cette IP : ```bash kubectl exec -it test-pod -n tenant-b -- wget -qO- --timeout=5 http://$NGINX_IP ``` Attendu : la commande expire car la politique réseau bloque l'entrée. Si vous obtenez une réponse, la politique réseau n'est pas appliquée, probablement en raison d'un CNI manquant comme indiqué précédemment. Testez maintenant l'accès inter-namespace avec le compte de service. Le compte de service `tenant-a-user` a uniquement des droits de gestion des pods dans `tenant-a`, donc tenter de lister les pods dans `tenant-b` devrait échouer : ```bash kubectl --token=$TOKEN --namespace=tenant-b get pods ``` Attendu : `Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:tenant-a:tenant-a-user" cannot list resource "pods" in API group "" in the namespace "tenant-b"`. Ces étapes de vérification montrent que les namespaces, les quotas, RBAC et les politiques réseau fonctionnent comme prévu. ## Modes de défaillance et récupération Dans une configuration multi-tenant, plusieurs modes de défaillance sont courants. En voici trois avec des étapes de diagnostic et de récupération. ### 1. Quota de ressources dépassé Si un locataire tente de créer un pod qui dépasse le quota, la demande est refusée. Par exemple, tentez de créer un pod qui demande 3 CPU dans `tenant-a`, alors que le quota est de 2 CPU. Vous verrez : ``` Error from server (Forbidden): error when creating "./big-pod.yaml": pods "big-pod" is forbidden: exceeded quota: tenant-a-quota, requested: requests.cpu=3, used: requests.cpu=100m, limited: requests.cpu=2 ``` **Récupération** : Réduisez les demandes de ressources, ou mettez à jour le quota si le locataire a légitimement besoin de plus. Coordonnez-vous toujours avec le propriétaire du locataire avant de modifier les quotas. ### 2. Politique réseau trop restrictive Si les locataires signalent des problèmes de connectivité, utilisez la commande `kubectl describe` pour inspecter les politiques réseau : ```bash kubectl describe networkpolicy -n tenant-a ``` Vous pouvez voir quels pods sont sélectionnés et quel trafic est autorisé. Une erreur courante est un sélecteur de pod qui correspond à trop de pods ou une règle de sortie manquante. Pour récupérer, autorisez temporairement tout le trafic entrant pour le débogage : ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-ingress-debug namespace: tenant-a spec: podSelector: {} ingress: - {} ``` Appliquez cette politique pour rétablir la connectivité, puis supprimez-la et appliquez la politique sélective correcte. ### 3. Mauvaise configuration RBAC Si un utilisateur ne peut pas effectuer une action qu'il devrait être autorisé à faire, vérifiez le rôle et la liaison de rôle. Utilisez `kubectl auth can-i` pour tester les autorisations : ```bash kubectl auth can-i create pods --as=system:serviceaccount:tenant-a:tenant-a-user -n tenant-a ``` Attendu pour notre configuration : `yes`. Si vous obtenez `no`, inspectez le rôle et la liaison avec `kubectl get role pod-manager -n tenant-a -o yaml` et `kubectl get rolebinding -n tenant-a`. Assurez-vous que le sujet est correct et que les règles du rôle incluent les groupes d'API et les ressources nécessaires. ## Liste de contrôle des opérations Utilisez cette liste de contrôle après chaque modification ou session de dépannage. Chaque élément a un propriétaire et une fréquence de révision. - [ ] Santé du cluster : `kubectl get nodes` montre tous les nœuds `Ready`. Utile quand : tout changement. Propriétaire : administrateur du cluster. Vérifier : avant et après chaque changement. - [ ] Isolation des namespaces : vérifiez que chaque namespace locataire existe et que ses libellés sont corrects : `kubectl get namespaces --show-labels`. Propriétaire : ingénieur plateforme. Fréquence : hebdomadaire. - [ ] Quotas de ressources : confirmez que les quotas sont appliqués et pas proches de la limite : `kubectl describe resourcequota -A`. Propriétaire : ingénieur plateforme. Fréquence : après chaque déploiement ou hebdomadaire. - [ ] RBAC : révisez les liaisons de rôles pour le moindre privilège : `kubectl get rolebindings -A`. Propriétaire : ingénieur sécurité. Fréquence : mensuelle. - [ ] Politiques réseau : testez que la connectivité inter-locataire est bloquée tandis que l'intra-locataire fonctionne. Propriétaire : ingénieur réseau. Fréquence : après tout changement de politique réseau ou mensuelle. - [ ] Journaux d'audit : si activés, vérifiez les demandes interdites qui indiquent une mauvaise configuration ou une attaque. Propriétaire : ingénieur sécurité. Fréquence : hebdomadaire. - [ ] Sauvegarde et récupération : vérifiez que les sauvegardes etcd peuvent restaurer le cluster, y compris les namespaces et les politiques. Propriétaire : administrateur du cluster. Fréquence : trimestrielle. ## Pièges courants ### Piège 1 : Utiliser le namespace par défaut pour tout De nombreux tutoriels utilisent le namespace `default`. En multi-location, créez toujours des namespaces explicites pour chaque locataire et évitez d'utiliser `default`. Cela empêche le partage accidentel de ressources. **Récupération** : Migrez les ressources en les recréant dans de nouveaux namespaces. Utilisez `kubectl get all -n default` pour inventorier, puis exportez et réappliquez dans le bon namespace. ### Piège 2 : Ignorer les exigences CNI pour les politiques réseau Les politiques réseau ne sont appliquées que si un plugin CNI qui les prend en charge est installé. Sans cela, les politiques sont silencieusement ignorées, donnant une fausse confiance. Testez toujours la connectivité après avoir appliqué des politiques, comme indiqué dans la section Vérification. ### Piège 3 : Autorisations RBAC trop larges Accorder `cluster-admin` aux utilisateurs locataires est courant dans les laboratoires mais dangereux en production. Utilisez des rôles et des liaisons limités au namespace. Auditez avec `kubectl get clusterrolebindings` et supprimez les sujets suspects. ### Piège 4 : Ne pas définir les demandes et limites de ressources Si les locataires ne définissent pas de demandes de ressources, ils peuvent affamer les autres locataires. Imposez-les via des plages de limites ou des politiques d'admission. Dans votre laboratoire, incluez toujours des demandes de ressources dans les spécifications des pods pour voir le comportement des quotas. ### Piège 5 : Oublier de supprimer les ressources de test Les pods de test, les politiques et les comptes de service laissés derrière peuvent perturber les expériences ultérieures. Nettoyez avec `kubectl delete` et vérifiez avec `kubectl get all -n `. ## Conclusion Un laboratoire local de multi-location Kubernetes offre un environnement sûr pour apprendre et vérifier les concepts de base : les namespaces, les quotas de ressources, RBAC et les politiques réseau. Cet article a parcouru la mise en place d'un cluster minimal à deux locataires, l'application des configurations, le test de l'isolation, le diagnostic des défaillances courantes et la récupération. La liste de contrôle des opérations aide à maintenir le contrôle, et la section des pièges met en garde contre les erreurs courantes. Comme prochaine étape, choisissez une vérification à faible risque de cet article, comme appliquer une politique réseau et tester la connectivité inter-locataire, et pratiquez jusqu'à ce que vous soyez à l'aise. Ensuite, passez à des sujets plus avancés comme le contrôle d'admission, les normes de sécurité des pods et les contrôleurs de namespaces hiérarchiques. N'oubliez pas que la véritable multi-location est une combinaison de nombreux contrôles qui fonctionnent ensemble, et qu'une révision régulière est essentielle pour garder votre cluster sûr et efficace.