Obtén información sobre los pasos de la solución de problemas que pueden servirte si tienes dificultades con Google Kubernetes Engine (GKE).
Si necesitas asistencia adicional, comunícate con Atención al cliente de Cloud.Depura los recursos de Kubernetes
Si tienes un problema con el clúster, consulta Soluciona problemas de clústeres en la documentación de Kubernetes.
Si tienes un problema con tu aplicación, sus Pods o tu objeto de controlador, consulta Soluciona problemas de aplicaciones.
Si tienes un problema relacionado con la conectividad entre las VMs de Compute Engine que se encuentran en la misma red de nube privada virtual (VPC) o en dos redes de VPC conectadas con el intercambio de tráfico entre redes de VPC, consulta Soluciona problemas La conectividad entre las instancias de máquina virtual (VM) con direcciones IP internas
Si experimentas una pérdida de paquetes cuando envías tráfico desde un clúster a una dirección IP externa mediante Cloud NAT, clústeres nativos de la VPC o Agente de enmascaramiento de IP, consulta Soluciona problemas de pérdida de paquetes de Cloud NAT desde un clúster de GKE.
Soluciona problemas con el comando kubectl
No se encuentra el comando kubectl
Instala el objeto binario
kubectl
mediante la ejecución del siguiente comando:gcloud components update kubectl
Responde “sí” cuando el instalador te solicite modificar la variable de entorno
$PATH
. Si modificas esta variable, podrás usar los comandoskubectl
sin necesidad que escribir la ruta de archivo completa.Como alternativa, agrega la siguiente línea a
~/.bashrc
(o~/.bash_profile
en macOS, o donde tu shell almacene las variables de entorno):export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
Ejecuta el siguiente comando para cargar el archivo
.bashrc
(o.bash_profile
) actualizado:source ~/.bashrc
Los comandos kubectl
muestran el error “conexión rechazada”
Establece el contexto del clúster con el siguiente comando:
gcloud container clusters get-credentials CLUSTER_NAME
Si tienes dudas sobre qué ingresar para CLUSTER_NAME
, usa el siguiente comando para hacer una lista de tus clústeres:
gcloud container clusters list
Se agota el tiempo de espera del comando kubectl
Después de crear un clúster, si se intenta ejecutar el comando kubectl
en el clúster, se muestra un error, como Unable to connect to the server: dial
tcp IP_ADDRESS: connect: connection timed out
o Unable to connect to the
server: dial tcp IP_ADDRESS: i/o timeout
.
Esto puede ocurrir cuando kubectl
no puede comunicarse con el plano de control del clúster.
Para resolver este problema, verifica que el contexto donde el clúster esté establecido:
Ve a
$HOME/.kube/config
o ejecuta el comandokubectl config view
para verificar que el archivo de configuración contenga el contexto del clúster y la dirección IP externa del plano de control.Configura las credenciales del clúster:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID
Reemplaza lo siguiente:
CLUSTER_NAME
: es el nombre de tu clúster.COMPUTE_LOCATION
: la ubicación de Compute Engine.PROJECT_ID
es el ID del proyecto en el que se creó el clúster de GKE.
Si el clúster es un clúster de GKE privado, asegúrate de que la IP saliente de la máquina desde la que intentas conectarte esté incluida en la lista de redes autorizadas existentes. Puedes encontrar las redes autorizadas existentes en Console o mediante la ejecución del siguiente comando:
gcloud container clusters describe CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID \ --format "flattened(masterAuthorizedNetworksConfig.cidrBlocks[])"
Si la IP saliente de la máquina no se incluye en la lista de redes autorizadas del resultado del comando anterior, sigue los pasos de No se puede acceder al plano de control de un clúster privado o Usa Cloud Shell para acceder a un clúster privado si te conectas desde Cloud Shell.
Los comandos kubectl
muestran el error “no se pudo negociar una versión de API”
Asegúrate de que kubectl tenga credenciales de autenticación:
gcloud auth application-default login
Los comandos kubectl
logs
, attach
, exec
y port-forward
dejan de responder
Estos comandos dependen que el plano de control del clúster pueda comunicarse con los nodos en el clúster. Sin embargo, debido a que el plano de control no está en la misma red de Compute Engine que los nodos del clúster, dependemos de los túneles SSH o de proxy de Konnectivity para habilitar comunicación segura.
GKE guarda un archivo de clave pública SSH en los metadatos del proyecto de Compute Engine. Todas las VM de Compute Engine que usan imágenes proporcionadas por Google verifican con regularidad los metadatos comunes del proyecto y los metadatos de la instancia para las claves SSH a fin de agregarlos a la lista de usuarios autorizados de la VM. GKE también agrega una regla de firewall a la red de Compute Engine, lo que permite el acceso SSH desde la dirección IP del plano de control a cada nodo en el clúster.
Si alguno de los comandos kubectl
anteriores no se ejecutan, es probable que el servidor de la API no pueda comunicarse con los nodos. Verifica las siguientes causas posibles:
El clúster no tiene nodos.
Si reduces la cantidad de nodos en tu clúster a cero, los comandos no funcionarán.
A fin de arreglarlo, cambia el tamaño del clúster para tener al menos un nodo.
SSH
Las reglas de firewall de la red no permiten el acceso de SSH desde el plano de control.
Todas las redes de Compute Engine se crean con una regla de firewall llamada
default-allow-ssh
que permite el acceso SSH desde todas las direcciones IP (por supuesto, mediante la solicitud de una clave privada válida). GKE también inserta una regla SSH para cada clúster público con el formatogke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh
que permite el acceso SSH de forma específica desde el plano de control del clúster hacia los nodos del clúster. Si no existe ninguna de estas reglas, el plano de control no puede abrir los túneles SSH.Para solucionar esto, vuelve a agregar una regla de firewall que permita el acceso a las VM con las etiquetas que se encuentran en todos los nodos del clúster desde la dirección IP del plano de control.
La entrada de los metadatos comunes del proyecto para las “ssh-keys” está llena.
Si la entrada de metadatos del proyecto llamada "ssh-keys" está cerca del límite de tamaño máximo, GKE no puede agregar su propia clave SSH a fin de habilitarla para abrir túneles SSH. Para ver los metadatos del proyecto, ejecuta el siguiente comando:
gcloud compute project-info describe [--project=PROJECT_ID]
Luego, verifica la longitud de la lista de llaves SSH.
Para arreglarlo, borra algunas de las llaves SSH que ya no sean necesarias.
Estableciste un campo de metadatos con la clave “ssh-keys” en las VM del clúster.
El agente de nodo en las VM prefiere claves SSH por instancia en vez de claves SSH por proyecto completo, por lo que, si estableciste claves SSH de forma específica en los nodos del clúster, los nodos no respetaran la clave SSH del plano de control en los metadatos del proyecto. Para verificarlo, ejecuta
gcloud compute instances describe VM_NAME
y busca un campossh-keys
en los metadatos.Para arreglarlo, borra las claves SSH por instancia de los metadatos de la instancia.
Proxy de Konnectivity
Determina si tu clúster usa el proxy de Konnectivity mediante la verificación de la siguiente implementación del sistema:
kubectl get deployments konnectivity-agent --namespace kube-system
Las reglas de firewall de la red no permiten el acceso del agente de Konnectivity al plano de control.
Durante la creación del clúster, los pods del agente de Konnectivity establecen y mantienen una conexión con el plano de control en el puerto
8132
. Cuando se ejecuta uno de los comandoskubectl
, el servidor de la API usa esta conexión para comunicarse con el clúster.Si las reglas de firewall de la red contienen reglas de denegación de salida, puede impedir que el agente se conecte. Debes permitir el tráfico de salida al plano de control del clúster en el puerto 8132. (En comparación, el servidor de la API usa 443).
La política de red del clúster bloquea la entrada del espacio de nombres
kube-system
al espacio de nombresworkload
. Para encontrar las políticas de red en el espacio de nombres afectado, ejecuta el siguiente comando:kubectl get networkpolicy --namespace AFFECTED_NAMESPACE
Para resolver el problema, agrega lo siguiente al campo
spec.ingress
de las políticas de red:- from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: konnectivity-agent
Estas características no se requieren para el funcionamiento correcto del clúster. Si prefieres mantener el acceso exterior bloqueado para la red del clúster, ten en cuenta que las características como estas no funcionarán.
Soluciona problemas de error 4xx
Errores de autenticación y autorización para conectarte a clústeres de GKE
Este problema puede ocurrir cuando intentas ejecutar un comando kubectl
en tu clúster de GKE desde un entorno local. El comando falla y muestra un mensaje de error, por lo general, con el código de estado HTTP 401 (no autorizado).
La causa de este problema podría ser una de las siguientes:
- El complemento de autenticación
gke-gcloud-auth-plugin
no está instalado ni configurado de forma correcta. - No tienes los permisos para conectarte al servidor de la API del clúster y ejecutar comandos de
kubectl
.
Para diagnosticar la causa, haz lo siguiente:
Conéctate al clúster mediante curl
.
Mediante curl
, se omiten la CLI de kubectl
y el complemento gke-gcloud-auth-plugin
.
Establece las variables de entorno:
APISERVER=https://$(gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(endpoint)") TOKEN=$(gcloud auth print-access-token)
Verifica que tu token de acceso sea válido:
curl https://oauth2.googleapis.com/tokeninfo?access_token=$TOKEN
Verifica que puedas conectarte al extremo principal de la API en el servidor de la API:
gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(masterAuth.clusterCaCertificate)" | base64 -d > /tmp/ca.crt curl -s -X GET "${APISERVER}/api/v1/namespaces" --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
Si el comando curl
falla con un resultado similar al siguiente, verifica que tengas los permisos correctos para acceder al clúster:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "Unauthorized",
"reason": "Unauthorized",
"code": 401
}
Si el comando curl
se ejecuta de forma correcta, verifica si el complemento es la causa.
Configura el complemento en kubeconfig
En los siguientes pasos, se configura tu entorno local para ignorar el objeto binario gke-gcloud-auth-plugin
cuando se autentique en el clúster. En los clientes de Kubernetes que ejecutan la versión 1.25 y posteriores, el objeto binario gke-gcloud-auth-plugin
es obligatorio, por lo que debes seguir estos pasos si deseas acceder a tu clúster sin necesidad del complemento.
Instala la versión 1.24 de la CLI de
kubectl
mediantecurl
:curl -LO https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl
Puedes usar cualquier versión 1.24 o anterior de la CLI de
kubectl
.Abre el archivo de secuencia de comandos de inicio de la shell, como
.bashrc
para la shell de Bash, en un editor de texto:vi ~/.bashrc
Agrega la siguiente línea al archivo y guárdala:
export USE_GKE_GCLOUD_AUTH_PLUGIN=False
Ejecuta la secuencia de comandos de inicio:
source ~/.bashrc
Obtén credenciales para el clúster, que configura el archivo
.kube/config
:gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION
Reemplaza lo siguiente:
CLUSTER_NAME
: el nombre del clústerCOMPUTE_LOCATION
: la ubicación de Compute Engine.
Ejecuta un comando
kubectl
:kubectl cluster-info
Si recibes un error 401 o un error de autorización similar, asegúrate de tener los permisos correctos para realizar la operación.
Error 400: El grupo de nodos requiere recreación
El siguiente problema ocurre cuando intentas realizar una acción que vuelve a crear el plano de control y los nodos, como cuando completas una rotación de credenciales en curso.
La operación falla porque GKE no volvió a crear uno o más grupos de nodos en el clúster. En el backend, los grupos de nodos están marcados para su recreación, pero la operación de recreación real puede tomar un tiempo en comenzar.
El mensaje de error es similar al siguiente:
ERROR: (gcloud.container.clusters.update) ResponseError: code=400, message=Node pool "test-pool-1" requires recreation.
Para solucionar este problema, realiza una de las siguientes acciones:
- Espera a que se realice la recreación. Esto puede tardar horas, días o semanas, según factores como los períodos de mantenimiento y las exclusiones existentes.
Inicia de forma manual una recreación de los grupos de nodos afectados mediante el inicio de una actualización de la versión a la misma versión que el plano de control. Para iniciar una recreación, ejecuta el siguiente comando:
gcloud container clusters upgrade CLUSTER_NAME \ --node-pool=POOL_NAME
Una vez completada la actualización, vuelve a intentar la operación.
Error 403: Permisos insuficientes
El siguiente error ocurre cuando intentas conectarte a un clúster de GKE mediante gcloud container clusters get-credentials
, pero la cuenta no tiene permiso para acceder al servidor de la API de Kubernetes.
ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/<your-project>/locations/<region>/clusters/<your-cluster>".
Para solucionar este problema, haz lo siguiente:
Identifica la cuenta que tiene el problema de acceso:
gcloud auth list
Otorga el acceso requerido a la cuenta mediante las instrucciones que aparecen en Autenticar en el servidor de la API de Kubernetes.
Error 404: Recurso “no encontrado” cuando se llama a los comandos gcloud container
Vuelve a autenticarte en Google Cloud CLI:
gcloud auth login
Error 400/403: Faltan permisos de edición en una cuenta
Se borró tu cuenta de servicio predeterminada de Compute Engine, el agente de servicio de las APIs de Google o la cuenta de servicio asociada con GKE o editar de forma manual.
Cuando habilitas la API de Compute Engine o la API de Kubernetes Engine, Google Cloud crea las siguientes cuentas de servicio y agentes:
- Cuenta de servicio predeterminada de Compute Engine con permisos de edición en tu proyecto.
- Agente de servicio de las APIs de Google con permisos de edición en tu proyecto.
- Cuenta de servicio de Google Kubernetes Engine con el rol de Agente de servicio de Kubernetes Engine en tu proyecto.
Si en algún momento editas esos permisos, quitas las vinculaciones de roles del proyecto, quitas la cuenta de servicio por completo o inhabilitas la API, la creación de clústeres y la funcionalidad de administración completa fallarán.
El nombre de tu cuenta de servicio de Google Kubernetes Engine es el siguiente, en el que PROJECT_NUMBER
es el número de proyecto:
service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
El siguiente comando se puede usar para verificar que la cuenta de servicio de Google Kubernetes Engine tenga el rol de Agente de servicio de Kubernetes Engine asignada en el proyecto:
gcloud projects get-iam-policy PROJECT_ID
Reemplaza PROJECT_ID
con el ID del proyecto.
Para resolver el problema, si quitaste el rol Agente de servicios de Kubernetes Engine de la cuenta de servicio de Google Kubernetes Engine, vuelve a agregarla. De lo contrario, puedes volver a habilitar la API de Kubernetes Engine, así, se restablecerán las cuentas de servicio y permisos de forma correcta.
Consola
Ve a la página API y servicios en la consola de Google Cloud.
Elige tu proyecto.
Haga clic en Habilitar API y servicios.
Busca Kubernetes y, luego, selecciona la API de los resultados de la búsqueda.
Haz clic en Habilitar. Si habilitaste la API antes, primero debes inhabilitarla y, luego, habilitarla de nuevo. La habilitación de la API y los servicios relacionados puede tomar varios minutos.
gcloud
Ejecuta el siguiente comando en la CLI de gcloud para volver a agregar la cuenta de servicio:
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID" --format 'get(projectNumber)')
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Soluciona problemas de creación de clústeres de GKE
Error CONDITION_NOT_MET: Restricción de constraints/compute.vmExternalIpAccess violada
Tienes la restricción de la política de la organización constraints/compute.vmExternalIpAccess configurada en Deny All
o para restringir las IP externas a instancias de VM específicas en el nivel de organización, carpeta o proyecto en el que intentas crear un clúster de GKE público.
Cuando creas clústeres de GKE públicos, las VMs de Compute Engine subyacentes, que conforman los nodos trabajadores de este clúster, tienen asignadas direcciones IP externas. Si configuras la restricción de la política de la organización constraints/compute.vmExternalIpAccess como Deny All
o para restringir IP externas a instancias de VM específicas, la política evitará que los nodos trabajadores de GKE obtengan direcciones IP externas, lo que da como resultado la falla de creación del clúster.
Para encontrar los registros de la operación de creación de clústeres, puedes revisar los Registros de auditoría de operaciones de clústeres de GKE mediante el Explorador de registros con una búsqueda similar a la siguiente:
resource.type="gke_cluster"
logName="projects/test-last-gke-sa/logs/cloudaudit.googleapis.com%2Factivity"
protoPayload.methodName="google.container.v1beta1.ClusterManager.CreateCluster"
resource.labels.cluster_name="CLUSTER_NAME"
resource.labels.project_id="PROJECT_ID"
Para resolver este problema, asegúrate de que la política vigente de la restricción constraints/compute.vmExternalIpAccess
sea Allow All
en el proyecto en el que intentas crear un clúster público de GKE. Consulta Restringe direcciones IP externas a instancias de VM específicas para obtener información sobre cómo trabajar con esta restricción. Después de establecer la restricción en Allow All
, borra el clúster con errores y crea uno nuevo. Esto es necesario porque no es posible reparar el clúster con errores.
Soluciona problemas de cargas de trabajo implementadas
GKE muestra un error si existen problemas con los pods de una carga de trabajo.
Puedes comprobar el estado de un pod mediante la herramienta de línea de comandos de kubectl
o la consola de Google Cloud.
kubectl
Para ver todos los pods en ejecución en tu clúster, ejecuta el comando siguiente:
kubectl get pods
Resultado:
NAME READY STATUS RESTARTS AGE
POD_NAME 0/1 CrashLoopBackOff 23 8d
Para obtener más información sobre un pod específico, ejecuta el siguiente comando:
kubectl describe pod POD_NAME
Reemplaza POD_NAME
con el nombre del pod que desees.
Consola
Sigue los siguientes pasos:
Ve a la página Cargas de trabajo en la consola de Google Cloud.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el mensaje de estado de error.
En las secciones siguientes, se explican algunos errores comunes que muestran las cargas de trabajo y cómo resolverlos.
CrashLoopBackOff
CrashLoopBackOff
indica que un contenedor falla repetidas veces después de reiniciarse. Un contenedor puede fallar por varias razones y verificar los registros de un pod puede ayudar a solucionar la causa del problema.
De forma predeterminada, los contenedores que fallan se reinician con una demora exponencial limitada a cinco minutos. Puedes cambiar este comportamiento si configuras el campo restartPolicy
de la especificación del pod de la implementación como spec: restartPolicy
. El valor predeterminado del campo es Always
.
Puedes solucionar los errores CrashLoopBackOff
con la consola de Google Cloud:
Ve a la guía interactiva de Pods en un bucle de fallas:
En
Clúster, ingresa el nombre del clúster en el que deseas solucionar problemas.En
Espacio de nombres, ingresa el espacio de nombres con el que deseas solucionar problemas.(Opcional) Crea una alerta que te notifique sobre errores
CrashLoopBackOff
futuros:- En la sección Sugerencias para la mitigación futura, selecciona Crear una alerta.
Inspecciona registros
Puedes averiguar por qué el contenedor de tu pod falla mediante la herramienta de línea de comandos de kubectl
o la consola de Google Cloud.
kubectl
Para ver todos los pods en ejecución en tu clúster, ejecuta el comando siguiente:
kubectl get pods
Busca el pod con el error CrashLoopBackOff
.
Para obtener los registros del pod, ejecuta el siguiente comando:
kubectl logs POD_NAME
Reemplaza POD_NAME
con el nombre del pod problemático.
También puedes pasar la marca -p
para obtener los registros de la instancia anterior del contenedor de un pod, si existe.
Consola
Sigue los siguientes pasos:
Ve a la página Cargas de trabajo en la consola de Google Cloud.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el pod problemático.
En el menú de pods, haz clic en la pestaña Registros.
Verifica el “Código de salida” del contenedor que falla
Para encontrar el código de salida, realiza las siguientes tareas:
Ejecuta el siguiente comando:
kubectl describe pod POD_NAME
Reemplaza
POD_NAME
con el nombre del pod.Revisa el valor en el campo
containers: CONTAINER_NAME: last state: exit code
:- Si el código de salida es 1, el contenedor falló debido a que la aplicación falló.
- Si el código de salida es 0, verifica por cuánto tiempo se ejecutó la app.
Los contenedores se detienen cuando el proceso principal de la aplicación se detiene. Si la app finaliza la ejecución con mucha rapidez, es posible que el contenedor continúe con el proceso de reinicio.
Conéctate a un contenedor en ejecución
Abre una shell al pod:
kubectl exec -it POD_NAME -- /bin/bash
Si hay más de un contenedor en tu pod, agrega -c CONTAINER_NAME
.
Ahora, puedes ejecutar comandos bash desde el contenedor: puedes probar la red o verificar si tienes acceso a los archivos o a las bases de datos que usa tu aplicación.
ImagePullBackOff y ErrImagePull
ImagePullBackOff
y ErrImagePull
indican que la imagen que usa un contenedor no se puede cargar desde el registro de imágenes.
Puedes verificar este problema mediante la consola de Google Cloud o la herramienta de línea de comandos de kubectl
.
kubectl
Para obtener más información sobre una imagen de contenedor de un Pod, ejecuta el comando siguiente:
kubectl describe pod POD_NAME
Consola
Sigue los siguientes pasos:
Ve a la página Cargas de trabajo en la consola de Google Cloud.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el pod problemático.
En el menú de pod, haz clic en la pestaña Eventos.
Si no se encuentra la imagen
Si tu imagen no se encuentra:
- Verifica que el nombre de la imagen sea correcto.
- Verifica que la etiqueta de la imagen sea correcta. (Intenta extraer la última imagen con
:latest
o sin etiqueta). - Si la imagen tiene una ruta de registro completa, verifica que exista en el registro Docker que usas. Si proporcionas solo el nombre de la imagen, verifica el registro de Docker Hub.
Prueba extraer la imagen de Docker de manera manual:
Establece una conexión SSH al nodo:
Por ejemplo, para establecer una conexión SSH a una VM, ejecuta lo siguiente:
gcloud compute ssh VM_NAME --zone=ZONE_NAME
Reemplaza lo siguiente:
VM_NAME
: el nombre de la VM.ZONE_NAME
: una zona de Compute Engine
Ejecuta
docker-credential-gcr configure-docker
. Con este comando, se genera un archivo de configuración en/home/[USER]/.docker/config.json
. Asegúrate de que este archivo incluya el registro de la imagen en el campocredHelpers
. Por ejemplo, el siguiente archivo incluye información de autenticación para imágenes alojadas en asia.gcr.io, eu.gcr.io, gcr.io, marketplace.gcr.io y us.gcr.io:{ "auths": {}, "credHelpers": { "asia.gcr.io": "gcr", "eu.gcr.io": "gcr", "gcr.io": "gcr", "marketplace.gcr.io": "gcr", "us.gcr.io": "gcr" } }
Ejecuta
docker pull IMAGE_NAME
.
Si esa opción funciona, necesitarás especificar ImagePullSecrets en un pod. Los pods solo pueden hacer referencia a los secretos de extracción de imagen en su propio espacio de nombres, por lo que este proceso puede realizarse una vez por espacio de nombres.
Error de permiso denegado
Si encuentras el error “permiso denegado” o “sin acceso de extracción”, verifica que accediste y tienes acceso a la imagen. Prueba uno de los siguientes métodos según el registro en el que alojas tus imágenes.
Artifact Registry
Si la imagen está en Artifact Registry, la cuenta de servicio del grupo de nodos necesita acceso de lectura al repositorio que contiene la imagen.
Otorga el rol artifactregistry.reader
a la cuenta de servicio:
gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
--location=REPOSITORY_LOCATION \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role="roles/artifactregistry.reader"
Reemplaza lo siguiente:
REPOSITORY_NAME
: Es el nombre de tu repositorio de Artifact Registry.REPOSITORY_LOCATION
: Es la región de tu repositorio de Artifact Registry.SERVICE_ACCOUNT_EMAIL
: La dirección de correo electrónico de la cuenta de servicio de IAM asociada con tu grupo de nodos.
Container Registry
Si la imagen está en Container Registry, la cuenta de servicio del grupo de nodos necesita acceso de lectura al bucket de Cloud Storage que contiene la imagen.
Otorga el rol roles/storage.objectViewer
a la cuenta de servicio para que pueda leer desde el bucket:
gsutil iam ch \
serviceAccount:SERVICE_ACCOUNT_EMAIL:roles/storage.objectViewer \
gs://BUCKET_NAME
Reemplaza lo siguiente:
SERVICE_ACCOUNT_EMAIL
: El correo electrónico de la cuenta de servicio asociada con tu grupo de nodos. Puedes enumerar todas las cuentas de servicio en tu proyecto mediantegcloud iam service-accounts list
.BUCKET_NAME
: es el nombre del bucket de Cloud Storage que contiene tus imágenes. Puedes enumerar todos los buckets de tu proyecto congsutil ls
.
Si tu administrador de registros configuró repositorios de gcr.io en Artifact Registry para almacenar imágenes del dominio gcr.io
en lugar de Container Registry, debes otorgar acceso de lectura a Artifact Registry en lugar de Container Registry.
Registro privado
Si la imagen está en un registro privado, es posible que necesites claves para acceder a las imágenes. Consulta Usa registros privados para obtener más información.
401 Autorizado: No se pueden extraer imágenes del repositorio de Container Registry privado
Un error similar al siguiente puede ocurrir cuando extraes una imagen de un repositorio de Container Registry privado:
gcr.io/PROJECT_ID/IMAGE:TAG: rpc error: code = Unknown desc = failed to pull and
unpack image gcr.io/PROJECT_ID/IMAGE:TAG: failed to resolve reference
gcr.io/PROJECT_ID/IMAGE]:TAG: unexpected status code [manifests 1.0]: 401 Unauthorized
Warning Failed 3m39s (x4 over 5m12s) kubelet Error: ErrImagePull
Warning Failed 3m9s (x6 over 5m12s) kubelet Error: ImagePullBackOff
Normal BackOff 2s (x18 over 5m12s) kubelet Back-off pulling image
Identifica el nodo que ejecuta el Pod:
kubectl describe pod POD_NAME | grep "Node:"
Verifica que el nodo tenga el permiso de almacenamiento:
gcloud compute instances describe NODE_NAME \ --zone=COMPUTE_ZONE --format="flattened(serviceAccounts[].scopes)"
El permiso de acceso del nodo debe contener al menos uno de los siguientes elementos:
serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/devstorage.read_only serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/cloud-platform
Vuelve a crear el grupo de nodos al que pertenece el nodo con suficiente permiso. No puedes modificar los nodos existentes, debes volver a crear el nodo con el permiso correcto.
Recomendado: Crea un grupo de nodos nuevo con el permiso
gke-default
:gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="gke-default"
Crea un grupo de nodos nuevo solo con el permiso de almacenamiento:
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="https://www.googleapis.com/auth/devstorage.read_only"
Pod no programable
PodUnschedulable
indica que tu pod no se puede programar debido a que los recursos son insuficientes o que hay algún error de configuración.
Si tienes configurado el clúster de GKE para enviar el servidor de la API de Kubernetes y las métricas del programador de Kubernetes a Cloud Monitoring, puedes encontrar más información sobre estos errores en métricas del programador y métricas del servidor de la API .
Puedes solucionar los errores PodUnschedulable
con la consola de Google Cloud:
Ve a la guía interactiva de Pods no programables:
En
Clúster, ingresa el nombre del clúster en el que deseas solucionar problemas.En
Espacio de nombres, ingresa el espacio de nombres con el que deseas solucionar problemas.(Opcional) Crea una alerta que te notifique sobre errores
PodUnschedulable
futuros:- En la sección Sugerencias para la mitigación futura, selecciona Crear una alerta.
Recursos insuficientes
Puedes encontrar un error que indique una falta de CPU, memoria o algún otro recurso. Por ejemplo: “No hay nodos disponibles que coincidan con todos los predicados: CPU insuficiente (2)”, que indica que no hay CPU suficiente disponible en dos nodos para cumplir con las solicitudes de un pod.
Si las solicitudes de recursos de tu pod superan las de un solo nodo de cualquier grupo de nodos apto, GKE no programa el pod ni activa el escalamiento vertical para agregar un nodo nuevo. Para que GKE programe el Pod, debes solicitar menos recursos para el Pod o crear un grupo de nodos nuevo con recursos suficientes.
También puedes habilitar el aprovisionamiento automático de nodos para que GKE pueda crear de forma automática grupos de nodos con nodos en los que puedan ejecutarse los Pods no programados.
La solicitud de CPU predeterminada es de 100m o el 10% de una CPU (o un núcleo).
Si deseas solicitar más o menos recursos, detalla el valor en la especificación del Pod en spec: containers: resources: requests
.
MatchNodeSelector
MatchNodeSelector
indica que no hay nodos que coincidan con el selector de etiquetas del pod.
Para verificar esto, revisa las etiquetas que se especifican en el campo nodeSelector
de la especificación del pod, debajo de spec: nodeSelector
.
Para ver cómo están etiquetados los nodos en tu clúster, ejecuta el siguiente comando:
kubectl get nodes --show-labels
Para adjuntar una etiqueta a un nodo, ejecuta el siguiente comando:
kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE
Reemplaza lo siguiente:
NODE_NAME
: el nodo deseado.LABEL_KEY
: la clave de la etiqueta.LABEL_VALUE
: el valor de la etiqueta.
Para obtener más información, consulta asigna Pods a nodos.
PodToleratesNodeTaints
PodToleratesNodeTaints
indica que el pod no se puede programar en ningún nodo porque, por el momento, ningún nodo tolera su taint de nodo.
Para verificar que este sea el caso, ejecuta el comando siguiente:
kubectl describe nodes NODE_NAME
En el resultado, verifica el campo Taints
, que enumera pares clave-valor y efectos de programación.
Si el efecto enumerado es NoSchedule
, entonces no se puede programar ningún pod en ese nodo, a menos que tenga una tolerancia coincidente.
Una manera de resolver este problema es quitar el taint. Por ejemplo, para quitar un taint NoSchedule, ejecuta el siguiente comando:
kubectl taint nodes NODE_NAME key:NoSchedule-
PodFitsHostPorts
PodFitsHostPorts
indica que un puerto que un nodo quiere usar ya está en uso.
Para resolver este problema, verifica el valor hostPort
de la especificación del pod en spec: containers: ports: hostPort
. Es posible que debas cambiar este valor para otro puerto.
No tiene disponibilidad mínima
Si un nodo tiene recursos adecuados, pero todavía ves el mensaje Does not have minimum availability
, comprueba el estado del pod. Si el estado es SchedulingDisabled
o Cordoned
, el nodo no puede programar pods nuevos. Puedes verificar el estado de un nodo con la consola de Google Cloud o la herramienta de línea de comandos de kubectl
.
kubectl
Para obtener los estados de los nodos, ejecuta el siguiente comando:
kubectl get nodes
Para habilitar la programación en el nodo, ejecuta lo siguiente:
kubectl uncordon NODE_NAME
Consola
Sigue los siguientes pasos:
Ve a la página de Google Kubernetes Engine en la consola de Google Cloud.
Selecciona el clúster deseado. La pestaña Nodos muestra los nodos y su estado.
Para habilitar la programación en el nodo, realiza los pasos siguientes:
En la lista, haz clic en el nodo deseado.
En Detalles del nodo, haz clic en el botón Desvincular.
Se alcanzó el límite máximo de Pods por nodo
Si todos los nodos del clúster alcanzan el límite de máximo de Pods por nodo, los Pods se detendrán en estado no programable. En la pestaña Eventos del Pod, verás un mensaje que incluye la frase Too many pods
.
Verifica la configuración de
Maximum pods per node
desde la pestaña Nodos en los detalles del clúster de GKE en la consola de Google Cloud.Obtén una lista de nodos:
kubectl get nodes
Para cada nodo, verifica la cantidad de Pods que se ejecutan en el nodo:
kubectl get pods -o wide | grep NODE_NAME | wc -l
Si se alcanza el límite, agrega un grupo de nodos nuevo o agrega nodos adicionales al grupo existente.
Se alcanzó el tamaño máximo del grupo de nodos con el escalador automático del clúster habilitado
Si el grupo de nodos alcanzó su tamaño máximo según la configuración del escalador automático de clústeres, GKE no activa el escalamiento vertical para el Pod que, de lo contrario, se programaría con este grupo de nodos. Si quieres que el pod se programe con este grupo de nodos, cambia la configuración del escalador automático de clústeres.
Tamaño máximo del grupo de nodos alcanzado con el escalador automático del clúster inhabilitado
Si el grupo de nodos alcanzó la cantidad máxima de nodos y el escalador automático de clústeres está inhabilitado, GKE no puede programar el Pod con el grupo de nodos. Aumenta el tamaño de tu grupo de nodos o habilita el escalador automático del clúster para que GKE cambie el tamaño del clúster de forma automática.
Desvincula PersistentVolumeClaims
Unbound PersistentVolumeClaims
indica que el pod hace referencia a una PersistentVolumeClaim que no está vinculada. Este error puede ocurrir si no se pudo aprovisionar el PersistentVolume. Puedes verificar que el aprovisionamiento falló, si obtienes los eventos de la PersistentVolumeClaim y los examinas en busca de errores.
Para obtener los eventos, ejecuta el siguiente comando:
kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0
Reemplaza lo siguiente:
STATEFULSET_NAME
: el nombre del objeto StatefulSet.PVC_NAME
: el nombre del objeto PersistentVolumeClaim.
Esto también puede ocurrir si hubo un error de configuración durante el aprovisionamiento previo manual de un PersistentVolume y su vinculación a una PersistentVolumeClaim. Puedes intentar aprovisionar el volumen de nuevo.
Cuota insuficiente
Verifica que tu proyecto tenga suficiente cuota de Compute Engine para que GKE escale verticalmente tu clúster. Si GKE intenta agregar un nodo a tu clúster para programar el pod y escalar verticalmente superaría la cuota disponible de tu proyecto, recibirás el mensaje de error scale.up.error.quota.exceeded
.
Para obtener más información, consulta Errores de ScaleUp.
APIs obsoletas
Asegúrate de no usar APIs obsoletas que se quitan con la versión secundaria de tu clúster. Para obtener más información, consulta Bajas de GKE.
Problemas de conectividad
Como se mencionó en el debate de Descripción general de la red, es importante comprender cómo los pods están conectados desde sus espacios de nombres de red con el espacio de nombres raíz en el nodo para solucionar problemas de manera efectiva. En el siguiente debate, supone que el clúster usa el CNI nativo de GKE en lugar del de Calico, a menos que se indique lo contrario. Es decir, no se aplicó ninguna política de red.
Los pods en nodos seleccionados no tienen disponibilidad
Si los pods en nodos seleccionados no tienen conectividad de red, asegúrate de que el puente de Linux esté activo:
ip address show cbr0
En caso contrario, actívalo:
sudo ip link set cbr0 up
Asegúrate de que el nodo esté aprendiendo las direcciones MAC de pod adjuntas en cbr0:
arp -an
Los pods en los nodos seleccionados tienen conectividad mínima
Si los pods en los nodos seleccionados tienen una conectividad mínima, primero debes confirmar si hay paquetes perdidos. Para ello, ejecuta tcpdump
en el contenedor de la caja de herramientas:
sudo toolbox bash
Instala tcpdump
en la caja de herramientas si aún no lo hiciste:
apt install -y tcpdump
Ejecuta tcpdump
para cbr0:
tcpdump -ni cbr0 host HOSTNAME and port PORT_NUMBER and [TCP|UDP|ICMP]
Si parece que los paquetes grandes se descartan más adelante en el puente (por ejemplo, el protocolo de enlace TCP se completa, pero no se reciben saludos SSL), asegúrate de que la MTU para cada interfaz de Pod de Linux esté configurada de manera correcta en la MTU de la red de VPC del clúster.
ip address show cbr0
Cuando se utilizan superposiciones (por ejemplo, Weave o Flannel), esta MTU debe reducirse aún más para acomodar la sobrecarga de encapsulación en la superposición.
MTU de GKE
La MTU seleccionada para una interfaz de Pod depende de la Interfaz de red de contenedor (CNI) que usan los nodos del clúster y la configuración de MTU de VPC subyacente. Para obtener más información, consulta Pods.
El valor de MTU de la interfaz del Pod es 1460
o se hereda de la interfaz principal del nodo.
CNI | MTU | GKE Standard |
---|---|---|
kubenet | 1,460 | Default |
kubenet (GKE versión 1.26.1 y posteriores) |
Heredada | Default |
Calico | 1,460 |
Se habilita mediante Para obtener más información, consulta Controla la comunicación entre Pods y Services mediante las políticas de red. |
netd | Heredada | Se habilita mediante cualquiera de las siguientes opciones: |
GKE Dataplane V2 | Heredada |
Se habilita mediante Para obtener más información, consulta Usa GKE Dataplane V2. |
Conexiones fallidas intermitentes
iptables reenvía las conexiones hacia y desde los pods. Los flujos se registran como entradas en la tabla conntrack y, cuando hay muchas cargas de trabajo por nodo, el agotamiento de la tabla de conntrack puede manifestarse como un error. Estos se pueden registrar en la consola en serie del nodo, por ejemplo:
nf_conntrack: table full, dropping packet
Si puedes determinar que los problemas intermitentes se generan debido al agotamiento de conntrack, es recomendable aumentar el tamaño del clúster (y así reducir la cantidad de cargas de trabajo y flujos por nodo) o aumentar nf_conntrack_max
:
new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
&& echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf
También puedes usar NodeLocal DNSCache para reducir las entradas de seguimiento de conexiones.
Se informa un mensaje que dice "vincular: la dirección ya está en uso" para un contenedor
Un contenedor en un pod no puede iniciarse porque, de acuerdo con los registros del contenedor, el puerto al que la aplicación intenta vincularse ya está reservado. El contenedor entra en una falla de repetición. Por ejemplo, en Cloud Logging, se muestra lo siguiente:
resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"
2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use
Cuando Docker falla, a veces un contenedor en ejecución se retrasa y queda inactivo. El proceso todavía se está ejecutando en el espacio de nombres de red asignado para el pod, y está escuchando en su puerto. Debido a que Docker y el kubelet no saben sobre el contenedor inactivo, intentan iniciar un nuevo contenedor con un proceso nuevo, que no puede vincularse en el puerto, ya que se agrega al espacio de nombres de red ya asociado con el pod.
Para diagnosticar este problema, haz lo siguiente:
Necesitas el UUID del pod en el campo
.metadata.uuid
:kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg name UUID ubuntu-6948dd5657-4gsgg db9ed086-edba-11e8-bdd6-42010a800164
Obtén el resultado de los siguientes comandos del nodo:
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
Verifica los procesos en ejecución de este pod. Debido a que el UUID de los espacios de nombres de cgroup contiene el UUID del pod, puedes usar el comando grep para buscar el UUID del pod en el resultado
ps
. Usa también el comando grep para analizar la línea anterior, de modo que obtengas los procesosdocker-containerd-shim
que tienen el ID del contenedor en el argumento. Corta el resto de la columna cgroup para obtener un resultado más simple:# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/ 1283089 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 276e173b0846e24b704d4 12: 1283107 1283089 Ss sys_pause 4026532393 pause /pause 12: 1283150 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim ab4c7762f5abf40951770 12: 1283169 1283150 Ss do_wait 4026532393 sh /bin/sh -c echo hello && sleep 6000000 12: 1283185 1283169 S hrtimer_nanosleep 4026532393 sleep sleep 6000000 12: 1283244 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 44e76e50e5ef4156fd5d3 12: 1283263 1283244 Ss sigsuspend 4026532393 nginx nginx: master process nginx -g daemon off; 12: 1283282 1283263 S ep_poll 4026532393 nginx nginx: worker process
En esta lista, puedes ver los ID de contenedor, que también deben estar visibles en
docker ps
.En este caso, ocurre lo siguiente:
docker-containerd-shim 276e173b0846e24b704d4
para pausardocker-containerd-shim ab4c7762f5abf40951770
para SH con sleep (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
para nginx (echoserver-ctr)
Verifica aquellos en el resultado de
docker ps
:# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3' 44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc "nginx -g 'daemon off;'" 14 hours ago Up 14 hours k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475 ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78 "/bin/sh -c 'echo hello && sleep 6000000'" 14 hours ago Up 14 hours k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327 registry.k8s.io/pause-amd64:3.1
En casos normales, verás todos los ID de contenedor de
ps
que aparecen endocker ps
. Si hay uno que no ves, es un contenedor inactivo, y es probable que veas un proceso secundario del procesodocker-containerd-shim process
a la escucha en el puerto TCP que informa que ya está en uso.Para verificar esto, ejecuta
netstat
en el espacio de nombres de red del contenedor. Obtén el pid de cualquier proceso de contenedor (así que NOdocker-containerd-shim
) del pod.En el ejemplo anterior, se incluye lo siguiente:
- 1283107 - pause
- 1283169 - sh
- 1283185 - sleep
- 1283263 - nginx master
- 1283282 - nginx worker
# nsenter -t 1283107 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast
También puedes ejecutar
netstat
medianteip netns
, pero necesitas vincular el espacio de nombres de red del proceso de forma manual, ya que Docker no realiza la vinculación:# ln -s /proc/1283169/ns/net /var/run/netns/1283169 gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list 1283169 (id: 2) gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
Mitigación:
La mitigación a corto plazo consiste en identificar procesos inactivos con el método descrito antes y finalizar los procesos mediante el comando kill [PID]
.
La mitigación a largo plazo implica identificar por qué Docker falla y solucionar el problema. Algunos motivos posibles son los siguientes:
- Los procesos zombie se acumulan, por lo que no hay espacios de nombres PID
- Error en Docker
- Presión de recursos / OOM
Error: “no se pudo asignar para el rango 0: no hay direcciones IP en el rango configurado”
La versión 1.18.17 y posteriores de GKE solucionaron un problema en el que los eventos de memoria insuficiente (OOM) generaban una expulsión incorrecta del Pod si el Pod se borró antes de que se iniciaran sus contenedores. Esta expulsión incorrecta podría provocar pods huérfanos que continuaron teniendo direcciones IP reservadas del rango de nodos asignado.
Con el tiempo, GKE se quedó sin direcciones IP para asignar a los Pods nuevos debido a la compilación de Pods huérfanos. Esto generó el mensaje de error failed
to allocate for range 0: no IP addresses in range set
, porque el rango de nodos asignado no tenía IP disponibles para asignar a pods nuevos.
Para resolver este problema, actualiza tu clúster y los grupos de nodos a la versión 1.18.17 o posterior de GKE.
Para evitar este problema y resolverlo en clústeres con versiones de GKE anteriores a la 1.18.17, aumenta tus límites de recursos a fin de evitar eventos de OOM en el futuro y, luego, recupera las direcciones IP mediante quitar los Pods huérfanos.
También puedes ver las estadísticas de uso de direcciones IP de GKE.
Quita los Pods huérfanos de los nodos afectados
Puedes quitar los Pods huérfanos si vacías el nodo, actualizas el grupo de nodos o mueves los directorios afectados.
Desvío del nodo (recomendado)
Acordona el nodo para evitar que se programen Pods nuevos en él:
kubectl cordon NODE
Reemplaza
NODE
por el nombre del nodo que deseas desviar.Desvía el nodo. GKE reprograma automáticamente los Pods administrados por implementaciones en otros nodos. Usa la marca
--force
para desviar los Pods huérfanos que no tienen un recurso de administración.kubectl drain NODE --force
Desacordona el nodo para permitir que GKE programe nuevos pods en él:
kubectl uncordon NODE
Mueve los directorios afectados
Puedes identificar los directorios de Pods huérfanos en /var/lib/kubelet/pods
y quitarlos del directorio principal para permitir que GKE finalice los Pods.
Soluciona problemas de finalización de recursos
Espacio de nombres atascado en el estado Terminating
Los espacios de nombres usan finalizadores de Kubernetes para evitar la eliminación cuando aún existen uno o más recursos dentro de un espacio de nombres.
Cuando borras un espacio de nombres mediante el comando kubectl delete
, este ingresa al estado Terminating
hasta que Kubernetes borre sus recursos dependientes y borra todos los finalizadores. El controlador del ciclo de vida del espacio de nombres primero enumera todos los recursos en el espacio de nombres que GKE debe borrar. Si GKE no puede borrar un recurso dependiente o si el controlador del ciclo de vida del espacio de nombres no puede verificar que el espacio de nombres está vacío, el espacio de nombres permanece en el estado Terminating
hasta que resuelvas el problema.
Para resolver un espacio de nombres atascado en el estado Terminating
, debes identificar y quitar los componentes en mal estado que bloquean la eliminación. Prueba una de las siguientes soluciones.
Busca y quita servicios de API no disponibles
Enumera los servicios de API no disponibles:
kubectl get apiservice | grep False
Soluciona los problemas de los servicios que no responden:
kubectl describe apiservice API_SERVICE
Reemplaza
API_SERVICE
por el nombre del servicio que no responde.Verifica si el espacio de nombres aún se está finalizando:
kubectl get ns | grep Terminating
Busca y quita los recursos restantes
Enumera todos los recursos restantes en el espacio de nombres de finalización:
kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get -n NAMESPACE
Reemplaza
NAMESPACE
por el nombre del espacio de nombres que deseas borrar.Quita cualquier recurso que se muestre en el resultado.
Verifica si el espacio de nombres aún se está finalizando:
kubectl get ns | grep Terminating
Fuerza la eliminación del espacio de nombres
Puedes quitar los finalizadores que bloquean la eliminación del espacio de nombres para forzar la finalización del espacio de nombres.
Guarda el manifiesto de espacio de nombre como un archivo YAML.
kubectl get ns NAMESPACE -o yaml > ns-terminating.yml
Abre el manifiesto en un editor de texto y quita todos los valores del campo
spec.finalizers
:vi ns-terminating.yml
Verifica que el campo de los finalizadores esté vacío:
cat ns-terminating.yml
El resultado debe tener el siguiente aspecto:
apiVersion: v1 kind: Namespace metadata: annotations: name: NAMESPACE spec: finalizers: status: phase: Terminating
Inicia un proxy HTTP para acceder a la API de Kubernetes:
kubectl proxy
Reemplaza el manifiesto del espacio de nombres mediante
curl
:curl -H "Content-Type: application/yaml" -X PUT --data-binary @ns-terminating.yml http://127.0.0.1:8001/api/v1/namespaces/NAMESPACE/finalize
Verifica si el espacio de nombres aún se está finalizando:
kubectl get ns | grep Terminating
Soluciona problemas de pérdida de paquetes de Cloud NAT desde un clúster de GKE
Las VMs de nodo en clústeres privados de GKE nativos de la VPC no tienen direcciones IP externas y no pueden conectarse a Internet por sí mismas. Puedes usar Cloud NAT para asignar las direcciones IP externas y los puertos que permiten que los clústeres privados hagan conexiones públicas.
Si una VM de nodo se queda sin su asignación de puertos IP y direcciones IP externas de Cloud NAT, los paquetes se descartarán. Para evitar esto, puedes reducir la frecuencia de paquetes salientes o aumentar la asignación de puertos y direcciones IP de origen de Cloud NAT disponibles. En las siguientes secciones, se describe cómo diagnosticar y solucionar problemas de pérdida de paquetes de Cloud NAT en el contexto de clústeres privados de GKE.
Diagnostica la pérdida de paquetes
En esta sección, se explica cómo registrar paquetes descartados con Cloud Logging y diagnosticar la causa de los paquetes descartados mediante Cloud Monitoring.
Registra paquetes descartados
Puedes registrar paquetes descartados con la siguiente consulta en Cloud Logging:
resource.type="nat_gateway" resource.labels.region=REGION resource.labels.gateway_name=GATEWAY_NAME jsonPayload.allocation_status="DROPPED"
REGION
: es el nombre de la región en la que se encuentra el clúster.GATEWAY_NAME
: el nombre de la puerta de enlace de Cloud NAT.
Este comando muestra una lista de todos los paquetes que descartó una puerta de enlace de Cloud NAT, pero no identifica la causa.
Supervisa las causas de la pérdida de paquetes
Para identificar las causas de los paquetes descartados, consulta el observador de métricas en Cloud Monitoring. Los paquetes se descartan por uno de tres motivos:
Para identificar los paquetes descartados debido a códigos de error OUT_OF_RESOURCES
o ENDPOINT_ALLOCATION_FAILED
, usa la siguiente consulta:
fetch nat_gateway metric 'router.googleapis.com/nat/dropped_sent_packets_count' filter (resource.gateway_name == NAT_NAME) align rate(1m) every 1m group_by [metric.reason], [value_dropped_sent_packets_count_aggregate: aggregate(value.dropped_sent_packets_count)]
Para identificar los paquetes descartados debido al código de error NAT_ALLOCATION_FAILED
, usa la siguiente consulta:
fetch nat_gateway metric 'router.googleapis.com/nat/nat_allocation_failed' group_by 1m, [value_nat_allocation_failed_count_true: count_true(value.nat_allocation_failed)] every 1m
Soluciona problemas de Cloud NAT con el enmascaramiento de IP de GKE
Si las consultas anteriores muestran resultados vacíos y los Pods de GKE no pueden comunicarse con direcciones IP externas, soluciona los siguientes problemas de configuración:
Configuración | Soluciona problemas |
Cloud NAT configurado para aplicarse solo al rango de direcciones IP principal de la subred. |
Cuando Cloud NAT se configura solo para el rango de direcciones IP principal de la subred, los paquetes enviados desde el clúster hacia direcciones IP externas deben tener una dirección IP de nodo de origen. En esta configuración de Cloud NAT, haz lo siguiente:
|
Cloud NAT configurado para aplicarse solo al rango de direcciones IP secundario de la subred utilizado para las IP de Pods. |
Cuando Cloud NAT se configura solo para el rango de direcciones IP secundario de la subred que usan las IP del Pod del clúster, los paquetes enviados desde el clúster hacia direcciones IP externas deben tener una dirección IP del Pod de origen. En esta configuración de Cloud NAT, se dan las siguientes situaciones:
|
Optimizaciones para evitar la pérdida de paquetes
Puedes detener la pérdida de paquetes de las siguientes maneras:
Configurar la puerta de enlace de Cloud NAT para usar la asignación de puerto dinámica y aumentar la cantidad máxima de puertos por VM
Aumenta la cantidad de puertos mínimos por VM si usas la asignación de puertos de estática.
Optimiza tu aplicación
Cuando una aplicación realiza varias conexiones salientes a la misma dirección IP y puerto de destino, puede consumir con rapidez todas las conexiones que Cloud NAT puede realizar a ese destino mediante la cantidad de direcciones de origen de NAT y tuplas de puertos de origen asignadas. En esta situación, reducir la tasa de paquetes salientes de la aplicación ayuda a reducir la pérdida de paquetes.
Para obtener detalles sobre cómo Cloud NAT usa direcciones de origen y puertos de origen para realizar conexiones, incluidos los límites de la cantidad de conexiones simultáneas a un destino, consultaPuertos y conexiones.
Reducir la tasa de conexiones salientes desde la aplicación puede ayudar a mitigar la pérdida de paquetes. Puedes lograr esto si reutlizar conexiones abiertas. Los métodos comunes para reutilizar conexiones incluyen la agrupación de conexiones, la multiplexación de conexiones con protocolos como HTTP/2 o el establecimiento de conexiones persistentes reutilizadas para varias solicitudes. Para obtener más información, consulta Puertos y conexiones.
La versión del nodo no es compatible con la versión del plano de control
Verifica qué versión de Kubernetes ejecuta el plano de control de tu clúster y, luego, verifica la versión de Kubernetes que ejecutan los grupos de nodos de tu clúster. Si alguno de los grupos de nodos del clúster tiene más de dos versiones secundarias anteriores a la versión del plano de control, es posible que esto genere problemas con tu clúster.
El equipo de GKE realiza actualizaciones periódicas del plano de control del clúster por ti de forma periódica. Los planos de control se actualizan a las versiones estables más nuevas de Kubernetes. De forma predeterminada, los nodos de un clúster tienen habilitada la actualización automática y se recomienda no inhabilitarla.
Si la actualización automática está inhabilitada para los nodos de un clúster y no actualizas manualmente la versión del grupo de nodos a una versión compatible con el plano de control, este no será compatible con tus nodos, ya que el plano de control se actualiza automáticamente con el tiempo. La incompatibilidad entre el plano de control y los nodos de tu clúster puede causar problemas inesperados.
Nota: La política de compatibilidad con el sesgo de versiones y versiones de Kubernetes garantiza que los planos de control sean compatibles con nodos de hasta dos versiones secundarias anteriores que el plano de control. Por ejemplo, los planos de control de Kubernetes 1.19 son compatibles con los nodos de Kubernetes 1.19, 1.18 y 1.17. Para resolver este problema, actualiza manualmente la versión del grupo de nodos a una versión compatible con el plano de control.
Si te preocupa que el proceso de actualización genere interrupciones en las cargas de trabajo que se ejecutan en los nodos afectados, sigue estos pasos para migrar tus cargas de trabajo a un grupo de nodos nuevo:
- Crea un grupo de nodos nuevo con una versión compatible.
- Acordona los nodos del grupo de nodos existente.
- De manera opcional, actualiza las cargas de trabajo que se ejecutan en el grupo de nodos existente para agregar un nodeSelector para la etiqueta
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
, en la queNEW_NODE_POOL_NAME
es el nombre del grupo de nodos nuevo. Esto garantiza que GKE coloque esas cargas de trabajo en nodos en el grupo de nodos nuevo. - Desvía el grupo de nodos existente.
- Comprueba que las cargas de trabajo se ejecuten de forma correcta en el grupo de nodos nuevo. Si es así, puedes borrar el grupo de nodos anterior. Si observas interrupciones en la carga de trabajo, reprograma las cargas de trabajo en los nodos existentes. Para ello, desacordona los nodos en el grupo de nodos existente y agota los nodos nuevos. Soluciona el problema y vuelve a intentarlo.
Las métricas del clúster no aparecen en Cloud Monitoring
Asegúrate de haber activado la API de Cloud Monitoring y la API de Cloud Logging en el proyecto y de que lo puedes ver en Cloud Monitoring.
Si el problema persiste, verifica alguna de las posibles causas siguientes:
Asegúrate de que habilitaste la supervisión en tu clúster.
Monitoring está habilitado de forma predeterminada para los clústeres creados desde la consola de Google Cloud y desde CLI de Google Cloud de ; pero puedes verificarlo si ejecutas el siguiente comando o haces clic en los detalles del clúster en la consola de Google Cloud:
gcloud container clusters describe CLUSTER_NAME
El resultado de este comando debe incluir
SYSTEM_COMPONENTS
en la lista deenableComponents
en la secciónmonitoringConfig
, similar a esto:monitoringConfig: componentConfig: enableComponents: - SYSTEM_COMPONENTS
Si la supervisión no está habilitada, ejecuta el siguiente comando para habilitarla:
gcloud container clusters update CLUSTER_NAME --monitoring=SYSTEM
¿Cuánto tiempo pasó desde que se creó el clúster o se habilitó la supervisión?
Puede tomar hasta una hora para que las métricas de un clúster nuevo comiencen a aparecer Cloud Monitoring.
¿Hay un
heapster
ogke-metrics-agent
(el colector de OpenTelemetry) ejecutándose en el clúster en el espacio de nombres “kube-system”?Es posible que este pod no pueda programar cargas de trabajo porque el clúster se está quedando sin recursos. Para comprobar si OpenTelemetry o Heapster están en ejecución, puedes llamar a
kubectl get pods --namespace=kube-system
y verificar los Pods conheapster
ogke-metrics-agent
en el nombre.¿El plano de control del clúster puede comunicarse con los nodos?
Cloud Monitoring depende de eso. Para verificar si este es el caso, ejecuta el siguiente comando:
kubectl logs POD_NAME
Si este comando muestra un error, es posible que los túneles SSH causen el problema. Consulta esta sección para obtener más información.
Si tienes un problema relacionado con el agente de Cloud Logging, consulta su documentación de solución de problemas.
Para obtener más información, consulta la documentación de Logging.
Faltan permisos en la cuenta de los clústeres de VPC compartida
En el caso de los clústeres de VPC compartida, asegúrate de que la cuenta de servicio de GKE del proyecto de servicio tenga una vinculación para la función de usuario del agente de servicios de host en el proyecto host. Puedes hacer esto con la CLI de gcloud.
Para verificar si la vinculación de rol existe, ejecuta el siguiente comando en tu proyecto host:
gcloud projects get-iam-policy PROJECT_ID \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:SERVICE_ACCOUNT_NAME
Reemplaza lo siguiente:
PROJECT_ID
: el ID de tu proyecto host.SERVICE_ACCOUNT_NAME
: El nombre de la cuenta de servicio de GKE
Busca la propiedad roles/container.hostServiceAgentUser
en el resultado.
ROLE
...
roles/container.hostServiceAgentUser
...
Si el rol hostServiceAgentUser
no está en la lista, sigue las instrucciones en Otorga el rol de usuario del agente de servicios de host para agregar la vinculación a la cuenta de servicio.
Restablece la cuenta de servicio predeterminada en el proyecto de Google Cloud
La cuenta de servicio predeterminada de GKE, container-engine-robot
, se puede desvincular de un proyecto por accidente. El agente de servicio de GKE es una función de administración de identidades y accesos (IAM) que otorga a la cuenta de servicio los permisos para administrar los recursos del clúster. Si quitas esta vinculación de rol de la cuenta de servicio, la cuenta de servicio predeterminada se desvincula del proyecto, lo que puede evitar que se implementen aplicaciones y que se realicen otras operaciones de clúster.
Puedes verificar si la cuenta de servicio se quitó del proyecto con la CLI de gcloud o la consola de Google Cloud
gcloud
Ejecuta el siguiente comando:
gcloud projects get-iam-policy PROJECT_ID
Reemplaza PROJECT_ID
con el ID del proyecto.
Consola
Visita la página IAM y administración en la consola de Google Cloud.
Si en el comando o el panel no se muestra container-engine-robot
entre las cuentas de servicio, la cuenta de servicio se desvinculó.
Si quitas la vinculación de función de agente de servicio de GKE, ejecuta los siguientes comandos para restablecer la vinculación de función:
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID" --format 'get(projectNumber)')
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Para confirmar que la vinculación de función se otorgó, usa lo siguiente:
gcloud projects get-iam-policy $PROJECT_ID
Si ves el nombre de la cuenta de servicio junto con la función container.serviceAgent
, se otorgó la vinculación de función. Por ejemplo:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Habilita la cuenta de servicio predeterminada de Compute Engine
Es posible que los nodos no se registren con el clúster si la cuenta de servicio que se usa para el grupo de nodos está inhabilitada, que suele ser la cuenta de servicio predeterminada de Compute Engine.
Puedes verificar si la cuenta de servicio se inhabilitó en el proyecto con la CLI de gcloud o la consola de Google Cloud.
gcloud
Ejecuta el siguiente comando:
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Consola
Ve a la página IAM y administración en la consola de Google Cloud.
Si en el comando o el panel se muestra que la cuenta de servicio está inhabilitada, ejecuta el siguiente comando para habilitarla:
gcloud iam service-accounts enable PROJECT_ID-compute@developer.gserviceaccount.com
Reemplaza PROJECT_ID
con el ID del proyecto.
Si esto no resuelve los problemas de registro de nodos, consulta Soluciona problemas de registro de nodos para obtener más instrucciones sobre la solución de problemas.
Pods que quedaron en estado pendiente después de habilitar la asignación de nodos
Si tienes un problema con los pods que quedaron en estado pendiente después de habilitar la asignación de nodos, ten en cuenta lo siguiente:
A partir de la versión 1.7.6, GKE reserva CPU y memoria para la sobrecarga de Kubernetes, incluidos Docker y el sistema operativo. Consulta Arquitectura del clúster para obtener información sobre la cantidad de cada tipo de máquina que los pods pueden programar.
Si los pods están pendientes después de una actualización, sugerimos realizar lo siguiente:
Asegúrate de que las solicitudes de CPU y memoria para los pods no excedan su uso máximo. Cuando GKE reserva CPU y memoria para la sobrecarga, los pods no pueden solicitar estos recursos. Los pods que solicitan más CPU o memoria de la que usan evitan que otros pods soliciten estos recursos y es posible que dejen el clúster con poco uso. Para obtener más información, consulta Cómo se programan los pods con solicitudes de recursos.
Considera cambiar el tamaño del clúster. Para obtener instrucciones, consulta Cambia el tamaño de un clúster.
Si deseas revertir este cambio, cambia a una versión inferior del clúster. Para obtener instrucciones, consulta Actualiza un clúster o grupo de nodos de forma manual.
- Configura tu clúster para enviar métricas del programador de Kubernetes a Cloud Monitoring y consulta las métricas del programador.
La autoridad de certificación raíz del clúster vencerá pronto
La autoridad de certificación raíz de tu clúster vencerá pronto. Para evitar que se interrumpan las operaciones normales del clúster, debes realizar una rotación de credenciales.
Ves el error “Instance Foo” no contiene metadatos 'instance-template'
Es posible que veas el error “Instance Foo” no contiene “instance-template” metadata” como un estado de un grupo de nodos que no puede actualizar, escalar ni realizar reparación automática de nodos.
Este mensaje indica que los metadatos de las instancias de VM, asignados por GKE, están dañados. Esto suele suceder cuando la automatización o las secuencias de comandos creadas de forma personalizada intentan agregar metadatos de instancia nuevos (como block-project-ssh-keys
) y, en lugar de solo agregar o actualizar valores, también se borran los metadatos existentes.
Puedes leer sobre los metadatos de instancias de VM en Establece metadatos personalizados.
En caso de cualquiera de los valores críticos de metadatos (entre otros: instance-template
, kube-labels
, kubelet-config
, kubeconfig
, cluster-name
, configure-sh
, cluster-uid
), se borraron el nodo o el grupo de nodos completo en un estado inestable, ya que estos valores son fundamentales para las operaciones de GKE.
Si los metadatos de la instancia se dañaron, la mejor manera de recuperarlos es volver a crear el grupo de nodos que contiene las instancias de VM dañadas. Deberás agregar un grupo de nodos al clúster y aumentar el recuento de nodos en el grupo nuevo, a la vez que acordonas y quitas los nodos del otro. Consulta las instrucciones para migrar cargas de trabajo entre grupos de nodos.
Para encontrar quién y cuándo se editaron los metadatos de la instancia, puedes revisar la información del registro de auditoría de Compute Engine o buscar registros mediante el Explorador de registros con la consulta de búsqueda similar a esta:
resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"
En los registros, puedes encontrar la dirección IP del creador de la solicitud y el usuario-agente:
requestMetadata: {
callerIp: "REDACTED"
callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}
La clave de Cloud KMS está inhabilitada.
El siguiente mensaje de error se produce si la cuenta de servicio predeterminada de GKE no puede acceder a la clave de Cloud KMS.
Cluster problem detected (Kubernetes Engine Service Agent account unable to use CloudKMS key configured for Application Level encryption).
Para resolver este problema, vuelve a habilitar la clave inhabilitada.
Para obtener más información sobre los secretos en GKE, consulta Encripta secretos en la capa de aplicación.
No se pudo actualizar la encriptación de secretos
Si falla la operación para habilitar, inhabilitar o actualizar la clave de Cloud KMS, consulta la guía Soluciona problemas de encriptación de Secrets de la capa de la aplicación.