En esta página, se muestra cómo inhabilitar el puerto de solo lectura de kubelet no seguro en clústeres de Google Kubernetes Engine (GKE) para reducir el riesgo de acceso no autorizado a kubelet y cómo migrar aplicaciones a un puerto más seguro.
En los clústeres de Kubernetes, incluido GKE, el proceso de kubelet que se ejecuta en los nodos entrega una API de solo lectura que usa el puerto no seguro 10255.
Kubernetes no realiza ninguna verificación de autenticación ni de autorización en este puerto. Kubelet entrega los mismos extremos en el puerto 10250 autenticado y más seguro.
Inhabilita el puerto de solo lectura de kubelet y cambia las cargas de trabajo que usan el puerto
10255 para usar el puerto 10250 más seguro en su lugar.
Antes de comenzar
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
- Habilita la API de Google Kubernetes Engine. Habilita la API de Google Kubernetes Engine
- Para usar Google Cloud CLI para esta tarea,
instala y, luego,
inicializa la
gcloud CLI. Si instalaste gcloud CLI anteriormente, ejecuta el comando
gcloud components updatepara obtener la versión más reciente. Es posible que las versiones anteriores de gcloud CLI no admitan la ejecución de los comandos de este documento.
- Asegúrate de tener un clúster de Autopilot o Standard existente. Para crear un clúster nuevo, consulta Crea un clúster de Autopilot.
Requisitos
- Solo puedes inhabilitar el puerto de solo lectura de kubelet no seguro en la versión 1.26.4-gke.500 de GKE o versiones posteriores.
Verifica el uso de puertos no seguros y migra aplicaciones
Antes de inhabilitar el puerto de solo lectura no seguro, migra cualquiera de tus aplicaciones en ejecución que usen el puerto al puerto de solo lectura más seguro. Las cargas de trabajo que podrían necesitar migración incluyen canalizaciones de métricas personalizadas y cargas de trabajo que acceden a extremos de kubelet.
- Para las cargas de trabajo que necesitan acceder a la información que entrega la API de kubelet en el nodo, como las métricas, usa el puerto
10250. - Para las cargas de trabajo que obtienen información de Kubernetes con la API de kubelet en el nodo, como la enumeración de Pods en el nodo, usa la API de Kubernetes en su lugar.
Verifica si las aplicaciones usan el puerto de solo lectura de kubelet no seguro
En esta sección, se muestra cómo verificar el uso de puertos no seguros en tu clúster.
Verifica el uso de puertos en el modo Autopilot
Para verificar el uso de puertos en un clúster de Autopilot, asegúrate de tener al menos una carga de trabajo que no sea un DaemonSet en ejecución en el clúster. Si realizas los siguientes pasos en un clúster de Autopilot vacío, es posible que los resultados no sean válidos.
Guarda el siguiente manifiesto como
read-only-port-metrics.yaml:# Create a namespace for the DaemonSet that checks for port usage. apiVersion: v1 kind: Namespace metadata: name: node-metrics-printer-namespace --- # Grant access to read node metrics in the cluster. 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 # Bind the ClusterRole to the ServiceAccount that the DaemonSet will use. subjects: - kind: ServiceAccount name: node-metrics-printer-sa namespace: node-metrics-printer-namespace --- # Create a ServiceAccount for the DaemonSet. 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: # Assign the ServiceAccount to the DaemonSet. serviceAccountName: node-metrics-printer-sa containers: - name: metrics-printer image: us-docker.pkg.dev/cloud-builders/ga/v1/curl:latest command: ["sh", "-c"] # Call the /metrics endpoint using the insecure kubelet read-only # port. 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: # Provide credentials and the IP address for the command. - 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.hostIPEste manifiesto hace lo siguiente:
- Crea un espacio de nombres y configura roles de RBAC para permitir la lectura de métricas de nodos.
- Implementa un DaemonSet que verifica las métricas de kubelet para el puerto de solo lectura no seguro.
Implementa el manifiesto:
kubectl create -f read-only-port-metrics.yamlVerifica los registros de DaemonSet:
kubectl logs --namespace=node-metrics-printer-namespace \ --all-containers --prefix \ --selector=app=node-metrics-printerSi el resultado tiene algún resultado que contenga la cadena
server_type=readonly, una aplicación usa el puerto de solo lectura no seguro.
Verifica el uso de puertos en el modo Standard
Ejecuta el siguiente comando en al menos un nodo de cada grupo de nodos de tu clúster:
kubectl get --raw /api/v1/nodes/NODE_NAME/proxy/metrics | grep http_requests_total | grep readonly
Reemplaza NODE_NAME por el nombre del conjunto de datos.
Si el resultado contiene entradas con la cadena server_type="readonly", pueden ocurrir las siguientes situaciones:
- Las cargas de trabajo en el nodo usan el puerto de solo lectura de kubelet no seguro.
- Después de inhabilitar el puerto no seguro, el comando aún muestra la cadena
server_type="readonly". Esto se debe a que la métricakubelet_http_requests_totalrepresenta la cantidad acumulada de solicitudes HTTP que recibe el servidor de kubelet desde su último reinicio. Este número no se restablece cuando se inhabilita el puerto no seguro. Este número se restablece después de que GKE reinicia el servidor de kubelet, como durante una actualización de nodos. Para obtener más información, consulta la referencia de métricas de Kubernetes.
Si el resultado está vacío, ninguna carga de trabajo en ese nodo usa el puerto de solo lectura no seguro.
Identifica las cargas de trabajo que usan el puerto de solo lectura de kubelet no seguro
Para identificar las cargas de trabajo que usan el puerto no seguro, verifica los archivos de configuración de la carga de trabajo, como ConfigMaps y Pods.
Ejecuta los siguientes comandos:
kubectl get pods --all-namespaces -o yaml | grep 10255
kubectl get configmaps --all-namespaces -o yaml | grep 10255
Si el resultado del comando no está vacío, usa la siguiente secuencia de comandos para identificar los nombres de los ConfigMaps o Pods que usan el puerto no seguro:
# This function checks if a Kubernetes resource is using the insecure port 10255.
#
# Arguments:
# $1 - Resource type (e.g., pod, configmap, )
# $2 - Resource name
# $3 - Namespace
#
# Output:
# Prints a message indicating whether the resource is using the insecure port.
isUsingInsecurePort() {
resource_type=$1
resource_name=$2
namespace=$3
config=$(kubectl get $resource_type $resource_name -n $namespace -o yaml)
# Check if kubectl output is empty
if [[ -z "$config" ]]; then
echo "No configuration file detected for $resource_type: $resource_name (Namespace: $namespace)"
return
fi
if echo "$config" | grep -q "10255"; then
echo "Warning: The configuration file ($resource_type: $namespace/$resource_name) is using insecure port 10255. It is recommended to migrate to port 10250 for enhanced security."
else
echo "Info: The configuration file ($resource_type: $namespace/$resource_name) is not using insecure port 10255."
fi
}
# Get the list of ConfigMaps with their namespaces
configmaps=$(kubectl get configmaps -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | tail -n +2 | awk '{print $1"/"$2}')
# Iterate over each ConfigMap
for configmap in $configmaps; do
namespace=$(echo $configmap | cut -d/ -f1)
configmap_name=$(echo $configmap | cut -d/ -f2)
isUsingInsecurePort "configmap" "$configmap_name" "$namespace"
done
# Get the list of Pods with their namespaces
pods=$(kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | tail -n +2 | awk '{print $1"/"$2}')
# Iterate over each Pod
for pod in $pods; do
namespace=$(echo $pod | cut -d/ -f1)
pod_name=$(echo $pod | cut -d/ -f2)
isUsingInsecurePort "pod" "$pod_name" "$namespace"
done
Una vez que hayas identificado las cargas de trabajo pertinentes, migra para que usen el puerto seguro 10250. Para ello, completa los pasos de la siguiente sección.
Migra desde el puerto de solo lectura de kubelet no seguro
Por lo general, la migración de una aplicación al puerto seguro implica los siguientes pasos:
Actualiza las URLs o los extremos que hacen referencia al puerto de solo lectura no seguro para usar el puerto de solo lectura seguro en su lugar. Por ejemplo, cambia
http://203.0.113.104:10255ahttp://203.0.113.104:10250.Configura el certificado de la autoridad certificadora (AC) del cliente HTTP como el certificado de AC del clúster. Para encontrar este certificado, ejecuta el siguiente comando:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="value(masterAuth.clusterCaCertificate)"Reemplaza lo siguiente:
CLUSTER_NAME: El nombre de tu clúster.LOCATION: Es la ubicación de tu clúster.
El puerto autenticado 10250 requiere que otorgues los roles de RBAC adecuados al sujeto para acceder a los recursos específicos. Para obtener más detalles, consulta la
autorización de kubeleten la
documentación de Kubernetes.
Si tu carga de trabajo usa el extremo /pods en el puerto de solo lectura no seguro de kubelet, debes otorgar el permiso de RBAC nodes/proxy para acceder al extremo en el puerto seguro de kubelet. nodes/proxy es un permiso potente que no puedes otorgar en los clústeres de GKE Autopilot y que no deberías otorgar en los clústeres de GKE Standard. En su lugar, usa la
API de Kubernetes con un fieldSelector
para el nombre del nodo.
Si usas aplicaciones de terceros que dependen del puerto de solo lectura no seguro de kubelet, consulta al proveedor de la aplicación para obtener instrucciones para migrar al puerto seguro 10250.
Ejemplo de migración
Considera un Pod que consulta las métricas del puerto de solo lectura de kubelet no seguro.
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
Esta aplicación hace lo siguiente:
- Usa la ServiceAccount
defaulten el espacio de nombresdefault. - Ejecuta el comando
curlen el extremo/metricsdel nodo.
Para actualizar este Pod y que use el puerto seguro 10250, sigue estos pasos:
Crea un ClusterRole con acceso para obtener métricas de nodos:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: curl-authenticated-role rules: # Grant access to read node metrics in the cluster. - apiGroups: - "" resources: - nodes/metrics verbs: - getVincula el ClusterRole a la identidad de tu aplicación:
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 # Bind the ClusterRole to the default ServiceAccount in the default # namespace. subjects: - kind: ServiceAccount name: default namespace: defaultActualiza el comando
curlpara usar el extremo del puerto seguro con los encabezados de autorización correspondientes: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 # Update the command to send a request with the ServiceAccount # credentials in the header. 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'
Modifica las reglas de firewall de VPC
Si actualizas las cargas de trabajo para usar el puerto 10250, crea reglas de firewall para que los Pods del clúster puedan alcanzar el puerto en los rangos de direcciones IP de tu nodo. Las reglas de firewall deben hacer lo siguiente:
- Permitir el tráfico entrante al puerto TCP
10250en tus rangos de direcciones IP de nodos desde rangos de direcciones IP de Pod internos - Denegar el tráfico entrante al puerto TCP
10250en tus rangos de direcciones IP de nodos desde la Internet pública
Puedes usar las siguientes reglas de firewall predeterminadas de GKE como plantilla para los parámetros que especifiques en tus reglas nuevas:
gke-[cluster-name]-[cluster-hash]-inkubeletgke-[cluster-name]-[cluster-hash]-exkubelet
Inhabilita el puerto de solo lectura no seguro en clústeres de Autopilot
Puedes inhabilitar el puerto de solo lectura de kubelet no seguro para clústeres de Autopilot nuevos y existentes.
Para inhabilitar el puerto de solo lectura de kubelet no seguro en un clúster de Autopilot, usa la marca --no-autoprovisioning-enable-insecure-kubelet-readonly-port, como en el siguiente comando. Todos los nodos nuevos y existentes del clúster dejan de usar el puerto.
gcloud container clusters update CLUSTER_NAME \
--location=LOCATION \
--no-autoprovisioning-enable-insecure-kubelet-readonly-port
Reemplaza lo siguiente:
CLUSTER_NAME: Es el nombre del clúster existente.LOCATION: Es la ubicación del clúster existente.
También puedes usar la
--no-autoprovisioning-enable-insecure-kubelet-readonly-port marca cuando
creas un clúster nuevo con el
comando gcloud container clusters create-auto.
Inhabilita el puerto de solo lectura no seguro en clústeres estándar
Puedes inhabilitar el puerto de solo lectura no seguro de kubelet para clústeres estándar completos o para grupos de nodos individuales. Te recomendamos que inhabilite el puerto para todo el clúster.
Si usas el aprovisionamiento automático de nodos, los grupos de nodos aprovisionados automáticamente heredan el parámetro de configuración de puerto que especificas a nivel del clúster. De manera opcional, puedes especificar una configuración diferente para los grupos de nodos aprovisionados automáticamente, pero te recomendamos que inhabilite el puerto en todos los nodos de tu clúster.
También puedes usar un archivo de configuración del sistema de nodos para inhabilitar de forma declarativa el puerto de solo lectura de kubelet no seguro. Si usas este archivo, no puedes usar los comandos de las siguientes secciones para controlar la configuración de kubelet.
Inhabilita el puerto de solo lectura no seguro en los clústeres estándar existentes
Para inhabilitar el puerto de solo lectura de kubelet no seguro en un clúster estándar existente, usa la marca --no-enable-insecure-kubelet-readonly-port como en el siguiente comando. Ningún grupo de nodos nuevo usará el puerto no seguro.
GKE no actualiza los grupos de nodos existentes de forma automática.
gcloud container clusters update CLUSTER_NAME \
--location=LOCATION \
--no-enable-insecure-kubelet-readonly-port
Reemplaza lo siguiente:
CLUSTER_NAME: Es el nombre de tu clúster estándar existente.LOCATION: Es la ubicación de tu clúster estándar existente.
También puedes usar la
--no-autoprovisioning-enable-insecure-kubelet-readonly-port marca cuando
creas un clúster nuevo con el
comando gcloud container clusters create.
Inhabilita el puerto de solo lectura no seguro en los grupos de nodos estándar
Te recomendamos que configures el puerto de solo lectura a nivel del clúster en todos los casos. Si inhabilitaste el puerto de solo lectura en un clúster existente que ya tenía grupos de nodos en ejecución, usa el siguiente comando para inhabilitar el puerto en esos grupos de nodos.
gcloud container node-pools update NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=LOCATION \
--no-enable-insecure-kubelet-readonly-port
Reemplaza lo siguiente:
NODE_POOL_NAME: es el nombre de tu grupo de nodos.CLUSTER_NAME: el nombre del clústerLOCATION: Es la ubicación del clúster.
Verifica que el puerto esté inhabilitado
Para verificar que el puerto de solo lectura de kubelet no seguro esté inhabilitado, describe el recurso de GKE.
Verifica el estado de los puertos en los clústeres de Autopilot
Ejecuta el siguiente comando:
gcloud container clusters describe CLUSTER_NAME \
--location=LOCATION \
--flatten=nodePoolAutoConfig \
--format="value(nodeKubeletConfig)"
Reemplaza lo siguiente:
CLUSTER_NAME: Es el nombre de tu clúster de Autopilot.LOCATION: Es la ubicación de tu clúster de Autopilot.
Si el puerto está inhabilitado, el resultado es el siguiente:
insecureKubeletReadonlyPortEnabled: false
Verifica el estado de los puertos en los clústeres estándar
El estado del puerto está disponible en el campo nodePoolDefaults.nodeConfigDefaults.nodeKubeletConfig cuando describes tu clúster con la API de GKE.
En los clústeres estándar, también verás un campo nodeConfig que establece un valor para el estado del puerto de solo lectura de kubelet. El campo nodeConfig está obsoleto y solo se aplica al grupo de nodos predeterminado que GKE crea cuando creas un clúster nuevo en modo estándar. El estado del puerto en el campo nodeConfig obsoleto no se aplica a otros grupos de nodos del clúster.
Ejecuta el siguiente comando:
gcloud container clusters describe CLUSTER_NAME \
--location=LOCATION \
--flatten=nodePoolDefaults.nodeConfigDefaults \
--format="value(nodeKubeletConfig)"
Reemplaza lo siguiente:
CLUSTER_NAME: es el nombre de tu clúster estándar.LOCATION: es la ubicación de tu clúster estándar.
Si el puerto está inhabilitado, el resultado es el siguiente:
insecureKubeletReadonlyPortEnabled: false
Si el resultado de este comando está en blanco, es posible que el puerto de solo lectura kubelet no seguro aún esté habilitado. Para inhabilitar el puerto, ejecuta el comando en la sección
Inhabilita el puerto de solo lectura no seguro en los clústeres estándar existentes.
Verifica el estado de los puertos en los grupos de nodos estándar
Ejecuta el siguiente comando:
gcloud container node-pools describe NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=LOCATION \
--flatten=config \
--format="value(kubeletConfig)"
Reemplaza lo siguiente:
NODE_POOL_NAME: es el nombre de tu grupo de nodos.CLUSTER_NAME: el nombre del clústerLOCATION: Es la ubicación del clúster.
Si el puerto está inhabilitado, el resultado es el siguiente:
insecureKubeletReadonlyPortEnabled: false
Evita el uso de puertos no seguros con una política de la organización
Puedes usar el servicio de políticas de la organización para exigir que los clústeres de tu organización, carpeta o proyecto inhabiliten el puerto de solo lectura kubelet no seguro. Para
aplicar este requisito, crea una
restricción personalizada,
y, luego, haz referencia a esa restricción en una política de la organización. Para denegar las operaciones de creación o actualización cuando se habilita el puerto de solo lectura kubelet no seguro, consulta estos ejemplos:
La siguiente restricción personalizada deniega las operaciones de creación o actualización de clústeres si se habilita el puerto de solo lectura
kubeletno seguro:name: organizations/ORGANIZATION_ID/customConstraints/custom.disableClusterInsecureKubeletReadOnlyPort resourceTypes: - container.googleapis.com/Cluster methodTypes: - CREATE - UPDATE condition: "resource.NodeKubeletConfig.insecureKubeletReadonlyPortEnabled == true || resource.AutoprovisioningNodePoolDefaults.insecureKubeletReadonlyPortEnabled == true || resource.NodePoolAutoConfig.NodeKubeletConfig.insecureKubeletReadonlyPortEnabled == true" actionType: DENY displayName: Disable insecure kubelet read-only port description: All new and existing clusters must disable the insecure kubelet read-only port.Reemplaza
ORGANIZATION_IDpor el ID de tu organización.La siguiente restricción personalizada deniega las operaciones de creación o actualización de grupos de nodos si se habilita el puerto de solo lectura
kubeletno seguro:name: organizations/ORGANIZATION_ID/customConstraints/custom.disableNodePoolInsecureKubeletReadOnlyPort resourceTypes: - container.googleapis.com/NodePool methodTypes: - CREATE - UPDATE condition: "resource.NodeConfig.NodeKubeletConfig.insecureKubeletReadonlyPortEnabled == true" actionType: DENY displayName: Disable insecure kubelet read-only port description: All new and existing node pools must disable the insecure kubelet read-only port.Reemplaza
ORGANIZATION_IDpor el ID de tu organización.
Para obtener más información sobre cómo crear una restricción personalizada y aplicar la restricción en una política de la organización, consulta Restringe acciones en los recursos de GKE mediante políticas de la organización personalizadas.