De Docker Compose à Helm#
Dans cet exercice, nous allons migrer une application web complète, définie avec Docker Compose, vers Kubernetes en créant notre propre chart Helm. (Si cela fait beaucoup pour vous, un exemple de solution est donné en fin d’exercice et vous permettra de vous “débloquer”)
L’application de départ#
L’application est un simple compteur de visites qui utilise une application backend en Flask, une base de données Redis pour la persistance, et un HAProxy comme reverse proxy. L’objectif est de reproduire cette architecture sur Kubernetes.
Voici l’arborescence du projet de départ :
projet-flask/
├── backend/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
├── haproxy/
│ └── haproxy.cfg
└── docker-compose.yml
Fichiers de l’application#
docker-compose.yml: Orchestre les servicesbackend,database(Redis), etproxy(HAProxy).version: '3.8' services: backend: build: ./backend ports: - "5000" environment: - REDIS_HOST=database database: image: "redis:alpine" proxy: image: "haproxy:2.5" volumes: - ./haproxy:/usr/local/etc/haproxy:ro ports: - "80:80" depends_on: - backend
backend/app.py: L’application Flask qui se connecte à Redis.from flask import Flask from redis import Redis import os app = Flask(__name__) redis = Redis(host=os.environ.get('REDIS_HOST', 'localhost'), port=6379) @app.route('/') def hello(): count = redis.incr('hits') return f'Hello! Cette page a été vue {count} fois.\n' if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)
backend/requirements.txt: Les dépendances Python.flask redis
backend/Dockerfile: Pour construire l’image du backend.FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["flask", "run", "--host=0.0.0.0"]
haproxy/haproxy.cfg: La configuration pour HAProxy qui redirige le trafic vers le backend.global daemon defaults mode http frontend http_front bind *:80 default_backend http_back backend http_back server backend1 backend:5000
Votre mission#
Votre tâche est de créer un chart Helm qui déploie cette application sur Kubernetes.
1. Créez l’arborescence du chart#
Dans un nouveau dossier, créez la structure de base d’un chart Helm :
mon-chart/
├── Chart.yaml
├── values.yaml
└── templates/
2. Rédigez le Chart.yaml#
Ce fichier contient les métadonnées de votre chart. Inspirez-vous des exercices précédents pour le remplir.
apiVersion: v2
name: mon-application-flask
description: Un chart pour déployer une application Flask avec Redis.
type: application
version: 0.1.0
appVersion: "1.0.0"
3. Définissez les valeurs par défaut dans values.yaml#
C’est ici que nous allons rendre notre chart configurable. Définissez les valeurs pour nos deux services, api et frontend.
backend:
image:
repository: <votre-registre>/mon-app-flask # À remplacer par l'image que vous aurez buildée
tag: "latest"
redis:
image:
repository: redis
tag: "alpine"
ingress:
enabled: true
host: flask.192.168.49.2.nip.io # Remplacez par l'IP de votre noeud minikube
4. Créez les templates Kubernetes#
Dans le dossier templates/, créez les manifestes pour les objets Kubernetes.
Déploiement et Service pour Redis (
deployment-redis.yamletservice-redis.yaml) Créez unDeploymentpour Redis et unServicede typeClusterIPnomméredis-servicepour que le backend puisse s’y connecter.Déploiement et Service pour le Backend (
deployment-backend.yamletservice-backend.yaml) Créez unDeploymentpour l’application Flask. Assurez-vous de passer la variable d’environnementREDIS_HOSTavec le nom du service Redis (redis-service). Créez également unServicepour exposer le backend.Ingress (
ingress.yaml) Créez unIngressqui expose le service du backend. Cet objet remplacera notreHAProxy.
Exemple de solution — Attention, ne dérouler qu'après avoir essayé
Votre dépôt a la structure suivante :
mon-chart/
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment-backend.yaml
├── deployment-redis.yaml
├── service-backend.yaml
├── service-redis.yaml
└── ingress.yaml
templates/deployment-redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}"
ports:
- containerPort: 6379
templates/service-redis.yaml
Service interne (ClusterIP) pour que le backend puisse parler à Redis.
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
type: ClusterIP
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
templates/deployment-backend.yaml
Deployment pour l’appli Flask.
On lui passe REDIS_HOST=redis-service pour qu’elle trouve Redis via le Service.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag }}"
ports:
- containerPort: 5000
env:
- name: REDIS_HOST
value: "redis-service"
templates/service-backend.yaml
Service interne sur le port 5000 (celui exposé par Flask).
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP
selector:
app: backend
ports:
- port: 5000
targetPort: 5000
templates/ingress.yaml
Ingress qui remplace le HAProxy du docker‑compose : il expose le Service backend vers l’extérieur.
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flask-ingress
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend
port:
number: 5000
{{- end }}
Avec cette structure, on a :
un fichier par objet K8s,
les images et le host d’Ingress configurables via
values.yaml,un Ingress qui remplace le rôle de HAProxy dans le
docker-compose.yml.
5. Testez et déployez#
Construisez et poussez l’image du backend sur un registre de conteneurs (comme celui de GitLab ou Docker Hub).
Mettez à jour votre
values.yamlavec le nom correct de l’image.Vérifiez le rendu de votre chart avec
helm template ..Déployez votre chart sur le cluster.
Expérimentations#
Accédez à votre application via l’URL de l’Ingress et rafraîchissez la page plusieurs fois. Le compteur s’incrémente-t-il ?
Supprimez le pod du backend. Que se passe-t-il ? Le compteur conserve-t-il sa valeur ?
Modifiez le tag de l’image Redis dans
values.yamlet redéployez. Observez le déploiement.