Problema
En entornos de Cloud Run es frecuente que un servicio despliegue sin errores aparentes y, sin embargo, cualquier petición HTTP termine en la página genérica “404. That’s an error”. El contenedor está activo, la sonda de arranque pasa y los logs de Cloud Run no registran ninguna solicitud entrante. El síntoma se repite tanto con la URL canónica (*.run.app) como con la URL numérica, y ocurre tanto desde navegadores externos como desde Cloud Shell. En estos casos el problema no está en la aplicación (por ejemplo, Flask/Gunicorn) sino en la capa de control que dirige el tráfico hacia el contenedor.
Causa
Los 404 que nunca llegan al contenedor suelen deberse a una de las siguientes configuraciones:
-
Restricciones de ingreso (Ingress) a nivel de servicio o de organización
INGRESS_TRAFFIC_ALLestá desactivado o sobreescrito por una política de organizaciónrun.allowedIngress.- Un Service Perimeter (VPC Service Controls) que bloquea tráfico externo aunque la política de ingreso sea permisiva.
-
Política de IAM del invocador
- Cuando
invokerIamDisabledestá enfalse, Cloud Run verifica que el solicitante tenga el rolroles/run.invoker. En organizaciones con dominio‑restricted sharing, el rol no puede asignarse aallUsers, lo que provoca un rechazo implícito que se traduce en 404. - Incluso con
invokerIamDisabled=true, una política organizacionalrun.managed.requireInvokerIamobligatoria anula la desactivación y vuelve a aplicar la verificación.
- Cuando
-
Desactivación de la URL predeterminada
- La bandera
defaultUriDisabledevita que la URL*.run.appsea pública. Si está activada, solo la URL numérica funciona, pero si la política de IAM también falla, ambas devuelven 404.
- La bandera
-
Perímetro de servicio o VPC Service Controls
- Un perímetro que incluye el proyecto pero no permite tráfico de salida hacia la red pública puede hacer que el front‑end de Cloud Run rechace la petición antes de que llegue al contenedor.
-
Configuración de rutas internas (Cloud Load Balancer / Cloud CDN)
- En entornos donde Cloud Run está detrás de un balanceador HTTP(S) personalizado, una regla de ruta mal definida o un host‑rule que no incluye el dominio
run.appredirige a una página 404 genérica.
- En entornos donde Cloud Run está detrás de un balanceador HTTP(S) personalizado, una regla de ruta mal definida o un host‑rule que no incluye el dominio
-
Problemas de propagación de cambios
- Después de modificar políticas (IAM, ingress, perímetro) puede haber un lapso de varios minutos antes de que el front‑end de Cloud Run refleje la nueva configuración. Durante ese tiempo, las peticiones siguen recibiendo 404.
Solución
1. Verificar y normalizar la política de ingreso
gcloud run services describe SERVICE_NAME \
--region REGION \
--format="value(ingress)"
- Si el valor no es
INGRESS_TRAFFIC_ALL, actualízalo:
gcloud run services update SERVICE_NAME \
--region REGION \
--ingress=all
- Revisa la política organizacional:
gcloud org-policies describe run.allowedIngress \
--effective \
--project PROJECT_ID
Si la política fuerza allowInternalOnly, elimínala o crea una excepción para el proyecto.
2. Confirmar que el control de IAM del invocador está desactivado
gcloud run services describe SERVICE_NAME \
--region REGION \
--format="value(spec.template.metadata.annotations.invokerIamDisabled)"
- Si devuelve
false, habilítalo:
gcloud run services update SERVICE_NAME \
--region REGION \
--no-invoker-iam
- Verifica que la política organizacional
run.managed.requireInvokerIamno esté forzada:
gcloud org-policies describe run.managed.requireInvokerIam \
--effective \
--project PROJECT_ID
Si está activa, solicite a la administración que la desactive o añada una excepción.
3. Revisar la flag de URL predeterminada
gcloud run services describe SERVICE_NAME \
--region REGION \
--format="value(spec.template.metadata.annotations.defaultUriDisabled)"
- Si está
true, desactívala:
gcloud run services update SERVICE_NAME \
--region REGION \
--no-default-uri-disabled
4. Inspeccionar perímetros de VPC Service Controls
gcloud access-context-manager perimeters list \
--project PROJECT_ID
- Si el proyecto pertenece a un perímetro, asegúrese de que la regla de acceso
accessLevelsincluyaallUserso que el perímetro permita tráfico de salida a*.run.app. - En caso contrario, añada una excepción o elimine temporalmente el perímetro para validar.
5. Validar rutas de balanceador (si aplica)
- En la consola de Cloud Load Balancing, compruebe que el host‑rule incluya
*.run.app. - Si usa un backend service de tipo “Serverless Network Endpoint Group”, confirme que la URL de backend sea la URL de Cloud Run y que el health check apunte a
/healthz.
6. Forzar una nueva revisión del servicio
A veces la configuración se queda en caché. Una forma rápida de “refrescar” es crear una nueva revisión sin cambiar nada:
gcloud run services update-traffic SERVICE_NAME \
--to-revisions=LATEST=100 \
--region REGION
Esto fuerza al control plane a volver a leer la configuración y a regenerar los endpoints.
7. Revisar logs de Cloud Run y Cloud Logging
- En Cloud Logging, filtre por
resource.type="cloud_run_revision"yseverity="ERROR"para detectar rechazos implícitos. - Si no aparecen entradas de request, el tráfico está siendo bloqueado antes de llegar al contenedor, confirmando una de las causas anteriores.
Cuándo aplicar esta solución
- Síntomas: 404 genérico de Google, sin logs de request; la sonda de arranque pasa; el contenedor está escuchando en
0.0.0.0:8080. - Entorno: proyectos dentro de organizaciones con políticas restrictivas (dominio‑restricted sharing, VPC Service Controls).
- Exclusiones: Si los logs muestran peticiones llegando al contenedor pero la aplicación responde 404, el problema está en la lógica de la aplicación, no en la capa de control.
Código
# 1. Verificar ingreso
gcloud run services describe $SERVICE \
--region $REGION \
--format="value(ingress)"
# 2. Habilitar ingreso total
gcloud run services update $SERVICE \
--region $REGION \
--ingress=all
# 3. Desactivar IAM del invocador
gcloud run services update $SERVICE \
--region $REGION \
--no-invoker-iam
# 4. Asegurar URL predeterminada habilitada
gcloud run services update $SERVICE \
--region $REGION \
--no-default-uri-disabled
# 5. Revisar políticas organizacionales
gcloud org-policies describe run.allowedIngress \
--effective \
--project $PROJECT_ID
gcloud org-policies describe run.managed.requireInvokerIam \
--effective \
--project $PROJECT_ID
# 6. Forzar nueva revisión
gcloud run services update-traffic $SERVICE \
--to-revisions=LATEST=100 \
--region $REGION
Verificación
- Prueba de salud:
curl -i https://SERVICE_NAME-REGION.run.app/healthz- Respuesta esperada:
200 OKy cuerpook.
- Respuesta esperada:
- Petición pública: Desde una ventana incógnita del navegador, acceda a la URL canónica. No debe aparecer la página de 404.
- Logs: En Cloud Logging, busque entradas
requestbajoresource.type="cloud_run_revision"y confirme que aparecen los registros de la petición. - Tiempo de propagación: Espere 2‑3 minutos después de cada cambio y repita la prueba; la mayoría de los cambios de política se materializan en ese intervalo.
Notas adicionales
- En organizaciones con dominio‑restricted sharing, es buena práctica crear un grupo de servicio (
serviceAccount) con el rolroles/run.invokery usar tokens de identidad para llamadas internas. - Si necesita exponer el servicio a internet pero no puede asignar
allUsers, considere usar Cloud Identity‑Aware Proxy (IAP) o un API Gateway que gestione la autenticación. - Cuando el proyecto está dentro de un perímetro, la regla
accessLevelsdebe incluiraccessPolicies/*/accessLevels/*que permitan tráfico externo; de lo contrario, cualquier endpoint público quedará inalcanzable. - Los cambios de política pueden tardar más de lo esperado si la organización tiene múltiples niveles de herencia; siempre valide con
gcloud org-policies list --effective.
Con estos pasos el ingeniero puede aislar rápidamente la causa de un 404 que nunca llega al contenedor y restablecer la disponibilidad del servicio Cloud Run sin necesidad de redeploys extensos.