Olivier Guandalini
ProjetsExpérienceContact

Visite guidée · 18 étapes

platform-eks-gitops, commande par commande

Dix-huit étapes, du git clone au make down. Au fil du défilement, le schéma se construit, et chaque commande dit ce qu'elle fait et montre ce qu'elle a affiché lors d'une vraie exécution.

Vue d'ensemble : la plateforme sur AWS, tous les contrôles réussisFaites défiler, la plateforme se construit
SUR LA MACHINE, DANS DOCKERun kubeconfig à partCOMPTE AWS · EU-NORTH-1À CRÉER · VPC 10.20.0.0/16 · EKS 1.36EU-NORTH-1 · VPC 10.20.0.0/16EKS 1.36Bucket d'étatverrou natifplatform-eks-gitopsterraform/gitops/apps/EN CHIFFRES1 dépôtlà où tout commence6 outilspour le local22 spour créer le cluster0 registreimportée directement49 spour Argo CD1 racinel'app-of-apps13 / 13applications prêtes9 / 9contrôles réussis3 ports8081, 3000 et 909074 / 245requêtes en échec0 clusteraprès make local-down1 commandepour débuter sur AWS28ressources à créer0,18 $par heure de démo12 / 12applications prêtes10 / 10contrôles sur EKS1 bucketseul à rester14contrôles par PRPOUR LA PLATEFORME LOCALEdockerk3dkubectlhelmpython3curlET POUR AWSterraformawsroot-local lit le dépôtroot-aws lit le dépôtArgo CDapp-of-appsVAGUES-2cert-managerEnvoy GatewayExternal Secrets-1CA plateformeSecretStoreVault0gatewayPrometheusGrafanaSloth1demo-api × 2/chaos : 3 sur 10 échouentroute Grafana:8081 · Argo CD:3000 · Grafana:9090 · PrometheusIMAGEdemo-api, importée dans k3dENTRÉElocalhost:8443NLB public · 80 et 443SECRETSVault en mode devSecrets Manager · Pod IdentitySLO · DISPONIBILITÉ99,5 % des requêtes sans erreurbudget d'erreurfond 60 fois trop vitealerte de burn rate déclenchée→ son runbooknœud Spot t3.medium · 1anœud Spot t3.medium · 1bCluster local suppriméle dépôt reste tel quelPréparé par make aws-setuple profil, et une session ouvertela région eu-north-1 et deux zonesle bucket d'état, ou sa création28 ressources à créerle VPC et deux sous-réseaux publicsla passerelle internet, sans NATle cluster EKS et deux nœuds Spotles rôles IAM, Pod Identity, 2 secretsCréé par Terraformle VPC et deux sous-réseaux publicsla passerelle internet, sans NATle cluster EKS et deux nœuds Spotles rôles IAM, Pod Identity, 2 secretsTout est détruitseul le bucket d'état resteGitHub Actions, à chaque pull requestPRE-COMMITfmt, validate, tflint, checkov, gitleaksMANIFESTESrendu kustomize et kubeconformIMAGE, QUAND L'API CHANGEconstruite, testée, scannée par Trivy, publiée sur GHCR depuis mainCHAQUE SEMAINEâge des images de base, nouveau scanBucketd'étatBucketd'étatplatform-eks-gitopsterraform/gitops/apps/POUR LA PLATEFORME LOCALEdockerk3dkubectlhelmpython3curlET POUR AWSterraformawsSUR LA MACHINE, DANS DOCKERun kubeconfig à partCOMPTE AWS · EU-NORTH-1À CRÉER · VPC 10.20.0.0/16 · EKS 1.36EU-NORTH-1 · VPC 10.20.0.0/16EKS 1.36root-local lit le dépôtroot-aws lit le dépôtArgo CDIMAGEdemo-api, importée dans k3dVAGUES-2cert-managerEnvoy GatewayExternal Secrets-1CA plateformeSecretStoreVault0gatewayPrometheusGrafanaSloth1demo-api × 2route Grafana/chaos : 3 sur 10 échouentENTRÉElocalhost:8443NLB public · 80 et 443SECRETSVault en mode devSecrets Manager · Pod IdentitySLO · DISPONIBILITÉ99,5 % des requêtes sans erreurbudget d'erreurfond 60 fois trop vitealerte de burn rate déclenchée→ son runbook:8081 · Argo CD:3000 · Grafana:9090 · Prometheusnœud Spot t3.medium · 1anœud Spot t3.medium · 1bCluster local suppriméle dépôt reste tel quelPréparé par make aws-setuple profil, et une session ouvertela région eu-north-1 et deux zonesle bucket d'état, ou sa création28 ressources à créerle VPC et deux sous-réseaux publicsla passerelle internet, sans NATle cluster EKS et deux nœuds Spotles rôles IAM, Pod Identity, 2 secretsCréé par Terraformle VPC et deux sous-réseaux publicsla passerelle internet, sans NATle cluster EKS et deux nœuds Spotles rôles IAM, Pod Identity, 2 secretsnœud Spot t3.medium · 1anœud Spot t3.medium · 1bTout est détruitseul le bucket d'état resteGitHub Actions, à chaque pull requestPRE-COMMITfmt, validate, tflint, checkov, gitleaksMANIFESTESrendu kustomize et kubeconformIMAGE, QUAND L'API CHANGEconstruite, testée, scannée par Trivy,publiée sur GHCR depuis mainCHAQUE SEMAINEâge des images de base, nouveau scan

Préparer · Étape 01/18

Le dépôt

Tout est dans git : Terraform pour AWS, les manifestes qu'Argo CD applique, l'API de démo et son Dockerfile, et le Makefile qui enchaîne le tout. Rien n'est créé à la main, ni en local ni sur AWS.

1 dépôt là où tout commence

~/platform-eks-gitops
$ git clone https://github.com/Olivg92/platform-eks-gitops.git
Cloning into 'platform-eks-gitops'...
$ cd platform-eks-gitops

Préparer · Étape 02/18

Les outils

Une commande dit ce qui est installé, groupé par usage. Six outils suffisent pour la plateforme locale ; Terraform et le CLI AWS ne servent qu'à partir du chapitre 3, les linters seulement pour contribuer.

6 outils pour le local

~/platform-eks-gitops
$ make check-tools
local platform (make local-up):
  ok       docker       29.1.3
  ok       k3d          v5.9.0
  ok       kubectl      v1.37.0
  ok       helm         v4.3.0+gbec5b06
  ok       python3      3.10.12
  ok       curl         7.81.0
AWS demo (make up):
  ok       terraform    v1.16.1
  ok       aws          2.36.49
contributing (make lint):
  ok       pre-commit   4.6.2
  ok       tflint       0.64.0
  ok       checkov      3.3.19
  ok       kubeconform  v0.8.0
everything needed is there

En local · Étape 03/18

Le cluster k3d

make local-up enchaîne cinq étapes, une ligne chacune. La première crée un cluster Kubernetes de deux nœuds dans Docker, à la même version de Kubernetes que sur EKS. Ses identifiants vont dans un fichier à lui, jamais dans le kubeconfig par défaut, qui peut viser d'autres clusters.

22 s pour créer le cluster

Cible appelée : make local-cluster

~/platform-eks-gitops
$ make local-up
  k3d cluster                                        22s  ok

En local · Étape 04/18

L'image de l'API

L'image de l'API de démo est construite sur la machine, puis importée directement dans le cluster : pas de registre à faire tourner en local.

0 registre importée directement

Cible appelée : make demo-image

~/platform-eks-gitops
$ make local-up
  k3d cluster                                        22s  ok
  Demo API image, built and imported                  8s  ok

En local · Étape 05/18

Argo CD

Helm installe Argo CD, le seul composant qu'Argo CD n'installe pas lui-même. Tout le reste viendra de git.

49 s pour Argo CD

Cible appelée : make local-argocd

~/platform-eks-gitops
$ make local-up
  k3d cluster                                        22s  ok
  Demo API image, built and imported                  8s  ok
  Argo CD                                            49s  ok

En local · Étape 06/18

L'application racine

Une seule Application, appliquée une fois, pointe Argo CD vers le dépôt : l'app-of-apps. À partir de là, Argo CD lit git et installe le reste tout seul.

1 racine l'app-of-apps

Cible appelée : make local-bootstrap

~/platform-eks-gitops
$ make local-up
  k3d cluster                                        22s  ok
  Demo API image, built and imported                  8s  ok
  Argo CD                                            49s  ok
  Root application                                    0s  ok

En local · Étape 07/18

La plateforme, vague par vague

Argo CD installe par vagues : les opérateurs et leurs CRD d'abord, puis ce qui s'en sert, puis l'API de démo. La commande attend que chaque application soit synchronisée et saine, et liste pendant l'attente ce que chacune attend encore.

13 / 13 applications prêtes

Cible appelée : make local-wait

~/platform-eks-gitops
$ make local-up
  k3d cluster                                        22s  ok
  Demo API image, built and imported                  8s  ok
  Argo CD                                            49s  ok
  Root application                                    0s  ok
  Platform, synced by Argo CD                      3m37s  ok  13/13 ready

The platform is up, in 4m56s. Log: logs/local-up-20261004-215503.log

En local · Étape 08/18

Vérifier

Neuf vérifications de bout en bout, chacune passe ou dit ce qui manque : les applications, la gateway en HTTP et en HTTPS, un secret venu de Vault, Grafana et l'API de démo derrière la gateway, les métriques, les règles de SLO et leur tableau de bord.

9 / 9 contrôles réussis

~/platform-eks-gitops
$ make local-verify
checking the local platform:
  ok    Argo CD applications                       all applications healthy
  ok    gateway, HTTP listener                     listener answers (HTTP 404)
  ok    gateway, HTTPS listener                    TLS terminated, issuer CN=platform-local-ca
  ok    secret synced from Vault                   "stored in Vault, never in git"
  ok    Grafana behind the gateway                 reachable over HTTPS (HTTP 200)
  ok    demo API behind the gateway                answers through the gateway
  ok    demo API scraped by Prometheus             ServiceMonitor in place
  ok    SLO rules from Sloth                       6 rule groups generated by Sloth
  ok    SLO dashboard in Grafana                   dashboard shipped with the application

En local · Étape 09/18

Explorer

Chaque interface s'ouvre par un port-forward à elle, jusqu'à Ctrl+C, sans toucher à /etc/hosts : Argo CD, Grafana, Prometheus. Leurs mots de passe viennent de make argocd-password et make grafana-password.

3 ports 8081, 3000 et 9090

~/platform-eks-gitops
$ make argocd-ui
kubectl port-forward -n argocd svc/argocd-server 8081:80
Forwarding from 127.0.0.1:8081 -> 8080
$ make grafana-ui
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
Forwarding from 127.0.0.1:3000 -> 3000
$ make prometheus-ui
kubectl port-forward -n monitoring svc/kube-prometheus-stack-prometheus 9090:9090
Forwarding from 127.0.0.1:9090 -> 9090

En local · Étape 10/18

Casser exprès

L'API de démo sait échouer sur commande. Avec 30 % de requêtes en échec pour un SLO de 99,5 %, le budget d'erreur fond 60 fois trop vite : l'alerte de burn rate générée par Sloth se déclenche, avec le lien vers son runbook. make demo-fix remet tout en ordre.

74 / 245 requêtes en échec

~/platform-eks-gitops
$ make demo-break
setting error_rate=0.3 latency_ms=0 on every pod
  demo-api-6bbd6667c-8wf8j: {"error_rate":0.3,"latency_ms":0}
  demo-api-6bbd6667c-knkhd: {"error_rate":0.3,"latency_ms":0}
$ make demo-load
sending ~5 req/s to https://demo.platform.local:8443/ (127.0.0.1) for 60s
sent 245 requests, 74 of them failed
$ make demo-fix
setting error_rate=0 latency_ms=0 on every pod
  demo-api-6bbd6667c-8wf8j: {"error_rate":0.0,"latency_ms":0}
  demo-api-6bbd6667c-knkhd: {"error_rate":0.0,"latency_ms":0}

En local · Étape 11/18

Tout supprimer

Une commande supprime le cluster et son kubeconfig, rien d'autre : le dépôt reste tel quel, prêt pour le prochain make local-up.

0 cluster après make local-down

~/platform-eks-gitops
$ make local-down
deleted the k3d cluster platform-local

Sur AWS · Étape 12/18

Préparer le compte

La première fois sur AWS tient en une commande, ici dans un clone neuf. Elle garde le profil dans local.mk, vérifie la session, trouve la région (ici, celle où le bucket d'état existe déjà) et deux zones qu'EKS accepte, puis écrit terraform.tfvars et backend.hcl. Sans bucket d'état, elle en créerait un, après en avoir montré le plan.

1 commande pour débuter sur AWS

~/platform-eks-gitops
$ make aws-setup
AWS setup of the demo environment:

Which AWS CLI profile should this project use? It is kept in local.mk, which is not committed.
Profiles on this machine: default perso my-profile
Profile (a new name is created at the login): perso

  profile            perso (now in local.mk)
  session            opened 0h00 ago, about 11h59 left
  account            <account id>
  region             eu-north-1, where the state bucket is (now in local.mk)
  terraform.tfvars   written, zones eu-north-1a eu-north-1b
  backend.hcl        written, bucket platform-eks-gitops-tfstate-og92

Ready. Next: make plan to see what would be created, or make up to create it.

Sur AWS · Étape 13/18

Voir le plan

Avant que rien n'existe, Terraform dit ce qu'il créerait : le VPC et ses sous-réseaux publics, le cluster EKS et deux nœuds Spot, les rôles IAM et les secrets. Pas de NAT gateway : les nœuds sont dans des sous-réseaux publics, derrière des groupes de sécurité stricts.

28 ressources à créer

~/platform-eks-gitops
$ make plan
# the detail of each of the 28 resources, then:
Plan: 28 to add, 0 to change, 0 to destroy.

Sur AWS · Étape 14/18

Créer l'infrastructure

make up montre le plan en quelques lignes et ce qu'il coûte, puis attend un oui. Terraform applique exactement ce plan : le réseau, le cluster, ses nœuds.

0,18 $ par heure de démo

~/platform-eks-gitops
$ make up
AWS session opened 0h01 ago, about 11h58 left
  Terraform init                                      2s  ok
  Terraform plan                                      6s  ok

Terraform plan:
  to create: 28
    1 aws_default_security_group, 4 aws_eks_addon, 1 aws_eks_cluster, 1 aws_eks_node_group,
    1 aws_eks_pod_identity_association, 3 aws_iam_role, 1 aws_iam_role_policy,
    4 aws_iam_role_policy_attachment, 1 aws_internet_gateway, 1 aws_launch_template,
    1 aws_route_table, 2 aws_route_table_association, 2 aws_secretsmanager_secret,
    2 aws_secretsmanager_secret_version, 2 aws_subnet, 1 aws_vpc
The Kubernetes API will answer to <your IP>/32 only.
This costs about $0.18 an hour, until `make down`.

Apply it? Only 'yes' will be accepted: yes

  Terraform apply                                 11m17s  ok  28 of 28 resources

Sur AWS · Étape 15/18

Installer la plateforme

La même commande écrit les identifiants du nouveau cluster dans un fichier à part, installe Argo CD, puis l'application racine, comme en local. Argo CD installe la version AWS : les secrets depuis Secrets Manager par Pod Identity, la gateway derrière un load balancer.

12 / 12 applications prêtes

Cible appelée : make aws-argocd, make aws-bootstrap, make aws-wait

~/platform-eks-gitops
$ make up
AWS session opened 0h01 ago, about 11h58 left
  Terraform init                                      2s  ok
  Terraform plan                                      6s  ok

Terraform plan:
  to create: 28
    1 aws_default_security_group, 4 aws_eks_addon, 1 aws_eks_cluster, 1 aws_eks_node_group,
    1 aws_eks_pod_identity_association, 3 aws_iam_role, 1 aws_iam_role_policy,
    4 aws_iam_role_policy_attachment, 1 aws_internet_gateway, 1 aws_launch_template,
    1 aws_route_table, 2 aws_route_table_association, 2 aws_secretsmanager_secret,
    2 aws_secretsmanager_secret_version, 2 aws_subnet, 1 aws_vpc
The Kubernetes API will answer to <your IP>/32 only.
This costs about $0.18 an hour, until `make down`.

Apply it? Only 'yes' will be accepted: yes

  Terraform apply                                 11m17s  ok  28 of 28 resources
  Credentials for the new cluster                     3s  ok
  Argo CD                                            49s  ok
  Root application                                    3s  ok
  Platform, synced by Argo CD                      5m45s  ok  12/12 ready

The platform is up, in 18m09s. Log: logs/up-20261005-092741.log

Sur AWS · Étape 16/18

Vérifier sur EKS

Dix vérifications pour la version AWS : les nœuds tournent bien en Spot, le magasin de secrets atteint Secrets Manager par Pod Identity, l'API de démo répond par le load balancer, avec l'image publiée par la CI. Ensuite, les mêmes interfaces qu'en local, avec ENV=aws.

10 / 10 contrôles sur EKS

~/platform-eks-gitops
$ make aws-verify
checking the platform on EKS:
  ok    Argo CD applications                       all applications healthy
  ok    nodes running on spot capacity             2 of 2 nodes on spot capacity
  ok    secret store (Pod Identity)                Secrets Manager reachable with Pod Identity
  ok    secret from Secrets Manager                credentials materialised for "admin"
  ok    gateway load balancer                      a07fe9cf596134f19a0589778c38f0ef-a5a171c81b806794.elb.eu-north-1.amazonaws.com
  ok    Grafana behind the gateway                 reachable over HTTPS (HTTP 200)
  ok    demo API behind the gateway                answers through the load balancer
  ok    demo API image                             published by CI, sha-339a41ab09ce
  ok    demo API scraped by Prometheus             ServiceMonitor in place
  ok    SLO rules from Sloth                       6 rule groups generated by Sloth

Sur AWS · Étape 17/18

Tout détruire

make down arrête Argo CD pour qu'il ne recrée pas ce qu'on supprime, retire le load balancer créé par Kubernetes, détruit le reste avec Terraform, puis demande à l'API d'AWS s'il reste quelque chose qui facture.

1 bucket seul à rester

~/platform-eks-gitops
$ make down
AWS session opened 0h20 ago, about 11h39 left
  Terraform init                                      3s  ok
  Terraform plan of the destroy                       9s  ok

Terraform plan:
  to destroy: 28
    1 aws_default_security_group, 4 aws_eks_addon, 1 aws_eks_cluster, 1 aws_eks_node_group,
    1 aws_eks_pod_identity_association, 3 aws_iam_role, 1 aws_iam_role_policy,
    4 aws_iam_role_policy_attachment, 1 aws_internet_gateway, 1 aws_launch_template,
    1 aws_route_table, 2 aws_route_table_association, 2 aws_secretsmanager_secret,
    2 aws_secretsmanager_secret_version, 2 aws_subnet, 1 aws_vpc

Destroy it? Only 'yes' will be accepted: yes

  Stopping Argo CD, so it stops recreating            5s  ok
  Removing the load balancer Kubernetes made          5s  ok
  Terraform destroy                                6m49s  ok  28 of 28 resources

checking nothing is left behind:
  ok    load balancers         none
  ok    classic load balancers none
  ok    elastic IPs            none
  ok    EBS volumes            none
  ok    EKS clusters           none
  ok    NAT gateways           none

Everything is gone, in 7m23s. The state bucket is the only resource left, and it costs cents.

En continu · Étape 18/18

La CI

Les mêmes vérifications tournent en local et à chaque pull request, depuis le même fichier : lint de Terraform et de Kubernetes, détection de secrets. Quand l'API de démo change, GitHub Actions construit aussi son image, la teste et la scanne avec Trivy, puis la publie sur GHCR depuis main ; chaque semaine, un workflow vérifie l'âge des images de base et scanne à nouveau l'image publiée.

14 contrôles par PR

~/platform-eks-gitops
$ make lint
pre-commit run -a
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check for merge conflicts................................................Passed
check for added large files..............................................Passed
detect private key.......................................................Passed
check yaml...............................................................Passed
Detect hardcoded secrets.................................................Passed
yamllint.................................................................Passed
Terraform fmt............................................................Passed
Terraform validate.......................................................Passed
Terraform validate with tflint...........................................Passed
Checkov..................................................................Passed
Lint GitHub Actions workflow files.......................................Passed
kubeconform..............................................................Passed