Que faire si les certificats sont pourris et que le cluster se transforme en citrouille?

Si en réponse à la commande kubectl get pod vous obtenez:

 Unable to connect to the server: x509: certificate has expired or is not yet valid 

puis, très probablement, une année s'est écoulée, vos certificats kubernetes ont expiré, les composants du cluster ont cessé de les utiliser, l'interaction entre eux s'est arrêtée et votre cluster s'est transformé en citrouille.

image

Que faire et comment restaurer un cluster?

Tout d'abord, nous devons comprendre où se trouvent les certificats qui doivent être mis à jour.

Selon la façon dont le cluster a été installé, l'emplacement et le nom des fichiers de certificat peuvent varier. Ainsi, par exemple, lors de la création d'un cluster, Kubeadm décompose les fichiers de certificat selon les meilleures pratiques . Ainsi, tous les certificats se trouvent dans le /etc/kuberenetes/pki , dans les fichiers portant l'extension .crt , les clés privées, respectivement, dans les fichiers .key . De plus, dans /etc/kubernetes/ trouvent des fichiers .conf avec une configuration d'accès pour l'administrateur des comptes d'utilisateurs, le contrôleur de gestion, le sheduler et le kubelet à partir du nœud maître. Les certificats dans les fichiers .conf se trouvent dans le champ user.client-certificate-data au format codé en base64.

Vous pouvez consulter la date d'expiration à laquelle il a été délivré et par qui le certificat a été signé à l'aide de ce petit script shcert

shcert
 #!/bin/bash [ -f "$1" ] || exit if [[ $1 =~ \.(crt|pem)$ ]]; then openssl x509 -in "$1" -text -noout fi if [[ $1 =~ \.conf$ ]]; then certfile=$(mktemp) grep 'client-certificate-data:' "$1"| awk '{ print $2}' | base64 -d > "$certfile" openssl x509 -in "$certfile" -text -noout rm -f "$certfile" fi 


Il existe toujours des certificats qui utilisent kubelet sur les nœuds de travail pour l'authentification dans l'API. Si vous avez utilisé la jointure kubeadm pour ajouter des nœuds au cluster, il est fort probable que le nœud ait été connecté à l'aide de la procédure d' amorçage TLS , auquel cas kubelet peut renouveler son certificat automatiquement s'il reçoit l'option --rotate-certificates . Dans les versions récentes de kubernetes, cette option est déjà activée par défaut.
Vérifier que le nœud est connecté à l'aide de la procédure d'amorçage TLS est assez simple - dans ce cas, le fichier /etc/kubernetes/kubelet.conf est généralement spécifié dans le fichier de certificat client du fichier /var/lib/kubelet/pki/kubelet-client-current.pem qui est un lien symbolique vers le certificat actuel.

Vous pouvez également voir les dates d'expiration de ce certificat à l'aide du script shcert

Nous revenons au problème du renouvellement des certificats.

Si vous avez installé le cluster à l'aide de kubeadm, j'ai de bonnes nouvelles pour vous. À partir de la version 1.15, kubeadm peut mettre à jour presque tous les certificats de plan de contrôle avec une seule commande

 kubeadm alpha certs renew all 

Cette commande renouvellera tous les certificats du répertoire / etc / kubernetes, même s'ils ont déjà expiré et que tout est cassé.

Seul le certificat kubelet ne sera pas mis à jour - c'est celui qui se trouve dans le fichier /etc/kubernetes/kubelet.conf !
Mise à jour: kubeadm, à partir de la version 1.17, inclut sur tous les nœuds (même sur le premier assistant où kubeadm init a été fait) le renouvellement automatique du certificat culet. La vérification est très simple - dans /etc/kubernetes/kubelet.conf chemin vers le fichier /var/lib/kubelet/pki/kubelet-client-current.pem sera indiqué dans le champ du certificat client

Pour renouveler ce certificat, utilisez la commande create user account

 kubeadm alpha kubeconfig user --client-name system:node:kube.slurm.io --org system:nodes > /etc/kubernetes/kubelet.conf 

Si le système possède un compte d'utilisateur, cette commande met à jour le certificat pour ce compte. N'oubliez pas de spécifier le nom d'hôte correct dans l'option --client-name , vous pouvez --client-name nom d'hôte dans le champ Objet d'un certificat existant:

 shcert /etc/kubernetes/kubelet.conf 

Et bien sûr, après la mise à jour des certificats, vous devez redémarrer tous les composants du plan de contrôle, redémarrer le nœud entier ou arrêter les conteneurs avec etcd, api, controller-manager et scheduler avec la docker stop , puis redémarrer kubelet systemctl restart kubelet .

Si votre cluster a une ancienne version: 1.13 ou moins, il ne fonctionnera tout simplement pas pour mettre à niveau kubeadm vers 1.15, car il tire le long des dépendances kubelet et kubernetes-cni, ce qui peut causer des problèmes, car les performances des composants du cluster diffèrent dans les versions par plusieurs. étape, non garantie. Le moyen le plus simple de sortir de cette situation est d'installer kubeadm sur une autre machine, de prendre le fichier binaire /usr/bin/kubeadm , de le copier sur les nœuds principaux du cluster décédé et de l'utiliser uniquement pour renouveler les certificats. Et une fois le cluster revitalisé, mettez-le à jour étape par étape à l'aide de méthodes régulières, en installant kubeadm une version plus tard.

Et enfin, à partir de la version 1.15, kubeadm a appris à renouveler tous les certificats lors de la mise à jour d'un cluster avec la commande de kubeadm upgrade . Ainsi, si vous mettez régulièrement à jour votre cluster au moins une fois par an, vos certificats seront toujours valables.

Mais si le cluster n'est pas installé à l'aide de kubeadm, vous devrez alors prendre openssl et renouveler tous les certificats individuellement.

Le problème est que les certificats contiennent des champs étendus et que différents outils d'installation de cluster peuvent ajouter leur propre ensemble de champs. De plus, les noms de ces champs dans la configuration openssl et dans la sortie du contenu du certificat sont corrélés, mais faiblement. Il faut google et sélectionner.

Je vais donner un exemple de configuration pour openssl, dans des sections distinctes dont les attributs étendus sont décrits, spécifiques à chaque type de certificat. Nous nous référerons à la section correspondante lors de la création et de la signature du csr. Cette configuration a été utilisée pour revitaliser le cluster créé il y a un an par l'éleveur.

openssl.cnf
 [req] distinguished_name = req_distinguished_name req_extensions = v3_req [v3_req] keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth [client] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth [apiproxyclient] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth [etcd] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth subjectAltName = @alt_names [api] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = ec2-us-east-1-1a-c1-master-2 DNS.2 = ec2-us-east-1-1a-c1-master-3 DNS.3 = ec2-us-east-1-1a-c1-master-1 DNS.4 = localhost DNS.5 = kubernetes DNS.6 = kubernetes.default DNS.7 = kubernetes.default.svc DNS.8 = kubernetes.default.svc.cluster.local IP.1 = 10.0.0.109 IP.2 = 10.0.0.159 IP.3 = 10.0.0.236 IP.4 = 127.0.0.1 IP.5 = 10.43.0.1 


Les attributs réels et les noms supplémentaires dans le certificat peuvent être affichés à l'aide de la commande

 openssl x509 -in cert.crt -text 

Lors du renouvellement du certificat pour l'API du serveur, j'ai eu un problème: le certificat mis à jour n'a pas fonctionné. La solution consistait à délivrer un certificat valable 1 an dans le passé.

Dans openssl, vous ne pouvez pas émettre un certificat valide dans le passé avec une simple commande, le code indique strictement que le certificat n'est valide qu'à partir du moment actuel. Mais vous pouvez localement remonter le temps en utilisant la bibliothèque libfaketime

 yum install libfaketime LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="-365d" openssl x509 -req ... 

Nous émettons des certificats étendus selon l'algorithme suivant:

Nous créons une CSR en utilisant un certificat existant, spécifiez la section souhaitée avec une liste d'attributs avancés dans le fichier de configuration:

 openssl x509 -x509toreq -in "node.cert" -out "node.csr" -signkey "node.key" -extfile "openssl.cnf" -extensions client 

Nous le signons avec le certificat racine correspondant, décalant l'heure d'il y a 1 an et spécifiant la section souhaitée avec une liste d'attributs avancés dans le fichier de configuration

 LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="-365d" openssl x509 -req -days 36500 -in "node.csr" -CA "kube-ca.pem" -CAkey "kube-ca-key.pem" -CAcreateserial -out "node.new.cert" -extfile "openssl.cnf" -extensions client 

Nous vérifions les attributs et redémarrons les composants du plan de contrôle.

Sergey Bondarev,
Prof de slurm
slurm.io

Source: https://habr.com/ru/post/fr465733/


All Articles