Kubeadm: utiliser des certificats de service kubelet signés

Créé le 9 nov. 2018  ·  38Commentaires  ·  Source: kubernetes/kubeadm

S'agit-il d'un rapport de bogue ou d'une demande de fonctionnalité?

/ genre bug

Ouverture du côté kubeadm pour ce problème sur le serveur de métriques

Versions

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:43:08Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}

Environnement :

  • Version Kubernetes (utilisez kubectl version ):
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:46:06Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.1", GitCommit:"4ed3216f3ec431b140b1d899130a69fc671678f4", GitTreeState:"clean", BuildDate:"2018-10-05T16:36:14Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}
  • Fournisseur de cloud ou configuration matérielle :
    Quelconque
  • OS (par exemple à partir de / etc / os-release):
    Quelconque
  • Noyau (par exemple uname -a ):
$ uname -a
Linux ip-172-31-1-118 4.15.0-1023-aws #23-Ubuntu SMP Mon Sep 24 16:31:06 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  • Autres :

Que s'est-il passé?

kubeadm crée des certificats sous /var/lib/kubelet/pki/kubelet.* signés avec une autorité de certification différente de celle sous /etc/kubernetes/pki/ca.pem

À quoi vous attendiez-vous?

En conséquence, certaines applications comme le serveur de métriques ne peuvent pas collecter de statistiques à partir d'un kubelet sécurisé car le kubelet a des certificats signés par un CA différent du ou des maîtres K8.

Exemple d'erreur:

E1108 23:49:32.090084       1 manager.go:102] unable to fully collect metrics: [unable to fully scrape metrics from source kubelet_summary:ip-x-x-x-x: unable to fetch metrics from Kubelet ip-x-x-x-x (ip-x-x-x-x): Get https://ip-x-x-x-x:10250/stats/summary/: x509: certificate signed by unknown authority, unable to fully scrape metrics from source kubelet_summary:ip-x-x-x-x: unable to fetch metrics from Kubelet ip-x-x-x-x (ip-x-x-x-x): Get https://ip-x-x-x-x:10250/stats/summary/: x509: certificate is valid for x.x.x.x not ip-x-x-x-x]

Comment le reproduire (le plus minimal et le plus précisément possible)?

Installez le serveur de métriques lors de l'exécution:

$ kubectl -n journaux kube-system

Y a-t-il autre chose que nous devons savoir?

Un peu plus de fond ici

Il y a également des étapes là-dedans que j'ai suivies pour résoudre le problème.


modifier: neolit123

le problème ici est que le certificat de service est auto-signé par défaut:
voir https://github.com/kubernetes/website/pull/27071 pour la mise à jour de la documentation.

aresecurity help wanted kinbug kinfeature lifecyclfrozen prioritimportant-longterm

Commentaire le plus utile

résumons le problème:

comme indiqué par @anitgandhi :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

le problème avec kubeadm ici est que nous ne passons pas quelques drapeaux au kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

sans ces indicateurs, le kubelet utilise par défaut l'auto-signature de son certificat lors de sa première exécution, ce qui peut être vérifié avec:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

avec un certificat auto-signé au lieu d'un certificat signé par l'autorité de certification du cluster ( /etc/kubernetes/ca.crt ), les déploiements comme le serveur de métriques ne peuvent pas gratter le kubelet, car le SAN de certificat auto-signé n'inclura que DNS:hostname .

solutions possibles:
A) implémentez le chant d'une nouvelle paire kubelet.crt/key , idéalement sous /var/lib/kubelet/pki et définissez les drapeaux de kubelet supplémentaires --tls-cert-file , --tls-private-key-file .

B) document signifie l'activer à la demande de la même manière que @ raravena80 l'a fait ici: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
sauf éventuellement en utilisant les commandes Kubernetes CSRs / kubeadm.

C) comme commenté par @alexbrand

Si possible, je pense que nous devrions utiliser les fonctionnalités d'amorçage TLS intégrées au kubelet pour demander / faire pivoter les certificats de service.

RÉ) ?

@ kubernetes / sig-cluster-lifecycle
pour moi, cela semble dans l'espace entre bogue / fonctionnalité.

regarde aussi:
https://github.com/kubernetes/community/pull/602/files

Tous les 38 commentaires

@ raravena80 Je n'ai connaissance d'aucun certificat créé par kubeadm sous /var/lib/kubelet/pki/ .. pourriez-vous nous fournir plus d'informations? par exemple, les fichiers de configuration de kubeadm, les étapes pour créer le cluster

@fabriziopandini Je ne suis pas tout à fait sûr que les certificats soient créés par kubeadm, mais la procédure générale est décrite ici .

Voici à quoi ressemble le contenu du répertoire:

root@ip-172-31-1-118:/var/lib/kubelet/pki# pwd
/var/lib/kubelet/pki
root@ip-172-31-1-118:/var/lib/kubelet/pki# ls -al
total 24
drwxr-xr-x 2 root root 4096 Jul 23 21:10 .
drwxr-xr-x 7 root root 4096 Nov 12 04:52 ..
-rw------- 1 root root 2810 Jul 23 21:09 kubelet-client-2018-07-23-21-09-53.pem
-rw------- 1 root root 1159 Jul 23 21:10 kubelet-client-2018-07-23-21-10-43.pem
lrwxrwxrwx 1 root root   59 Jul 23 21:10 kubelet-client-current.pem -> /var/lib/kubelet/pki/kubelet-client-2018-07-23-21-10-43.pem
-rw-r--r-- 1 root root 1501 Nov  8 23:53 kubelet.crt
-rw------- 1 root root 1679 Nov  8 23:53 kubelet.key
root@ip-172-31-1-118:/var/lib/kubelet/pki#

S'agit-il kubelet.crt fichiers kubelet.key créés par le kubelet lors de son premier chargement?

@ raravena80 merci pour la clarification
Je n'ai probablement pas le contexte complet ici, donc je laisse la place aux autres de répondre.

Une seule note latérale (peut-être que cela peut aider)
Kubeadm crée déjà un certificat nommé apiserver-kubelet-client pour permettre au serveur api de parler en toute sécurité avec les kubelets; il est signé par ca et lié aux règles RBAC nécessaires.

/ assign @liztio

Je pense que c'est pour pré-générer les certificats de serveur de kubelet. J'ai bricolé en essayant d'utiliser les indicateurs Kubelet pour l'amorçage du serveur TLS et la rotation des certificats de serveur, malheureusement, je n'ai pas pu demander à Kubelet de demander un certificat de serveur pour lui-même en utilisant le jeton d'amorçage. Kubelet finit par revenir à son comportement par défaut pour les certificats de serveur, qui est de générer un certificat auto-signé.

À ma connaissance, pour le moment, le seul moyen de contourner cela est de générer des certificats de serveur de Kubelet hors bande et de les placer sur un chemin déterministe et kubelet (configuré par kubeadm) le récupérera et définira des indicateurs de kubelet en conséquence. ; référence: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#client -and-servant-des certificats

Le apiserver-kubelet-client est le certificat client que le serveur API présentera à un kubelet, mais kubelet est configuré pour approuver les clients qui sont signés par l'autorité de certification k8s:

# cat /var/lib/kubelet/config.yaml 
address: 0.0.0.0
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    cacheTTL: 2m0s
    enabled: true
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt

C'est l'identité du kubelet en tant que serveur présenté qui doit être signée par l'autorité de certification k8s, ce qui revient à la question d'origine.

Il y a aussi une discussion pertinente à la fin de ce fil: https://github.com/kubernetes/kubeadm/issues/118

Je pense que kubeadm devra peut-être ajouter un approbateur CSR pour les demandes de certificat de serveur avec un jeton d'amorçage valide, tout comme il le fait pour les demandes de certificat client?

Qu'en est-il que le kubelet télécharge son CA auto-signé dans une configmap quelque part? le plugin nodeadmission pourrait le limiter à sa propre configuration. metrics-server peut l'utiliser pour contacter le nœud.

Des idées à ce sujet?

Si possible, je pense que nous devrions utiliser les fonctionnalités d'amorçage TLS intégrées au kubelet pour demander / faire pivoter les certificats de service.

@alexbrand je suis d'accord là-dessus

Le bootstrap de kubelet TLS ne génère que des certificats clients pour une raison quelconque:
--bootstrap-kubeconfig string
Path to a kubeconfig file that will be used to get client certificate for kubelet. If the file specified by --kubeconfig does not exist, the bootstrap kubeconfig is used to request a client certificate from the API server. On success, a kubeconfig file referencing the generated client certificate and key is written to the path specified by --kubeconfig. The client certificate and key file will be stored in the directory pointed by --cert-dir.

Et kubeadm le fait déjà. Peut-être s'agit-il d'une demande de fonctionnalité kubelet?

résumons le problème:

comme indiqué par @anitgandhi :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

le problème avec kubeadm ici est que nous ne passons pas quelques drapeaux au kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

sans ces indicateurs, le kubelet utilise par défaut l'auto-signature de son certificat lors de sa première exécution, ce qui peut être vérifié avec:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

avec un certificat auto-signé au lieu d'un certificat signé par l'autorité de certification du cluster ( /etc/kubernetes/ca.crt ), les déploiements comme le serveur de métriques ne peuvent pas gratter le kubelet, car le SAN de certificat auto-signé n'inclura que DNS:hostname .

solutions possibles:
A) implémentez le chant d'une nouvelle paire kubelet.crt/key , idéalement sous /var/lib/kubelet/pki et définissez les drapeaux de kubelet supplémentaires --tls-cert-file , --tls-private-key-file .

B) document signifie l'activer à la demande de la même manière que @ raravena80 l'a fait ici: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
sauf éventuellement en utilisant les commandes Kubernetes CSRs / kubeadm.

C) comme commenté par @alexbrand

Si possible, je pense que nous devrions utiliser les fonctionnalités d'amorçage TLS intégrées au kubelet pour demander / faire pivoter les certificats de service.

RÉ) ?

@ kubernetes / sig-cluster-lifecycle
pour moi, cela semble dans l'espace entre bogue / fonctionnalité.

regarde aussi:
https://github.com/kubernetes/community/pull/602/files

Je pense que quelque chose entre les options B + C devrait être fait car une grande partie de la logique du client de jeton d'amorçage cert / CSR kubelet + kubeadm aurait une logique commune à cela.

résumons le problème:

comme indiqué par @anitgandhi :
# 1223 (commentaire)

le problème avec kubeadm ici est que nous ne passons pas quelques drapeaux au kubelet:

--tls-cert-file=<some-path>/kubelet.crt
--tls-private-key-file=<some-path>/kubelet.key

sans ces indicateurs, le kubelet utilise par défaut l'auto-signature de son certificat lors de sa première exécution, ce qui peut être vérifié avec:

sudo openssl verify -verbose -CAfile /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.crt

avec un certificat auto-signé au lieu d'un certificat signé par l'autorité de certification du cluster ( /etc/kubernetes/ca.crt ), les déploiements comme le serveur de métriques ne peuvent pas gratter le kubelet, car le SAN de certificat auto-signé n'inclura que DNS:hostname .

solutions possibles:
A) implémentez le chant d'une nouvelle paire kubelet.crt/key , idéalement sous /var/lib/kubelet/pki et définissez les drapeaux de kubelet supplémentaires --tls-cert-file , --tls-private-key-file .

B) document signifie l'activer à la demande de la même manière que @ raravena80 l'a fait ici: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
sauf éventuellement en utilisant les commandes Kubernetes CSRs / kubeadm.

C) comme commenté par @alexbrand

Si possible, je pense que nous devrions utiliser les fonctionnalités d'amorçage TLS intégrées au kubelet pour demander / faire pivoter les certificats de service.

RÉ) ?

@ kubernetes / sig-cluster-lifecycle
pour moi, cela semble dans l'espace entre bogue / fonctionnalité.

regarde aussi:
https://github.com/kubernetes/community/pull/602/files

excellent résumé @ neolit123 . Savez-vous si cela passera au prochain cycle ou aux travaux en cours au moment où nous parlons? Demander principalement à cause du serveur de métriques auquel chaque déploiement veut l'avoir;)

@randomvariable a mentionné qu'il existe une autre solution de contournement pour cela.
D'après les discussions jusqu'à présent, nous hésitons à signer le certificat de service de kubelet avec le cluster CA. ce sujet nécessite une discussion plus approfondie.

/ remove-help

car la solution à mettre en œuvre n'a pas encore été choisie.

Un mouvement à ce sujet? Je me heurte à cela pour prendre en charge les fonctionnalités d'autoscaling dans un cluster déployé par kubeadm.

La solution de contournement actuelle consiste à désactiver la vérification par l'autorité de certification du certificat kubelet.

helm install --set 'args={--kubelet-insecure-tls}' --namespace kube-system metrics stable/metrics-serve

pas vraiment, il est bloqué sur les propositions de design.
il existe un certain nombre de solutions de contournement, mais le travail de documentation de celles-ci est bloqué:
https://github.com/kubernetes/kubeadm/issues/1602

--kubelet-insecure-tls

cela n'est peut-être pas idéal pour tous les utilisateurs.

Les problèmes deviennent obsolètes après 90 jours d'inactivité.
Marquez le problème comme récent avec /remove-lifecycle stale .
Les problèmes obsolètes pourrissent après 30 jours supplémentaires d'inactivité et finissent par se fermer.

Si ce problème peut être résolu en toute sécurité, veuillez le faire avec /close .

Envoyez vos commentaires à sig-testing, kubernetes / test-infra et / ou fejta .
/ cycle de vie périmé

/ cycle de vie gelé

Rencontrer ce problème exact lors de la création d'un cluster v1.18.2 avec kubeadm.

Lors de la configuration du serveur de métriques, cela ne fonctionne pas sans définir le drapeau kubelet-insecure-tls OU émettre des certificats pour kublet "hors bande", en le signant avec l'autorité de certification kubernetes.

J'ai pensé à réutiliser le certificat client kubelet mais il est bien sûr émis pour CN = system:node:nodename et pas de SAN. Et je l'ai testé, ce qui modifie bien sûr l'erreur pour indiquer exactement cela. Le même certificat pourrait être utilisé à la fois comme serveur / client s'il avait le nom de nœud comme autre nom de sujet? Mais je suppose qu'il serait plus approprié d'utiliser des certificats séparés pour le serveur / client?

/ remove-lifecycle gelé

/ cycle de vie gelé

il est gelé pour que les bots ne clôturent pas le problème.

Le même certificat pourrait être utilisé à la fois comme serveur / client s'il avait le nom de nœud comme autre nom de sujet?

en théorie et à moins que le kubelet ne les valide - par exemple "le certificat client ne doit pas avoir de SAN".

Mais je suppose qu'il serait plus approprié d'utiliser des certificats séparés pour le serveur / client?

il est courant de les utiliser séparément, même dans les cas où cela semble évitable. il est peu probable que les responsables de kubelet / auth {z | n} modifient ce détail.

Hey. J'ai creusé un peu plus. L'option de configuration de Kubelet serverTLSBootstrap: true peut en fait créer un CSR pour le certificat de service. Mais cela le laisse non approuvé. Ce qui peut convenir?

Définir à la fois rotateCertificates: true et serverTLSBootsrap: true , puis approuver le CSR pour le certificat de service semble être le moyen le plus simple d'aller ici. Le certificat de service demandé / émis est pour O = system:nodes, CN = system:node:<nodename> avec des noms alternatifs de sujet pour DNS: <nodename>, IP Address: <node IP address>

Est-ce que kubeadm at activer au moins l'option de configuration serverTLSBootstrap afin d'approuver le certificat de serveur serait une chose facile à faire? Ou même kubeadm pourrait aussi faire l'approbation?

Hey. J'ai creusé un peu plus. L'option de configuration de Kubelet serverTLSBootstrap: true peut en fait créer un CSR pour le certificat de service. Mais cela le laisse non approuvé. Ce qui peut convenir?

Définir à la fois rotateCertificates: true et serverTLSBootsrap: true , puis approuver le CSR pour le certificat de service semble être le moyen le plus simple d'aller ici. Le certificat de service demandé / émis est pour O = system:nodes, CN = system:node:<nodename> avec des noms alternatifs de sujet pour DNS: <nodename>, IP Address: <node IP address>

Est-ce que kubeadm at activer au moins l'option de configuration serverTLSBootstrap afin d'approuver le certificat de serveur serait une chose facile à faire? Ou même kubeadm pourrait aussi faire l'approbation?

Je ne suis pas sûr des implémentations de sécurité, mais vous pouvez combiner serverTLSBootstrap avec cet opérateur pour approuver automatiquement les CSR https://github.com/kontena/kubelet-rubber-stamp

Est-ce que kubeadm at activer au moins l'option de configuration serverTLSBootstrap afin d'approuver le certificat de serveur serait une chose facile à faire? Ou même kubeadm pourrait aussi faire l'approbation?

kubeadm ne peut pas faire l'approbation car kubeadm n'est pas un démon. il doit déployer un contrôleur / opérateur qui gère cela pour l'utilisateur. peut-être à l'avenir.

l'API des certificats devrait bientôt devenir GA et j'espère que nous aurons un meilleur moyen de gérer cela dans k8s. regarde s'il te plait:
https://github.com/kubernetes/enhancements/issues/267
(je ne sais pas encore avec quoi nous allons nous retrouver ...)

nous avons également des idées alternatives. mais si tout cela tente de résoudre le problème du serveur de métrique, vous pouvez aussi bien utiliser https://github.com/brancz/kube-rbac-proxy qui peut effectuer un SAR sur les requêtes MS au kubelet. malheureusement cela n'est pas encore documenté de notre côté:
https://github.com/kubernetes/kubeadm/issues/1602

@ neolit123 J'ai au moins commencé à m'y intéresser en essayant de mettre en place un serveur de métriques sur kubeadm et des clusters «à la dure» pour une expérience d'apprentissage. Le moyen le plus simple était bien sûr de signaler MS avec --kubelet-insecure-tls , mais je voulais vraiment voir comment le résoudre de manière sécurisée, puis je me suis intéressé au problème. 🙂

Pour l'instant, il est assez facile pour moi d'ajouter l'indicateur serverTLSbootstrap à la configuration de kubelet et d'approuver manuellement les certificats. J'ai cependant remarqué un inconvénient, à savoir que vous ne pouvez pas interagir pleinement avec les pods sur le nœud tant que vous n'avez pas approuvé le certificat. (kubectl exec ne parvient pas à exécuter la commande sur les pods s'exécutant sur un nœud avant approbation par exemple)

Je vais également suivre le problème des améliorations. Merci.

C'est vraiment triste qu'avec kubeadm qui semble assez mature, le résultat prêt à l'emploi pour kubeletet cert soit d'être auto-signé et beaucoup de gens choisissent kubelet-insecure-tls pour le serveur de métriques au lieu de faire les choses correctement & etc :(

c'est un problème compliqué.

s'il vous plaît essayez:
https://github.com/kontena/kubelet-rubber-stamp
ou alors
https://github.com/brancz/kube-rbac-proxy
comme solutions de contournement

c'est un problème compliqué.

s'il vous plaît essayez:
https://github.com/kontena/kubelet-rubber-stamp
ou alors
https://github.com/brancz/kube-rbac-proxy
comme solutions de contournement

En fait, https://github.com/kontena/kubelet-rubber-stamp fonctionne plutôt bien et imo semble être une solution plus correcte que le proxy.

Étape 1:
Ajouter
serverTLSBootstrap: true à la fin de chaque /var/lib/kubelet/config.yaml pour la reconfiguration des kubelets et n'oubliez pas d'appliquer la configuration (ou simplement de les redémarrer)

Étape 2:
Déployer kubelet-rubber-stamp

service_account.yaml
role.yaml
role_binding.yaml
operator.yaml

Étape 3:
Modifier le déploiement du serveur de métriques et supprimer --kubelet-insecure-tls

Résultat:

kubectl get csr
NAME        AGE   SIGNERNAME                      REQUESTOR          CONDITION
csr-7dvsx   31m   kubernetes.io/kubelet-serving   system:node:u-02   Approved,Issued
csr-d6rvm   31m   kubernetes.io/kubelet-serving   system:node:u-03   Approved,Issued
csr-szblz   31m   kubernetes.io/kubelet-serving   system:node:u-01   Approved,Issued
csr-zjfgj   31m   kubernetes.io/kubelet-serving   system:node:u-04   Approved,Issued

Hé, juste pour ajouter à ça @vainkop
Au cours de votre kubeadm init initial pour créer le cluster, vous devriez également être en mesure de transmettre un fichier objet d'API KubeletConfiguration pour définir le serverTLSBootstrap

`` kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration

...

apiVersion: kubelet.config.k8s.io/v1beta1
genre: KubeletConfiguration
serverTLSBootstrap: vrai

`kubeadm init --config=kubeadm-config.yaml`

Then all kubelet's will automatically be set up using the `serverTLSBootstrap` flag.

To get the CSRs

kubectl obtenir csr
NOM AGE SIGNERNAME DEMANDEUR CONDITION
csr-2qkdw 2m1s kubernetes.io/kube-apiserver-client-kubelet system: bootstrap : fcufbo Approuvé, publié
csr-9wvgt 114s kubernetes.io/kubelet-serving system: node : worker-1 En attente
csr-lz97v 4m58s kubernetes.io/kubelet-serving system: node : master-1 En attente
csr-rsdsp 4m59s kubernetes.io/kube-apiserver-client-kubelet system: node : master-1 Approuvé, émis
csr-wgxqs 4m49s kubernetes.io/kubelet-serving system: node : master-1 En attente

Then either approve them manually or deploy https://github.com/kontena/kubelet-rubber-stamp which approves them automatically. I just tried it with kubelet-rubber-stamp and it works great.

Also I did not seem to need to restart the kubelet's this way, they picked up their certificates as soon as I approvde the CSR, but a caveat is that the kublet's have NO cert until the CSR is approved, it does not get a self signed certificate first.

Le certificat kubectl approuve csr-ab123 # OU déploie un tampon en caoutchouc!

kubectl obtenir csr
NOM AGE SIGNERNAME DEMANDEUR CONDITION
csr-9wvgt 3m kubernetes.io/kubelet-serving system: node : worker-1 Approuvé, publié
...
''

Une autre chose étrange semble se produire ici btw, c'est que le nœud maître semble créer son CSR deux fois. (Au moins les deux fois où j'ai essayé ça)

Mais comme le dit @nijave dans un commentaire ci-dessus, je ne sais pas quelles sont les implications de sécurité de l'utilisation du tampon en caoutchouc.

@allir , @vainkop dans la mesure où je peux voir le kubelet-rubber-stamp ne vérifie que si le nom commun du CSR correspond au nom du demandeur mais ne vérifie pas si les noms d'hôte et les adresses IP supplémentaires demandés par le kubelet sont valides. Cela signifie qu'un attaquant qui a accès au certificat client kubelet peut créer des certificats pour pratiquement n'importe quel nom de domaine ou adresse IP. Tous les clients configurés pour approuver l'autorité de certification racine accepteront alors ce certificat.
Bien sûr, il est difficile de valider le nom d'hôte et les adresses IP valides pour un kubelet donné car il n'y a actuellement aucune autorité qui puisse confirmer ce qu'un kubelet est autorisé à demander. Par exemple, l'utilisation de l'objet nœud sur le serveur API n'est pas suffisante car les kubelets peuvent mettre à jour l'objet sans limites.

Hé, juste pour ajouter à ça @vainkop
Au cours de votre kubeadm init initial pour créer le cluster, vous devriez également être en mesure de transmettre un fichier objet d'API KubeletConfiguration pour définir le serverTLSBootstrap
kubeadm init --config=kubeadm-config.yaml
Ensuite, tous les kubelet seront automatiquement configurés en utilisant le drapeau serverTLSBootstrap .

Ou pour une configuration K8 existante utilisant Ansible, cela peut être:

  tasks:
    - name: Insert a line at the end of /var/lib/kubelet/config.yaml
      lineinfile:
        path: /var/lib/kubelet/config.yaml
        line: 'serverTLSBootstrap: true'

+ redémarrer les kubelets

Wow, je suis si heureux d'avoir trouvé ce problème, et je ne suis pas le seul à vouloir faire ce bon chemin. :)

Maintenant, permettez-moi de partager mes réflexions sur ce problème (veuillez me corriger si je me trompe quelque part) :

D'abord ma vision du problème d'origine:
Actuellement, kubeadm active l'authentification webhook pour tous les kubelets par défaut, donc kubelet valide les certificats clients pour les connexions entrantes sans problème même si l'option --kubelet-insecure-tls est spécifiée.
De l'autre côté, le serveur de métriques n'a pas la possibilité de vérifier le certificat de kubelet spécifique car il est auto-signé sur le nœud.

Risques possibles liés à l'utilisation de --kubelet-insecure-tls pour le serveur de métriques:
Bien que les données de kubelet soient quelque peu sécurisées et ne seront jamais fournies au serveur de métriques sans authentification réussie du webhook.
En théorie, quelqu'un peut compromettre l'adresse IP ou le nom d'hôte du serveur et fournir des statistiques erronées. Mais pour établir les connexions, metricserver utilise une adresse IP et des noms d'hôte spécifiés pour le nœud via kube-apiserver, de sorte que l'attaquant doit d'abord pirater le serveur API, DNS ou l'adresse IP du nœud.

Petite observation:
Le serveur de métriques n'est pas un service unique qui accède directement aux kubelets. Kube-apiserver fait également cela pour lire les journaux de conteneurs ou exécuter le shell sur eux. La bonne question est de savoir comment kube-apiserver s'assure qu'il établit une connexion avec le kubelet spécifique alors qu'il n'a aucune information sur l'autorité de certification qui a émis son certificat?
Ne se comporte-t-il pas de la même manière que le serveur de métriques avec l'option --kubelet-insecure-tls dans ce cas?

Solution possible:
De nos jours, les webhooks et l'agrégation d'API sont très populaires dans Kubernetes. Tous se comportent de la même manière, en générant leur propre CA et crt / key pair. Le hachage de l'autorité de certification est également stocké dans une ressource spécifique pour fournir à kube-apiserver des informations sur le certificat auquel il peut faire confiance.

Par example:

  • APIServices stocke le hachage CA associé dans leur ressource apiservices.apiregistration.k8s.io :

    spec:
    caBundle: <ca-hash>
    
  • Les webhooks stockent le hachage CA associé dans leurs ressources validatingwebhookconfigurations.admissionregistration.k8s.io et mutatingwebhookconfigurations.admissionregistration.k8s.io :

    webhooks:
    - clientConfig:
      caBundle: <ca-hash>
    

Pour moi, il est assez évident que chaque ressource de nœud devrait avoir un caBundle similaire dans leur spec , où les kubelets peuvent enregistrer leur propre autorité de certification pour servir à l'aide de leur certificat client:

spec:
  caBundle: <ca-hash>

Metris-server et kube-apiserver doivent utiliser ces certificats pour vérifier et faire confiance à la connexion aux kubelets.

merci à @ kfox1111 qui a exprimé une idée similaire précédemment https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -460854312

La bonne question est de savoir comment kube-apiserver s'assure qu'il établit une connexion avec le kubelet spécifique alors qu'il n'a aucune information sur l'autorité de certification qui a émis son certificat?
Ne se comporte-t-il pas de la même manière que le serveur de métriques avec l'option --kubelet-insecure-tls dans ce cas?

Pour répondre à cette question, je peux citer @luxas ici:

Oui, nous ne pouvons pas vérifier les connexions du serveur API aux serveurs kubelet, car chaque kubelet a son propre certificat auto-signé. Nous pourrions envisager un flux d'approbation manuelle pour les kubelet servant des certificats à l'avenir, mais ce n'est pas sécurisé par défaut pour le moment.

depuis https://github.com/kubernetes/kubeadm/issues/118#issuecomment -407498529

j'espère qu'il pourra être résolu un jour

[root<strong i="6">@jenkins</strong> metrics-server]# kubectl -n kube-system logs -f metrics-server-6955d88db9-lftlz
I1120 08:23:09.094132       1 requestheader_controller.go:169] Starting RequestHeaderAuthRequestController
I1120 08:23:09.094234       1 shared_informer.go:240] Waiting for caches to sync for RequestHeaderAuthRequestController
I1120 08:23:09.094270       1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:09.094279       1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:09.094307       1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:09.094315       1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:09.095064       1 dynamic_serving_content.go:130] Starting serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key
I1120 08:23:09.095207       1 secure_serving.go:197] Serving securely on [::]:4443
I1120 08:23:09.095259       1 tlsconfig.go:240] Starting DynamicServingCertificateController
I1120 08:23:09.194453       1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file 
I1120 08:23:09.194660       1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::client-ca-file 
I1120 08:23:09.194455       1 shared_informer.go:247] Caches are synced for RequestHeaderAuthRequestController 
E1120 08:23:10.420643       1 server.go:132] unable to fully scrape metrics: [unable to fully scrape metrics from node k8s-master3: unable to fetch metrics from node k8s-master3: Get "https://10.39.140.250:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.250 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-master1: unable to fetch metrics from node k8s-master1: Get "https://10.39.140.248:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.248 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-master2: unable to fetch metrics from node k8s-master2: Get "https://10.39.140.249:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.249 because it doesn't contain any IP SANs, unable to fully scrape metrics from node k8s-node1: unable to fetch metrics from node k8s-node1: Get "https://10.39.140.251:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 10.39.140.251 because it doesn't contain any IP SANs]
I1120 08:23:33.874949       1 requestheader_controller.go:183] Shutting down RequestHeaderAuthRequestController
I1120 08:23:33.874978       1 configmap_cafile_content.go:223] Shutting down client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I1120 08:23:33.874993       1 configmap_cafile_content.go:223] Shutting down client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I1120 08:23:33.875019       1 tlsconfig.go:255] Shutting down DynamicServingCertificateController
I1120 08:23:33.875026       1 dynamic_serving_content.go:145] Shutting down serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key
I1120 08:23:33.875041       1 secure_serving.go:241] Stopped listening on [::]:4443

Pas de nouvelles de ce numéro? Je serais également intéressé d'avoir une solution pour cela.

nous documentons les solutions de contournement ici:
https://github.com/kubernetes/website/pull/27071
https://github.com/kubernetes/kubeadm/issues/1602

nous pouvons garder ce problème ouvert, mais en raison de la complexité de devoir déployer un signataire avec kubeadm par défaut, il est peu probable que nous apportions ce changement de sitôt.

Cette page vous a été utile?
0 / 5 - 0 notes