Cours

Introduction à Kubernetes The Hard Way

Objectif

Kubernetes The Hard Way est un tutoriel conçu pour apprendre les fondamentaux de Kubernetes en suivant une approche manuelle et détaillée. Il n'est pas destiné à la production, mais à la compréhension des composants de base et de leur interaction.

Public cible

Le tutoriel s'adresse à toute personne souhaitant comprendre comment fonctionne Kubernetes en profondeur, en réalisant chaque étape de bootstrap d'un cluster.

Licence

Ce travail est sous licence Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).

⚠️ Les résultats de ce tutoriel ne doivent pas être considérés comme prêts pour la production.

Architecture du cluster

Vue d'ensemble

Le cluster bootstrapé comprend un nœud de contrôle unique (server) et deux nœuds workers (node-0 et node-1). Tous les composants du plan de contrôle s'exécutent sur le même nœud.

Versions des composants

  • Kubernetes : v1.32.x
  • Containerd : v2.1.x
  • CNI (Container Network Interface) : v1.6.x
  • etcd : v3.6.x

Cette configuration minimale permet d'apprendre les concepts essentiels sans complexité inutile.

Prérequis matériels et logiciels

Machines requises

Le tutoriel nécessite quatre machines (physiques ou virtuelles) avec les spécifications suivantes :

NomRôleCPURAMStockage
jumpboxMachine d'administration1512 MB10 GB
serverPlan de contrôle Kubernetes12 GB20 GB
node-0Nœud worker12 GB20 GB
node-1Nœud worker12 GB20 GB

Système d'exploitation

Toutes les machines doivent exécuter Debian 12 (bookworm). Pour vérifier, utilisez cat /etc/os-release ; la sortie doit contenir PRETTY_NAME="Debian GNU/Linux 12 (bookworm)".

Les machines doivent être connectées au même réseau.

Configuration du jumpbox et installation des outils

Objectif

Le jumpbox est une machine d'administration dédiée servant de base pour déployer un cluster Kubernetes The Hard Way. Toutes les commandes de la procédure sont exécutées en tant qu'utilisateur root sur cette machine.

Étapes de mise en place

  1. Connexion SSH : ssh root@jumpbox
  2. Mise à jour des paquets et installation des utilitaires :
    apt-get update
    apt-get -y install wget curl vim openssl git
    
  3. Clonage du dépôt GitHub :
    git clone --depth 1 https://github.com/kelseyhightower/kubernetes-the-hard-way.git
    cd kubernetes-the-hard-way
    
    Le répertoire de travail devient /root/kubernetes-the-hard-way.

Installation de kubectl

  • Copier le binaire kubectl depuis downloads/client/kubectl vers /usr/local/bin/.
  • Vérifier avec kubectl version --client.

Points clés

  • Le jumpbox centralise l’administration et évite de télécharger plusieurs fois les binaires.
  • Toutes les commandes sont exécutées en tant que root pour simplifier.
  • Le dépôt cloné contient les fichiers de configuration et templates nécessaires.
Téléchargement et organisation des binaires Kubernetes

Objectif

Télécharger une fois les binaires des composants Kubernetes sur le jumpbox, puis les organiser dans des sous-répertoires par rôle (client, controller, worker, cni-plugins). Cela évite de télécharger plusieurs fois les mêmes fichiers.

Procédure

  1. Lister les binaires à télécharger :
    cat downloads-$(dpkg --print-architecture).txt
    
  2. Télécharger les archives dans un dossier downloads :
    wget -q --show-progress --https-only --timestamping -P downloads -i downloads-$(dpkg --print-architecture).txt
    
    Plus de 500 Mo de données.
  3. Extraire et organiser les binaires :
    • Créer les sous-répertoires : client, cni-plugins, controller, worker.
    • Extraire chaque archive (crictl, containerd, cni-plugins, etcd) dans le bon dossier.
    • Déplacer les binaires : etcdctl et kubectl dans client/ ; etcd, kube-apiserver, kube-controller-manager, kube-scheduler dans controller/ ; kubelet, kube-proxy dans worker/ ; runc.ARCH dans worker/.
  4. Nettoyer les archives : rm -rf downloads/*gz.
  5. Rendre les binaires exécutables :
    chmod +x downloads/{client,cni-plugins,controller,worker}/*
    

Résultat

Les binaires sont prêts à être copiés sur les machines du cluster (contrôleur et workers) lors des étapes suivantes.

Provisionnement des machines du cluster (machines.txt, SSH, hostnames, hosts)

Fichier machines.txt

Chaque ligne du fichier machines.txt contient quatre colonnes :

  • IPV4_ADDRESS : adresse IP de la machine
  • FQDN : nom de domaine complet (ex: server.kubernetes.local)
  • HOSTNAME : nom court (ex: server)
  • POD_SUBNET : sous-réseau CIDR pour les pods (ex: 10.200.0.0/24)

Exemple :

XXX.XXX.XXX.XXX server.kubernetes.local server
XXX.XXX.XXX.XXX node-0.kubernetes.local node-0 10.200.0.0/24
XXX.XXX.XXX.XXX node-1.kubernetes.local node-1 10.200.1.0/24

Configuration SSH

  • Activer l'accès root SSH sur chaque machine : modifier /etc/ssh/sshd_config (PermitRootLogin yes) et redémarrer sshd.
  • Générer une paire de clés SSH sur le jumpbox : ssh-keygen.
  • Copier la clé publique sur chaque machine : ssh-copy-id root@IP.
  • Vérifier : ssh -n root@IP hostname doit retourner le hostname.

Attribution des hostnames

Sur le jumpbox, pour chaque machine dans machines.txt :

  • Modifier /etc/hosts : remplacer l’entrée 127.0.1.1 par 127.0.1.1 FQDN HOST.
  • Définir le hostname : hostnamectl set-hostname HOST.
  • Redémarrer systemd-hostnamed.
  • Vérifier : hostname --fqdn doit retourner le FQDN.

Fichier hosts partagé

  1. Créer un fichier hosts avec un en-tête et les lignes IP FQDN HOST pour chaque machine.
  2. Ajouter ces entrées au /etc/hosts du jumpbox : cat hosts >> /etc/hosts.
  3. Copier et ajouter le fichier hosts sur chaque machine distante : scp hosts root@HOST:~/ puis cat hosts >> /etc/hosts.

Résultat : les machines sont joignables par hostname (server, node-0, node-1) depuis le jumpbox ou entre elles.

Mise en place d'une autorité de certification (CA) avec OpenSSL

Objectif

Créer une infrastructure à clé publique (PKI) pour Kubernetes en utilisant OpenSSL. L'autorité de certification (CA) est auto-signée (non recommandée en production) et sert à signer les certificats des composants.

Étapes

  1. Génération de la clé privée du CA : openssl genrsa -out ca.key 4096
  2. Création du certificat racine auto-signé : openssl req -x509 -new -sha512 -noenc -key ca.key -days 3653 -config ca.conf -out ca.crt
    • Le fichier ca.conf définit les paramètres (durée de validité, algorithmes, etc.)
    • Résultat : deux fichiers ca.crt (certificat) et ca.key (clé privée)

Fichiers produits

  • ca.crt : certificat racine (public)
  • ca.key : clé privée du CA (à protéger)

Piège

  • Un CA auto-signé ne doit pas être utilisé en production ; il faut une autorité reconnue.
  • La clé privée ca.key est extrêmement sensible : elle permet de signer tous les certificats du cluster.
Génération des certificats clients et serveurs pour Kubernetes

Composants concernés

Huit certificats sont générés pour : admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server, service-accounts.

Processus pour chaque composant

  1. Génération de la clé privée : openssl genrsa -out ${i}.key 4096
  2. Création de la demande de signature (CSR) : openssl req -new -key ${i}.key -sha256 -config ca.conf -section ${i} -out ${i}.csr
    • La section dans ca.conf définit le sujet (CN, SAN) propre au composant.
  3. Signature par le CA : openssl x509 -req -days 3653 -in ${i}.csr -copy_extensions copyall -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -out ${i}.crt
    • L'option -copy_extensions copyall recopie les extensions (SAN) de la CSR dans le certificat final.

Résultat

Pour chaque composant : un fichier .key (clé privée), .csr (demande), .crt (certificat signé).

Piège

  • La clé privée ne doit jamais être partagée.
  • Les certificats sont valables 3653 jours (~10 ans) ; à adapter en production.
Distribution des certificats aux machines du cluster

Machines cibles

  • node-0 et node-1 : reçoivent ca.crt et leur propre certificat/clé pour le kubelet.
    • Dossier de destination : /var/lib/kubelet/
    • Fichiers : ca.crt, kubelet.crt (renommé depuis node-X.crt), kubelet.key
  • server (machine du plan de contrôle) : reçoit ca.key, ca.crt, kube-api-server.key, kube-api-server.crt, service-accounts.key, service-accounts.crt
    • Dossier : ~/ (répertoire personnel de root)

Commandes

for host in node-0 node-1; do
  ssh root@${host} mkdir /var/lib/kubelet/
  scp ca.crt root@${host}:/var/lib/kubelet/
  scp ${host}.crt root@${host}:/var/lib/kubelet/kubelet.crt
  scp ${host}.key root@${host}:/var/lib/kubelet/kubelet.key
done

scp ca.key ca.crt kube-api-server.key kube-api-server.crt service-accounts.key service-accounts.crt root@server:~/ 

Remarques

  • Les certificats kube-proxy, kube-controller-manager, kube-scheduler et kubelet (client) serviront à générer les fichiers de configuration d'authentification dans un prochain TP.
  • En production, ces certificats doivent être traités comme des secrets sensibles (ils servent d'identifiants pour l'authentification mutuelle entre composants).
Génération des fichiers kubeconfig pour l'authentification

Fichiers kubeconfig

Un fichier kubeconfig (ou Kubernetes client configuration file) permet à un client (ex: kubelet, kubectl) de se connecter et de s'authentifier auprès du serveur d'API Kubernetes. Il regroupe trois informations essentielles :

  • cluster : le point de terminaison du serveur d'API et le certificat de l'autorité de certification (CA).
  • user : les certificats et clés du client (ou un token) pour l'authentification.
  • context : l'association d'un cluster, d'un utilisateur et éventuellement d'un namespace.

Commandes de génération

La commande kubectl config permet de construire un fichier kubeconfig. Les sous-commandes principales sont :

  • kubectl config set-cluster <nom> : définit le serveur (--server) et l'autorité de certification (--certificate-authority). L'option --embed-certs=true intègre directement le certificat CA dans le fichier (évite un chemin externe).
  • kubectl config set-credentials <nom> : associe un certificat client (--client-certificate) et sa clé (--client-key).
  • kubectl config set-context <nom> : lie un cluster et un utilisateur.
  • kubectl config use-context <nom> : définit le contexte courant (celui utilisé par défaut).

Chaque commande prend --kubeconfig=<fichier> pour écrire dans un fichier spécifique.

Exemple : fichier kubeconfig pour un nœud

kubectl config set-cluster kubernetes-the-hard-way \
  --certificate-authority=ca.crt \
  --embed-certs=true \
  --server=https://server.kubernetes.local:6443 \
  --kubeconfig=node-0.kubeconfig

kubectl config set-credentials system:node:node-0 \
  --client-certificate=node-0.crt \
  --client-key=node-0.key \
  --embed-certs=true \
  --kubeconfig=node-0.kubeconfig

kubectl config set-context default \
  --cluster=kubernetes-the-hard-way \
  --user=system:node:node-0 \
  --kubeconfig=node-0.kubeconfig

kubectl config use-context default \
  --kubeconfig=node-0.kubeconfig

Piège : le nom d’utilisateur pour un kubelet doit être system:node:<nom_du_noeud> pour que l’authentification soit correcte (via le Node Authorizer).

Fichiers kubeconfig par composant et distribution

Fichiers générés pour chaque composant

Chaque composant Kubernetes possède son propre fichier kubeconfig, avec un nom d’utilisateur et des certificats distincts.

  • kubelet (un par nœud) : fichier <nom_noeud>.kubeconfig, utilisateur system:node:<nom>.
  • kube-proxy : fichier kube-proxy.kubeconfig, utilisateur system:kube-proxy.
  • kube-controller-manager : fichier kube-controller-manager.kubeconfig, utilisateur system:kube-controller-manager.
  • kube-scheduler : fichier kube-scheduler.kubeconfig, utilisateur system:kube-scheduler.
  • admin : fichier admin.kubeconfig, utilisateur admin.

Tous ces fichiers sont générés avec les mêmes paramètres de cluster (--server=https://server.kubernetes.local:6443 ou https://127.0.0.1:6443 pour admin) et utilisent le même certificat CA (ca.crt).

Distribution des fichiers

Après génération, les fichiers sont copiés sur les machines correspondantes :

  • Nœuds workers (node-0, node-1) :

    • kube-proxy.kubeconfig/var/lib/kube-proxy/kubeconfig
    • <noeud>.kubeconfig/var/lib/kubelet/kubeconfig
    • Création préalable des répertoires /var/lib/kube-proxy et /var/lib/kubelet via SSH.
  • Serveur de contrôle (server) :

    • admin.kubeconfig, kube-controller-manager.kubeconfig, kube-scheduler.kubeconfig~/ (répertoire home de root).

Remarque : L’emplacement exact des fichiers kubeconfig est important car les services système les lisent depuis ces chemins par défaut.

Chiffrement au repos des Secrets : clé et configuration

Pourquoi chiffrer les données au repos ?

Kubernetes stocke de nombreuses données sensibles dans son stockage persistant (etcd), notamment les Secrets (mots de passe, tokens, clés privées). Le chiffrement au repos protège ces données en cas d’accès non autorisé à l’espace de stockage.

Génération d’une clé de chiffrement

Une clé de chiffrement est générée aléatoirement à l’aide de la commande suivante :

export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
  • head -c 32 /dev/urandom : lit 32 octets depuis le générateur de nombres aléatoires du noyau.
  • base64 : encode la clé en base64 pour pouvoir l’inclure dans un fichier YAML.

Fichier de configuration de chiffrement

Le fichier encryption-config.yaml est créé à partir d’un template (configs/encryption-config.yaml) en substituant la variable d’environnement ENCRYPTION_KEY :

envsubst < configs/encryption-config.yaml > encryption-config.yaml

Ce fichier YAML contient la configuration du fournisseur de chiffrement (par exemple aesgcm ou secretbox). Il est ensuite copié sur chaque instance du plan de contrôle :

scp encryption-config.yaml root@server:~/

Piège : Le fichier encryption-config.yaml doit être présent sur tous les serveurs API (control plane) pour que le chiffrement fonctionne. Il est souvent placé dans /etc/kubernetes/encryption-config.yaml (ici copié dans ~).

Rôle d'etcd dans Kubernetes

Rôle d'etcd dans Kubernetes

etcd est un magasin de données clé-valeur distribué et fiable. Dans Kubernetes, les composants sont stateless (sans état) : ils stockent l'état du cluster dans etcd. Cela inclut la configuration, les objets (pods, services, etc.) et l'état global du cluster.

  • etcd est un projet open source (github.com/etcd-io/etcd).
  • Un cluster etcd peut être composé d'un ou plusieurs nœuds ; dans ce tutoriel, on met en place un cluster à un seul nœud.
  • Chaque membre etcd doit avoir un nom unique au sein du cluster. Ici, le nom correspond au hostname de la machine (par exemple controller).

Piège : Ne pas confondre etcd avec la base de données interne de Kubernetes. etcd est un composant externe mais essentiel.

Installation et configuration d'etcd

Installation et configuration d'etcd

Les étapes pour installer et configurer etcd sur une machine (ici server) :

  1. Copie des binaires : Depuis une machine de contrôle, copier les fichiers etcd (serveur) et etcdctl (client) ainsi que le fichier d'unité systemd etcd.service vers le répertoire personnel de root sur le serveur.

    scp downloads/controller/etcd downloads/client/etcdctl units/etcd.service root@server:~/
    
  2. Installation des binaires : Déplacer etcd et etcdctl dans /usr/local/bin/.

    mv etcd etcdctl /usr/local/bin/
    
  3. Configuration des répertoires : Créer /etc/etcd (pour les certificats) et /var/lib/etcd (pour les données). Donner les droits 700 sur le répertoire de données.

    mkdir -p /etc/etcd /var/lib/etcd
    chmod 700 /var/lib/etcd
    
  4. Copie des certificats : Copier ca.crt, kube-api-server.key, kube-api-server.crt dans /etc/etcd/.

    cp ca.crt kube-api-server.key kube-api-server.crt /etc/etcd/
    
  5. Mise en place du service systemd : Déplacer le fichier etcd.service dans /etc/systemd/system/.

    mv etcd.service /etc/systemd/system/
    

Remarque : Chaque membre etcd doit avoir un nom unique. Ici, le nom est défini dans le fichier etcd.service (non détaillé dans la source, mais on sait qu'il correspond au hostname).

Démarrage et vérification d'etcd

Démarrage et vérification d'etcd

Après l'installation et la configuration, on démarre le service etcd.

Commandes systemd

systemctl daemon-reload      # Recharger la configuration systemd
systemctl enable etcd        # Activer le démarrage automatique au boot
systemctl start etcd         # Démarrer le service

Vérification

Utiliser etcdctl pour lister les membres du cluster :

etcdctl member list

Sortie typique (pour un cluster à un nœud) :

6702b0a34e2cfd39, started, controller, http://127.0.0.1:2380, http://127.0.0.1:2379, false
  • ID : 6702b0a34e2cfd39 (identifiant unique du membre)
  • Statut : started
  • Nom : controller (correspond au hostname)
  • URL pair : http://127.0.0.1:2380 (communication entre membres)
  • URL client : http://127.0.0.1:2379 (accès client)
  • Is learner : false (membre votant)

Piège : Ne pas oublier d'exécuter systemctl daemon-reload après avoir modifié les fichiers unités. Vérifier que le service est actif avec systemctl status etcd.

Vue d'ensemble du démarrage du plan de contrôle

Composants du plan de contrôle

Le plan de contrôle Kubernetes est constitué de trois composants principaux :

  • API Server (kube-apiserver) : expose l'API REST de Kubernetes.
  • Controller Manager (kube-controller-manager) : gère les contrôleurs intégrés.
  • Scheduler (kube-scheduler) : affecte les Pods aux nœuds.

Ces composants sont installés sur la machine server (le nœud maître).

Étapes générales

  1. Copier les binaires et les fichiers unités systemd depuis jumpbox vers server via scp.
  2. Connecter en SSH à server (ssh root@server).
  3. Créer le répertoire de configuration Kubernetes : /etc/kubernetes/config.
  4. Déplacer les binaires dans /usr/local/bin/.
  5. Configurer chaque composant : déplacer certificats, kubeconfigs, fichiers de configuration et fichiers unités systemd.
  6. Recharger systemd, activer et démarrer les services.
  7. Vérifier le bon fonctionnement avec kubectl cluster-info et curl.

Piège fréquent

Ne pas oublier d'attendre 10 secondes après le démarrage de l'API Server pour qu'il soit complètement initialisé. Utiliser systemctl is-active kube-apiserver pour vérifier.

Exemple concret

# Vérification de l'état du service après démarrage
systemctl is-active kube-apiserver
# Affiche 'active' si tout va bien.
Configuration des services du plan de contrôle

Répertoires et fichiers importants

  • /etc/kubernetes/config/ → contient la configuration du scheduler (kube-scheduler.yaml).
  • /var/lib/kubernetes/ → stocke les certificats, clés, kubeconfigs et le fichier de chiffrement (encryption-config.yaml).
  • /etc/systemd/system/ → contient les fichiers unités systemd des trois composants.

API Server (kube-apiserver.service)

  • Déplacer les certificats (ca.crt, ca.key, kube-api-server.key, kube-api-server.crt), les clés de service account, et encryption-config.yaml dans /var/lib/kubernetes/.
  • Le fichier unité systemd est copié directement dans /etc/systemd/system/.

Controller Manager (kube-controller-manager.service)

  • Déplacer son kubeconfig (kube-controller-manager.kubeconfig) dans /var/lib/kubernetes/.
  • Le fichier service systemd est déplacé dans /etc/systemd/system/.

Scheduler (kube-scheduler.service)

  • Déplacer son kubeconfig (kube-scheduler.kubeconfig) dans /var/lib/kubernetes/.
  • Déplacer son fichier de configuration YAML (kube-scheduler.yaml) dans /etc/kubernetes/config/.
  • Le fichier service systemd est déplacé dans /etc/systemd/system/.

Démarrage des services

systemctl daemon-reload
systemctl enable kube-apiserver kube-controller-manager kube-scheduler
systemctl start kube-apiserver kube-controller-manager kube-scheduler

Utiliser systemctl status pour un état détaillé et journalctl -u <service> pour consulter les logs.

RBAC pour l'autorisation Kubelet et vérification

RBAC pour l'autorisation Kubelet

Le mode d'autorisation du Kubelet est configuré sur Webhook. Ce mode utilise l'API SubjectAccessReview pour déterminer les autorisations.

Pour permettre à l'API Server d'accéder à l'API Kubelet (nécessaire pour récupérer métriques, logs et exécuter des commandes dans les Pods), on crée un ClusterRole nommé system:kube-apiserver-to-kubelet avec les permissions appropriées.

Commande :

kubectl apply -f kube-apiserver-to-kubelet.yaml --kubeconfig admin.kubeconfig

Le fichier kube-apiserver-to-kubelet.yaml est copié au préalable sur server.

Vérification du plan de contrôle

Depuis le jumpbox, on peut vérifier avec curl :

curl --cacert ca.crt https://server.kubernetes.local:6443/version

Cela retourne un JSON contenant la version de Kubernetes (ex: v1.32.3).

Depuis server, on utilise kubectl cluster-info --kubeconfig admin.kubeconfig :

Kubernetes control plane is running at https://127.0.0.1:6443

Piège fréquent

Ne pas oublier d'utiliser le bon kubeconfig (admin.kubeconfig) pour les commandes kubectl car le plan de contrôle n'est pas encore entièrement accessible sans authentification.

Vue d'ensemble du démarrage des nœuds workers

Composants installés

Les nœuds workers exécutent les conteneurs. Les composants suivants sont installés : runc, container networking plugins (CNI), containerd, kubelet et kube-proxy.

Étapes principales

  1. Copie des fichiers depuis le jumpbox vers chaque worker via scp.
  2. Installation des dépendances OS : socat, conntrack, ipset, kmod.
  3. Désactivation du swap (swapoff -a) car Kubernetes a un support limité du swap.
  4. Création des répertoires : /etc/cni/net.d, /opt/cni/bin, /var/lib/kubelet, /var/lib/kube-proxy, /var/lib/kubernetes, /var/run/kubernetes.
  5. Installation des binaires : déplacement de crictl, kube-proxy, kubelet, runc dans /usr/local/bin/ ; containerd, containerd-shim-runc-v2, containerd-stress dans /bin/ ; plugins CNI dans /opt/cni/bin/.
  6. Configuration du réseau CNI, containerd, kubelet et kube-proxy.
  7. Démarrage des services : containerd, kubelet, kube-proxy.
  8. Vérification : depuis le jumpbox, kubectl get nodes affiche les nœuds avec le statut Ready.
Configuration réseau et containerd

Configuration CNI

Les fichiers 10-bridge.conf et 99-loopback.conf sont déplacés dans /etc/cni/net.d/. Pour que le trafic réseau traversant le pont CNI soit traité par iptables, le module kernel br-netfilter est chargé (modprobe br-netfilter) et ajouté à /etc/modules-load.d/modules.conf. Les paramètres sysctl suivants sont appliqués :

  • net.bridge.bridge-nf-call-iptables = 1
  • net.bridge.bridge-nf-call-ip6tables = 1

Configuration containerd

Le répertoire /etc/containerd/ est créé. Le fichier containerd-config.toml est déplacé dans /etc/containerd/config.toml et le fichier containerd.service dans /etc/systemd/system/.

Configuration et démarrage de kubelet et kube-proxy

Configuration kubelet

Le fichier kubelet-config.yaml est déplacé dans /var/lib/kubelet/ et le fichier kubelet.service dans /etc/systemd/system/.

Configuration kube-proxy

Le fichier kube-proxy-config.yaml est déplacé dans /var/lib/kube-proxy/ et le fichier kube-proxy.service dans /etc/systemd/system/.

Démarrage des services

Après avoir déplacé tous les fichiers, on exécute :

systemctl daemon-reload
systemctl enable containerd kubelet kube-proxy
systemctl start containerd kubelet kube-proxy

L'état du kubelet peut être vérifié avec systemctl is-active kubelet (retourne active).

Vérification finale

Depuis le jumpbox, la commande kubectl get nodes --kubeconfig admin.kubeconfig liste les nœuds enregistrés avec leur statut, âge et version (ex: v1.32.3).

Configuration de kubectl pour l'accès distant

Objectif

Générer un fichier kubeconfig pour l'utilisateur admin afin d'utiliser kubectl depuis un poste de travail (jumpbox).

Étapes

  1. Vérifier l'API Server : curl --cacert ca.crt https://server.kubernetes.local:6443/version (retourne la version du serveur).
  2. Créer la configuration : Utiliser kubectl config pour définir le cluster, les credentials et le contexte.
    • kubectl config set-cluster kubernetes-the-hard-way --certificate-authority=ca.crt --embed-certs=true --server=https://server.kubernetes.local:6443
    • kubectl config set-credentials admin --client-certificate=admin.crt --client-key=admin.key
    • kubectl config set-context kubernetes-the-hard-way --cluster=kubernetes-the-hard-way --user=admin
    • kubectl config use-context kubernetes-the-hard-way
  3. Fichier généré : Le fichier kubeconfig est créé dans ~/.kube/config.

Vérification

  • kubectl version affiche les versions client et serveur (ex: Client Version: v1.32.3).
  • kubectl get nodes liste les nœuds du cluster (ex: node-0 et node-1 avec STATUS: Ready).

Piège : Ne pas oublier d'utiliser --embed-certs=true pour intégrer les certificats dans le fichier, sinon il faut les référencer séparément.

Routage réseau des Pods

Problème

Les Pods reçoivent une IP dans la plage CIDR de leur nœud. Sans routes, ils ne peuvent pas communiquer entre nœuds.

Solution

Ajouter des routes statiques sur chaque machine (server, node-0, node-1) pour mapper la plage CIDR d'un nœud à son adresse IP interne.

Commandes

D'abord, récupérer les adresses IP internes et les plages CIDR depuis un fichier machines.txt :

SERVER_IP=$(grep server machines.txt | cut -d " " -f 1)
NODE_0_IP=$(grep node-0 machines.txt | cut -d " " -f 1)
NODE_0_SUBNET=$(grep node-0 machines.txt | cut -d " " -f 4)
NODE_1_IP=$(grep node-1 machines.txt | cut -d " " -f 1)
NODE_1_SUBNET=$(grep node-1 machines.txt | cut -d " " -f 4)

Ensuite, sur chaque machine :

  • Server : ip route add ${NODE_0_SUBNET} via ${NODE_0_IP} et ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
  • Node-0 : ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
  • Node-1 : ip route add ${NODE_0_SUBNET} via ${NODE_0_IP}

Vérification

ip route affiche les routes. Exemple sur server : 10.200.0.0/24 via ... (CIDR de node-0) et 10.200.1.0/24 via ... (CIDR de node-1).

Piège : Les routes sont ajoutées via SSH sur chaque machine ; il faut exécuter les commandes sur les bonnes machines.

Tests de validation (Smoke Tests)

Objectif

Vérifier le bon fonctionnement du cluster Kubernetes.

Cryptage des données au repos

  1. Créer un secret : kubectl create secret generic kubernetes-the-hard-way --from-literal="mykey=mydata"
  2. Vérifier dans etcd : ssh root@server 'etcdctl get /registry/secrets/default/kubernetes-the-hard-way | hexdump -C'
    • La clé doit être préfixée par k8s:enc:aescbc:v1:key1 indiquant un chiffrement AES-CBC avec la clé key1.

Déploiements

  • Créer un déploiement nginx : kubectl create deployment nginx --image=nginx:latest
  • Lister les pods : kubectl get pods -l app=nginx

Port Forwarding

  • Récupérer le nom du pod : POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
  • Forwarder le port local 8080 vers le port 80 du pod : kubectl port-forward $POD_NAME 8080:80
  • Tester : curl --head http://127.0.0.1:8080 (réponse HTTP/1.1 200 OK)

Logs

  • kubectl logs $POD_NAME affiche les logs du conteneur (ex: requête HEAD).

Exec

  • kubectl exec -ti $POD_NAME -- nginx -v retourne la version de nginx (ex: nginx version: nginx/1.27.4).

Services

  • Exposer le déploiement via un service NodePort : kubectl expose deployment nginx --port 80 --type NodePort
  • Récupérer le NodePort : NODE_PORT=$(kubectl get svc nginx --output=jsonpath='{range .spec.ports[0]}{.nodePort}')
  • Récupérer le nom du nœud : NODE_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].spec.nodeName}")
  • Tester : curl -I http://${NODE_NAME}:${NODE_PORT}

Piège : Le type LoadBalancer n'est pas disponible car le cluster n'a pas d'intégration cloud provider.