TP après-midi — Kubernetes Développeur
Exposer une application avec un Ingress, appliquer des NetworkPolicies, et packager avec Kustomize.
Durée : 1h30
Contexte
Vous avez déployé une stack Redis ce matin. Cet après-midi, vous allez exposer une application web via un Ingress, sécuriser les communications réseau avec une NetworkPolicy, puis packager votre configuration avec Kustomize pour gérer deux environnements (dev et prod).
Focus Kubernetes Dev
- ✅ Ingress : Exposer une application via un nom de domaine HTTP
- ✅ NetworkPolicy : Restreindre les communications entre pods
- ✅ CronJob : Planifier une tâche récurrente
- ✅ Kustomize : Factoriser des manifestes pour plusieurs environnements
L'objectif n'est PAS de configurer un vrai nom de domaine en production, mais d'apprendre à exposer et sécuriser des applications dans Kubernetes.
Objectif
À la fin de ce TP, vous devez avoir :
- ✅ Un Deployment
my-appexposé via un Service ClusterIP et un Ingress - ✅ Une NetworkPolicy qui restreint l'accès à
my-appsauf pour les pods autorisés - ✅ Un CronJob qui teste périodiquement l'accès au service
- ✅ Deux overlays Kustomize (dev et prod) avec des configurations différentes
Étape 1 - Déployer une application et l'exposer avec un Service
Objectif : Créer la base applicative.
Action : Créer un Deployment
my-appavec l'imagenginx:latest, 2 replicas, port 80 Observation :kubectl get podsmontre 2 podsmy-app-*en étatRunningAction : Créer un Service
my-app-servicede typeClusterIPsur le port 80 avec le selectorapp: my-appObservation :kubectl get svc my-app-servicemontre le service.kubectl get endpoints my-app-servicemontre les 2 IPs de pods
Indice
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: mynamespace
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app-service
namespace: mynamespace
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Étape 2 - Exposer avec un Ingress
Objectif : Accéder à l'application depuis l'extérieur via un nom de domaine.
Action : Vérifier que l'Ingress Controller est installé dans le cluster
kubectl get pods -n kube-system | grep -i ingress
# ou pour k3s avec traefik :
kubectl get pods -n kube-system | grep traefikObservation : Le pod de l'ingress controller est en état
RunningAction : Créer un Ingress
my-app-ingressqui routeMY.DOMAIN.COMversmy-app-service:80avec la classetraefikObservation :kubectl get ingressmontre l'ingress avec une adresse IPAction : Tester l'accès en ajoutant une entrée dans
/etc/hostspointant vers l'IP du cluster, puiscurl http://MY.DOMAIN.COMObservation : La page nginx par défaut s'affiche
Indice
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
namespace: mynamespace
spec:
ingressClassName: traefik
rules:
- host: MY.DOMAIN.COM
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
Pour trouver l'IP du cluster :
kubectl get nodes -o wide # colonne EXTERNAL-IP ou INTERNAL-IP
Étape 3 - CronJob pour tester le service
Objectif : Vérifier périodiquement l'accessibilité du service.
Action : Créer un CronJob
test-cronjobqui toutes les minutes tente d'accéder àweb-serviceavecwget -qO- http://my-app-serviceObservation : Après 1-2 minutes,kubectl get jobsmontre des Jobs créésAction : Vérifier les logs du Job créé
kubectl logs job/<nom-du-job>Observation : Les logs montrent la page HTML nginx
Indice
apiVersion: batch/v1
kind: CronJob
metadata:
name: test-cronjob
namespace: mynamespace
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
metadata:
labels:
app: tester
spec:
containers:
- name: busybox
image: busybox
command: ["wget", "-qO-", "http://my-app-service"]
restartPolicy: Never
Étape 4 - Appliquer une NetworkPolicy
Objectif : Sécuriser l'accès à my-app par NetworkPolicy.
Action : Appliquer une NetworkPolicy
deny-all-except-allowedqui bloque tout trafic entrant sur les podsapp: my-appsauf depuis les pods avec le labelrole: allowedObservation : Le CronJob existant échoue maintenant (il n'a pas le labelrole: allowed)Action : Vérifier que le CronJob échoue :
kubectl get jobs
kubectl logs job/<nom-du-job-récent>Observation : Le log montre une erreur de connexion (timeout ou connection refused)
Action : Modifier le CronJob pour ajouter le label
role: alloweddans le template de pod, puis re-appliquer Observation : Le nouveau Job réussit — les logs montrent à nouveau la page HTML
Indice
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-except-allowed
namespace: mynamespace
spec:
podSelector:
matchLabels:
app: my-app
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: allowed
Pour autoriser le CronJob, ajouter dans le jobTemplate.spec.template.metadata.labels :
labels:
role: allowed
Étape 5 - Kustomize : dev et prod
Objectif : Gérer deux environnements avec des paramètres différents.
Action : Créer la structure de dossiers suivante :
kustomize/
base/
deployment.yaml # my-app, 1 replica
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml # patch: 1 replica, image nginx:latest
prod/
kustomization.yaml # patch: 3 replicas, image nginx:1.25Observation : La structure existe avec les fichiers
Action : Visualiser le résultat pour l'overlay dev :
kubectl kustomize kustomize/overlays/devObservation : Le YAML final affiche les manifestes avec les valeurs dev
Action : Appliquer l'overlay dev dans un namespace
dev:kubectl create namespace dev
kubectl apply -k kustomize/overlays/dev -n devObservation : Les ressources sont créées dans le namespace
dev
Indice
kustomize/base/kustomization.yaml :
resources:
- deployment.yaml
- service.yaml
kustomize/overlays/dev/kustomization.yaml :
bases:
- ../../base
patches:
- target:
kind: Deployment
name: my-app
patch: |-
- op: replace
path: /spec/replicas
value: 1
kustomize/overlays/prod/kustomization.yaml :
bases:
- ../../base
patches:
- target:
kind: Deployment
name: my-app
patch: |-
- op: replace
path: /spec/replicas
value: 3
- op: replace
path: /spec/template/spec/containers/0/image
value: nginx:1.25
Avancé
- Ingress TLS : Comment ajouter un certificat HTTPS sur votre Ingress avec certmanager ? (Indice : annotations
cert-manager.io/issuer) - ArgoCD : Comment configureriez-vous ArgoCD pour déployer automatiquement depuis votre dépôt Git quand vous pushez sur
main? - HPA : Ajoutez un HorizontalPodAutoscaler sur
my-apppour scaler entre 2 et 6 replicas si le CPU dépasse 70%. Que faut-il ajouter au Deployment pour que le HPA fonctionne ? - NetworkPolicy namespace : Modifiez la NetworkPolicy pour autoriser tout le trafic venant du namespace
monitoring(Indice :namespaceSelector)
Synthèse
Qu'est-ce qui a bien fonctionné ?
- L'Ingress a-t-il correctement routé le trafic vers le service ?
- La NetworkPolicy a-t-elle bloqué le CronJob comme attendu ?
Quels sont les problèmes rencontrés ?
- L'Ingress Controller était-il déjà présent dans le cluster ?
- Les labels dans le CronJob ont-ils bien correspondu à la NetworkPolicy ?
Quelles compétences avez-vous développées ?
- ✅ Exposer une application avec un Ingress et un IngressController
- ✅ Restreindre les communications réseau avec une NetworkPolicy
- ✅ Planifier des tâches avec un CronJob
- ✅ Factoriser des manifestes pour plusieurs environnements avec Kustomize
Prochaine étape : En formation Kubernetes Tips, vous approfondirez les bonnes pratiques : probes, scanning d'images, NetworkPolicies avancées, et outils de diagnostic.