Aller au contenu principal

Multi-environnements


Table des matières

  1. Stratégies de gestion
  2. Promotion entre environnements
  3. Kustomize pour multi-env
  4. Helm pour multi-env
  5. ApplicationSet (ArgoCD)
  6. Exercices pratiques

1 - Stratégies de gestion

Les environnements typiques

Stratégie 1 : Branch per environment

main         → Production
staging → Staging
develop → Development
# ArgoCD - Application par branche
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-prod
spec:
source:
targetRevision: main # Branche
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-staging
spec:
source:
targetRevision: staging

Stratégie 2 : Directory per environment

gitops-repo/
├── apps/myapp/
│ ├── base/
│ └── overlays/
│ ├── dev/
│ ├── staging/
│ └── prod/
# Applications ciblant différents dossiers
spec:
source:
path: apps/myapp/overlays/prod

Stratégie 3 : Repo per environment

org/gitops-dev
org/gitops-staging
org/gitops-prod

Comparaison

StratégieAvantagesInconvénients
BranchSimple, PR pour promotionMerge conflicts
DirectoryAtomic commits, vue unifiéeDuplication
RepoIsolation totale, permissionsFragmentation

🔝 Retour à la table des matières


2 - Promotion entre environnements

Workflow de promotion

Promotion manuelle (PR)

# 1. Tester en staging
git checkout staging
git merge develop
git push

# 2. Vérifier le déploiement staging

# 3. Promouvoir en production
git checkout main
git merge staging
git push

Promotion automatique (Image Automation)

# Flux Image Automation
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImagePolicy
metadata:
name: myapp
spec:
imageRepositoryRef:
name: myapp
policy:
semver:
range: 1.x.x

---
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: myapp
spec:
git:
checkout:
ref:
branch: main
commit:
author:
email: [email protected]
name: Flux
messageTemplate: 'Update {{.AutomationObject.Name}}'
update:
path: ./apps/myapp

Gates et Approvals

# ArgoCD Sync Waves
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
argocd.argoproj.io/sync-wave: "1" # Ordre de sync
# Flux - Dépendance entre Kustomizations
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
spec:
dependsOn:
- name: infrastructure # Déployer infra d'abord

🔝 Retour à la table des matières


3 - Kustomize pour multi-env

Structure

apps/myapp/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
└── overlays/
├── dev/
│ ├── kustomization.yaml
│ ├── namespace.yaml
│ └── replicas-patch.yaml
├── staging/
│ ├── kustomization.yaml
│ ├── namespace.yaml
│ └── replicas-patch.yaml
└── prod/
├── kustomization.yaml
├── namespace.yaml
├── replicas-patch.yaml
├── resources-patch.yaml
└── hpa.yaml

Base commune

# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- service.yaml
- configmap.yaml

commonLabels:
app: myapp
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
template:
spec:
containers:
- name: myapp
image: myapp:latest
env:
- name: LOG_LEVEL
value: info
resources:
requests:
memory: "64Mi"
cpu: "50m"

Overlay Dev

# overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: dev

resources:
- ../../base
- namespace.yaml

patches:
- path: replicas-patch.yaml

images:
- name: myapp
newTag: dev-latest

configMapGenerator:
- name: myapp-config
behavior: merge
literals:
- LOG_LEVEL=debug

Overlay Prod

# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: production

resources:
- ../../base
- namespace.yaml
- hpa.yaml

patches:
- path: replicas-patch.yaml
- path: resources-patch.yaml

images:
- name: myapp
newTag: v1.2.3

configMapGenerator:
- name: myapp-config
behavior: merge
literals:
- LOG_LEVEL=warn
# overlays/prod/replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5

# overlays/prod/resources-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"

🔝 Retour à la table des matières


4 - Helm pour multi-env

Structure values files

apps/myapp/
├── Chart.yaml
├── values.yaml # Base
├── values-dev.yaml
├── values-staging.yaml
└── values-prod.yaml

values.yaml (base)

replicaCount: 1

image:
repository: myapp
tag: latest

resources:
requests:
memory: 64Mi
cpu: 50m

config:
logLevel: info

values-prod.yaml

replicaCount: 5

image:
tag: v1.2.3

resources:
requests:
memory: 512Mi
cpu: 500m
limits:
memory: 1Gi
cpu: 1

config:
logLevel: warn

autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10

ArgoCD avec Helm

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-prod
spec:
source:
repoURL: https://github.com/org/gitops-repo
path: apps/myapp
helm:
valueFiles:
- values.yaml
- values-prod.yaml # Override

Flux avec Helm

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: myapp
namespace: production
spec:
chart:
spec:
chart: ./apps/myapp
sourceRef:
kind: GitRepository
name: gitops-repo
values:
replicaCount: 5
image:
tag: v1.2.3

🔝 Retour à la table des matières


5 - ApplicationSet (ArgoCD)

Concept

ApplicationSet génère automatiquement des Applications ArgoCD.

List Generator

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp
spec:
generators:
- list:
elements:
- env: dev
namespace: dev
replicas: "1"
- env: staging
namespace: staging
replicas: "2"
- env: prod
namespace: production
replicas: "5"
template:
metadata:
name: 'myapp-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/org/gitops-repo
path: 'apps/myapp/overlays/{{env}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true

Git Generator

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-envs
spec:
generators:
- git:
repoURL: https://github.com/org/gitops-repo
revision: HEAD
directories:
- path: apps/myapp/overlays/*
template:
metadata:
name: 'myapp-{{path.basename}}'
spec:
source:
path: '{{path}}'
destination:
namespace: '{{path.basename}}'

Cluster Generator (Multi-cluster)

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-clusters
spec:
generators:
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: 'myapp-{{name}}'
spec:
destination:
server: '{{server}}'
namespace: production

🔝 Retour à la table des matières


6 - Exercices pratiques

Quiz

Q1. Quelle stratégie évite les merge conflicts ?

Réponse

Directory per environment car tous les environnements sont sur la même branche (main). Les changements sont isolés dans des dossiers différents.

Q2. Comment déployer la même app sur 3 clusters avec ArgoCD ?

Réponse

Utiliser un ApplicationSet avec un Cluster Generator :

generators:
- clusters:
selector:
matchLabels:
env: production

Exercice : Configuration multi-env

Créez les overlays Kustomize pour dev et prod avec ces différences :

AspectDevProd
Replicas15
Memory128Mi1Gi
Log leveldebugwarn
Solution
# overlays/dev/kustomization.yaml
namespace: dev
resources:
- ../../base
configMapGenerator:
- name: config
literals:
- LOG_LEVEL=debug

# overlays/prod/kustomization.yaml
namespace: prod
resources:
- ../../base
patches:
- path: deployment-patch.yaml
configMapGenerator:
- name: config
literals:
- LOG_LEVEL=warn

# overlays/prod/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5
template:
spec:
containers:
- name: myapp
resources:
requests:
memory: 1Gi

🔝 Retour à la table des matières


Points clés à retenir

  • 3 stratégies : Branch, Directory, Repo per env
  • Directory évite les merge conflicts
  • Promotion via PR ou automatique (Image Automation)
  • Kustomize : base + overlays
  • Helm : values files par environnement
  • ApplicationSet : génération automatique multi-env

🔝 Retour à la table des matières


← Chapitre précédent | Chapitre suivant : Bonnes pratiques →