Désactiver le port accessible en lecture seule du kubelet dans les clusters GKE


Cette page explique comment désactiver le port non sécurisé du kubelet accessible en lecture seule, dans les clusters Google Kubernetes Engine (GKE), afin de réduire le risque d'accès non autorisé au kubelet. Elle explique également comment migrer des applications vers un port plus sécurisé.

Dans les clusters Kubernetes, y compris GKE, le processus kubelet exécuté sur les nœuds diffuse une API en lecture seule via le port non sécurisé 10255. Kubernetes n'effectue aucun contrôle d'authentification ou d'autorisation sur ce port. Le kubelet diffuse les mêmes points de terminaison sur le port 10250, authentifié et plus sécurisé.

Désactivez le port en lecture seule du kubelet et modifiez toutes les charges de travail qui utilisent le port 10255 pour qu'elles utilisent le port plus sécurisé 10250.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande gcloud components update.

Conditions requises

  • Vous ne pouvez désactiver le port accessible en lecture seule et non sécurisé du kubelet que dans la version 1.26.4-gke.500 ou une version ultérieure de GKE.

Vérifier l'utilisation des ports non sécurisés et migrer les applications

Avant de désactiver le port en lecture seule non sécurisé, migrez toutes vos applications en cours d'exécution qui utilisent le port vers le port en lecture seule plus sécurisé. Les charges de travail qui peuvent nécessiter une migration incluent les pipelines de métriques personnalisées et les charges de travail qui accèdent aux points de terminaison kubelet.

  • Pour les charges de travail qui doivent accéder aux informations diffusées par l'API kubelet sur le nœud, telles que les métriques, utilisez le port 10250.
  • Pour les charges de travail qui obtiennent des informations Kubernetes à l'aide de l'API kubelet sur le nœud, comme la liste des pods sur le nœud, utilisez plutôt l'API Kubernetes.

Vérifier si les applications utilisent le port accessible en lecture seule et non sécurisé du kubelet

Cette section explique comment vérifier l'utilisation de ports non sécurisés dans votre cluster.

Vérifier l'utilisation des ports en mode Autopilot

Pour vérifier l'utilisation des ports dans un cluster Autopilot, assurez-vous d'avoir au moins une charge de travail qui n'est pas un DaemonSet exécuté dans le cluster. Si vous effectuez les étapes suivantes sur un cluster Autopilot vide, les résultats peuvent ne pas être valides.

  1. Enregistrez le manifeste suivant sous le nom 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
    

    Ce fichier manifeste effectue les opérations suivantes :

    1. Crée un espace de noms et configure des rôles RBAC pour permettre la lecture des métriques de nœud.
    2. Déploie un DaemonSet qui vérifie les métriques kubelet pour le port en lecture seule non sécurisé.
  2. Déployez le fichier manifeste :

    kubectl create -f read-only-port-metrics.yaml
    
  3. Vérifiez les journaux DaemonSet :

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

    Si le résultat contient des résultats contenant la chaîne server_type=readonly, une application utilise le port non sécurisé en lecture seule.

Vérifier l'utilisation des ports en mode standard

Exécutez la commande suivante sur au moins un nœud de chaque pool de nœuds de votre cluster :

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

Remplacez NODE_NAME par le nom du nœud.

Si les charges de travail du nœud utilisent le port accessible en lecture seule non sécurisé du kubelet, le résultat contient des entrées avec la chaîne server_type="readonly", comme dans l'exemple suivant :

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

Si le résultat est vide, aucune application sur ce nœud n'utilise le port non sécurisé en lecture seule.

Migrer depuis le port accessible en lecture seule et non sécurisé du kubelet

En règle générale, la migration d'une application vers le port sécurisé implique les étapes suivantes :

  1. Mettez à jour les URL ou les points de terminaison qui font référence au port en lecture seule non sécurisé afin d'utiliser le port en lecture seule sécurisé à la place. Par exemple, remplacez http://203.0.113.104:10255 par http://203.0.113.104:10250.

  2. Définissez le certificat CA du client HTTP sur le certificat CA du cluster. Pour trouver ce certificat, exécutez la commande suivante :

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

    Remplacez les éléments suivants :

    • CLUSTER_NAME : nom du cluster
    • LOCATION : emplacement de votre cluster.

Le port authentifié 10250 nécessite que vous accordiez des rôles RBAC appropriés à l'utilisateur pour accéder aux ressources spécifiques. Pour en savoir plus, consultez la page concernant l'autorisation kubelet dans la documentation Kubernetes.

Si votre charge de travail utilise le point de terminaison /pods sur le port en lecture seule non sécurisé du kubelet, vous devez accorder l'autorisation RBAC nodes/proxy d'accéder au point de terminaison sur le port sécurisé du kubelet. nodes/proxy est une autorisation puissante que vous ne pouvez pas accorder dans les clusters GKE Autopilot et que vous ne devez pas accorder dans les clusters GKE Standard. Utilisez plutôt l'API Kubernetes avec un fieldSelector pour le nom du nœud.

Si vous utilisez des applications tierces qui dépendent du port en lecture seule non sécurisé du kubelet, contactez le fournisseur de l'application pour obtenir des instructions sur la migration vers le port sécurisé 10250.

Exemple de migration

Prenons l'exemple d'un pod qui interroge les métriques du port non sécurisé en lecture seule du kubelet.

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

Cette application effectue les opérations suivantes :

  • Utilise le compte de service default dans l'espace de noms default.
  • Exécute la commande curl sur le point de terminaison /metrics du nœud.

Pour mettre à jour ce pod afin qu'il utilise le port sécurisé 10250, procédez comme suit :

  1. Créez un objet ClusterRole ayant accès pour obtenir des métriques de nœud :

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: curl-authenticated-role
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes/metrics
      verbs:
      - get
    
  2. Liez le ClusterRole à l'identité de votre application :

    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. Mettez à jour la commande curl pour utiliser le point de terminaison du port sécurisé avec les en-têtes d'autorisation correspondants :

    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'
    

Modifier des règles de pare-feu VPC

Si vous mettez à jour des charges de travail pour qu'elles utilisent le port 10250, créez des règles de pare-feu afin que les pods du cluster puissent atteindre le port situé dans les plages d'adresses IP de vos nœuds. Les règles de pare-feu doivent effectuer les opérations suivantes :

  • Autorisez le trafic entrant vers le port TCP 10250 sur les plages d'adresses IP de vos nœuds à partir de plages d'adresses IP de pods internes.
  • Refusez le trafic entrant vers le port TCP 10250 sur les plages d'adresses IP de votre nœud depuis l'Internet public.

Vous pouvez utiliser les règles de pare-feu GKE par défaut ci-dessous comme modèle pour les paramètres à spécifier dans vos nouvelles règles :

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

Désactiver le port non sécurisé en lecture seule sur les clusters Autopilot

Vous pouvez désactiver le port accessible en lecture seule et non sécurisé du kubelet pour les clusters Autopilot nouveaux et existants.

Désactiver le port non sécurisé en lecture seule sur les nouveaux clusters Autopilot

Pour désactiver le port accessible en lecture seule et non sécurisé du kubelet lorsque vous créez un cluster Autopilot, utilisez l'option --no-autoprovisioning-enable-insecure-kubelet-readonly-port, comme dans la commande suivante :

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre nouveau cluster Autopilot.
  • LOCATION : emplacement de votre nouveau cluster Autopilot.

Désactiver le port non sécurisé en lecture seule sur les clusters Autopilot existants

Pour désactiver le port accessible en lecture seule et non sécurisé du kubelet sur un cluster Autopilot existant, utilisez l'option --no-autoprovisioning-enable-insecure-kubelet-readonly-port, comme dans la commande suivante. Tous les nœuds nouveaux et existants du cluster cessent d'utiliser le port.

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre cluster existant.
  • LOCATION : emplacement de votre cluster existant.

Désactiver le port non sécurisé en lecture seule sur les clusters standards

Vous pouvez désactiver le port non sécurisé en lecture seule du kubelet pour des clusters standards ou pour les pools de nœuds individuels. Nous vous recommandons de désactiver le port pour l'ensemble du cluster.

Si vous utilisez le provisionnement automatique des nœuds, les pools de nœuds provisionnés automatiquement héritent du paramètre de port que vous spécifiez au niveau du cluster. Vous pouvez éventuellement spécifier un paramètre différent pour les pools de nœuds provisionnés automatiquement, mais nous vous recommandons de désactiver le port sur tous les nœuds de votre cluster.

Vous pouvez également utiliser un fichier de configuration du système de nœud pour désactiver de manière déclarative le port non sécurisé du kubelet accessible en lecture seule. Si vous utilisez ce fichier, vous ne pouvez pas contrôler le paramètre kubelet à l'aide des commandes des sections suivantes.

Désactiver le port non sécurisé en lecture seule sur les nouveaux clusters standards

Pour désactiver le port accessible en lecture seule et non sécurisé du kubelet sur un nouveau cluster Standard, utilisez l'option --no-enable-insecure-kubelet-readonly-port comme dans la commande suivante :

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre nouveau cluster Standard.
  • LOCATION : emplacement de votre nouveau cluster Standard.

Vous pouvez éventuellement ajouter l'indicateur --no-autoprovisioning-enable-insure-kubelet-readonly-port pour contrôler séparément le paramètre de provisionnement automatique des nœuds, mais nous ne recommandons pas cette approche. Cette option lance une mise à jour progressive de vos pools de nœuds provisionnés automatiquement, ce qui peut perturber vos charges de travail en cours d'exécution.

Désactiver le port non sécurisé en lecture seule sur des clusters standards existants

Pour désactiver le port accessible en lecture seule et non sécurisé du kubelet sur un cluster Standard existant, utilisez l'option --no-enable-insecure-kubelet-readonly-port comme dans la commande suivante. Les nouveaux pools de nœuds n'utilisent pas le port non sécurisé. GKE ne met pas automatiquement à jour les pools de nœuds existants.

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre cluster Standard existant.
  • LOCATION : emplacement de votre cluster standard existant.

Désactiver le port non sécurisé en lecture seule sur les pools de nœuds standards

Dans tous les cas, nous vous recommandons de définir le paramètre de port en lecture seule au niveau du cluster. Si vous avez désactivé le port en lecture seule sur un cluster existant qui disposait déjà de pools de nœuds en cours d'exécution, utilisez la commande suivante pour désactiver le port sur ces pools de nœuds.

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

Remplacez les éléments suivants :

  • NODE_POOL_NAME : nom de votre pool de nœuds.
  • CLUSTER_NAME : nom du cluster.
  • LOCATION : emplacement du cluster.

Vérifier que le port est désactivé

Pour vérifier que le port accessible en lecture seule et non sécurisé du kubelet est désactivé, décrivez la ressource GKE.

Vérifier l'état du port dans les clusters Autopilot

Exécutez la commande ci-dessous.

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre cluster Autopilot.
  • LOCATION : emplacement de votre cluster Autopilot.

Si le port est désactivé, le résultat est le suivant :

insecureKubeletReadonlyPortEnabled: false

Vérifier l'état du port dans les clusters standards

L'état du port est disponible dans le champ nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig lorsque vous décrivez votre cluster à l'aide de l'API GKE.

Dans les clusters standards, vous verrez également un champ nodeConfig qui définit une valeur pour l'état du port en lecture seule du kubelet. Le champ nodeConfig est obsolète et ne s'applique qu'au pool de nœuds par défaut créé par GKE lorsque vous créez un cluster en mode Standard. L'état du port dans le champ obsolète nodeConfig ne s'applique pas aux autres pools de nœuds du cluster.

Exécutez la commande ci-dessous.

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

Remplacez les éléments suivants :

  • CLUSTER_NAME : nom de votre cluster Standard.
  • LOCATION : emplacement de votre cluster standard.

Si le port est désactivé, le résultat est le suivant :

insecureKubeletReadonlyPortEnabled: false

Vérifier l'état des ports dans les pools de nœuds standards

Exécutez la commande ci-dessous.

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

Remplacez les éléments suivants :

  • NODE_POOL_NAME : nom de votre pool de nœuds.
  • CLUSTER_NAME : nom du cluster.
  • LOCATION : emplacement du cluster.

Si le port est désactivé, le résultat est le suivant :

insecureKubeletReadonlyPortEnabled: false