Aller au contenu

Lab : Signalements sur Kapsule

Prérequis

Testé avec kubernetes 1.36 scaleway-cli 2.62.0 terraform 1.16.1 , vérifié le 5 octobre 2026

Ce lab rassemble le cours Kapsule : Kubernetes managé chez Scaleway. Vous décrivez en Terraform le cluster de production de Signalements comme à la leçon 8, vous l'appliquez, vous y déployez l'application du lab Kubernetes, puis un script vérifie le cluster par l'API Scaleway et par kubectl. Il valide le niveau 200 des compétences « Kubernetes : objets fondamentaux » et « Fondamentaux du cloud ».

Comptez une journée et quelques euros : supprimez tout en fin de séance.

Note

Le script a été écrit à partir de l'aide de la CLI scw 2.62 et des structures de réponse du SDK Go de Scaleway. Il ne fait que des lectures.

Les exigences

ExigenceLeçon
Le cluster signalements est créé en Terraform dans le projet signalements-prod, rattaché au réseau privé pn-signalements, avec Cilium2, 8
Les mises à jour automatiques sont activées, avec une fenêtre de maintenance6
Au moins deux pools, dans deux zones différentes, chacun avec autoscaling (minimum d'au moins un nœud) et autoréparation3
L'accès à l'API du cluster est restreint : aucune règle n'autorise 0.0.0.0/02, 5
Tous les nœuds sont Ready, et ils sont répartis sur au moins deux zones3
La classe de stockage par défaut est fournie par le pilote CSI de Scaleway4
Le contrôleur d'entrée est exposé par un seul Service LoadBalancer, dont l'adresse est réservée4
Signalements tourne, avec deux répliques disponibles8, cours Kubernetes

Vérifier

Enregistrez le script sous verifier-lab.sh et lancez-le avec votre profil scw et le kubeconfig du cluster.

#!/usr/bin/env bash
# Vérifie les propriétés attendues du lab « Signalements sur Kapsule ».
# Usage : KUBECONFIG=<kubeconfig du cluster> bash verifier-lab.sh   (exige scw, kubectl et jq)
# Chaque contrôle affiche OK ou ÉCHEC ; le code de sortie est le nombre d'échecs.
set -uo pipefail
echecs=0

controle() {   # controle "libellé" commande...
  local libelle=$1; shift
  if "$@" > /dev/null 2>&1; then
    echo "OK     $libelle"
  else
    echo "ÉCHEC  $libelle"
    echecs=$((echecs + 1))
  fi
}

PROD=$(scw account project list -o json | jq -r '.[] | select(.name == "signalements-prod") | .id')
PN=$(scw vpc private-network list project-id="$PROD" region=fr-par -o json | jq -r '.[] | select(.name == "pn-signalements") | .id')
cluster=$(scw k8s cluster list project-id="$PROD" region=fr-par -o json | jq -c '[.[] | select(.name == "signalements")][0] // empty')
CID=$(jq -r '.id // empty' <<< "$cluster")

controle "le cluster signalements existe en production" test -n "$CID"
controle "il est rattaché à pn-signalements" \
  bash -c 'jq -e --arg pn "$2" ".private_network_id == \$pn" <<< "$1"' _ "$cluster" "$PN"
controle "son plugin réseau est Cilium" \
  bash -c 'jq -e ".cni == \"cilium\"" <<< "$1"' _ "$cluster"
controle "les mises à jour automatiques sont activées avec une fenêtre" \
  bash -c 'jq -e ".auto_upgrade.enabled == true and .auto_upgrade.maintenance_window != null" <<< "$1"' _ "$cluster"

pools=$(scw k8s pool list cluster-id="$CID" region=fr-par -o json 2>/dev/null)
controle "au moins deux pools dans deux zones" \
  bash -c 'jq -e "length >= 2 and ([.[].zone] | unique | length) >= 2" <<< "$1"' _ "$pools"
controle "chaque pool a l'autoscaling (minimum >= 1) et l'autoréparation" \
  bash -c 'jq -e "all(.autoscaling == true and .min_size >= 1 and .autohealing == true)" <<< "$1"' _ "$pools"
controle "l'accès à l'API n'est pas ouvert à tout Internet" \
  bash -c 'scw k8s acl list cluster-id="$1" region=fr-par -o json | jq -e "length > 0 and all(.ip != \"0.0.0.0/0\")"' _ "$CID"

controle "tous les nœuds sont Ready" \
  bash -c 'kubectl get nodes -o json | jq -e "[.items[] | .status.conditions[] | select(.type == \"Ready\") | .status == \"True\"] | length > 0 and all"'
controle "les nœuds sont répartis sur au moins deux zones" \
  bash -c '[ "$(kubectl get nodes -o json | jq "[.items[].metadata.labels[\"topology.kubernetes.io/zone\"]] | unique | length")" -ge 2 ]'
controle "la classe de stockage par défaut vient du pilote CSI de Scaleway" \
  bash -c 'kubectl get storageclass -o json | jq -e "[.items[] | select(.metadata.annotations[\"storageclass.kubernetes.io/is-default-class\"] == \"true\") | .provisioner] == [\"csi.scaleway.com\"]"'

lbs=$(kubectl get services -A -o json | jq -c '[.items[] | select(.spec.type == "LoadBalancer")]')
controle "un seul Service LoadBalancer dans le cluster" \
  bash -c 'jq -e "length == 1" <<< "$1"' _ "$lbs"
controle "son adresse est réservée (annotation d'IP ou loadBalancerIP)" \
  bash -c 'jq -e ".[0] | (.metadata.annotations // {} | keys | any(test(\"scw-loadbalancer-ip-ids|scw-loadbalancer-ip\"))) or (.spec.loadBalancerIP != null)" <<< "$1"' _ "$lbs"

controle "Signalements a deux répliques disponibles" \
  bash -c 'kubectl -n signalements get deployment signalements -o json | jq -e ".status.availableReplicas >= 2"'

echo
echo "$echecs échec(s)"
exit "$echecs"

Quelques contrôles demandent une explication :

  • La répartition par zone se lit sur l'étiquette standard topology.kubernetes.io/zone que le gestionnaire de contrôleurs de Scaleway pose sur chaque nœud.
  • L'adresse réservée : un Service LoadBalancer sans indication reçoit une adresse éphémère, perdue si le Service est recréé. Le script accepte les deux façons documentées de l'épingler (annotation du gestionnaire de contrôleurs de Scaleway ou champ loadBalancerIP) ; relisez la leçon 4 pour celle à préférer.
  • Un seul répartiteur : chaque Service LoadBalancer crée un Load Balancer facturé ; les applications passent par le contrôleur d'entrée.

Démonter

terraform destroy supprime le cluster et ses pools. Les répartiteurs et les volumes créés par le cluster (Services LoadBalancer, PVC) ne sont pas dans l'état Terraform : supprimez d'abord les objets Kubernetes qui les ont créés, ou utilisez l'option de suppression des ressources additionnelles décrite à la leçon 8, puis vérifiez avec l'inventaire de la leçon 8 du cours cloud qu'il ne reste rien.

Plan du cours