Lab : Signalements sur Kapsule
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
| Exigence | Leçon |
|---|---|
Le cluster signalements est créé en Terraform dans le projet signalements-prod, rattaché au réseau privé pn-signalements, avec Cilium | 2, 8 |
| Les mises à jour automatiques sont activées, avec une fenêtre de maintenance | 6 |
| Au moins deux pools, dans deux zones différentes, chacun avec autoscaling (minimum d'au moins un nœud) et autoréparation | 3 |
L'accès à l'API du cluster est restreint : aucune règle n'autorise 0.0.0.0/0 | 2, 5 |
Tous les nœuds sont Ready, et ils sont répartis sur au moins deux zones | 3 |
| La classe de stockage par défaut est fournie par le pilote CSI de Scaleway | 4 |
Le contrôleur d'entrée est exposé par un seul Service LoadBalancer, dont l'adresse est réservée | 4 |
| Signalements tourne, avec deux répliques disponibles | 8, 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/zoneque le gestionnaire de contrôleurs de Scaleway pose sur chaque nœud. - L'adresse réservée : un Service
LoadBalancersans 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 champloadBalancerIP) ; relisez la leçon 4 pour celle à préférer. - Un seul répartiteur : chaque Service
LoadBalancercré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.