L'optimisation d'un NGINX Ingress Controller pour le trafic de production ne consiste pas à trouver un unique réglage magique. C'est un processus discipliné qui commence par la mesure d'un comportement de référence, applique des changements ciblés à la gestion des connexions, à la mise en tampon, au TLS et au routage du trafic, puis vérifie l'impact avec une charge réelle. Ce guide décrit ce processus avec des exemples de configuration concrets, une stratégie de déploiement sécuritaire et des procédures de restauration que vous pouvez exécuter dès aujourd'hui.
Architecture et flux de trafic
Une requête suit généralement ce chemin : Client → Équilibreur de charge cloud (terminaison TLS ou passage transparent) → Service NodePort ou LoadBalancer → Pod Ingress Controller (processus master et worker NGINX) → Service ClusterIP → Pods backend.
Le paramètre externalTrafficPolicy sur le Service du contrôleur modifie à la fois le nombre de sauts et la visibilité de l'IP source. Avec Local, l'équilibreur de charge envoie le trafic uniquement aux nœuds qui hébergent un pod contrôleur, ce qui préserve l'IP cliente dans X-Forwarded-For et élimine un saut kube-proxy. Avec Cluster, le trafic peut être routé vers n'importe quel nœud, ajoutant un saut kube-proxy et masquant l'IP cliente derrière l'IP du nœud.
À l'intérieur du pod, NGINX exécute un processus master et un nombre configurable de processus worker. Chaque worker gère jusqu'à worker_connections connexions simultanées. Les pools de connexions persistantes upstream (upstream-keepalive) sont par worker, donc le total de connexions upstream inactives équivaut à worker-processes × upstream-keepalive. Comprendre cette multiplication est essentiel pour dimensionner les limites de connexions.
Inventaire et référence initiale
Avant de modifier quoi que ce soit, capturez votre environnement actuel. Exécutez ces commandes pour enregistrer les versions, la topologie et les annotations existantes :
kubectl version --short
kubectl -n ingress-nginx get deploy -o wide
kubectl -n ingress-nginx describe deploy ingress-nginx-controller
kubectl get nodes -o wide
kubectl -n ingress-nginx get pods -o wide
kubectl -n ingress-nginx get svc
kubectl -n ingress-nginx describe svc ingress-nginx-controller
kubectl get ingress --all-namespaces -o yaml | grep -E "nginx.ingress.kubernetes.io"
Visez Kubernetes 1.29 ou plus récent (1.27 a atteint sa fin de vie en juin 2024) et NGINX Ingress Controller 1.11.x (graphique Helm 4.11+). La politique de décalage de version exige que la version mineure du contrôleur soit inférieure ou égale à la version mineure de Kubernetes.
Étape 0 : Application de test Echo
Déployez une charge de travail isolée pour des mesures sûres et reproductibles. Ce serveur echo renvoie une réponse statique et expose un profil de latence prévisible.
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: hashicorp/http-echo:0.2.3
args: ["-text=ok"]
ports:
- containerPort: 5678
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: echo
namespace: default
spec:
selector:
app: echo
ports:
- name: http
port: 80
targetPort: 5678
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo
namespace: default
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
nginx.ingress.kubernetes.io/proxy-send-timeout: "30"
nginx.ingress.kubernetes.io/keepalive: "64"
nginx.ingress.kubernetes.io/limit-rps: "100"
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers: "8 16k"
spec:
ingressClassName: nginx
rules:
- host: echo.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo
port:
number: 80
Appliquez et testez :
kubectl apply -f echo.yaml
kubectl get endpoints echo -n default
curl -H "Host: echo.example.test" http://LB_ADDRESS/
Enregistrez une référence de 60 secondes à charge stable (par exemple 100 RPS) en capturant les latences p50, p95 et p99. Cette référence servira de point de comparaison pour chaque changement subséquent.
Configuration du contrôleur (ConfigMap)
Mettez à jour le ConfigMap nginx-configuration dans l'espace de noms ingress-nginx. Les clés marquées "Restart" nécessitent un redémarrage du pod ; les autres se rechargent à chaud via le mécanisme de rechargement du contrôleur.
Valeurs recommandées pour le ConfigMap
| Clé | Type | Défaut | Plage recommandée | Rechargement/Redémarrage | Version |
|---|---|---|---|---|---|
| worker-processes | string | "1" | "auto" ou 2-4 | Restart | 1.5.0+ |
| worker-connections | string | "16384" | 16384-65536 | Restart | 1.5.0+ |
| keep-alive | string | "75" | 60-300 | Reload | 1.0+ |
| keep-alive-requests | string | "1000" | 1000-10000 | Reload | 1.0+ |
| upstream-keepalive | string | "0" (désactivé) | 32-256 | Reload | 1.0+ |
| upstream-keepalive-requests | string | "1000" | 100-10000 | Reload | 1.3+ |
| upstream-keepalive-timeout | string | "60s" | 30-300s | Reload | 1.3+ |
| proxy-buffer-size | string | "4k/8k" | 8k-16k | Reload | 1.0+ |
| proxy-buffers-number | string | "8" | 8-16 | Reload | 1.0+ |
| proxy-buffers | string | "8 4k/8k" | "8 16k" | Reload | 1.0+ |
| proxy-busy-buffers-size | string | "8k/16k" | 16k-32k | Reload | 1.0+ |
| use-http2 | string | "true" | "true" | Reload | 1.0+ |
| http2-max-concurrent-streams | string | "128" | 128-256 | Reload | 1.3+ |
| http2-max-field-size | string | "4k" | 4k-16k | Reload | 1.3+ |
| http2-max-header-size | string | "16k" | 16k-32k | Reload | 1.3+ |
| proxy-request-buffering | string | "on" | "on"/"off" (par Ingress pour gros envois) | Reload | 1.0+ |
| proxy-read-timeout | string | "60" | 30-300 | Reload | 1.0+ |
| proxy-send-timeout | string | "60" | 30-300 | Reload | 1.0+ |
| proxy-next-upstream | string | "error timeout" | "error timeout http_500 http_502 http_503 http_504" | Reload | 1.0+ |
| proxy-intercept-errors | string | "off" | "on" pour pages d'erreur personnalisées | Reload | 1.0+ |
| ssl-session-cache | string | "shared:SSL:10m" | "shared:SSL:10m-50m" | Reload | 1.0+ |
| ssl-session-timeout | string | "10m" | 10m-60m | Reload | 1.0+ |
| ssl-session-tickets | string | "on" | "on"/"off" (FIPS/PCI peut exiger off) | Reload | 1.0+ |
| ssl-prefer-server-ciphers | string | "off" | "off" (TLS 1.3) | Reload | 1.0+ |
| ssl-ciphers | string | Mozilla Intermediate | Suite moderne pour compatibilité TLS 1.2 | Reload | 1.0+ |
| ssl-ecdh-curve | string | "X25519:P-256" | "X25519:P-256" | Reload | 1.0+ |
| ssl-dh-param | string | "" | chemin vers fichier DH param personnalisé | Reload | 1.0+ |
| enable-ssl-chain-completion | string | "false" | "true" | Reload | 1.3+ |
| ssl-stapling | string | "off" | "on" | Reload | 1.3+ |
| ssl-stapling-verify | string | "off" | "on" | Reload | 1.3+ |
| log-format-escape-json | string | "false" | "true" | Reload | 1.3+ |
| error-log-level | string | "warn" | "warn"/"notice" | Reload | 1.0+ |
| limit-req-zone | string | "" | "zone=global:10m rate=1000r/s" | Reload | 1.0+ |
| limit-conn-zone | string | "" | "zone=conn:10m" | Reload | 1.0+ |
| hsts | string | "false" | "true" | Reload | 1.3+ |
| hsts-max-age | string | "2592000" | 31536000 (1 an) | Reload | 1.3+ |
| proxy-hide-headers | string | "" | "Server,X-Powered-By" | Reload | 1.0+ |
| enable-underscores-in-headers | string | "false" | "false" | Reload | 1.0+ |
Exemple de correctif ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
worker-processes: "auto"
worker-connections: "32768"
keep-alive: "100"
keep-alive-requests: "10000"
upstream-keepalive: "128"
upstream-keepalive-requests: "5000"
upstream-keepalive-timeout: "60s"
proxy-buffer-size: "16k"
proxy-buffers-number: "8"
proxy-buffers: "8 16k"
proxy-busy-buffers-size: "32k"
use-http2: "true"
http2-max-concurrent-streams: "256"
http2-max-field-size: "16k"
http2-max-header-size: "32k"
proxy-request-buffering: "on"
proxy-read-timeout: "60"
proxy-send-timeout: "60"
proxy-next-upstream: "error timeout http_500 http_502 http_503 http_504"
proxy-intercept-errors: "off"
ssl-session-cache: "shared:SSL:20m"
ssl-session-timeout: "20m"
ssl-session-tickets: "on"
ssl-prefer-server-ciphers: "off"
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
ssl-ecdh-curve: "X25519:P-256"
enable-ssl-chain-completion: "true"
ssl-stapling: "on"
ssl-stapling-verify: "on"
log-format-escape-json: "true"
error-log-level: "warn"
limit-req-zone: "zone=global:10m rate=2000r/s"
limit-conn-zone: "zone=conn:10m"
hsts: "true"
hsts-max-age: "31536000"
proxy-hide-headers: "Server,X-Powered-By"
enable-underscores-in-headers: "false"
Appliquez et vérifiez le rechargement :
kubectl -n ingress-nginx apply -f nginx-configmap.yaml
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller | grep -i reload
Note de sécurité : TLS 1.3 est privilégié ; la liste de chiffrement ci-dessus couvre la rétrocompatibilité TLS 1.2. Désactivez ssl-session-tickets si la conformité FIPS ou PCI-DSS l'exige. Activez l'agrafage OCSP (ssl-stapling: "on") et HSTS pour la production.
Optimisation TLS
Le processeur consommé par la négociation TLS domine aux taux de connexion élevés. La réutilisation de session via ssl-session-cache et ssl-session-tickets évite les négociations complètes sur les connexions subséquentes. Pour les clients TLS 1.2, des ssl-ciphers et ssl-ecdh-curve explicites assurent des courbes modernes (X25519) et des chiffrements AEAD. Utilisez des certificats ECDSA lorsque possible (plus petits, vérification plus rapide). Cert-manager avec un solveur dns01 automatise la rotation des certificats wildcard et maintient les secrets à jour.
Politique de trafic du Service
externalTrafficPolicy: Local préserve l'IP cliente et supprime un saut kube-proxy. Il nécessite un pod contrôleur sur chaque nœud qui reçoit le trafic de l'équilibreur de charge. Utilisez l'anti-affinité de pod et topologySpreadConstraints pour garantir la distribution sur les nœuds. externalTrafficPolicy: Cluster équilibre uniformément mais masque l'IP cliente derrière l'IP du nœud.
Corrigez le Service :
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
Appliquez et vérifiez :
kubectl -n ingress-nginx apply -f svc-patch.yaml
curl -H "Host: echo.example.test" http://LB_ADDRESS/ -v 2>&1 | grep -i "x-forwarded-for"
kubectl -n ingress-nginx get endpoints ingress-nginx-controller -o wide
Avertissement : Si des endpoints manquent sur certains nœuds, le trafic n'atteindra pas ces nœuds. Corrigez l'ordonnancement ou revenez à Cluster.
Annotations par route
Les annotations permettent d'ajuster le comportement pour des ressources Ingress spécifiques sans affecter l'ensemble du contrôleur. Appliquez-les d'abord aux objets Ingress à fort trafic.
| Annotation | Portée | Défaut | Exemple | Cas d'usage | Version |
|---|---|---|---|---|---|
| nginx.ingress.kubernetes.io/limit-rps | Ingress | illimité | "1000" | Limite de débit par IP | 1.0+ |
| nginx.ingress.kubernetes.io/limit-burst | Ingress | 0 | "2000" | Tolérance de rafale | 1.0+ |
| nginx.ingress.kubernetes.io/limit-connections | Ingress | illimité | "100" | Connexions simultanées par IP | 1.3+ |
| nginx.ingress.kubernetes.io/keepalive | Ingress | 0 (désactivé) | "100" | Pool keepalive upstream | 1.0+ |
| nginx.ingress.kubernetes.io/proxy-body-size | Ingress | "1m" | "20m" | Taille max d'envoi | 1.0+ |
| nginx.ingress.kubernetes.io/proxy-buffer-size | Ingress | global | "16k" | Gestion gros en-têtes | 1.0+ |
| nginx.ingress.kubernetes.io/proxy-buffers | Ingress | global | "8 16k" | Mise en tampon réponse | 1.0+ |
| nginx.ingress.kubernetes.io/proxy-read-timeout | Ingress | "60" | "60" | Tolérance backend lent | 1.0+ |
| nginx.ingress.kubernetes.io/proxy-send-timeout | Ingress | "60" | "60" | Tolérance client lent | 1.0+ |
| nginx.ingress.kubernetes.io/backend-protocol | Ingress | "HTTP" | "GRPC" | Upstream gRPC | 1.0+ |
| nginx.ingress.kubernetes.io/grpc-pass-through | Ingress | "false" | "true" | Passage TLS pour gRPC | 1.3+ |
| nginx.ingress.kubernetes.io/proxy-request-buffering | Ingress | "on" | "off" | Diffusion gros envois | 1.0+ |
| nginx.ingress.kubernetes.io/canary | Ingress | "false" | "true" | Déploiement canary | 1.0+ |
| nginx.ingress.kubernetes.io/canary-weight | Ingress | "0" | "10" | % trafic canary | 1.0+ |
| nginx.ingress.kubernetes.io/mirror-target | Ingress | "" | "mirror-svc" | Miroir de trafic | 1.3+ |
| nginx.ingress.kubernetes.io/rewrite-target | Ingress | "" | "/" | Réécriture de chemin | 1.0+ |
| nginx.ingress.kubernetes.io/enable-cors | Ingress | "false" | "true" | En-têtes CORS | 1.0+ |
| nginx.ingress.kubernetes.io/auth-url | Ingress | "" | "https://auth.example.com" | Authentification externe | 1.0+ |
| nginx.ingress.kubernetes.io/limit-req-zone | Ingress | global | "zone=api:10m rate=500r/s" | Zone limite débit personnalisée | 1.3+ |
Exemple pour une passerelle API à fort trafic :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-gateway
namespace: production
annotations:
nginx.ingress.kubernetes.io/limit-rps: "1000"
nginx.ingress.kubernetes.io/limit-burst: "2000"
nginx.ingress.kubernetes.io/limit-connections: "200"
nginx.ingress.kubernetes.io/keepalive: "100"
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers: "8 16k"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-gateway
port:
number: 80
Déploiements plus sûrs (PDB, HPA, PreStop)
PodDisruptionBudget
Un PDB avec maxUnavailable: 1 autorise un pod indisponible pendant les perturbations volontaires (mises à niveau de nœud, déploiements) tout en maintenant la haute disponibilité.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: ingress-nginx-pdb
namespace: ingress-nginx
spec:
maxUnavailable: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
Arrêt gracieux
L'image par défaut ne contient pas de binaire /wait-shutdown. Utilisez un hook preStop qui arrête NGINX gracieusement et attend pour permettre l'écoulement des requêtes en cours.
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
terminationGracePeriodSeconds: 60
containers:
- name: controller
lifecycle:
preStop:
exec:
command: ["/bin/sh","-c","nginx -s quit && sleep 30"]
HorizontalPodAutoscaler avec métriques personnalisées
Échellez sur le CPU et le taux de requêtes (nécessite Prometheus Adapter).
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ingress-nginx-hpa
namespace: ingress-nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ingress-nginx-controller
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Pods
pods:
metric:
name: nginx_ingress_controller_requests
target:
type: AverageValue
averageValue: "1000"
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
Vérification et tests de charge
Décomposition du temps avec curl
curl -H "Host: echo.example.test" -w "namelookup:%{time_namelookup} connect:%{time_connect} appconnect:%{time_appconnect} starttransfer:%{time_starttransfer} total:%{time_total}\n" -o /dev/null -s http://LB_ADDRESS/
Résultat attendu : appconnect proche de zéro pour HTTP ; pour HTTPS, appconnect chute sur les requêtes subséquentes grâce à la réutilisation de session. starttransfer et total doivent rester stables d'un essai à l'autre.
Génération de charge en cluster
Utilisez une image hey épinglée ou k6 pour des tests reproductibles.
kubectl run -it loadgen --image=docker.io/rakyll/hey@sha256:2a5b3c4d5e6f7g8h9i0j --restart=Never --rm -- -z 60s -c 100 -q 100 -H "Host: echo.example.test" http://ingress-nginx-controller.ingress-nginx.svc.cluster.local/
Script k6 pour CI :
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 },
{ duration: '2m', target: 200 },
{ duration: '30s', target: 500 },
{ duration: '30s', target: 0 }
],
thresholds: { http_req_duration: ['p(95)<500', 'p(99)<1000'], http_req_failed: ['rate<0.01'] }
};
export default function () {
const res = http.get('http://ingress-nginx-controller.ingress-nginx.svc.cluster.local/', { headers: { Host: 'echo.example.test' } });
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(0.1);
}
Métriques et journaux du contrôleur
Point de terminaison métriques dans v1.11+ : /metrics sur le port 10254 (format Prometheus). Configurez un ServiceMonitor pour Prometheus.
kubectl -n ingress-nginx exec -it deploy/ingress-nginx-controller -- curl -s localhost:10254/metrics | grep -E "nginx_ingress_controller_requests|nginx_ingress_controller_request_duration_seconds|nginx_ingress_controller_upstream_latency|nginx_ingress_controller_connections_active|nginx_ingress_controller_ssl_handshakes_total"
Métriques clés :
nginx_ingress_controller_requests_total(compteur par code)nginx_ingress_controller_request_duration_seconds_bucket(histogramme)nginx_ingress_controller_upstream_latency_seconds_bucket(histogramme)nginx_ingress_controller_connections_active(jauge)nginx_ingress_controller_connections_waiting(jauge)nginx_ingress_controller_ssl_handshakes_total(compteur)
Tableau de bord Grafana : importez le tableau de bord communautaire depuis kubernetes-mixin/ingress-nginx (JSON disponible dans leur dépôt).
Format de journal JSON pour analyse structurée :
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller --tail=100 | jq .
Vérification de la distribution des endpoints
kubectl -n ingress-nginx get endpoints ingress-nginx-controller -o wide
Confirmez la présence d'adresses prêtes sur tous les nœuds recevant le trafic LB lors de l'utilisation de Local.
Modes de défaillance et restauration
Procédure 1 : Pic de 502/504
- Vérifiez la disponibilité upstream :
kubectl get pods -n <ns-backend> -l app=<backend> - Vérifiez
proxy-read-timeoutsur l'Ingress ; augmentez si le backend est légitimement lent. - Consultez les journaux d'erreur NGINX :
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller | grep "upstream timed out" - Correction : augmentez le délai, échellez le backend, ou optimisez les performances du backend.
- Restauration : annulez l'annotation de délai.
Procédure 2 : Latence élevée p99
- Comparez
nginx_ingress_controller_connections_activeàworker-connections × worker-processes. - Surveillez le taux de négociation TLS :
nginx_ingress_controller_ssl_handshakes_totalen hausse rapide. - Vérifiez le vidage des tampons : grosses réponses avec de petits
proxy-buffers. - Vérifiez la résolution DNS : résolveur dans ConfigMap si noms de domaine upstream.
- Correction : augmentez
worker-connections, activez le cache de session TLS, ajustez les tampons, ajoutez un résolveur. - Restauration : annulez le ConfigMap.
Procédure 3 : IP cliente manquante
- Vérifiez
externalTrafficPolicy: Localsur le Service. - Vérifiez
use-forwarded-headers: "true"etcompute-full-forwarded-for: "true"dans le ConfigMap. - Si LB L4 avec protocole PROXY : activez
use-proxy-protocol: "true"dans le ConfigMap et annotez le Service avecservice.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"(AWS NLB) ou équivalent. - Correction : ajustez la politique de Service et le ConfigMap.
- Restauration : revenez à la politique
Cluster.
Procédure 4 : Erreurs de certificat
- Vérifiez l'état du Certificate cert-manager :
kubectl get certificate -n <ns> - Vérifiez que le secret contient
tls.crt,tls.key,ca.crt(pour complétion de chaîne). - Vérifiez la correspondance SNI :
kubectl -n ingress-nginx exec deploy/ingress-nginx-controller -- nginx -T | grep server_name - Correction : renouvelez le certificat, activez
enable-ssl-chain-completion: "true", vérifiez le format du secret. - Restauration : revenez au secret valide précédent.
Commandes de restauration rapide
# Restauration ConfigMap
kubectl -n ingress-nginx apply -f nginx-configmap-prev.yaml
# Restauration déploiement
kubectl -n ingress-nginx rollout undo deploy/ingress-nginx-controller
# Suppression annotation
kubectl annotate ingress myapp nginx.ingress.kubernetes.io/limit-rps- --overwrite
# Restauration politique Service
kubectl -n ingress-nginx patch svc ingress-nginx-controller -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
# Augmentation capacité
kubectl -n ingress-nginx scale deploy ingress-nginx-controller --replicas=10
Liste de contrôle opérationnelle
- Définissez un essai pilote étroit avec un Ingress et la route de test echo.
- Inventoriez les versions : Kubernetes 1.29+, Contrôleur 1.11+, Graphique Helm 4.11+, Cert-manager 1.14+.
- Enregistrez la référence : RPS et p50/p95/p99 pendant 60s à charge stable.
- Dimensionnez correctement les répliques du contrôleur (min 3) et les ressources (requêtes 500m/512Mi, limites 2/1Gi) ; confirmez HPA et PDB.
- Appliquez les changements ConfigMap du contrôleur :
worker-processes,worker-connections,keep-alive,upstream-keepalive, tampons, délais, TLS, journalisation, limitation de débit. - Vérifiez le temps curl et les métriques du contrôleur après rechargement.
- Optimisez TLS : activez le cache de session, les tickets (si autorisés), l'agrafage OCSP, HSTS ; vérifiez les améliorations
appconnectsur HTTPS. - Choisissez
externalTrafficPolicydu Service selon les besoins d'IP cliente ; confirmez la distribution des endpoints. - Ajoutez des annotations par Ingress pour la mise en tampon, la taille du corps, le keepalive, les limites de débit, le canary selon les besoins.
- Retestez et comparez à la référence ; documentez les écarts.
- En cas de régression : restaurez le ConfigMap ou le déploiement ; augmentez temporairement l'échelle.
- Planifiez une revue trimestrielle : retestez les hypothèses, versions et paramètres ajustables.
Conclusion
La performance de l'Ingress ne repose pas sur un unique drapeau magique ; c'est un petit ensemble de changements ciblés, mesurables et cumulatifs. En inventoriant votre environnement, en établissant une référence et en appliquant une mise au point sûre et réversible aux connexions, tampons, TLS et politique de trafic, vous pouvez améliorer la latence et le débit sans risquer d'interruption. Commencez par une route pilote étroite, vérifiez chaque changement avec une charge simple et le temps curl, et gardez les étapes de restauration prêtes. Avec cette liste de contrôle en main, vous pouvez répéter le processus pour chaque Ingress à fort trafic et maintenir la performance au fur et à mesure que votre trafic et vos services évoluent.