Kubeadm: Verwenden Sie signierte Kubelet-Servierzertifikate

Erstellt am 9. Nov. 2018  ·  38Kommentare  ·  Quelle: kubernetes/kubeadm

Ist dies ein BUG REPORT oder eine FEATURE REQUEST?

/ Art Bug

Öffnen der kubeadm -Seite für dieses Problem auf dem Metrics-Server

Versionen

$ 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"}

Umwelt :

  • Kubernetes-Version (verwenden Sie 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"}
  • Cloud-Anbieter oder Hardwarekonfiguration :
    Irgendein
  • Betriebssystem (zB aus / etc / os-release):
    Irgendein
  • Kernel (zB 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
  • Andere :

Was ist passiert?

kubeadm erstellt Zertifikate unter /var/lib/kubelet/pki/kubelet.* die mit einer anderen Zertifizierungsstelle signiert sind als unter /etc/kubernetes/pki/ca.pem

Was hast du erwartet?

Infolgedessen können einige Apps wie der Metrics-Server keine Statistiken von einem gesicherten Kubelet sammeln, da das Kubelet Zertifikate hat, die von einem anderen Ca als den K8s-Master (s) signiert wurden.

Fehlerbeispiel:

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]

Wie kann man es reproduzieren (so minimal und präzise wie möglich)?

Installieren Sie den Metrics-Server beim Ausführen:

$ kubectl -n Kube-System-Protokolle

Was müssen wir noch wissen?

Noch etwas Hintergrundwissen hier

Es gibt auch Schritte, die ich befolgt habe, um das Problem zu beheben.


edit: neolit123

Das Problem hierbei ist, dass das Serving-Zertifikat standardmäßig selbst signiert ist:
Aktualisierung der Dokumentation finden Sie unter https://github.com/kubernetes/website/pull/27071 .

aresecurity help wanted kinbug kinfeature lifecyclfrozen prioritimportant-longterm

Hilfreichster Kommentar

Lassen Sie uns das Problem zusammenfassen:

wie von @anitgandhi beschrieben :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

Das Problem mit Kubeadm hier ist, dass wir nicht ein paar Flaggen an das Kubelet übergeben:

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

Ohne diese Flags signiert das Kubelet standardmäßig das Serving-Zertifikat selbst, wenn es zum ersten Mal ausgeführt wird. Dies kann überprüft werden mit:

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

Mit einem selbstsignierten Zertifikat anstelle eines von der Cluster-Zertifizierungsstelle signierten Zertifikats ( /etc/kubernetes/ca.crt ) können Bereitstellungen wie der Metrikserver das Kubelet nicht kratzen, da das selbstsignierte Zertifikat-SAN nur DNS:hostname .

mögliche Lösungen:
A) Implementieren Sie das Singen eines neuen kubelet.crt/key -Paares, idealerweise unter /var/lib/kubelet/pki und setzen Sie die zusätzlichen Kubelet-Flags --tls-cert-file , --tls-private-key-file .

B) Dokument bedeutet, dies bei Bedarf zu aktivieren, ähnlich wie @ raravena80 es hier getan hat: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
außer möglicherweise mit Kubernetes CSRs / kubeadm-Befehlen.

C) wie von @alexbrand kommentiert

Wenn möglich, sollten wir die im Kubelet integrierten TLS-Bootstrapping-Funktionen zum Anfordern / Drehen von Serving-Zertifikaten verwenden.

D)?

@ kubernetes / sig-cluster-lifecycle
Für mich scheint dies im Raum zwischen Bug / Feature zu liegen.

siehe auch:
https://github.com/kubernetes/community/pull/602/files

Alle 38 Kommentare

@ raravena80 Mir ist kein Zertifikat bekannt, das von kubeadm unter /var/lib/kubelet/pki/ erstellt wurde. Könnten Sie uns bitte weitere Informationen geben? zB kubeadm Konfigurationsdateien, Schritte zum Erstellen des Clusters

@fabriziopandini Ich bin mir nicht ganz sicher, ob die Zertifikate vom Kubeadm erstellt wurden, aber die allgemeine Vorgehensweise wird hier beschrieben.

So sieht der Inhalt des Verzeichnisses aus:

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#

Sind es kubelet.crt und kubelet.key Dateien, die vom Kubelet beim ersten Laden erstellt wurden?

@ raravena80 danke für die Klarstellung
Wahrscheinlich habe ich hier nicht den vollständigen Kontext, also überlasse ich anderen Raum für Antworten.

Nur eine Randnotiz (möglicherweise kann es helfen)
Kubeadm erstellt bereits ein Zertifikat mit dem Namen apiserver-kubelet-client damit der API-Server sicher mit den Kubelets kommunizieren kann. es ist von ca signiert und an die notwendigen RBAC-Regeln gebunden.

/ @liztio zuweisen

Ich denke, dies dient dazu, die Server- Zertifikate von kubelet vorab zu generieren. Ich habe versucht, die Kubelet-Flags für den TLS-Server-Bootstrap zu verwenden und Server-Zertifikate zu drehen. Leider konnte ich Kubelet nicht dazu bringen, mithilfe des Bootstrap-Tokens ein Server-Zertifikat für sich selbst anzufordern. Kubelet greift schließlich auf sein Standardverhalten für Serverzertifikate zurück, bei dem ein selbstsigniertes generiert wird.

Nach meinem besten Wissen besteht der einzige Weg, dies zu umgehen, darin, Kubelets Server-Zertifikate außerhalb des Bandes zu generieren und sie auf einem deterministischen Pfad zu platzieren. Kubelet (konfiguriert von kubeadm) nimmt sie auf und setzt einige Kubelet-Flags entsprechend ;; Referenz: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#client -and-Serving-Zertifikate

Das apiserver-kubelet-client ist das Client-Zertifikat, das der API-Server einem Kubelet präsentiert. Kubelet ist jedoch so konfiguriert, dass es Clients vertraut, die von der k8s-Zertifizierungsstelle signiert sind:

# 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

Es ist die Identität des Kubelets als Server, die präsentiert wird und von der k8s-Zertifizierungsstelle signiert werden muss, was die ursprüngliche Frage betrifft.

Es gibt auch einige relevante Diskussionen am Ende dieses Threads: https://github.com/kubernetes/kubeadm/issues/118

Ich denke, kubeadm muss möglicherweise einen CSR-Genehmiger für Serverzertifizierungsanforderungen mit einem gültigen Bootstrap-Token hinzufügen, genau wie dies für Clientzertifizierungsanforderungen der Fall ist.

Wie wäre es, wenn das Kubelet sein selbstsigniertes Ca irgendwo in eine Konfigurationskarte hochlädt? Das Nodeadmission-Plugin könnte es auf seine eigene Konfigurationskarte beschränken. Der Metrics-Server kann damit den Knoten kontaktieren.

Irgendwelche Ideen dazu?

Wenn möglich, sollten wir die im Kubelet integrierten TLS-Bootstrapping-Funktionen zum Anfordern / Drehen von Serving-Zertifikaten verwenden.

@alexbrand Da stimme ich zu

kubelet TLS-Bootstrapping generiert nur Client-Zertifikate aus irgendeinem Grund:
--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.

Und kubeadm macht das schon. Vielleicht ist dies eine Kubelet-Feature-Anfrage?

Lassen Sie uns das Problem zusammenfassen:

wie von @anitgandhi beschrieben :
https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -454572577

Das Problem mit Kubeadm hier ist, dass wir nicht ein paar Flaggen an das Kubelet übergeben:

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

Ohne diese Flags signiert das Kubelet standardmäßig das Serving-Zertifikat selbst, wenn es zum ersten Mal ausgeführt wird. Dies kann überprüft werden mit:

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

Mit einem selbstsignierten Zertifikat anstelle eines von der Cluster-Zertifizierungsstelle signierten Zertifikats ( /etc/kubernetes/ca.crt ) können Bereitstellungen wie der Metrikserver das Kubelet nicht kratzen, da das selbstsignierte Zertifikat-SAN nur DNS:hostname .

mögliche Lösungen:
A) Implementieren Sie das Singen eines neuen kubelet.crt/key -Paares, idealerweise unter /var/lib/kubelet/pki und setzen Sie die zusätzlichen Kubelet-Flags --tls-cert-file , --tls-private-key-file .

B) Dokument bedeutet, dies bei Bedarf zu aktivieren, ähnlich wie @ raravena80 es hier getan hat: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
außer möglicherweise mit Kubernetes CSRs / kubeadm-Befehlen.

C) wie von @alexbrand kommentiert

Wenn möglich, sollten wir die im Kubelet integrierten TLS-Bootstrapping-Funktionen zum Anfordern / Drehen von Serving-Zertifikaten verwenden.

D)?

@ kubernetes / sig-cluster-lifecycle
Für mich scheint dies im Raum zwischen Bug / Feature zu liegen.

siehe auch:
https://github.com/kubernetes/community/pull/602/files

Ich denke, etwas zwischen den Optionen B + C sollte getan werden, da ein Großteil der Bootstrap-Token-Client-Zertifikat- / CSR-Logik kubelet + kubeadm eine gemeinsame Logik dafür haben würde.

Lassen Sie uns das Problem zusammenfassen:

wie von @anitgandhi beschrieben :
# 1223 (Kommentar)

Das Problem mit Kubeadm hier ist, dass wir nicht ein paar Flaggen an das Kubelet übergeben:

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

Ohne diese Flags signiert das Kubelet standardmäßig das Serving-Zertifikat selbst, wenn es zum ersten Mal ausgeführt wird. Dies kann überprüft werden mit:

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

Mit einem selbstsignierten Zertifikat anstelle eines von der Cluster-Zertifizierungsstelle signierten Zertifikats ( /etc/kubernetes/ca.crt ) können Bereitstellungen wie der Metrikserver das Kubelet nicht kratzen, da das selbstsignierte Zertifikat-SAN nur DNS:hostname .

mögliche Lösungen:
A) Implementieren Sie das Singen eines neuen kubelet.crt/key -Paares, idealerweise unter /var/lib/kubelet/pki und setzen Sie die zusätzlichen Kubelet-Flags --tls-cert-file , --tls-private-key-file .

B) Dokument bedeutet, dies bei Bedarf zu aktivieren, ähnlich wie @ raravena80 es hier getan hat: https://stackoverflow.com/questions/53212149/x509-certificate-signed-by-unknown-authority-kubeadm/53218524#53218524
außer möglicherweise mit Kubernetes CSRs / kubeadm-Befehlen.

C) wie von @alexbrand kommentiert

Wenn möglich, sollten wir die im Kubelet integrierten TLS-Bootstrapping-Funktionen zum Anfordern / Drehen von Serving-Zertifikaten verwenden.

D)?

@ kubernetes / sig-cluster-lifecycle
Für mich scheint dies im Raum zwischen Bug / Feature zu liegen.

siehe auch:
https://github.com/kubernetes/community/pull/602/files

tolle Zusammenfassung @ neolit123 . Wissen Sie, ob dies in den nächsten Zyklus übergeht oder in Arbeit ist, während wir sprechen? Fragen hauptsächlich wegen des Metrik-Servers, den imo jede Bereitstellung haben möchte;)

@randomvariable erwähnte, dass es dafür eine andere
Nach den bisherigen Diskussionen zögern wir, das Kubelet-Serving-Zertifikat mit der Cluster-Zertifizierungsstelle zu unterzeichnen. Dieses Thema bedarf weiterer Diskussion.

/ remove-help

weil die zu implementierende Lösung noch nicht ausgewählt wurde.

Irgendeine Bewegung dazu? Ich stoße darauf, um Autoscaling-Funktionen in einem von kubeadm bereitgestellten Cluster zu unterstützen.

Die aktuelle Problemumgehung besteht darin, die CA-Überprüfung des Kubelet-Zertifikats zu deaktivieren.

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

nicht wirklich, es ist auf Designvorschlägen blockiert.
Es gibt eine Reihe von Problemumgehungen, aber die Dokumentation der festgefahrenen Probleme:
https://github.com/kubernetes/kubeadm/issues/1602

--kubelet-unsicher-tls

Dies ist möglicherweise nicht für alle Benutzer ideal.

Probleme sind nach 90 Tagen Inaktivität veraltet.
Markieren Sie das Problem mit /remove-lifecycle stale als frisch.
Veraltete Probleme verrotten nach weiteren 30 Tagen Inaktivität und schließen schließlich.

Wenn dieses Problem jetzt sicher geschlossen werden kann, tun Sie dies bitte mit /close .

Senden Sie Feedback an sig-testing, kubernetes / test-infra und / oder fejta .
/ Lebenszyklus abgestanden

/ Lebenszyklus eingefroren

Genau dieses Problem tritt beim Erstellen des Clusters v1.18.2 mit kubeadm auf.

Beim Einrichten des Metrics-Servers funktioniert dies nicht, ohne das Flag kubelet-insecure-tls ODER Zertifikate für kublet "out of band" auszustellen und mit der Kubernetes-Zertifizierungsstelle zu signieren.

Ich habe darüber nachgedacht, das Kubelet-Client-Zertifikat wiederzuverwenden, aber das wird natürlich für CN = system:node:nodename und keine SANs ausgestellt. Und ich habe es getestet, obwohl natürlich der Fehler geändert wird, um genau das anzuzeigen. Das gleiche Zertifikat könnte sowohl als Server als auch als Client verwendet werden, wenn es den Knotennamen als alternativen Betreffnamen hat. Aber ich vermute, es wäre besser, separate Zertifikate für Server / Client zu verwenden?

/ remove-lifecycle eingefroren

/ Lebenszyklus eingefroren

Es ist eingefroren, damit die Bots das Problem nicht schließen.

Das gleiche Zertifikat könnte sowohl als Server als auch als Client verwendet werden, wenn es den Knotennamen als alternativen Betreffnamen hat.

Theoretisch und sofern das Kubelet sie nicht validiert - z. B. "Client-Zertifikat darf keine SANs haben".

Aber ich vermute, es wäre besser, separate Zertifikate für Server / Client zu verwenden?

Es ist üblich, sie auch dann getrennt zu verwenden, wenn dies vermeidbar erscheint. Es ist unwahrscheinlich, dass die Betreuer von kubelet / auth {z | n} dieses Detail ändern.

Hallo. Hab ein bisschen mehr Diggin gemacht. Die Kubelet-Konfigurationsoption serverTLSBootstrap: true kann tatsächlich eine CSR für das Serving-Zertifikat erstellen. Aber es lässt es nicht genehmigt. Welches kann in Ordnung sein?

Das Festlegen von rotateCertificates: true und serverTLSBootsrap: true und das anschließende Genehmigen der CSR für das Serving-Zertifikat scheint der einfachste Weg zu sein. Das angeforderte / ausgestellte Serving-Zertifikat ist für O = system:nodes, CN = system:node:<nodename> mit alternativen Betreffnamen für DNS: <nodename>, IP Address: <node IP address>

Sollte kubeadm at zumindest die Konfigurationsoption serverTLSBootstrap aktivieren, damit die Genehmigung des Serverzertifikats einfach ist? Oder könnte sogar kubeadm die Genehmigung geben?

Hallo. Hab ein bisschen mehr Diggin gemacht. Die Kubelet-Konfigurationsoption serverTLSBootstrap: true kann tatsächlich eine CSR für das Serving-Zertifikat erstellen. Aber es lässt es nicht genehmigt. Welches kann in Ordnung sein?

Das Festlegen von rotateCertificates: true und serverTLSBootsrap: true und das anschließende Genehmigen der CSR für das Serving-Zertifikat scheint der einfachste Weg zu sein. Das angeforderte / ausgestellte Serving-Zertifikat ist für O = system:nodes, CN = system:node:<nodename> mit alternativen Betreffnamen für DNS: <nodename>, IP Address: <node IP address>

Sollte kubeadm at zumindest die Konfigurationsoption serverTLSBootstrap aktivieren, damit die Genehmigung des Serverzertifikats einfach ist? Oder könnte sogar kubeadm die Genehmigung geben?

Sie sind sich der Sicherheitsimplementierungen nicht sicher, können jedoch serverTLSBootstrap mit diesem Operator kombinieren, um die CSRs automatisch zu genehmigen. Https://github.com/kontena/kubelet-rubber-stamp

Sollte kubeadm at zumindest die Konfigurationsoption serverTLSBootstrap aktivieren, damit die Genehmigung des Serverzertifikats einfach ist? Oder könnte sogar kubeadm die Genehmigung geben?

kubeadm kann die Genehmigung nicht ausführen, da kubeadm kein Daemon ist. Es muss ein Controller / Operator bereitgestellt werden, der dies für den Benutzer verwaltet. vielleicht in der Zukunft.

Die Zertifikats-API sollte bald GA-fähig sein, und wir hoffen, dass wir dies in k8s besser verwalten können. bitte hinschauen:
https://github.com/kubernetes/enhancements/issues/267
(Noch unklar für mich, womit wir enden werden ...)

Wir haben auch alternative Ideen. Wenn dies alles versucht, das Metrik-Server-Problem zu lösen, können Sie auch einfach https://github.com/brancz/kube-rbac-proxy verwenden, das SAR für die MS-Anforderungen an das Kubelet ausführen kann. Leider ist dies auf unserer Seite noch nicht dokumentiert:
https://github.com/kubernetes/kubeadm/issues/1602

@ neolit123 Ich habe zumindest angefangen, --kubelet-insecure-tls zu kennzeichnen, aber ich wollte unbedingt sehen, wie man es auf sichere Weise behebt, und interessierte mich dann einfach für das Problem. 🙂

Im Moment ist es für mich einfach genug, der Kubelet-Konfiguration das Flag serverTLSbootstrap hinzuzufügen und die Zertifikate manuell zu genehmigen. Ich habe jedoch einen Nachteil festgestellt, nämlich, dass Sie erst dann vollständig mit Pods auf dem Knoten interagieren können, wenn Sie das Zertifikat genehmigt haben. (kubectl exec kann beispielsweise vor der Genehmigung keinen Befehl für Pods ausführen, die auf einem Knoten ausgeführt werden.)

Ich werde auch das Problem der Verbesserungen verfolgen. Vielen Dank.

Das ist wirklich traurig, dass mit kubeadm, das ausgereift genug zu sein scheint, das Out-of-the-Box-Ergebnis für das Kubeletet-Zertifikat selbstsigniert sein muss und viele Leute kubelet-insecure-tls für den Metrics-Server wählen, anstatt die Dinge richtig zu machen & etc :(

Es ist ein kompliziertes Problem.

bitte versuche:
https://github.com/kontena/kubelet-rubber-stamp
oder
https://github.com/brancz/kube-rbac-proxy
als Problemumgehungen

Es ist ein kompliziertes Problem.

bitte versuche:
https://github.com/kontena/kubelet-rubber-stamp
oder
https://github.com/brancz/kube-rbac-proxy
als Problemumgehungen

Eigentlich funktioniert https://github.com/kontena/kubelet-rubber-stamp ziemlich gut und imo scheint eine korrektere Lösung anstelle von Proxy zu sein.

Schritt 1:
Hinzufügen
serverTLSBootstrap: true bis zum Ende jedes /var/lib/kubelet/config.yaml für die Neukonfiguration von Kubelets und vergessen Sie nicht, config anzuwenden (oder starten Sie sie einfach neu).

Schritt 2:
Kubelet-Stempel einsetzen

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

Schritt 3:
Bearbeiten Sie die Bereitstellung des Metrikservers und entfernen Sie --kubelet-insecure-tls

Ergebnis:

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

Hey, nur um das @vainkop hinzuzufügen
Während Ihres anfänglichen kubeadm init zum Erstellen des Clusters sollten Sie auch in der Lage sein, eine KubeletConfiguration-API-Objektdatei zu übergeben, um serverTLSBootstrap festzulegen

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

...

apiVersion: kubelet.config.k8s.io/v1beta1
Art: KubeletConfiguration
serverTLSBootstrap: true

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

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

To get the CSRs

kubectl get csr
NAME AGE SIGNERNAME REQUESTOR ZUSTAND
csr-2qkdw 2m1s kubernetes.io/kube-apiserver-client-kubelet System: Bootstrap : fcufbo Genehmigt, ausgestellt
csr-9wvgt 114s kubernetes.io/kubelet-serving System: Knoten : Worker-1 Ausstehend
csr-lz97v 4m58s kubernetes.io/kubelet-serving System: Knoten : master-1 Ausstehend
csr-rsdsp 4m59s kubernetes.io/kube-apiserver-client-kubelet System: Knoten : master-1 Genehmigt, ausgestellt
csr-wgxqs 4m49s kubernetes.io/kubelet-serving System: Knoten : master-1 Ausstehend

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.

Kubectl-Zertifikat genehmigt csr-ab123 # ODER Stempel einsetzen!

kubectl get csr
NAME AGE SIGNERNAME REQUESTOR ZUSTAND
csr-9wvgt 3m kubernetes.io/kubelet-serving System: Knoten : Worker-1 Genehmigt, ausgestellt
...
`` `

Eine andere seltsame Sache scheint hier übrigens zu passieren, nämlich dass der Master-Knoten seine CSR zweimal zu erstellen scheint. (Zumindest die zwei Male habe ich das versucht)

Aber wie @nijave oben in einem Kommentar sagt, bin ich mir nicht sicher, welche Sicherheitsauswirkungen die Verwendung des Gummistempels hat.

@allir , @vainkop Soweit ich sehen kann, überprüft der Kubelet-Stempel nur, ob der allgemeine Name des CSR mit dem Namen des Anforderers übereinstimmt, überprüft jedoch nicht, ob die vom Kubelet angeforderten zusätzlichen Hostnamen und IP-Adressen gültig sind. Dies bedeutet, dass ein Angreifer, der Zugriff auf das Kubelet-Client-Zertifikat hat, Zertifikate für grundsätzlich jeden Domänennamen oder jede IP-Adresse erstellen kann. Alle Clients, die so konfiguriert sind, dass sie der Stammzertifizierungsstelle vertrauen, akzeptieren dieses Zertifikat.
Natürlich ist es schwierig, den Hostnamen und die IP-Adressen zu überprüfen, die für ein bestimmtes Kubelet gültig sind, da es derzeit keine Autorität gibt, die bestätigen kann, was ein Kubelet anfordern darf. Beispielsweise reicht die Verwendung des Knotenobjekts auf dem API-Server nicht aus, da Kubelets das Objekt ohne Einschränkungen aktualisieren können.

Hey, nur um das @vainkop hinzuzufügen
Während Ihres anfänglichen kubeadm init zum Erstellen des Clusters sollten Sie auch in der Lage sein, eine KubeletConfiguration-API-Objektdatei zu übergeben, um serverTLSBootstrap festzulegen
kubeadm init --config=kubeadm-config.yaml
Dann werden alle Kubelets automatisch mit dem Flag serverTLSBootstrap .

Oder für ein vorhandenes K8-Setup mit Ansible kann es sein:

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

+ Kubelets neu starten

Wow, ich bin so froh, dass ich dieses Problem gefunden habe, und ich bin nicht allein, wer diesen richtigen Weg gehen will. :) :)

Lassen Sie mich jetzt meine Gedanken zu diesem Thema teilen (bitte korrigieren Sie mich, wenn ich irgendwo falsch liege) :

Zuerst meine Vision des ursprünglichen Problems:
Derzeit aktiviert kubeadm standardmäßig die Webhook-Authentifizierung für alle Kubelets, sodass kubelet Client-Zertifikate für eingehende Verbindungen problemlos überprüft, selbst wenn die Option --kubelet-insecure-tls angegeben ist.
Auf der anderen Seite haben Metrics-Server keine Möglichkeit, ein bestimmtes Kubelet-Zertifikat zu überprüfen, da es auf dem Knoten selbst signiert ist.

Mögliche Risiken bei der Verwendung von --kubelet-insecure-tls für Metrics-Server:
Die Kubelet-Daten sind zwar etwas gesichert und werden dem Metrics-Server ohne erfolgreiche Webhook-Authentifizierung niemals zur Verfügung gestellt.
Theoretisch kann jemand die Server-IP oder den Hostnamen gefährden und falsche Statistiken bereitstellen. Zum Herstellen der Verbindungen verwendet der Metricserver jedoch eine IP-Adresse und Hostnamen, die für den Knoten über kube-apiserver angegeben wurden. Daher muss der Angreifer zuerst den API-Server, DNS oder die IP-Adresse des Knotens hacken.

Kleine Beobachtung:
Der Metrics-Server ist kein einzelner Dienst, der direkt auf die Kubelets zugreift. Kube-apiserver tut dies auch, um die Containerprotokolle zu lesen oder die Shell darauf auszuführen. Die gute Frage ist, wie kube-apiserver sicherstellt, dass eine Verbindung mit dem spezifischen Kubelet hergestellt wird, während keine Informationen über die Zertifizierungsstelle vorliegen, die das Zertifikat ausgestellt hat.
Verhält es sich in diesem Fall nicht genauso wie der Metrikserver mit der Option --kubelet-insecure-tls ?

Mögliche Lösung:
Heutzutage sind die Webhooks und die API-Aggregation in Kubernetes sehr beliebt. Alle verhalten sich ähnlich, indem sie ein eigenes Paar aus Zertifizierungsstelle und CRT / Schlüssel generieren. Der CA-Hash wird auch in einer bestimmten Ressource gespeichert, um kube-apiserver Informationen darüber bereitzustellen, welchem ​​Zertifikat er vertrauen kann.

Beispielsweise:

  • APIServices speichern verwandten CA-Hash in ihrer apiservices.apiregistration.k8s.io -Ressource:

    spec:
    caBundle: <ca-hash>
    
  • Webhooks speichern verwandten CA-Hash in ihren Ressourcen validatingwebhookconfigurations.admissionregistration.k8s.io und mutatingwebhookconfigurations.admissionregistration.k8s.io :

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

Für mich ist es ziemlich offensichtlich, dass jede Knotenressource ähnliche caBundle in ihren spec , wobei Kubelets ihre eigene Zertifizierungsstelle für die Bereitstellung mithilfe ihres Client-Zertifikats registrieren können:

spec:
  caBundle: <ca-hash>

Sowohl der Metris-Server als auch der Kube-Apiserver sollten diese Zertifikate verwenden, um die Verbindung zu den Kubelets zu überprüfen und ihnen zu vertrauen.

Vielen Dank an https://github.com/kubernetes/kubeadm/issues/1223#issuecomment -460854312

Die gute Frage ist, wie kube-apiserver sicherstellt, dass eine Verbindung mit dem spezifischen Kubelet hergestellt wird, während keine Informationen über die Zertifizierungsstelle vorliegen, die das Zertifikat ausgestellt hat.
Verhält es sich in diesem Fall nicht genauso wie der Metrikserver mit der Option --kubelet-insecure-tls ?

Um diese Frage zu beantworten, kann ich hier

Richtig, wir können die Verbindungen vom API-Server zu den Kubelet-Servern nicht überprüfen, da jedes Kubelet über ein eigenes selbstsigniertes Zertifikat verfügt. Wir könnten in Zukunft ein Handbuch in Betracht ziehen, das Flow Wrt Kubelet Serving Certs genehmigt, aber das ist derzeit nicht standardmäßig gesichert.

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

hoffe, es kann eines Tages gelöst werden

[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

Keine Neuigkeiten aus dieser Ausgabe? Ich wäre auch daran interessiert, eine Lösung zu finden.

Wir dokumentieren hier Problemumgehungen:
https://github.com/kubernetes/website/pull/27071
https://github.com/kubernetes/kubeadm/issues/1602

Wir können dieses Problem offen halten, aber aufgrund der Komplexität der standardmäßigen Bereitstellung eines Unterzeichners mit kubeadm ist es unwahrscheinlich, dass wir diese Änderung bald vornehmen werden.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen