Schreibgeschützten Port für Kubelet in GKE-Clustern deaktivieren


Auf dieser Seite wird beschrieben, wie Sie den unsicheren schreibgeschützten Kubelet-Port in GKE-Clustern (Google Kubernetes Engine) deaktivieren, um das Risiko eines nicht autorisierten Zugriffs auf das Kubelet zu reduzieren und Anwendungen zu einem sichereren Port zu migrieren.

In Kubernetes-Clustern, einschließlich GKE, stellt der auf Knoten ausgeführte kubelet-Prozess eine schreibgeschützte API mit dem unsicheren Port 10255 bereit. Kubernetes führt an diesem Port keine Authentifizierungs- oder Autorisierungsprüfungen durch. Kubelet stellt dieselben Endpunkte auf dem sichereren, authentifizierten Port 10250 bereit.

Deaktivieren Sie den schreibgeschützten Port von Kubelet und wechseln Sie alle Arbeitslasten, die Port 10255 verwenden, um stattdessen den sichereren Port 10250 zu verwenden.

Hinweise

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

  • Aktivieren Sie die Google Kubernetes Engine API.
  • Google Kubernetes Engine API aktivieren
  • Wenn Sie die Google Cloud CLI für diese Aufgabe verwenden möchten, müssen Sie die gcloud CLI installieren und dann initialisieren. Wenn Sie die gcloud CLI bereits installiert haben, rufen Sie die neueste Version mit gcloud components update ab.

Voraussetzungen

  • Sie können den unsicheren schreibgeschützten Kubelet-Port nur in GKE-Version 1.26.4-gke.500 oder höher deaktivieren.

Auf unsichere Portnutzung prüfen und Anwendungen migrieren

Bevor Sie den unsicheren schreibgeschützten Port deaktivieren, migrieren Sie alle ausgeführten Anwendungen, die diesen Port verwenden, zum sichereren schreibgeschützten Port. Zu den Arbeitslasten, die möglicherweise eine Migration benötigen, gehören benutzerdefinierte Messwertpipelines und Arbeitslasten, die auf Kubelet-Endpunkte zugreifen.

  • Verwenden Sie für Arbeitslasten, die Zugriff auf die von der kubelet API auf dem Knoten bereitgestellten Informationen benötigen, z. B. Messwerte, den Port 10250.
  • Verwenden Sie stattdessen die Kubernetes API für Arbeitslasten, die Kubernetes-Informationen über die kubelet API auf dem Knoten abrufen, z. B. das Auflisten von Pods auf dem Knoten.

Prüfen, ob Anwendungen den unsicheren schreibgeschützten Kubelet-Port verwenden

In diesem Abschnitt erfahren Sie, wie Sie die unsichere Portnutzung in Ihrem Cluster prüfen.

Im Autopilot-Modus auf Portnutzung prüfen

Zur Prüfung der Portnutzung in einem Autopilot-Cluster benötigen Sie mindestens eine Arbeitslast, die kein DaemonSet im Cluster ist. Wenn Sie die folgenden Schritte auf einem leeren Autopilot-Cluster ausführen, sind die Ergebnisse möglicherweise ungültig.

  1. Speichern Sie das folgende Manifest als read-only-port-metrics.yaml:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: node-metrics-printer-namespace
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: node-metrics-printer-role
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes/metrics
      verbs:
      - get
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: node-metrics-printer-binding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: node-metrics-printer-role
    subjects:
    - kind: ServiceAccount
      name: node-metrics-printer-sa
      namespace: node-metrics-printer-namespace
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: node-metrics-printer-sa
      namespace: node-metrics-printer-namespace
    ---
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-metrics-printer
      namespace: node-metrics-printer-namespace
    spec:
      selector:
        matchLabels:
          app: node-metrics-printer
      template:
        metadata:
          labels:
            app: node-metrics-printer
        spec:
          serviceAccountName: node-metrics-printer-sa
          containers:
          - name: metrics-printer
            image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest
            command: ["sh", "-c"]
            args:
            - 'while true; do curl -s --cacert "${CA_CERT}" -H "Authorization: Bearer $(cat ${TOKEN_FILE})" "https://${NODE_ADDRESS}:10250/metrics"|grep kubelet_http_requests_total; sleep 20; done'
            env:
            - name: CA_CERT
              value: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
            - name: TOKEN_FILE
              value: /var/run/secrets/kubernetes.io/serviceaccount/token
            - name: NODE_ADDRESS
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
    

    Das Manifest tut Folgendes:

    1. Erstellt einen Namespace und richtet RBAC-Rollen ein, um das Lesen von Knotenmesswerten zu ermöglichen.
    2. Stellt ein DaemonSet bereit, das die Kubelet-Messwerte auf den unsicheren schreibgeschützten Port prüft.
  2. Stellen Sie das Manifest bereit:

    kubectl create -f read-only-port-metrics.yaml
    
  3. Prüfen Sie die DaemonSet-Logs:

    kubectl logs --namespace=node-metrics-printer-namespace \
        --all-containers --prefix \
        --selector=app=node-metrics-printer
    

    Wenn die Ausgabe Ergebnisse liefert, die den String server_type=readonly enthalten, verwendet eine Anwendung den unsicheren schreibgeschützten Port.

Im Standardmodus auf Portnutzung prüfen

Führen Sie den folgenden Befehl auf mindestens einem Knoten in jedem Knotenpool in Ihrem Cluster aus:

kubectl get --raw /api/v1/nodes/NODE_NAME/proxy/metrics | grep http_requests_total | grep readonly

Ersetzen Sie NODE_NAME durch den Namen des Knotens.

Wenn Arbeitslasten auf dem Knoten den unsicheren schreibgeschützten Kubelet-Port verwenden, enthält die Ausgabe Einträge mit dem String server_type="readonly" wie im folgenden Beispiel:

kubelet_http_requests_total{long_running="false",method="GET",path="healthz",server_type="readonly"} 3
kubelet_http_requests_total{long_running="false",method="GET",path="metrics",server_type="readonly"} 2549
kubelet_http_requests_total{long_running="false",method="GET",path="metrics/probes",server_type="readonly"} 2546
kubelet_http_requests_total{long_running="false",method="GET",path="other",server_type="readonly"} 2
kubelet_http_requests_total{long_running="false",method="GET",path="pods",server_type="readonly"} 1
kubelet_http_requests_total{long_running="false",method="GET",path="stats",server_type="readonly"} 2549

Wenn die Ausgabe leer ist, verwenden keine Anwendungen auf diesem Knoten den unsicheren schreibgeschützten Port.

Vom unsicheren schreibgeschützten Kubelet-Port migrieren

Das Migrieren einer Anwendung zum sicheren Port umfasst in der Regel die folgenden Schritte:

  1. Aktualisieren Sie URLs oder Endpunkte, die auf den unsicheren schreibgeschützten Port verweisen, um stattdessen den sicheren schreibgeschützten Port zu verwenden. Ändern Sie beispielsweise http://203.0.113.104:10255 in http://203.0.113.104:10250.

  2. Legen Sie das Zertifikat der Zertifizierungsstelle (Certificate Authority, CA) des HTTP-Clients auf das Cluster-CA-Zertifikat fest. Führen Sie den folgenden Befehl aus, um dieses Zertifikat zu ermitteln:

    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --format="value(masterAuth.clusterCaCertificate)"
    

    Ersetzen Sie Folgendes:

    • CLUSTER_NAME: Der Name Ihres Clusters.
    • LOCATION: Der Standort Ihres Clusters.

Für den authentifizierten Port 10250 müssen Sie dem Subjekt die entsprechenden RBAC-Rollen zuweisen, um auf die jeweiligen Ressourcen zugreifen zu können. Weitere Informationen finden Sie in der Kubernetes-Dokumentation unter Kubelet-Autorisierung.

Wenn Ihre Arbeitslast den Endpunkt /pods auf dem unsicheren schreibgeschützten Kubelet-Port verwendet, müssen Sie die RBAC-Berechtigung nodes/proxy für den Zugriff auf den Endpunkt auf dem sicheren Kubelet-Port erteilen. nodes/proxy ist eine leistungsstarke Berechtigung, die Sie in GKE Autopilot-Clustern nicht erteilen können und die Sie in GKE Standard-Clustern nicht gewähren sollten. Verwenden Sie stattdessen die Kubernetes API mit einem fieldSelector für den Knotennamen.

Wenn Sie Anwendungen von Drittanbietern verwenden, die vom unsicheren schreibgeschützten Kubelet-Port abhängen, wenden Sie sich an den Anwendungsanbieter, um eine Anleitung zum Migrieren zum sicheren Port 10250 zu erhalten.

Beispielmigration

Betrachten Sie einen Pod, der Messwerte aus dem unsicheren schreibgeschützten Kubelet-Port abfragt.

apiVersion: v1
kind: Pod
metadata:
  name: kubelet-readonly-example
spec:
  restartPolicy: Never
  containers:
  - name: kubelet-readonly-example
    image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest
    command:
      - curl
      - http://$(NODE_ADDRESS):10255/metrics
    env:
    - name: NODE_ADDRESS
      valueFrom:
        fieldRef:
          fieldPath: status.hostIP

Diese Anwendung tut Folgendes:

  • Verwendet das default-Dienstkonto im Namespace default
  • Führt den Befehl curl für den Endpunkt /metrics auf dem Knoten aus.

So aktualisieren Sie diesen Pod für die Verwendung des sicheren Ports 10250:

  1. Erstellen Sie eine ClusterRole mit Zugriff zum Abrufen von Knotenmesswerten:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: curl-authenticated-role
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes/metrics
      verbs:
      - get
    
  2. Binden Sie die ClusterRole an die Identität Ihrer Anwendung:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: curl-authenticated-role-binding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: curl-authenticated-role
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: default
    
  3. Aktualisieren Sie den Befehl curl, um den sicheren Port-Endpunkt mit den entsprechenden Autorisierungsheadern zu verwenden:

    apiVersion: v1
    kind: Pod
    metadata:
      name: kubelet-authenticated-example
    spec:
      restartPolicy: Never
      containers:
      - name: kubelet-readonly-example
        image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest
        env:
        - name: NODE_ADDRESS
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        command:
        - sh
        - -c
        - 'curl -s --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization:
          Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://${NODE_ADDRESS}:10250/metrics'
    

VPC-Firewallregeln ändern

Wenn Sie Arbeitslasten für die Verwendung von Port 10250 aktualisieren, erstellen Sie Firewallregeln, damit Pods im Cluster den Port in Ihren Knoten-IP-Adressbereichen erreichen können. Die Firewallregeln sollten Folgendes tun:

  • Eingehenden Traffic zum TCP-Port 10250 in den Knoten-IP-Adressbereichen aus internen Pod-IP-Adressbereichen zulassen
  • Verweigern Sie eingehenden Traffic zum TCP-Port 10250 in Ihren Knoten-IP-Adressbereichen aus dem öffentlichen Internet.

Sie können die folgenden Standard-GKE-Firewallregeln als Vorlage für die Parameter verwenden, die in Ihren neuen Regeln angegeben werden sollen:

  • gke-[cluster-name]-[cluster-hash]-inkubelet
  • gke-[cluster-name]-[cluster-hash]-exkubelet

Unsicheren schreibgeschützten Port in Autopilot-Clustern deaktivieren

Sie können den unsicheren schreibgeschützten Kubelet-Port für neue und vorhandene Autopilot-Cluster deaktivieren.

Unsicheren schreibgeschützten Port für neue Autopilot-Cluster deaktivieren

Zum Deaktivieren des unsicheren schreibgeschützten Kubelet-Ports beim Erstellen eines neuen Autopilot-Clusters verwenden Sie das Flag --no-autoprovisioning-enable-insecure-kubelet-readonly-port wie im folgenden Befehl:

gcloud container clusters create-auto CLUSTER_NAME \
    --location=LOCATION \
    --no-autoprovisioning-enable-insecure-kubelet-readonly-port

Ersetzen Sie Folgendes:

  • CLUSTER_NAME: Der Name Ihres neuen Autopilot-Clusters.
  • LOCATION: Der Standort Ihres neuen Autopilot-Clusters.

Unsicheren schreibgeschützten Port auf vorhandenen Autopilot-Clustern deaktivieren

Verwenden Sie das Flag --no-autoprovisioning-enable-insecure-kubelet-readonly-port, wie im folgenden Befehl, um den unsicheren schreibgeschützten Kubelet-Port auf einem vorhandenen Autopilot-Cluster zu deaktivieren. Alle neuen und vorhandenen Knoten im Cluster verwenden den Port nicht mehr.

gcloud container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --no-autoprovisioning-enable-insecure-kubelet-readonly-port

Ersetzen Sie Folgendes:

  • CLUSTER_NAME ist der Name Ihres vorhandenen Clusters.
  • LOCATION ist der Standort Ihres vorhandenen Clusters.

Unsicheren schreibgeschützten Port in Standardclustern deaktivieren

Sie können den unsicheren schreibgeschützten Kubelet-Port für ganze Standardcluster oder für einzelne Knotenpools deaktivieren. Wir empfehlen, den Port für den gesamten Cluster zu deaktivieren.

Wenn Sie die automatische Knotenbereitstellung verwenden, übernehmen automatisch bereitgestellte Knotenpools die Porteinstellung, die Sie auf Clusterebene angeben. Sie können optional eine andere Einstellung für automatisch bereitgestellte Knotenpools angeben. Wir empfehlen jedoch, den Port für alle Knoten in Ihrem Cluster zu deaktivieren.

Sie können auch eine Knotensystemkonfigurationsdatei verwenden, um den unsicheren schreibgeschützten Kubelet-Port deklarativ zu deaktivieren. Wenn Sie diese Datei verwenden, können Sie die Befehle in den folgenden Abschnitten nicht verwenden, um die Kubelet-Einstellung zu steuern.

Unsicheren schreibgeschützten Port für neue Standardcluster deaktivieren

Verwenden Sie das Flag --no-enable-insecure-kubelet-readonly-port wie im folgenden Befehl, um den unsicheren schreibgeschützten Kubelet-Port für einen neuen Standardcluster zu deaktivieren:

gcloud container clusters create CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-insecure-kubelet-readonly-port

Ersetzen Sie Folgendes:

  • CLUSTER_NAME: Der Name des neuen Standardclusters.
  • LOCATION: Der Standort des neuen Standardclusters.

Sie können optional das Flag --no-autoprovisioning-enable-insure-kubelet-readonly-port hinzufügen, um die Einstellung für die automatische Knotenbereitstellung separat zu steuern. Dieser Ansatz wird jedoch nicht empfohlen. Mit diesem Flag wird ein Rolling Update Ihrer automatisch bereitgestellten Knotenpools gestartet, was zu Unterbrechungen bei den laufenden Arbeitslasten führen kann.

Unsicheren schreibgeschützten Port auf vorhandenen Standardclustern deaktivieren

Um den unsicheren schreibgeschützten Kubelet-Port auf einem vorhandenen Standardcluster zu deaktivieren, verwenden Sie das Flag --no-enable-insecure-kubelet-readonly-port wie im folgenden Befehl. Neue Knotenpools verwenden nicht den unsicheren Port. GKE aktualisiert vorhandene Knotenpools nicht automatisch.

gcloud container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-insecure-kubelet-readonly-port

Ersetzen Sie Folgendes:

  • CLUSTER_NAME ist der Name Ihres vorhandenen Standardclusters.
  • LOCATION: Der Standort Ihres vorhandenen Standardclusters.

Unsicheren schreibgeschützten Port in Standardknotenpools deaktivieren

Es wird empfohlen, die Einstellung für den schreibgeschützten Port in jedem Fall auf Clusterebene festzulegen. Wenn Sie den schreibgeschützten Port in einem vorhandenen Cluster deaktiviert haben, in dem bereits Knotenpools ausgeführt wurden, deaktivieren Sie den Port mit dem folgenden Befehl auf diesen Knotenpools.

gcloud container node-pools update NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --no-enable-insecure-kubelet-readonly-port

Ersetzen Sie Folgendes:

  • NODE_POOL_NAME: Der Name des Knotenpools.
  • CLUSTER_NAME ist der Name des Clusters.
  • LOCATION: Der Standort des Clusters.

Prüfen Sie, ob der Port deaktiviert ist

Beschreiben Sie die GKE-Ressource, um zu prüfen, ob der unsichere schreibgeschützte Kubelet-Port deaktiviert ist.

Portstatus in Autopilot-Clustern prüfen

Führen Sie dazu diesen Befehl aus:

gcloud container clusters describe CLUSTER_NAME \
    --location=LOCATION \
    --flatten=nodePoolAutoConfig \
    --format="value(nodeKubeletConfig)"

Ersetzen Sie Folgendes:

  • CLUSTER_NAME: Der Name Ihres Autopilot-Clusters.
  • LOCATION: Der Standort Ihres Autopilot-Clusters.

Wenn der Port deaktiviert ist, sieht die Ausgabe so aus:

insecureKubeletReadonlyPortEnabled: false

Portstatus in Standardclustern prüfen

Der Portstatus ist im Feld nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig verfügbar, wenn Sie Ihren Cluster mit der GKE API beschreiben.

In Standardclustern wird auch das Feld nodeConfig angezeigt, das einen Wert für den schreibgeschützten Kubelet-Portstatus festlegt. Das Feld nodeConfig wurde verworfen und gilt nur für den Standardknotenpool, den GKE beim Erstellen eines neuen Clusters im Standardmodus erstellt. Der Status des Ports im verworfenen Feld nodeConfig gilt nicht für andere Knotenpools im Cluster.

Führen Sie dazu diesen Befehl aus:

gcloud container clusters describe CLUSTER_NAME \
    --location=LOCATION \
    --flatten=nodePoolDefaults.nodeConfigDefaults \
    --format="value(nodeKubeletConfig)"

Ersetzen Sie Folgendes:

  • CLUSTER_NAME: Der Name Ihres Standardclusters.
  • LOCATION: Der Standort Ihres Standardclusters.

Wenn der Port deaktiviert ist, sieht die Ausgabe so aus:

insecureKubeletReadonlyPortEnabled: false

Portstatus in Standardknotenpools prüfen

Führen Sie dazu diesen Befehl aus:

gcloud container node-pools describe NODE_POOL_NAME \
    --cluster= CLUSTER_NAME \
    --location=LOCATION \
    --flatten=config \
    --format="value(kubeletConfig)"

Ersetzen Sie Folgendes:

  • NODE_POOL_NAME: Der Name des Knotenpools.
  • CLUSTER_NAME ist der Name des Clusters.
  • LOCATION: Der Standort des Clusters.

Wenn der Port deaktiviert ist, sieht die Ausgabe so aus:

insecureKubeletReadonlyPortEnabled: false