Ressources
ECS ou EKS : choisir, puis migrer d'ECS vers EKS service par service, sans big bang
ECS vs EKS : critères de choix, tarifs et versions vérifiés, puis migration d'ECS vers EKS service par service, retour arrière et pièges Terraform.
L'équipe CTN Solutions · publié le · 25 min de lecture
Base d'expérience : Méthode et documentation officielle (guide EKS, modèles d'API et listes de prix AWS, documentation Kubernetes, Terraform, fournisseur Terraform AWS, modules terraform-aws-modules et contrôleur AWS Load Balancer) ; sans récit, donnée, configuration ni référence client.
Faits vérifiés sur les sources primaires le
Une équipe qui exploite ses conteneurs sur Amazon ECS peut en venir à se poser la question d'Amazon EKS : pour un opérateur qui n'existe que sur Kubernetes, pour un outillage GitOps ou pour une exigence de portabilité. La question mérite une réponse honnête, et « rester sur ECS » en fait partie. Si la réponse est EKS, le risque principal n'est pas Kubernetes : c'est la bascule de tous les services en une nuit, avec un retour arrière qui n'existe que sur le papier.
Faits datés
Les critères de décision viennent d'abord, puis une migration service par service, de l'inventaire au décommissionnement. Cette lecture est établie sur Amazon EKS (versions 1.34 à 1.37 en support standard), le fournisseur Terraform AWS 6.69.1 et les modules terraform-aws-modules/eks 21.26.0 et terraform-aws-modules/ecs 7.6.1 ; tarifs, calendrier et versions ont été revérifiés le , les autres sources citées le 7 octobre 2026.
Vérifié le
ECS, EKS ou rester simple : les critères de décision
Les deux services exécutent des conteneurs sur la même infrastructure AWS. Ce qui les sépare est le modèle d'exploitation : ce que l'équipe maintient, à quel rythme, et ce qu'elle obtient en échange.
ECS : un orchestrateur sans version à suivre
La liste de prix d'Amazon ECS ne comporte aucun frais d'orchestration : l'usage sur instances EC2 y est compté à 0 $, seuls le calcul et les ressources associées se paient. Le calcul vient de Fargate (facturé au vCPU, à la mémoire et au stockage éphémère), d'instances EC2 gérées par l'équipe, ou d'ECS Managed Instances : ECS gère des instances EC2 pour le compte de l'équipe, contre des frais de gestion par instance ajoutés au prix EC2, avec des types d'instance choisis par attributs, GPU compris.
L'API ECS ne comporte aucun paramètre de version de cluster, mais la maintenance existe : quand AWS doit appliquer une mise à jour de sécurité ou d'infrastructure, les tâches Fargate concernées sont arrêtées et remplacées, avec un préavis réglable à 0, 7 ou 14 jours (fargateTaskRetirementWaitPeriod). Un service maintient son nombre de tâches (desiredCount) et relance donc les tâches retirées ; une tâche lancée hors service n'a pas ce mécanisme.
EKS : un plan de contrôle Kubernetes et son calendrier
Amazon EKS facture chaque cluster 0,10 $ de l'heure tant que sa version de Kubernetes est en support standard, et 0,50 $ de plus en support étendu, soit 0,60 $ (tarifs publics de la région Paris) pour le niveau standard du plan de contrôle ; les niveaux provisionnés (XL et au-delà) sont facturés davantage. Une version mineure reste 14 mois en support standard après sa sortie sur EKS, puis 12 mois en support étendu ; ensuite, EKS met à jour le plan de contrôle d'office. Une mise à jour ne franchit qu'une version mineure et ne peut être ni suspendue ni arrêtée une fois lancée ; les modules (VPC CNI, CoreDNS, kube-proxy) et les nœuds suivent séparément. Un retour à la version précédente reste possible dans les 7 jours, sauf après une mise à jour d'office en fin de support étendu. Au , les versions 1.34 à 1.37 sont en support standard (la 1.37 y est entrée le 1er octobre 2026 ; la 1.34 le quitte le 2 décembre 2026) et les versions 1.31 à 1.33 en support étendu ; les échéances de fin 2026 et leur coût sont détaillés dans « Support étendu EKS et RDS : calendrier de fin 2026, tarifs et calcul de l'exposition ».
Côté nœuds, trois options :
- Groupes de nœuds gérés, ou nœuds provisionnés par Karpenter, projet open source qui crée des nœuds pour les pods non planifiables et les retire quand ils ne servent plus. Pour un groupe de nœuds géré sur une AMI optimisée EKS, la console signale les mises à jour et les applique en un clic ; les déclencher reste à l'équipe.
- EKS Auto Mode : AWS gère les instances (système, correctifs, durée de vie maximale de 21 jours), leur mise à l'échelle sur la base de Karpenter, les répartiteurs de charge et le stockage bloc, contre des frais de gestion par instance. L'équipe déclenche la montée de version du plan de contrôle ; Auto Mode renouvelle ensuite les nœuds en respectant les PodDisruptionBudgets.
- Fargate pour EKS : un environnement isolé par pod, sans DaemonSet, conteneur privilégié, volume EBS ni EKS Pod Identity (les rôles IAM pour comptes de service, IRSA, restent la voie pour un rôle IAM), avec des cibles de type IP uniquement.
Ce que Kubernetes apporte, et ce qu'il coûte
Les apports sont réels quand l'équipe en a l'usage :
- Réconciliation continue : un contrôleur GitOps comme Argo CD ramène en permanence le cluster à l'état déclaré dans Git, là où un déploiement ECS reste un acte ponctuel de pipeline ou de Terraform (voir « Argo CD App-of-Apps et ApplicationSet : amorcer un cluster sans masquer les dépendances » et « GitOps en production : Argo CD ou Flux, santé des applications et nettoyage des orphelins »).
- Opérateurs : des extensions qui ajoutent des ressources personnalisées à l'API Kubernetes pour automatiser l'exploitation d'un logiciel.
- Agents par nœud : journaux, sécurité ou réseau s'installent une fois par nœud en DaemonSet. ECS offre l'équivalent sur instances EC2 avec la stratégie
DAEMON, mais pas sur Fargate, où il faut un conteneur annexe par tâche, comme le routeur de journaux FireLens. - Une API commune à plusieurs fournisseurs, qui ne suffit pas à rendre une plateforme portable (« Kubernetes cloud-agnostique : choisir et vérifier une plateforme portable, de l'API au test de sortie »).
Le prix est tout aussi réel : des frais par cluster, une montée de version à suivre au rythme du calendrier, des composants de plus à maintenir (contrôleur de répartiteur de charge, pilote de secrets, collecte de journaux, nœuds) et des compétences à détenir à plusieurs. Pour une équipe réduite, ce dernier point peut peser plus que la facture ; « Platform engineering pour une scale-up : par où commencer sans sur-ingénierie » traite ce dimensionnement.
Tableau de décision
| Critère | ECS (Fargate, EC2 ou Managed Instances) | EKS, groupes de nœuds gérés ou Karpenter | EKS Auto Mode | EKS sur Fargate |
|---|---|---|---|---|
| Frais fixes d'orchestration | Aucun | 0,10 $ par heure et par cluster, 0,60 $ en support étendu | Idem, plus frais de gestion par instance | Idem |
| Gestion des machines | AWS (Fargate, Managed Instances) ou équipe (EC2) | Équipe (AMI, mises à jour), aidée de Karpenter | AWS (21 jours au plus par nœud) | AWS |
| Montées de version | Aucune ; retraits de tâches Fargate | Plan de contrôle dans les 14 mois de support standard, puis modules et nœuds | Plan de contrôle par l'équipe, nœuds par AWS | Plan de contrôle par l'équipe |
| Agents par nœud | Sur EC2 : stratégie DAEMON ; sur Fargate : conteneurs annexes | Oui | Oui | Non |
| Identité IAM | Rôle de tâche | Pod Identity ou IRSA | Pod Identity ou IRSA | IRSA |
| Compétences à détenir à plusieurs | IAM, VPC, ECS | Kubernetes et gestion des nœuds | Kubernetes | Kubernetes et limites de Fargate |
| Bon choix quand (avis) | Peu de services, ni opérateur ni GitOps, équipe réduite | Plateforme partagée, agents et opérateurs, rythme de version tenable | Mêmes besoins, sans gérer de nœuds | Charges isolées, sans agent ni stockage bloc |
La dernière ligne est un avis, pas une règle. Rester sur ECS, ou passer d'EC2 à Fargate ou à Managed Instances pour ne plus gérer d'instances, peut être la décision la plus raisonnable quand aucun des apports ci-dessus n'est attendu.
Chiffrer le coût fixe sans fausse comparaison
Exemple fictif. Trois clusters EKS (production, préproduction, outillage) coûtent, sur un mois moyen de 730 heures, 3 × 730 × 0,10 $ = 219 $ de plan de contrôle en support standard, 1 314 $ en support étendu ; sur ECS, cette composante n'existe pas. Le coût du calcul dépend du remplissage des instances, des réservations et des Savings Plans : il se compare dans l'export de coûts, pas sur les pages de prix, comme le détaille « Coût facturé, coût amorti, crédits : réconcilier des montants AWS qui ne tombent jamais juste ».
Chiffrage fondé sur vos données
Inventorier ce que chaque service ECS fait sans le dire
Un service ECS porte bien plus qu'une image : identité IAM, secrets, nom de découverte, groupe cible, mise à l'échelle, journaux, parfois des tâches planifiées. La migration commence par une fiche par service qui recense ces éléments, leur équivalent côté EKS, et les bases, caches et files où le service écrit.
Correspondance ECS vers EKS
| Élément ECS | Équivalent EKS | Point de vigilance |
|---|---|---|
| Définition de tâche (image, CPU, mémoire, ports, variables) | Deployment, Service, requêtes et limites | Même image, au même condensat (digest) |
Rôle de tâche (ecs-tasks.amazonaws.com) | EKS Pod Identity (pods.eks.amazonaws.com) ou IRSA | Pas de Pod Identity sur Fargate ; le rôle d'exécution ECS, qui sert à l'agent pour préparer la tâche, n'a pas d'équivalent direct |
secrets et valueFrom, valeur injectée en variable d'environnement | Pilote CSI Secrets Store et fournisseur AWS (ASCP), secrets montés en fichiers | Même entrée Secrets Manager des deux côtés, jamais une copie ; ASCP non pris en charge sur Fargate pour EKS |
| Service Connect ou Cloud Map | Service Kubernetes et DNS du cluster | Aucun des deux noms ne se résout de l'autre côté |
Groupe cible ALB de type ip | TargetGroupBinding vers un groupe cible dédié | Un groupe cible par plateforme |
Application Auto Scaling (CPU, mémoire, ALBRequestCountPerTarget, métrique personnalisée) | HorizontalPodAutoscaler ; Karpenter ou Auto Mode pour les nœuds | Le HPA lit CPU et mémoire via Metrics Server ; au-delà, il exige un adaptateur de métriques |
awslogs ou FireLens | Agent de journaux en DaemonSet, par exemple Fluent Bit | Mêmes destinations et même format, sinon les alertes deviennent aveugles |
| Tâches planifiées (EventBridge Scheduler) | CronJob | Jamais actives des deux côtés à la fois |
| Migrations de schéma en tâche ponctuelle | Job ou hook PreSync d'Argo CD | Une seule plateforme les lance |
Ce que Terraform ne voit pas
L'état Terraform décrit ce qui a été déclaré, pas ce qui existe. Une règle d'écoute ajoutée dans la console n'apparaît dans aucun plan, et Terraform ne la recréera pas si l'écouteur est remplacé. Ces commandes en lecture seule comparent les deux :
# Services ECS : définition de tâche, nombre de groupes cibles et de registres Cloud Map (hors Service Connect)
CLUSTER=production
for s in $(aws ecs list-services --cluster "$CLUSTER" --query 'serviceArns[]' --output text); do
aws ecs describe-services --cluster "$CLUSTER" --services "$s" \
--query 'services[0].[serviceName, taskDefinition, length(loadBalancers), length(serviceRegistries)]' \
--output text
done
# Tâches planifiées déclarées dans EventBridge Scheduler
aws scheduler list-schedules --query 'Schedules[].[Name, State, Target.Arn]' --output text
# Règles d'écoute réelles, à rapprocher de l'état Terraform
aws elbv2 describe-rules --listener-arn "$LISTENER_ARN" --query 'Rules[].[Priority, RuleArn]' --output text
terraform state list | grep aws_lb_listener_ruleTout objet présent dans AWS et absent de l'état reçoit un propriétaire et un bloc import (chapitre 5) avant la première bascule. Les planifications plus anciennes, créées comme règles EventBridge, se listent avec aws events list-rules.
Faire tourner ECS et EKS côte à côte
La cohabitation dure le temps de basculer tous les services et repose sur quatre règles, détaillées ci-dessous. Tout élément provisoire de la cohabitation reçoit une date de retrait.
Un groupe cible par plateforme, derrière la même règle
Le montage le plus simple garde un seul ALB et une règle par service, dont l'action forward répartit les requêtes entre deux groupes cibles pondérés créés par Terraform : ECS enregistre ses tâches dans le premier, une TargetGroupBinding du contrôleur AWS Load Balancer enregistre les pods dans le second. Deux groupes cibles, pas un : avec multiClusterTargetGroup à false (valeur par défaut), le contrôleur prend le contrôle complet du groupe cible et désenregistre toute cible absente du cluster, tâches ECS comprises.
resource "aws_lb_target_group" "api_eks" {
name_prefix = "apik-"
port = 8080
protocol = "HTTP"
target_type = "ip" # adresses des pods
vpc_id = var.vpc_id
deregistration_delay = 30 # à aligner sur l'arrêt gracieux des pods
health_check {
path = "/healthz"
matcher = "200"
}
lifecycle {
create_before_destroy = true
}
}apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: api
namespace: api
spec:
serviceRef:
name: api
port: 8080
targetGroupARN: "<ARN du groupe cible api_eks, sortie de la pile Terraform>"
targetType: ipTrois précisions :
- Porte de disponibilité : le libellé
elbv2.k8s.aws/pod-readiness-gate-inject: enabledsur l'espace de noms fait attendre qu'un nouveau pod soit sain dans le groupe cible avant d'arrêter l'ancien (ciblesipseulement). - EKS Auto Mode : la ressource passe en
eks.amazonaws.com/v1,targetTypedevient obligatoire, le groupe cible porte l'étiquetteeks:eks-cluster-name, et le contrôleur le supprime avec la TargetGroupBinding ou le cluster ; un groupe cible créé par Terraform aurait deux propriétaires, point à trancher avant la première bascule. - Bleu/vert natif d'ECS : ECS modifie lui-même la règle d'écoute de production qu'on lui confie, au moyen d'un rôle qui l'autorise à appeler les API Elastic Load Balancing ; les déploiements ECS du service sont gelés pendant sa bascule.
Mêmes identités, mêmes secrets
Pendant la cohabitation, les deux formes d'un même service doivent avoir exactement les mêmes droits : un seul rôle IAM par service, approuvé à la fois pour ECS et pour EKS Pod Identity, dont le principal ECS est retiré au décommissionnement.
data "aws_iam_policy_document" "api_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
statement {
actions = ["sts:AssumeRole", "sts:TagSession"]
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
}
}
resource "aws_iam_role" "api" {
name = "api"
assume_role_policy = data.aws_iam_policy_document.api_trust.json
}
resource "aws_eks_pod_identity_association" "api" {
cluster_name = var.cluster_name
namespace = "api"
service_account = "api"
role_arn = aws_iam_role.api.arn
}Sur Fargate pour EKS, le second bloc devient une approbation IRSA. Pour un autre compte, Pod Identity enchaîne un rôle cible (target_role_arn), le rôle Pod Identity restant dans le compte du cluster ; ce cas sort du périmètre de cette lecture.
Les deux plateformes lisent la même entrée Secrets Manager. ECS injecte la valeur en variable d'environnement, fixée au lancement de la tâche : une rotation n'atteint les tâches qu'à leur remplacement. Changer un secret pendant la cohabitation impose donc de redéployer les deux côtés.
Une adresse stable entre services
Deux services qui s'appellent peuvent se retrouver de part et d'autre de la frontière ; or les noms Service Connect ne sont servis qu'aux tâches ECS du même espace de noms, et les noms en .svc.cluster.local ne se résolvent que dans le cluster. Avant la première bascule, chaque service appelé reçoit donc une adresse indépendante de la plateforme (ALB interne à règle pondérée, ou nom DNS privé dans Cloud Map ou Route 53, qu'ExternalDNS sait alimenter), et ses appelants y passent d'abord.
Aucune exécution en double
Le poids d'un ALB répartit des requêtes, pas les traitements qui démarrent seuls : pour chacun, une seule plateforme est active à la fois. Le CronJob est livré suspendu tant que la planification ECS tourne :
apiVersion: batch/v1
kind: CronJob
metadata:
name: traitement-planifie
namespace: api
spec:
schedule: "0 3 * * *"
timeZone: "Europe/Paris"
suspend: true # tant que la planification ECS est active
startingDeadlineSeconds: 600 # borne le rattrapage à la réactivation
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: api
restartPolicy: Never
containers:
- name: traitement
image: "<même image et même condensat que la tâche ECS>"Pour basculer : désactiver la planification ECS (state = "DISABLED" sur aws_scheduler_schedule), vérifier qu'aucune tâche lancée par elle ne tourne encore, puis passer suspend à false. Sans startingDeadlineSeconds, les exécutions manquées partent dès la réactivation ; et un CronJob peut, dans certaines circonstances, créer deux Jobs pour une échéance : le traitement doit être idempotent.
Le consommateur de file EKS démarre à zéro réplique et prend le relais quand ECS descend à zéro, sauf idempotence prouvée et non supposée. Les migrations de schéma partent de la plateforme qui sert la version de référence du code.
Basculer service par service, revenir en arrière, décommissionner
L'ordre des services
Le premier service à basculer est sans état, bien observé, peu appelé par les autres, et sa panne serait visible et bornée. Ceux qui écrivent beaucoup, reçoivent des webhooks de partenaires ou portent des connexions longues passent en dernier. Deux services ne changent jamais de poids dans la même fenêtre : un incident doit pouvoir s'attribuer.
Déplacer les poids par paliers
Les poids d'une action forward vont de 0 à 999 et sont relatifs ; une seule variable suffit à les piloter :
variable "poids_eks" {
type = number
default = 0
validation {
condition = var.poids_eks >= 0 && var.poids_eks <= 100
error_message = "Le poids EKS est compris entre 0 et 100."
}
}
resource "aws_lb_listener_rule" "api" {
listener_arn = aws_lb_listener.https.arn
priority = 100
action {
type = "forward"
forward {
target_group {
arn = aws_lb_target_group.api_ecs.arn
weight = 100 - var.poids_eks
}
target_group {
arn = aws_lb_target_group.api_eks.arn
weight = var.poids_eks
}
}
}
condition {
host_header {
values = ["api.example.com"]
}
}
}Exemple fictif de progression : 0, 5, 25, 50 puis 100 % vers EKS, avec une durée d'observation fixée par l'équipe à chaque palier. La répartition se fait requête par requête ; pour une application à sessions, la persistance de groupe cible (bloc stickiness de l'action forward) garde un client sur le même groupe cible pendant la durée choisie. Le retour arrière ne s'attend pas du répartiteur : c'est une action préparée.
Avant le dernier palier, EKS est dimensionné pour porter seul la charge ; ECS, qui réduit ses tâches à mesure que son trafic baisse, garde une capacité minimale relevée pendant l'observation pour que le retour arrière reste immédiat.
Avec deux répartiteurs distincts, la pondération passe par Route 53 (poids de 0 à 255, trafic proportionnel au poids rapporté à la somme des poids), plus lente à inverser à cause du cache des résolveurs et des connexions ouvertes. Le TTL de l'enregistrement s'abaisse avant la fenêtre.
Le chemin d'écriture ne suit pas les poids
Le poids déplace les nouvelles requêtes HTTP, pas les connexions ouvertes, les workers, les tâches planifiées, ni les webhooks d'un partenaire qui a mis l'adresse en cache. Avant la fenêtre, il faut savoir quels chemins écrivent, lesquels restent actifs côté ECS, et comment le prouver. La base de données, elle, ne bouge pas : les deux versions du code doivent rester compatibles avec le même schéma pendant toute la cohabitation.
Critères de retour arrière
| Signal | Où le lire | Décision |
|---|---|---|
| 5xx du groupe cible EKS au-dessus de la ligne de base ECS | HTTPCode_Target_5XX_Count (dimensions TargetGroup, LoadBalancer) | Poids EKS à 0 |
| Latence au-delà du seuil sur la durée d'observation | TargetResponseTime, traces applicatives | Poids EKS à 0 |
| Cibles EKS non saines | UnHealthyHostCount, état des pods | Poids EKS à 0 |
| Indicateur métier en écart | Tableaux de bord applicatifs | Poids EKS à 0, puis analyse |
| Journaux ou métriques absents côté EKS | Plateforme d'observabilité | Poids EKS à 0 : une bascule invisible ne se poursuit pas |
| Traitement unique exécuté deux fois | Journaux des planifications et consommateurs | Arrêt du côté fautif, examen des données |
Les seuils se fixent avant la fenêtre, à partir de la ligne de base ECS. Le retour arrière est une commande préparée et testée (terraform apply -var 'poids_eks=0'), plus, si les planifications ont basculé, la réactivation de celle d'ECS et la suspension du CronJob.
Bascule d'un service par paliers, avec retour arrière
Le trafic d'un service passe d'ECS à EKS par paliers observés ; un critère atteint ramène le poids EKS à zéro, et le décommissionnement ne vient qu'après la fenêtre d'observation.
Schéma défilable horizontalement ; sa version textuelle complète suit.
Lire le schéma sous forme textuelle
- Service prêt sur EKS : groupe cible dédié, cibles saines, CronJobs suspendus.
- La règle de l'ALB envoie tout le trafic à ECS.
- Un palier augmente la part d'EKS, puis l'équipe observe pendant la durée fixée.
- Critère de retour arrière atteint : poids EKS à zéro, planifications ECS réactivées si besoin, analyse, puis reprise à l'étape 2.
- Sinon, tant que le trafic n'est pas entièrement sur EKS, un nouveau palier suit.
- Tout le trafic HTTP sur EKS : les chemins hors HTTP basculent (planifications, consommateurs, webhooks).
- Fenêtre d'observation, ECS à zéro tâche mais service conservé ; un critère atteint renvoie à l'étape 4.
- En fin de fenêtre, décommissionnement : groupe cible ECS retiré de la règle, service ECS et pile Terraform supprimés.
Liste de contrôle avant bascule
- Fiche du service complète, chemins d'écriture compris.
terraform plansans modification sur la pile socle ; rien hors état (règles, groupes de sécurité, DNS).- Groupe cible EKS dédié, de type
ip, cibles saines ;multiClusterTargetGroupabsent ou àfalse; porte de disponibilité activée ; délai de désenregistrement aligné sur l'arrêt gracieux des pods. - Rôle IAM approuvé pour les deux principaux ; un appel réel à chaque service AWS utilisé réussi depuis un pod.
- Même entrée Secrets Manager lue des deux côtés, à la même version.
- Appelants internes passés sur l'adresse stable du service.
- CronJobs suspendus, consommateurs EKS à zéro ou idempotence prouvée, migrations de schéma attribuées à une seule plateforme.
- Journaux, métriques et alertes du service visibles côté EKS, dans les mêmes tableaux de bord.
- Capacité EKS dimensionnée pour tout le trafic ; capacité minimale ECS relevée.
- Seuils écrits ; commande de retour arrière testée hors production.
- Déploiements ECS du service gelés ; décideur disponible.
Décommissionner, puis transmettre
Le décommissionnement commence quand le service tourne entièrement sur EKS depuis toute la fenêtre d'observation :
- ECS à zéro tâche, service conservé. Le module terraform-aws-modules/ecs ignore toujours
desired_count: la mise à zéro passe par les capacités minimale et maximale d'Application Auto Scaling ramenées à 0 (ou, sans mise à l'échelle, paraws ecs update-service --desired-count 0) ; sinon la mise à l'échelle relance des tâches. - Groupe cible ECS retiré de la règle, puis supprimé.
- Service, définitions de tâches, planifications et Cloud Map supprimés ; principal
ecs-tasks.amazonaws.comretiré du rôle. - Journaux ECS conservés selon la rétention prévue.
- Cluster ECS en dernier.
La migration n'est terminée que si l'équipe sait refaire seule les gestes suivants : monter de version EKS, faire tourner un secret, ajouter un service, revenir en arrière sur un déploiement Argo CD, chacun avec un runbook court exercé par une autre personne que son auteur. Le cadrage d'une telle migration, de l'inventaire à la transmission, est décrit sur la page Migration Kubernetes : avancer par vagues.
Les pièges Terraform de la cohabitation
Un propriétaire par ressource, et une pile socle
Pendant la cohabitation, la pile Terraform ECS, la pile Terraform EKS et le contrôleur AWS Load Balancer modifient des objets AWS ; chaque objet n'a qu'un propriétaire. Une pile « socle » porte l'ALB, les écouteurs, les règles pondérées, les deux groupes cibles de chaque service et les groupes de sécurité partagés ; la pile ECS ne porte plus que les services et leurs définitions de tâches ; la pile EKS, le cluster, ses nœuds et ses associations d'identité ; le dépôt GitOps, les TargetGroupBinding. Les ARN passent d'une pile à l'autre par des sorties ou des sources de données, jamais par copie. Décommissionner ECS revient alors à détruire une pile sans toucher au trafic.
Changer une ressource de pile : removed, puis import
Le bloc moved (Terraform 1.1 et plus) change l'adresse d'une ressource dans l'état de la configuration qui le porte ; il ne transfère rien vers une autre pile. Pour transférer un groupe cible de la pile ECS à la pile socle sans le détruire :
# Pile ECS : cesser de gérer la ressource sans la détruire (Terraform 1.7 et plus)
removed {
from = aws_lb_target_group.api_ecs
lifecycle {
destroy = false
}
}# Pile socle : adopter la ressource existante (Terraform 1.5 et plus)
import {
to = aws_lb_target_group.api_ecs
id = "arn:aws:elasticloadbalancing:eu-west-3:111122223333:targetgroup/api-ecs/0123456789abcdef"
}
resource "aws_lb_target_group" "api_ecs" {
# configuration identique à l'existant
}L'ordre : geler les apply des deux piles, importer côté socle et obtenir un plan sans modification, puis appliquer le removed côté ECS en vérifiant que le plan annonce l'abandon de gestion sans destruction. terraform state rm ferait le même travail sans plan à relire ; la documentation Terraform recommande removed, plus sûr précisément parce qu'il se prévisualise.
Importer ce que la console a créé
Pour les règles, groupes de sécurité ou enregistrements créés à la main, terraform plan -generate-config-out=generated.tf écrit une configuration de départ à partir des blocs import (Terraform 1.5 et plus, fonction encore signalée comme expérimentale), et for_each sur import (1.7 et plus) traite une liste en une fois. La configuration générée se relit ligne à ligne : elle reproduit l'existant, y compris ce qui n'aurait pas dû exister.
ignore_changes : utile pour un compteur, dangereux pour une valeur
ignore_changes fait ignorer à Terraform, lorsqu'il planifie des mises à jour, les attributs listés ; ils ne comptent qu'à la création. Trois cas :
- Légitime :
desired_countd'un service ECS piloté par la mise à l'échelle. - Piège silencieux : un
ignore_changessur un attribut de valeur (paramètre, variable, valeur de configuration) fige cette valeur après la création ; toute modification ultérieure passe inaperçue au plan. Tout attribut ignoré se vérifie dans AWS avant la fenêtre. - Piège de module : avec
ignore_task_definition_changes = true, le module ECS ignore aussi le blocload_balancerdu service.
Enfin, un retour arrière fait à la console serait annulé par le prochain apply : il passe par la variable de la bascule.
create_before_destroy et noms uniques
Remplacer un groupe cible encore attaché à une règle échoue si Terraform détruit avant de créer. create_before_destroy inverse l'ordre, mais deux objets du même nom ne coexistent pas, d'où name_prefix (6 caractères au plus) plutôt que name sur aws_lb_target_group. Sur un groupe de sécurité partagé entre piles, les règles en ligne (ingress, egress) et les ressources de règle séparées ne se mélangent pas, sous peine de conflits et de règles écrasées : chaque pile déclare ses propres aws_vpc_security_group_ingress_rule.
Versions du fournisseur et des modules
Au , la dernière version publiée du fournisseur AWS est la 6.69.1 ; le module terraform-aws-modules/eks 21.26.0 exige Terraform 1.5.7 et le fournisseur 6.59 au minimum, le module ECS 7.6.1 Terraform 1.5.7 et le fournisseur 6.41. Une pile restée sur un fournisseur 5.x monte donc d'abord de fournisseur, seule, avec un plan relu, avant tout ajout lié à EKS. La version 21 du module EKS a aussi renommé ses variables (cluster_name devient name, cluster_version devient kubernetes_version) et retiré son sous-module aws-auth.
terraform {
required_version = ">= 1.7.0" # blocs removed et import avec for_each
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.69"
}
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 21.26"
# ...
}Le fichier .terraform.lock.hcl se versionne avec le code, pour que bascule et retour arrière s'exécutent avec les mêmes versions de fournisseur.
aws-auth ou access entries
Le ConfigMap aws-auth est déprécié au profit des access entries, gérées par l'API EKS. Trois faits orientent le choix : un cluster créé par l'API EKS, un SDK ou CloudFormation sans précision est en mode CONFIG_MAP, alors que le module EKS fixe API_AND_CONFIG_MAP par défaut ; une fois activées, les access entries ne peuvent plus être retirées du mode d'authentification ; EKS Auto Mode les exige. Pour un cluster neuf, le mode API (authentication_mode = "API" dans le module) évite deux sources de vérité. Le module n'ajoute pas non plus l'identité qui exécute Terraform comme administrateur (enable_cluster_creator_admin_permissions vaut false) : les administrateurs se déclarent explicitement.
resource "aws_eks_access_entry" "plateforme" {
cluster_name = var.cluster_name
principal_arn = var.role_plateforme_arn
}
resource "aws_eks_access_policy_association" "plateforme" {
cluster_name = var.cluster_name
principal_arn = var.role_plateforme_arn
policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
access_scope {
type = "cluster"
}
}Sources officielles et limites de lecture
Tarifs, calendrier et versions d'outils ont été revérifiés le , les autres paramètres le 7 octobre 2026, dans les sources ci-dessous, à relire avant toute décision : AWS et les modules Terraform publient souvent. Les pages de la documentation AWS citées ont été lues sur docs.aws.amazon.com ou dans leur dépôt source publié par AWS, les paramètres d'API dans les modèles qu'AWS publie et les tarifs dans les fichiers de l'AWS Price List.
- Méthode, pas récit : aucune migration particulière n'est relatée ; ni durée, ni volume, ni résultat observé.
- Tarifs publics en dollars, région Paris, avant remises et taxes ; l'exemple ne porte que sur le plan de contrôle.
- Périmètre : un compte et une région ; nœuds autogérés ou hybrides, EKS Anywhere, ECS Anywhere, Outposts et migrations de données hors champ.
- Aucune garantie : une bascule par paliers réduit le rayon d'un incident, elle ne garantit pas son absence.
Sources
- AWS Price List, offre AmazonEKS, région eu-west-3 (publication du 28/09/2026), Amazon Web Services, https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEKS/current/eu-west-3/index.csv, consulté le 18/10/2026.
- AWS Price List, offre AmazonECS, région eu-west-3 (publication du 11/09/2026), Amazon Web Services, https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonECS/current/eu-west-3/index.csv, consulté le 18/10/2026.
- Understand the Kubernetes version lifecycle on EKS, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html, consulté le 18/10/2026.
- Update existing cluster to new Kubernetes version, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html, consulté le 18/10/2026.
- Amazon ECS API, modèle d'API publié par AWS (PutAccountSettingDefault, CreateService, CreateCluster, Secret, LoadBalancer, AdvancedConfiguration, ServiceConnectClientAlias, FirelensConfiguration), https://github.com/boto/botocore/blob/develop/botocore/data/ecs/2014-11-13/service-2.json, consulté le 18/10/2026.
- Manage compute resources by using nodes, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/eks-compute.html, consulté le 07/10/2026.
- Karpenter documentation, projet Karpenter, https://github.com/aws/karpenter-provider-aws/blob/main/website/content/en/docs/_index.md, consulté le 07/10/2026.
- Automate cluster infrastructure with EKS Auto Mode, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/automode.html, consulté le 18/10/2026.
- Update the Kubernetes version of an EKS Auto Mode cluster, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/auto-upgrade.html, consulté le 07/10/2026.
- Simplify compute management with AWS Fargate, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/fargate.html, consulté le 18/10/2026.
- Learn how EKS Pod Identity grants pods access to AWS services, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html, consulté le 18/10/2026.
- Create IAM role with trust policy required by EKS Pod Identity, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html, consulté le 07/10/2026.
- Access AWS resources using EKS Pod Identity target IAM roles, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/pod-id-assign-target-role.html, consulté le 07/10/2026.
- Grant Kubernetes workloads access to AWS using Kubernetes Service Accounts, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/service-accounts.html, consulté le 07/10/2026.
- Use AWS Secrets Manager secrets with Amazon EKS Pods, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/manage-secrets.html, consulté le 07/10/2026.
- DNS for Services and Pods, Kubernetes, https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/, consulté le 07/10/2026.
- Extend Amazon EKS capabilities with open source projects (ExternalDNS), Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/related-projects.html, consulté le 07/10/2026.
- Monitor your cluster performance and view logs, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/eks-observe.html, consulté le 07/10/2026.
- Elastic Load Balancing v2 API, modèle d'API publié par AWS (TargetGroupTuple, TargetGroupAttribute), https://github.com/boto/botocore/blob/develop/botocore/data/elbv2/2015-12-01/service-2.json, consulté le 07/10/2026.
- AWS CDK, ApplicationTargetGroup (métriques CloudWatch des groupes cibles), Amazon Web Services, https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts, consulté le 07/10/2026.
- Amazon Route 53 API, modèle d'API publié par AWS (ResourceRecordSet, Weight), https://github.com/boto/botocore/blob/develop/botocore/data/route53/2013-04-01/service-2.json, consulté le 18/10/2026.
- TargetGroupBinding, AWS Load Balancer Controller, Kubernetes SIGs, https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/docs/guide/targetgroupbinding/targetgroupbinding.md, consulté le 07/10/2026.
- Pod readiness gate, AWS Load Balancer Controller, Kubernetes SIGs, https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/docs/deploy/pod_readiness_gate.md, consulté le 07/10/2026.
- Create an IngressClass to configure an Application Load Balancer (EKS Auto Mode), Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/auto-configure-alb.html, consulté le 07/10/2026.
- Application Auto Scaling API, modèle d'API publié par AWS (MetricType), https://github.com/boto/botocore/blob/develop/botocore/data/application-autoscaling/2016-02-06/service-2.json, consulté le 07/10/2026.
- Horizontal Pod Autoscaling, Kubernetes, https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/, consulté le 07/10/2026.
- EventBridge Scheduler API, modèle d'API publié par AWS (EcsParameters, ScheduleSummary), https://github.com/boto/botocore/blob/develop/botocore/data/scheduler/2021-06-30/service-2.json, consulté le 07/10/2026.
- CronJob, Kubernetes, https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/, consulté le 18/10/2026.
- Sync Phases and Waves, Argo CD, https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/, consulté le 07/10/2026.
- Operator pattern, Kubernetes, https://kubernetes.io/docs/concepts/extend-kubernetes/operator/, consulté le 07/10/2026.
- Refactor modules (moved blocks), HashiCorp, https://developer.hashicorp.com/terraform/language/modules/develop/refactoring, consulté le 07/10/2026.
- Generate configuration for import blocks, HashiCorp, https://developer.hashicorp.com/terraform/language/import/generating-configuration, consulté le 07/10/2026.
- Remove a resource from state (removed block), HashiCorp, https://developer.hashicorp.com/terraform/language/state/remove, consulté le 07/10/2026.
- Terraform CHANGELOG, branche v1.5 (1.5.0 : blocs import, -generate-config-out), HashiCorp, https://github.com/hashicorp/terraform/blob/v1.5/CHANGELOG.md, consulté le 07/10/2026.
- Terraform CHANGELOG, branche v1.7 (1.7.0 : bloc removed, import avec for_each), HashiCorp, https://github.com/hashicorp/terraform/blob/v1.7/CHANGELOG.md, consulté le 07/10/2026.
- The lifecycle meta-argument, HashiCorp, https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle, consulté le 07/10/2026.
- Resource aws_lb_listener_rule, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/lb_listener_rule.html.markdown, consulté le 07/10/2026.
- Resource aws_lb_target_group, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/lb_target_group.html.markdown, consulté le 07/10/2026.
- Resource aws_security_group, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/security_group.html.markdown, consulté le 07/10/2026.
- Resource aws_eks_access_entry, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/eks_access_entry.html.markdown, consulté le 07/10/2026.
- Resource aws_eks_access_policy_association, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/eks_access_policy_association.html.markdown, consulté le 07/10/2026.
- Resource aws_eks_pod_identity_association, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/eks_pod_identity_association.html.markdown, consulté le 07/10/2026.
- Resource aws_scheduler_schedule, fournisseur Terraform AWS, HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/scheduler_schedule.html.markdown, consulté le 18/10/2026.
- Terraform AWS provider CHANGELOG (6.69.1 du 15/10/2026), HashiCorp, https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md, consulté le 18/10/2026.
- terraform-aws-modules/eks, tag v21.26.0 (versions.tf, variables.tf), terraform-aws-modules, https://github.com/terraform-aws-modules/terraform-aws-eks/tree/v21.26.0, consulté le 18/10/2026.
- Upgrade from v20.x to v21.x, terraform-aws-modules, https://github.com/terraform-aws-modules/terraform-aws-eks/blob/v21.26.0/docs/UPGRADE-21.0.md, consulté le 07/10/2026.
- terraform-aws-modules/ecs, tag v7.6.1 (versions.tf, modules/service/main.tf), terraform-aws-modules, https://github.com/terraform-aws-modules/terraform-aws-ecs/tree/v7.6.1, consulté le 18/10/2026.
- Grant IAM users and roles access to Kubernetes APIs, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/grant-k8s-access.html, consulté le 18/10/2026.
- Change authentication mode to use access entries, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html, consulté le 18/10/2026.
- Grant IAM users access to Kubernetes with a ConfigMap, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/auth-configmap.html, consulté le 07/10/2026.
- Amazon EKS API, modèle d'API publié par AWS (CreateAccessConfigRequest), https://github.com/boto/botocore/blob/develop/botocore/data/eks/2017-11-01/service-2.json, consulté le 07/10/2026.
- Review access policy permissions, Amazon Web Services, https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html, consulté le 07/10/2026.