Rancher – mise à jour des modules (k3s, rke2, longhorn, cert-manager, calico)

Pour des erreurs qui s’accumuleraient tel que des éléments d’API disparus, révoqués ou obsolètes ou d’autres bugs concernant des versions intermédiaires, je vous conseille fortement d’effectuer vos mises à jour régulièrement (une fois par mois au minimum).

En cas de gros problème (node NotReady par exemple), redémarrez tout simplement votre serveur (c’est moche mais c’est comme ça).

Vérification du noeud

Il faut absolument que la commande ci-dessous renvoie « Ready » dans la colonne STATUS :

kubectl get node
NAME       STATUS   ROLES                  AGE     VERSION
ns1        Ready    control-plane,master   3y77d   v1.26.10+k3s2

Si vous ne voyez pas votre cluster à l’état Ready, il vous faudra résoudre le problème, soit en relançant k3s (ou rke ou kubelet) soit en redémarrant votre serveur soit en faisant un describe sur le noeud pour comprendre d’où vient le problème :

kubectl describe node

Mise à jour de K3s

Avant de mettre à jour K3S, vérifiez la matrice de compatibilité sur : https://www.suse.com/fr-fr/suse-rancher/support-matrix/all-supported-versions/rancher-v2-8-4/ en adaptant le lien à la version de Rancher que vous souhaitez installer.

Lors des mises à jour, vous retrouverez les logs soit au format syslog (si système compatible) donc dans /var/log/syslog ou via journalctl -f -u k3s soit dans /var/log/k3s.log. Les logs sont configurables via des options k3s.

Pour mettre à jour k3s, il suffit de récupérer les paramètres de votre cluster k3s sur votre master ou agent en allant les récupérer dans /etc/systemd/system/k3s.service et de refaire un curl sur get.k3s.io. Par exemple, dans mon k3s installé en mode « External DB » sous postgresql :

ExecStart=/usr/local/bin/k3s \
    server \
        '--datastore-endpoint=postgres://k3s:[email protected]:5432/k3s' \
        --flannel-backend=none \
        --disable-network-policy \

Ainsi, il faudra lancer la commande :

curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.26.0+k3s1 sh -s - server --datastore-endpoint='postgres://k3s:[email protected]:5432/k3s' --flannel-backend=none  --disable-network-policy

Pour trouver la version de k3s exacte, vous pouvez jeter un œil sur le git officiel. N’oubliez pas d’utiliser une version compatible avec la version de rancher souhaitée.

Mise à jour de RKE2

Avant de procéder à la mise à jour de RKE2, assurez-vous de vérifier la compatibilité des versions via la matrice officielle : SUSE Rancher Support Matrix pour garantir que la version cible est compatible avec vos autres composants.

Étapes préliminaires

Avant toute mise à jour, il est recommandé de sauvegarder les données critiques de votre cluster, en particulier si vous utilisez etcd comme backend de stockage. De plus, il est essentiel de consulter les logs pour identifier les éventuelles erreurs durant la mise à jour. Les logs RKE2 peuvent être visualisés via :

journalctl -f -u rke2-server

ou dans /var/log/syslog selon votre configuration.

Mise à jour du service RKE2

Pour mettre à jour RKE2 à la version souhaitée, suivez ces étapes :

Arrêter proprement RKE2 :
Avant de lancer la mise à jour, il est nécessaire d’arrêter le service RKE2 pour éviter les conflits :

   sudo systemctl stop rke2-server
   sudo systemctl stop containerd

Télécharger et installer la nouvelle version :
Téléchargez la version désirée en exécutant la commande suivante, en remplaçant v1.30.4+rke2r1 par la version cible en root :

sudo curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=v1.30.4+rke2r1 sh -

Redémarrer RKE2 :
Une fois la mise à jour effectuée, redémarrez le service RKE2 :

   sudo systemctl start rke2-server

Vérification post-mise à jour :
Après redémarrage, vérifiez que le service RKE2 fonctionne correctement et que les nœuds et les Pods sont en bon état :

   kubectl get nodes
   kubectl get pods -A

Logs de mise à jour

Lors du processus de mise à jour, vous pouvez suivre les logs détaillés du service avec :

journalctl -u rke2-server -xe

Une fois la mise à jour terminée, assurez-vous que tout fonctionne correctement en validant le statut des composants critiques du cluster. Pour plus d’informations sur les versions disponibles et les correctifs, consultez le GitHub officiel de RKE2.

Mise à jour de Rancher

Avant toute mise à jour, il faut bien s’assurer de la compatibilité de Rancher avec votre cluster (version de kubernetes, etc.), lien à adapter en fonction de la version de la Rancher à installer (v2.9.2 dans notre cas) : https://www.suse.com/suse-rancher/support-matrix/all-supported-versions/rancher-v2-9-2/

De la même manière, on va récupérer les valeurs actuelles de votre déploiement Rancher via la commande :

helm repo update
helm fetch rancher-stable/rancher
# Pour voir les versions disponibles dans le repo helm en question :
helm search repo rancher-stable/rancher --versions
helm get values rancher -n cattle-system > values.yaml

On modifie le fichier en question pour enlever la première ligne (« USER-SUPPLIED VALUES: »).
Puis on lance l’upgrade :

helm upgrade rancher rancher-stable/rancher --namespace cattle-system -f values.yaml

Exemple de fichier values :

hostname: rancher.pascal-mietlicki.fr
ingress:
  tls:
    source: letsEncrypt
letsEncrypt:
  email: [email protected]

Pour « scaler » le deployment de rancher à 1 au lieu des 4 instances par défaut, vous pouvez utiliser la commande :

kubectl scale deployment/rancher --replicas=1 -n cattle-system

Pour basculer sur le namespace cattle-system par défaut, vous pouvez utiliser la commande :

kubectl config set-context --current --namespace=cattle-system

Ou encore plus simple en utilisant kubens :

kubens cattle-system

Mise à jour de Longhorn

Vous pouvez soit faire l’upgrade avec helm soit avec kubectl si vous avez des problèmes lors du déploiement, il vaut mieux effectuer les mises à jour intermédiaires (1.4.1 puis 1.4.X puis 1.5.0 puis 1.5.3 par exemple) :

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.7.1/deploy/longhorn.yaml

Avec helm :

helm repo upgrade
helm upgrade longhorn longhorn/longhorn --namespace longhorn-system --version 1.7.1

Pour information, si vous avez des problèmes, la KB longhorn est très complète.

Mise à jour de Cert-manager

Pour connaître la version actuellement installée, vous pouvez taper :

kubectl describe deployment -n cert-manager cert-manager

Vous pourrez alors voir la version dans la partie controller :

 Containers:
   cert-manager-controller:
    Image:       quay.io/jetstack/cert-manager-controller:v1.15.3

Vous pouvez soit faire l’upgrade avec helm soit avec kubectl si vous avez des problèmes lors du déploiement, il vaut mieux effectuer les mises à jour intermédiaires comme pour longhorn. Pour ma part, cela a été indispensable (v1.0.4 puis v1.1.1, etc.).

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.crds.yaml
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.yaml

Avec helm :

helm repo upgrade
helm upgrade cert-manager jetstack/cert-manager --namespace cert-manager --version 1.15.0 --reset-then-reuse-values

MariaDB en master / slave

Cela n’a pas de lien direct avec les mises à jour mais ce sont des commandes utiles pour vérifier que votre slave est bien synchronisé avec le master.

Sur le slave, vérifiez l’état avec :

mysql
SHOW SLAVE STATUS
# En plus synthétique
SHOW SLAVE STATUS \G

Si on voit le « Read_Master_Log_Pos » évoluer (s’incrémenter), cela indique que la synchronisation se déroule correctement. Il faut aussi que le « Seconds_Behind_Master » soit le plus proche de 0.

Pour forcer une resynchronisation, on peut redémarrer le slave :

mysql
STOP SLAVE
START SLAVE

Forcer une synchronisation

Si le slave est très éloigné du master, on peut via mysqldump, remettre le slave d’aplomb.

Pour effectuer une synchronisation manuelle d’un slave MySQL avec un master, voici les commandes pour chaque étape :

  1. Arrêter le Slave : mysqladmin -u root -p shutdown
  2. Créer un Dump sur le Master et le Copier vers le Nœud Local :
    • Créez le dump sur le pod master : kubectl exec <pod-master-mysql> -- mysqldump -u root -p --all-databases --master-data > master_dump.sql
    • Copiez le dump du pod master vers votre machine locale : kubectl cp <namespace>/<pod-master-mysql>:/path/to/master_dump.sql ./master_dump.sql
  3. Copier le Dump du Nœud Local vers le Slave :
    • Copiez le dump de votre machine locale vers le pod slave : kubectl cp ./master_dump.sql <namespace>/<pod-slave-mysql>:/path/to/
  4. Restaurer sur le Slave : mysql -u root -p < master_dump.sql
  5. Configurer et Démarrer le Slave : Configurez le slave avec les informations de position de log obtenues du dump, puis redémarrez MySQL. CHANGE MASTER TO MASTER_LOG_FILE='fichier_log', MASTER_LOG_POS=position_log; START SLAVE;

Pour connaître le MASTER_LOG_FILE et le MASTER_LOG_POS lors de la restauration d’un slave MySQL, vous pouvez les obtenir à partir du dump du master. Lorsque vous effectuez le mysqldump avec l’option --master-data, le fichier de dump inclura des commentaires indiquant le fichier de log binaire (MASTER_LOG_FILE) et la position dans ce fichier (MASTER_LOG_POS). Ces informations sont utilisées pour configurer le slave afin qu’il commence la réplication à partir du bon point dans le log binaire du master.

Troubleshoot

J’ai eu divers soucis lors des différentes mises à jour que ce soit avec k3s, rancher ou cert-manager. Si vous avez vraiment un gros souci avec un cluster qui n’est pas à l’état Ready ou qui ne se stabilise jamais, dans le doute, on reboot.

Étapes pour la Résolution de Problèmes

La gestion d’un cluster Kubernetes peut être une tâche complexe, mais avec les bonnes étapes et astuces de résolution de problèmes, vous pouvez rapidement identifier et résoudre les problèmes qui se posent.

  1. Identification du Problème :
    • La première étape de la résolution de problèmes consiste à identifier le problème. Il peut s’agir de pods en échec, d’erreurs de réseau, de problèmes de performances, etc. Utilisez des outils tels que kubectl get et kubectl describe pour obtenir des informations sur les ressources en cause.
  2. Collecte d’Informations :
    • Une fois le problème identifié, collectez des informations supplémentaires telles que les journaux des pods, les événements du cluster, les métriques, etc. Cela vous aidera à mieux comprendre la cause sous-jacente.
  3. Analyse des Journaux :
    • Les journaux système avec journalctl -u k3s ou tail -f /var/log/syslog
    • Les journaux des pods sont une source précieuse d’informations. Utilisez la commande kubectl logs pour afficher les journaux des pods en échec et recherchez des messages d’erreur ou des indicateurs de problème.
  4. Vérification des Événements :
    • Exécutez la commande kubectl get events pour afficher les événements du cluster. Cela peut révéler des erreurs ou des avertissements liés au problème.
  5. Vérification de la Configuration :
    • Assurez-vous que la configuration de votre cluster, des pods et des services est correcte. Les problèmes de configuration sont courants et peuvent provoquer des dysfonctionnements.
  6. Exécution de Diagnostics :
    • Utilisez des outils de diagnostic tels que kubectl describe et kubectl exec pour examiner l’état des pods en direct et exécuter des commandes de débogage.

Problème unable to recognize «  »: no matches for kind « Issuer » in version « cert-manager.io/v1beta1 » lors de l’upgrade avec helm

Dans ce cas, c’est lié à un de vos secrets intitulé sh.helm.release.v1.rancher.v* qui contient des références vers un élément d’API obsolète. Pour résoudre le problème, vous pouvez suivre les instructions disponibles sur ce site.

Problème « no endpoints available for service « rancher-webhook »

J’ai donc dû forcer la rotation des webhooks : https://github.com/rancher/rancher/issues/35068#issuecomment-954457381

kubectl get validatingwebhookconfiguration rancher.cattle.io -o yaml > vwc-rancher.cattle.io.yaml
kubectl get mutatingwebhookconfiguration rancher.cattle.io -o yaml > mwc-rancher.cattle.io.yaml
kubectl delete validatingwebhookconfiguration rancher.cattle.io
kubectl delete mutatingwebhookconfiguration rancher.cattle.io

Puis lorsque le webhook est de nouveau « healthy » :

kubectl apply -f vwc-rancher.cattle.io.yaml
kubectl apply -f mwc-rancher.cattle.io.yaml

Problème coredns « 8.8.8.8:53: i/o timeout » et pas de connectivité externe dans les pods

Le problème venait de flannel, même en ajoutant toutes les options possibles que ce soit dans iptables ou en désactivant le checksum via ethtool sur l’interface flannel.1 ou cni0 (ethtool -K flannel.1 tx-checksum-ip-generic off), rien n’a résolu le problème. Je crois que cela vient d’une incompatibilité avec un kernel Linux trop ancien. Un tcpdump -i any port 53 renvoyait des « ServFail » et je ne voyais rien passer dans l’interface flannel.1.

Passage à calico

J’ai ajouté les options « –flannel-backend=none –disable-network-policy » dans les options de démarrage de k3s (/etc/systemd/system/k3s.service) puis :

systemctl daemon-reload
systemctl restart k3s

Puis on peut suivre le quickstart : https://projectcalico.docs.tigera.io/getting-started/kubernetes/k3s/quickstart

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/custom-resources.yaml

Puis modifier le configmap « cni-config » du namespace « calico-system » en mettant :

"container_settings": { 
"allow_ip_forwarding": true 
}

Pour ce faire, vous avez la commande kubectl edit configmap cni-config -n calico-system.

Mise à jour de calico

Vous pouvez utiliser kubectl replace -f au lieu de create, par exemple :

kubectl replace -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml
kubectl replace -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml

Problème calico, ip_forwarding repasse à false systématiquement

Pour résoudre définitivement le problème, vous pouvez modifier et appliquer le custom-resources.yaml modifié en intégrant l’option containerIPForwarding : « Enabled ».

wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml

# This section includes base Calico installation configuration.
# For more information, see: https://projectcalico.docs.tigera.io/v3.23/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    # Note: The ipPools section cannot be modified post-install.
    ipPools:
    - blockSize: 26
      cidr: 192.168.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()
    containerIPForwarding: "Enabled"

---

# This section configures the Calico API server.
# For more information, see: https://projectcalico.docs.tigera.io/v3.23/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer 
metadata: 
  name: default 
spec: {}

Puis l’appliquer en faisant :

kubectl apply -f custom-resources.yaml

Longhorn : suppression de ressources bloquées

J’ai eu des blocages sur les composants csi du deployment longhorn dans le namespace longhorn-system. En regardant de plus près, j’avais ce finalizer sur les composants csi (attacher, provisioner, resizer et snapshotter) :

finalizers:
  - foregroundDeletion

Le finalizer foregroundDeletion est utilisé dans Kubernetes pour indiquer qu’une ressource doit être supprimée de manière prioritaire avant la suppression de l’objet parent. Malheureusement, l’état global des ressources étant devenu incohérent faisait que la suppression n’aboutissait jamais.

J’ai donc « patché » les finalizers de cette manière :

kubectl patch deployment/csi-attacher -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl patch deployment/csi-provisioner -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl patch deployment/csi-resizer -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl patch deployment/csi-snapshotter -p '{"metadata":{"finalizers":[]}}' --type=merge

Cela a permis d’exécuter les suppressions correctement et de retrouver un état cohérent.