Aller au contenu principal

Installer des clusters Kubernetes avec Kubeadm

Kubeadm est un outil conçu pour simplifier le déploiement de clusters Kubernetes sur vos serveurs. Il permet d'initialiser un cluster Kubernetes en quelques commandes seulement et assure la configuration de tous les composants nécessaires pour le faire fonctionner.

Introduction

Avec Kubeadm, vous pouvez créer des clusters vanilla avec une installation plus rapide et plus fiable. L'outil est extensible et adaptable, permettant aux administrateurs de personnaliser les configurations selon les besoins spécifiques de leur environnement. Kubeadm gère également la mise à jour et la configuration des clusters, ce qui simplifie grandement le processus d'administration continue.

L'objectif principal de ce guide est de fournir une vue d'ensemble complète de Kubeadm, en couvrant ses fonctionnalités principales, les concepts de base, les étapes d'installation et les meilleures pratiques pour installer et maintenir un cluster Kubernetes.

Historique de Kubeadm

Kubeadm a été introduit par la communauté Kubernetes pour répondre à la complexité croissante de l'installation et de la gestion des clusters Kubernetes. Avant Kubeadm, le déploiement de Kubernetes nécessitait de nombreuses étapes manuelles, une configuration complexe et une bonne compréhension des composants internes de Kubernetes. Cela rendait le processus non seulement fastidieux, mais aussi sujet aux erreurs, surtout pour les nouveaux utilisateurs.

L'outil Kubeadm a été lancé officiellement avec la version 1.6 de Kubernetes en 2017. Son objectif principal était de fournir une méthode simple, rapide et reproductible pour installer Kubernetes, sans pour autant compromettre la flexibilité et la robustesse des déploiements.

Avec chaque nouvelle version de Kubernetes, Kubeadm a été amélioré pour prendre en compte les changements de l'API de Kubernetes et en charge de nouvelles fonctionnalités et les changements de l'API de Kubernetes. Aujourd'hui, Kubeadm est largement utilisé dans les environnements de production, les environnements de test et par les développeurs souhaitant configurer des clusters Kubernetes sur leurs machines.

Fonctionnalités de Kubeadm

Kubeadm offre plusieurs fonctionnalités clés qui simplifient le déploiement et la gestion des clusters Kubernetes :

  • Initialisation du cluster : Configure automatiquement les composants critiques du plan de contrôle.
  • Ajout de nœuds : Génère des jetons d'adhésion sécurisés pour intégrer de nouveaux nœuds au cluster.
  • Gestion des mises à jour : Simplifie la mise à jour des composants du plan de contrôle et des nœuds de travail.
  • Gestion des certificats : Génère, renouvelle et distribue les certificats de sécurité nécessaires.
  • Configuration du réseau de pods : Supporte plusieurs plugins de réseau comme Calico et Flannel.
  • Support multi-plateforme : Compatible avec plusieurs systèmes d'exploitation et architectures matérielles.
  • Automatisation : S'intègre avec des outils comme Ansible, Terraform et des scripts bash pour automatiser les tâches d'administration.
  • Vérification de l'état du cluster : Fournit des outils pour diagnostiquer et vérifier l'état du cluster.

Prérequis

Avant de commencer avec Kubeadm, il est essentiel de s'assurer que votre environnement est correctement configuré pour supporter le déploiement et la gestion d'un cluster Kubernetes. Voici les prérequis nécessaires pour un déploiement réussi avec Kubeadm :

Infrastructure matérielle

Vous aurez besoin d'un ensemble de machines virtuelles ou physiques pour constituer les nœuds de votre cluster. Typiquement, un cluster Kubernetes comprend un nœud maître et plusieurs nœuds de travail. Voici les spécifications matérielles recommandées pour chaque type de nœud :

  • Nœud maître :

    • CPU : 2 cœurs minimum
    • Mémoire : 2 GB de RAM minimum
    • Stockage : 20 GB de disque
  • Nœud de travail :

    • CPU : 1 cœur minimum
    • Mémoire : 1 GB de RAM minimum
    • Stockage : 20 GB de disque

Dans mon cas je vais utiliser des machines virtuelles instanciées sur le cloud Ouitscale. Je vais utiliser 3 maîtres et 2 workers.

Système d'exploitation

Kubeadm supporte plusieurs distributions Linux. Voici quelques exemples courants :

  • Ubuntu 22.04+
  • Rocky Linux 8+
  • Debian 11+

Il est recommandé de maintenir votre système d'exploitation à jour avec les dernières mises à jour de sécurité.

Logiciels nécessaires

Avant d'installer Kubeadm, certains logiciels doivent être installés et configurés sur chaque nœud :

  1. Un runtime de conteneurs parmi :
  • containerd : Un runtime de conteneur léger et rapide, maintenu par la CNCF. Il est souvent utilisé comme runtime par défaut pour Kubernetes.
  • CRI-O : Un runtime de conteneur optimisé pour Kubernetes, conforme à l'interface CRI (Container Runtime Interface). Il est conçu pour fonctionner avec les pods Kubernetes de manière efficace et sécurisée.
  • Docker : Bien que Kubernetes ait déprécié l'utilisation directe de Docker en faveur de runtimes conformes à CRI, Docker peut toujours être utilisé comme runtime en conjonction avec un plugin CRI comme cri-dockerd.
  • gVisor : Un runtime de conteneur sécurisé développé par Google, qui offre une isolation renforcée des conteneurs.
  1. Kubeadm, Kubelet et Kubectl : Ces trois composants sont essentiels pour la gestion du cluster Kubernetes.

Configuration réseau

Kubernetes nécessite une configuration réseau correcte pour permettre la communication entre les nœuds. Assurez-vous que les ports suivants sont disponibles sur vos machines :

  • Port 6443 (kube-apiserver) sur le nœud maître
  • Ports 10250, 10251, 10252 (kubelet, scheduler, controller-manager) sur le nœud maître
  • Port 10250 (kubelet) sur les nœuds de travail
  • Port 179 (BGP) si vous l'utilisez

De plus, les nœuds doivent pouvoir communiquer entre eux sans restriction.

Accès utilisateur

Vous aurez besoin d'un accès root ou sudo sur toutes les machines pour exécuter les commandes nécessaires à l'installation et à la configuration de Kubernetes.

Synchronisation de l'heure

Il est crucial que toutes les machines du cluster aient des horloges synchronisées. Utilisez un service comme NTP ou Chrony (Network Time Protocol) pour assurer la synchronisation de l'heure.

Création des machines sur le cloud Outscale

Ici, je vais suivre une architecture similaire à celle utilisée pour provisionner des machines sur le cloud Outscale avec Terraform, en l'adaptant pour déployer un cluster Kubernetes avec Kubeadm.

Avant de commencer, assurez-vous d'avoir installé les outils nécessaires comme Terraform, Ansible et d'avoir également vos identifiants d'accès pour Outscale.

Définissez un VPC (Virtual Private Cloud) et des sous-réseaux pour isoler vos ressources cloud. Créer les 5 machines dans le subnet privé.

Pour plus de détails, vous pouvez consulter l'article original sur le provisionnement de machines avec Terraform sur Outscale.

Installation des prérequis

Pour installer Kubeadm, ainsi que Kubelet et Kubectl, nous devons d'abord installer et configurer containerd comme runtime de conteneur. containerd est une alternative légère et performante à Docker, souvent utilisée dans les environnements Kubernetes.

Pour faciliter et accélérer leur déploiement quoi de mieux que d'utiliser Packer et de créer une OMI.

Voici le contenu du playbook Ansible :

- name: Install soft for kubernetes VM
  become: true
  hosts: all
  vars:
    kubectl_version: "1.29.6-1.1"
    kube_version_full: "1.29.6-1.1"
    kube_version: "1.29"
    sysctl_config:
      net.ipv4.ip_forward: 1
      net.bridge.bridge-nf-call-ip6tables: 1
      net.bridge.bridge-nf-call-iptables: 1
  tasks:
    - name: Add Kubernetes GPG key | {{ inventory_hostname }}
      ansible.builtin.get_url:
        url: https://pkgs.k8s.io/core:/stable:/v{{ kube_version }}/deb/Release.key
        dest: /etc/apt/keyrings/kubernetes-apt-keyring.asc
        mode: '0644'
        force: true
    - name: Add Kubernetes repository | {{ inventory_hostname }}
      ansible.builtin.apt_repository:
        repo: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.asc] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /"
        state: present
        update_cache: true
    - name: Add Docker GPG key | {{ inventory_hostname }}
      ansible.builtin.apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
    - name: Add Docker repository | {{ inventory_hostname }}
      ansible.builtin.apt_repository:
        repo: deb https://download.docker.com/linux/ubuntu jammy stable
        state: present
        update_cache: true
    - name: Install packages | {{ inventory_hostname }}
      ansible.builtin.package:
        name:
          - gnupg2
          - software-properties-common
          - apt-transport-https
          - ca-certificates
          - kubelet={{ kube_version_full }}
          - kubeadm={{ kube_version_full }}
          - kubectl={{ kubectl_version }}
          - cri-tools
          - containerd.io
          - net-tools
          - chrony
        state: present
    - name: Hold version | {{ inventory_hostname }}
      ansible.builtin.dpkg_selections:
        name: "{{ item }}"
        selection: hold
      with_items:
        - kubeadm
        - kubelet
        - kubectl
    - name: Load modules overlay and br_netfilter
      community.general.modprobe:
        name: overlay
        state: present
      with_items:
        - overlay
        - br_netfilter
    - name: Load modprobe
      ansible.builtin.shell:
        cmd: modprobe {{ item }}
      with_items:
        - overlay
        - br_netfilter
    - name: Configure systctl
      ansible.posix.sysctl:
        name: "{{ item.key }}"
        value: "{{ item.value }}"
        state: present
        sysctl_file: /etc/sysctl.d/kubernetes.conf
      with_dict: '{{ sysctl_config }}'
    - name: Configure crictl tools config
      ansible.builtin.copy:
        src: files/crictl.yaml
        dest: /etc/
        owner: root
        group: root
        mode: 0644
    - name: Check swap State
      ansible.builtin.stat:
        path: /swap.img
      register: swap_file_check
    - name: Unmount swap | {{ inventory_hostname }}
      ansible.builtin.shell:
        cmd: swapoff -a
      when: ansible_swaptotal_mb > 0
    - name: Disable swap | {{ inventory_hostname }}
      ansible.builtin.lineinfile:
        path: /etc/fstab
        regexp: '\sswap\s+sw\s+'
        state: absent
      when: swap_file_check.stat.exists
    - name: Delete swap file
      ansible.builtin.file:
        path: /swap.img
        state: absent
      when: swap_file_check.stat.exists
    - name: Create containerd folder
      ansible.builtin.file:
        name: /etc/containerd/
        owner: root
        group: root
        mode: 0644
        state: directory
    - name: Create Container default config
      ansible.builtin.copy:
        src: files/config.toml
        dest: /etc/containerd/config.toml
        owner: root
        group: root
        mode: 0644
      notify: Restart containerd
  handlers:
    - name: Restart containerd
      ansible.builtin.service:
        name: containerd
        state: restarted

Le contenu des templates :

  • config.toml :

    disabled_plugins = []
    imports = []
    oom_score = 0
    plugin_dir = ""
    required_plugins = []
    root = "/var/lib/containerd"
    state = "/run/containerd"
    temp = ""
    version = 2
    
    [cgroup]
      path = ""
    
    [debug]
      address = ""
      format = ""
      gid = 0
      level = ""
      uid = 0
    
    [grpc]
      address = "/run/containerd/containerd.sock"
      gid = 0
      max_recv_message_size = 16777216
      max_send_message_size = 16777216
      tcp_address = ""
      tcp_tls_ca = ""
      tcp_tls_cert = ""
      tcp_tls_key = ""
      uid = 0
    
    [metrics]
      address = ""
      grpc_histogram = false
    
    [plugins]
    
      [plugins."io.containerd.gc.v1.scheduler"]
        deletion_threshold = 0
        mutation_threshold = 100
        pause_threshold = 0.02
        schedule_delay = "0s"
        startup_delay = "100ms"
    
      [plugins."io.containerd.grpc.v1.cri"]
        device_ownership_from_security_context = false
        disable_apparmor = false
        disable_cgroup = false
        disable_hugetlb_controller = true
        disable_proc_mount = false
        disable_tcp_service = true
        enable_selinux = false
        enable_tls_streaming = false
        enable_unprivileged_icmp = false
        enable_unprivileged_ports = false
        ignore_image_defined_volumes = false
        max_concurrent_downloads = 3
        max_container_log_line_size = 16384
        netns_mounts_under_state_dir = false
        restrict_oom_score_adj = false
        sandbox_image = "registry.k8s.io/pause:3.9"
        selinux_category_range = 1024
        stats_collect_period = 10
        stream_idle_timeout = "4h0m0s"
        stream_server_address = "127.0.0.1"
        stream_server_port = "0"
        systemd_cgroup = false
        tolerate_missing_hugetlb_controller = true
        unset_seccomp_profile = ""
    
        [plugins."io.containerd.grpc.v1.cri".cni]
          bin_dir = "/opt/cni/bin"
          conf_dir = "/etc/cni/net.d"
          conf_template = ""
          ip_pref = ""
          max_conf_num = 1
    
        [plugins."io.containerd.grpc.v1.cri".containerd]
          default_runtime_name = "runc"
          disable_snapshot_annotations = true
          discard_unpacked_layers = false
          ignore_rdt_not_enabled_errors = false
          no_pivot = false
          snapshotter = "overlayfs"
    
          [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
            base_runtime_spec = ""
            cni_conf_dir = ""
            cni_max_conf_num = 0
            container_annotations = []
            pod_annotations = []
            privileged_without_host_devices = false
            runtime_engine = ""
            runtime_path = ""
            runtime_root = ""
            runtime_type = ""
    
            [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
    
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
    
            [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
              base_runtime_spec = ""
              cni_conf_dir = ""
              cni_max_conf_num = 0
              container_annotations = []
              pod_annotations = []
              privileged_without_host_devices = false
              runtime_engine = ""
              runtime_path = ""
              runtime_root = ""
              runtime_type = "io.containerd.runc.v2"
    
              [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
                BinaryName = ""
                CriuImagePath = ""
                CriuPath = ""
                CriuWorkPath = ""
                IoGid = 0
                IoUid = 0
                NoNewKeyring = false
                NoPivotRoot = false
                Root = ""
                ShimCgroup = ""
                SystemdCgroup = true
    
          [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
            base_runtime_spec = ""
            cni_conf_dir = ""
            cni_max_conf_num = 0
            container_annotations = []
            pod_annotations = []
            privileged_without_host_devices = false
            runtime_engine = ""
            runtime_path = ""
            runtime_root = ""
            runtime_type = ""
    
            [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
    
        [plugins."io.containerd.grpc.v1.cri".image_decryption]
          key_model = "node"
    
        [plugins."io.containerd.grpc.v1.cri".registry]
          config_path = ""
    
          [plugins."io.containerd.grpc.v1.cri".registry.auths]
    
          [plugins."io.containerd.grpc.v1.cri".registry.configs]
    
          [plugins."io.containerd.grpc.v1.cri".registry.headers]
    
          [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    
        [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
          tls_cert_file = ""
          tls_key_file = ""
    
      [plugins."io.containerd.internal.v1.opt"]
        path = "/opt/containerd"
    
      [plugins."io.containerd.internal.v1.restart"]
        interval = "10s"
    
      [plugins."io.containerd.internal.v1.tracing"]
        sampling_ratio = 1.0
        service_name = "containerd"
    
      [plugins."io.containerd.metadata.v1.bolt"]
        content_sharing_policy = "shared"
    
      [plugins."io.containerd.monitor.v1.cgroups"]
        no_prometheus = false
    
      [plugins."io.containerd.runtime.v1.linux"]
        no_shim = false
        runtime = "runc"
        runtime_root = ""
        shim = "containerd-shim"
        shim_debug = false
    
      [plugins."io.containerd.runtime.v2.task"]
        platforms = ["linux/amd64"]
        sched_core = false
    
      [plugins."io.containerd.service.v1.diff-service"]
        default = ["walking"]
    
      [plugins."io.containerd.service.v1.tasks-service"]
        rdt_config_file = ""
    
      [plugins."io.containerd.snapshotter.v1.aufs"]
        root_path = ""
    
      [plugins."io.containerd.snapshotter.v1.btrfs"]
        root_path = ""
    
      [plugins."io.containerd.snapshotter.v1.devmapper"]
        async_remove = false
        base_image_size = ""
        discard_blocks = false
        fs_options = ""
        fs_type = ""
        pool_name = ""
        root_path = ""
    
      [plugins."io.containerd.snapshotter.v1.native"]
        root_path = ""
    
      [plugins."io.containerd.snapshotter.v1.overlayfs"]
        root_path = ""
        upperdir_label = false
    
      [plugins."io.containerd.snapshotter.v1.zfs"]
        root_path = ""
    
      [plugins."io.containerd.tracing.processor.v1.otlp"]
        endpoint = ""
        insecure = false
        protocol = ""
    
    [proxy_plugins]
    
    [stream_processors]
    
      [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
        accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
        args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
        env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
        path = "ctd-decoder"
        returns = "application/vnd.oci.image.layer.v1.tar"
    
      [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
        accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
        args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
        env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
        path = "ctd-decoder"
        returns = "application/vnd.oci.image.layer.v1.tar+gzip"
    
    [timeouts]
      "io.containerd.timeout.bolt.open" = "0s"
      "io.containerd.timeout.shim.cleanup" = "5s"
      "io.containerd.timeout.shim.load" = "5s"
      "io.containerd.timeout.shim.shutdown" = "3s"
      "io.containerd.timeout.task.state" = "2s"
    
    [ttrpc]
      address = ""
      gid = 0
      uid = 0
    
  • circtl.yml :

    runtime-endpoint: unix:///run/containerd/containerd.sock
    image-endpoint: unix:///run/containerd/containerd.sock
    timeout: 2
    debug: false
    pull-image-on-create: false
    

Il faudrait encore ajouter quelques variables et le coupler avec un outil de gestion des dépendances comme Renovate pour automatiser la production d'images.

Initialisation d'un cluster

Sur le premier nœud maître, exécutez la commande suivante pour initialiser le cluster :

sudo kubeadm init --pod-network-cidr=192.168.0.0/16

Cette commande initialise un cluster Kubernetes et configure les composants du plan de contrôle.

Pour permettre à l'utilisateur non-root d'accéder au cluster, exécutez les commandes suivantes sur votre machine (dans mon cas c'est mon bastion) :

mkdir -p $HOME/.kube
sudo scp -i <MASTER_IP>:/etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Ajout de nœuds au cluster

Pour ajouter des nœuds masters supplémentaires au cluster, utilisez le jeton d'adhésion fourni par Kubeadm lors de l'initialisation. Exécutez cette commande sur chaque nœud master :

kubeadm join <MASTER_IP>:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH> --control-plane

Pour ajouter des nœuds workers supplémentaires au cluster, utilisez le jeton d'adhésion fourni par Kubeadm lors de l'initialisation. Exécutez cette commande sur chaque nœud worker :

sudo kubeadm join <MASTER_IP>:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>

Remplacez <MASTER_IP>, <TOKEN>, et <HASH> par les valeurs retourner par la commande kubeadm init.

Déploiement d'un réseau de pods

Le réseau de pods est essentiel pour permettre la communication entre les différents nœuds d'un cluster Kubernetes. Sans un réseau de pods configuré, les pods sur différents nœuds ne pourront pas communiquer entre eux. Il existe plusieurs solutions de réseaux de pods disponibles pour Kubernetes, comme Calico, Flannel, Weave Net, et Canal. Ici je vais utiliser Cillium :

helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --version 1.15.6   --namespace kube-system

Vérification du cluster

Après avoir ajouté tous les nœuds, vous pouvez vérifier que votre cluster est opérationnel en utilisant la commande suivante depuis la machine bastion :

kubectl get nodes
NAME                   STATUS   ROLES           AGE   VERSION
master-a1.test.local   Ready    control-plane   29h   v1.29.6
master-a2.test.local   Ready    control-plane   29h   v1.29.6
master-a3.test.local   Ready    control-plane   29h   v1.29.6
worker-a1.test.local   Ready    <none>          29h   v1.29.6

Vous devriez voir une liste de tous les nœuds de votre cluster avec leur statut.

Vérifiez également que tous les pods du namespace kube-system tournent de manière normale (pas trop d'arrêt/relance) :

kubectl get pods -n kube-system
NAME                                           READY   STATUS    RESTARTS      AGE
cilium-685xt                                   1/1     Running   1 (29h ago)   29h
cilium-7sg7d                                   1/1     Running   1 (29h ago)   29h
cilium-operator-7b4db5848b-jb27r               1/1     Running   1 (29h ago)   29h
cilium-operator-7b4db5848b-jkkx6               1/1     Running   2 (29h ago)   29h
cilium-p86t8                                   1/1     Running   1 (29h ago)   29h
cilium-shzzt                                   1/1     Running   1 (29h ago)   29h
coredns-76f75df574-5v8sw                       1/1     Running   0             29h
coredns-76f75df574-x5q6p                       1/1     Running   0             29h
etcd-master-a1.test.local                      1/1     Running   5 (29h ago)   29h
etcd-master-a2.test.local                      1/1     Running   1 (29h ago)   29h
etcd-master-a3.test.local                      1/1     Running   1 (29h ago)   29h
kube-apiserver-master-a1.test.local            1/1     Running   7 (29h ago)   29h
kube-apiserver-master-a2.test.local            1/1     Running   1 (29h ago)   29h
kube-apiserver-master-a3.test.local            1/1     Running   2 (29h ago)   29h
kube-controller-manager-master-a1.test.local   1/1     Running   4 (29h ago)   29h
kube-controller-manager-master-a2.test.local   1/1     Running   1 (29h ago)   29h
kube-controller-manager-master-a3.test.local   1/1     Running   1 (29h ago)   29h
kube-proxy-2sz8l                               1/1     Running   1 (29h ago)   29h
kube-proxy-8pcfp                               1/1     Running   1 (29h ago)   29h
kube-proxy-8w2tf                               1/1     Running   1 (29h ago)   29h
kube-proxy-q42zt                               1/1     Running   1 (29h ago)   29h
kube-scheduler-master-a1.test.local            1/1     Running   6 (29h ago)   29h
kube-scheduler-master-a2.test.local            1/1     Running   1 (29h ago)   29h
kube-scheduler-master-a3.test.local            1/1     Running   1 (29h ago)   29h

À partir de ce moment, vous pouvez commencer à déployer des applications sur votre cluster Kubernetes.

Mise à jour et gestion du cluster

Une gestion efficace et des mises à jour régulières sont essentielles pour maintenir un cluster Kubernetes sécurisé, performant et fiable. Kubeadm simplifie ces processus en fournissant des outils et des commandes pour gérer les mises à jour de Kubernetes et assurer une administration continue du cluster.

important

Cette procédure doit être maitrisée, je vous conseille donc de la répéter sur des clusters de test.

Mise à jour du plan de contrôle

La mise à jour du plan de contrôle est une étape critique lors de la mise à jour de votre cluster Kubernetes. Cela inclut la mise à jour de l'API Server, du Controller Manager et du Scheduler.

Avant de commencer, vérifiez la version actuelle de Kubernetes :

kubectl version
Client Version: v1.29.6
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.29.6

Contrôler ensuite les versions disponibles :

sudo apt-cache madison kubeadm
   kubeadm | 1.29.6-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.5-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.4-2.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.3-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.2-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.1-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages
   kubeadm | 1.29.0-1.1 | https://pkgs.k8s.io/core:/stable:/v1.29/deb  Packages

Il faut ensuite releaser le package kubeadm et kubelet :

sudo apt-mark unhold kubeadm && \
sudo apt-get update && sudo apt-get install -y kubeadm='1.29.x-y.y' && \
sudo apt-mark hold kubeadm

Kubeadm offre une commande pour planifier la mise à jour et vérifier les versions disponibles :

sudo kubeadm upgrade plan

Cette commande affiche les versions disponibles et vérifie la compatibilité avec les composants actuels du cluster.

Pour appliquer la mise à jour, utilisez la commande suivante en remplaçant vX.Y.Z par la version cible de Kubernetes :

sudo kubeadm upgrade apply vX.Y.Z

Cette commande met à jour les composants du plan de contrôle. Il faut procéder de la même manière pour kubelet.

Après l'exécution, redémarrez les composants pour appliquer les changements :

sudo systemctl restart kubelet

Vérifiez que les composants du plan de contrôle sont à jour :

kubectl get nodes
kubectl get pods -n kube-system

Il faudra répéter cette procédure sur les autres nœuds masters, mais au lieu d'utiliser la commande sudo kubeadm upgrade apply il faudra utiliser la commande suivante :

sudo kubeadm upgrade apply

Mise à jour des nœuds de travail (workers)

Après la mise à jour du plan de contrôle, mettez à jour les nœuds de travail pour assurer la compatibilité avec la nouvelle version du cluster.

Pour éviter les interruptions de service, drainez chaque nœud de travail avant la mise à jour. Le drainage évacue tous les pods en cours d'exécution sur le nœud :

kubectl drain <node-name> --ignore-daemonsets

Sur chaque nœud de travail, mettez à jour kubelet et kubectl :

sudo apt-get update
sudo apt-get install -y kubelet kubectl
sudo apt-mark hold kubelet kubectl

Redémarrez le service kubelet pour appliquer la mise à jour :

sudo systemctl restart kubelet

Une fois le nœud mis à jour, annulez le drainage pour rendre le nœud à nouveau disponible pour les pods :

kubectl uncordon <node-name>

Surveillance du cluster

La surveillance continue est essentielle pour assurer la santé du cluster. Utilisez des outils comme Prometheus et Grafana pour surveiller les performances et les métriques du cluster.

Sauvegarde et restauration

Assurez-vous d'avoir des stratégies de sauvegarde et de restauration en place pour protéger les données de votre cluster.

Sauvegarde des etcd

etcd stocke les données de l'état du cluster. Sauvegardez régulièrement les données d'etcd :

ETCDCTL_API=3 etcdctl snapshot save snapshot.db

Stockez ensuite la sauvegarde sur un bucket S3.

Restauration des etcd

Pour restaurer une sauvegarde, utilisez la commande suivante :

ETCDCTL_API=3 etcdctl snapshot restore snapshot.db

Rotation des certificats

Kubernetes utilise des certificats pour sécuriser la communication. Assurez-vous que les certificats sont renouvelés avant leur expiration.

Vérification des certificats

Vérifiez la validité des certificats avec la commande suivante :

kubectl get csr

Renouvellement des certificats

Renouvelez les certificats si nécessaire :

sudo kubeadm alpha certs renew all

Nettoyage du cluster

Maintenez votre cluster propre en supprimant régulièrement les ressources inutilisées.

Suppression des pods orphelins

Listez et supprimez les pods orphelins ou en échec :

kubectl get pods --all-namespaces --field-selector=status.phase=Failed
kubectl delete pod <pod-name> --namespace=<namespace>

En suivant ces pratiques, vous pouvez assurer une gestion efficace et des mises à jour régulières de votre cluster Kubernetes, garantissant ainsi sa stabilité et sa sécurité.

Conclusion

En conclusion, Kubeadm est un outil puissant et indispensable pour simplifier le déploiement et la gestion des clusters Kubernetes. Grâce à ses fonctionnalités robustes et à son intégration étroite avec Kubernetes, Kubeadm facilite la mise en place de clusters de production fiables et performants.

La gestion continue de votre cluster Kubernetes est cruciale pour garantir sa performance, sa sécurité et sa fiabilité. Les mises à jour régulières, la surveillance active, la sauvegarde des données et la rotation des certificats sont autant de pratiques essentielles pour maintenir un environnement Kubernetes optimal.

Plus d'infos

Pour approfondir vos connaissances et rester à jour avec les meilleures pratiques, je vous recommande de consulter les ressources suivantes :

  • Documentation officielle de Kubernetes : La documentation officielle est une source complète et à jour pour toutes les fonctionnalités et configurations de Kubernetes. Consulter la documentation
  • Projets GitHub : Les dépôts GitHub des projets Kubernetes et Kubeadm offrent un accès direct au code source et aux discussions de la communauté. Consulter le projet Kubeadm
  • Communauté Kubernetes : Participer aux forums, aux groupes de discussion et aux événements de la communauté Kubernetes peut vous fournir des informations précieuses et des opportunités de collaboration avec d'autres professionnels.