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.
Antes de comenzar
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
- Habilita la API de Google Kubernetes Engine. Habilitar la API de Google Kubernetes Engine
- Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa la CLI de gcloud. Si ya instalaste la CLI de gcloud, ejecuta
gcloud components update
para obtener la versión más reciente.
Verifica si las aplicaciones usan el puerto
Antes de inhabilitar el puerto, asegúrate de que las aplicaciones de tu clúster no accedan al puerto de solo lectura. Si inhabilitas el puerto mientras una carga de trabajo aún necesita acceso a un extremo, es posible que la carga de trabajo falle.
Obtén una lista de nodos en el clúster:
kubectl get nodes
Para cada nodo, verifica las métricas del servidor HTTP de kubelet:
kubectl get --raw /api/v1/nodes/NODE_NAME/proxy/metrics \ | grep http_requests_total \ | grep readonly
Si una aplicación envía solicitudes al puerto de solo lectura, el resultado será similar al siguiente:
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="pods",server_type="readonly"} 1
Para detener este uso, consulta Evita que las aplicaciones usen el puerto de solo lectura.
Si el resultado está en blanco, ve a Inhabilita el puerto de solo lectura en el clúster.
Evita que las aplicaciones usen el puerto de solo lectura
Si tienes una aplicación de terceros que usa el puerto de solo lectura, consulta la documentación del proveedor para obtener una opción de usar el puerto kubelet autenticado.
En la mayoría de los casos, debes realizar los siguientes cambios en tu aplicación para evitar que use el puerto de solo lectura:
- Actualiza la URL o los extremos que hacen referencia al puerto de solo lectura. Por ejemplo, cambiarías las referencias de extremos de nodo como http://192.0.2.167:10255 a https://192.0.2.167:10250.
Configura el certificado de CA del cliente HTTP como el certificado de CA del clúster. Para obtener este certificado de CA, usa uno de los siguientes métodos:
- Usa el objeto
masterAuth.clusterCaCertificate
de la API de GKE. - Desde un Pod, accede al certificado en
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
.
- Usa el objeto
Actualiza el mecanismo de autorización en el clúster, como las reglas de RBAC, para que la aplicación otorgue los permisos adecuados en el recurso
nodes/*
o en subrecursos específicos. Para obtener una lista de subrecursos, consulta Autorización de kubelet.
Después de actualizar tus aplicaciones, vuelve a verificar el uso de puertos de solo lectura para verificar que el resultado esté en blanco. Luego, inhabilita el puerto de solo lectura en el clúster.
Ejemplo de migración de aplicaciones
En el siguiente ejemplo, se modifica un Pod que consulta las métricas del puerto de solo lectura de kubelet. Estas solicitudes no están autenticadas, por lo que cualquier aplicación que pueda acceder a los extremos de nodos también puede enviar cualquier consulta.
Guarda el siguiente manifiesto como
example-readonly.yaml
:apiVersion: v1 kind: Pod metadata: name: kubelet-readonly-example spec: restartPolicy: Never containers: - name: kubelet-readonly-example image: gcr.io/cloud-builders/curl:latest command: - curl - http://$(NODE_ADDRESS):10255/metrics env: - name: NODE_ADDRESS valueFrom: fieldRef: fieldPath: status.hostIP
Este Pod ejecuta un comando
curl
para obtener el extremo/metrics
en el puerto de solo lectura de kubelet.Aplica el manifiesto
kubectl create -f example-readonly.yaml
Verifica los registros del Pod:
kubectl logs -f kubelet-readonly-example
El resultado contiene métricas de nodo y es similar al siguiente:
# HELP apiserver_audit_event_total [ALPHA] Counter of audit events generated and sent to the audit backend. # TYPE apiserver_audit_event_total counter ... kubelet_runtime_operations_total{operation_type="container_status"} 93 ...
Crea un ClusterRole que otorgue acceso
get
a las métricas de nodo:Guarda el siguiente manifiesto como
metrics-role.yaml
:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: curl-authenticated-role rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get
Aplica el manifiesto
kubectl create -f metrics-role.yaml
Vincula el ClusterRole a la identidad de la aplicación, como ServiceAccount:
Guarda el siguiente manifiesto como
metrics-binding.yaml
: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
En este ejemplo, se vincula la ClusterRole a la ServiceAccount
default
en el espacio de nombresdefault
.Aplica el manifiesto
kubectl create -f metrics-binding.yaml
Modifica el manifiesto
example-readonly.yaml
de la siguiente manera:apiVersion: v1 kind: Pod metadata: name: kubelet-authenticated-example spec: restartPolicy: Never containers: - name: kubelet-readonly-example image: gcr.io/cloud-builders/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'
El comando que el Pod envía a la API de kubelet incluye lo siguiente:
- El certificado de CA del clúster ubicado en
/var/run/secrets/kubernetes.io/ca.crt
para autenticar la solicitud. - El token del portador de ServiceAccount ubicado en
/var/run/secrets/kubernetes.io/serviceaccount/token
para autorizar la solicitud.
- El certificado de CA del clúster ubicado en
Implementa el manifiesto actualizado:
kubectl apply -f example-readonly.yaml
Inhabilita el puerto de solo lectura en el clúster
Puedes inhabilitar el puerto de solo lectura de kubelet no seguro en clústeres de Standard nuevos o existentes, y en clústeres de Autopilot nuevos. No puedes inhabilitar el puerto en clústeres de Autopilot existentes.
Se aplican los siguientes requisitos de versión:
- Solo puedes inhabilitar el puerto a nivel del clúster en la versión 1.26.4-gke.500 de GKE y versiones posteriores, y en la versión 1.27 y posteriores.
- Debes usar la versión 439 o una versión posterior de la CLI de gcloud.
Asegúrate de tener la última versión de la CLI de gcloud. Para actualizar la CLI de gcloud, consulta Instala la CLI de gcloud.
Inhabilita el puerto para todos los nodos del clúster:
gcloud container clusters update CLUSTER_NAME \ --location=LOCATION_NAME \ --no-enable-insecure-kubelet-readonly-port
Reemplaza lo siguiente:
CLUSTER_NAME
: el nombre del clústerLOCATION_NAME
: es la región o zona de Compute Engine del clúster, comous-central1
.
Este comando anula cualquier configuración a nivel de nodo para el puerto de solo lectura, incluidos los especificados en el archivo de configuración de kubelet.
Para inhabilitar el puerto cuando creas un clúster nuevo, especifica la marca
--no-enable-insecure-kubelet-readonly-port
en tu comando create.
Verifica que el puerto esté inhabilitado
Para verificar que el puerto esté inhabilitado, usa el manifiesto de la sección Migración de ejemplo.
Guarda el siguiente manifiesto como readonly-verify.yaml:
apiVersion: v1 kind: Pod metadata: name: kubelet-readonly-verify spec: restartPolicy: Never containers: - name: kubelet-readonly-verify image: gcr.io/cloud-builders/curl:latest command: - curl - http://$(NODE_ADDRESS):10255/metrics env: - name: NODE_ADDRESS valueFrom: fieldRef: fieldPath: status.hostIP
Aplica el manifiesto
kubectl create -f readonly-verify.yaml
Verifica los registros del Pod:
kubectl logs -f kubelet-readonly-verify
Si el puerto está inhabilitado, verás un error similar al siguiente:
curl: (7) Failed to connect to NODE_ADDRESS port 10255: Connection refused
Si el puerto aún está habilitado, verás un resultado de métricas del nodo similar al siguiente:
# HELP apiserver_audit_event_total [ALPHA] Counter of audit events generated and sent to the audit backend.
# TYPE apiserver_audit_event_total counter
...
kubelet_runtime_operations_total{operation_type="container_status"} 93
...
En este caso, asegúrate de que tu clúster cumpla con los requisitos de la versión y que uses la versión más reciente de la CLI de gcloud.
¿Qué sigue?
- Lee la guía de endurecimiento de GKE.
- Obtén información para bloquear el acceso del plano de control a las redes autorizadas