Migra al proxy de servicio extensible V2

El proxy de servicio extensible V2 (ESPv2) es un proxy basado en Envoy que le permite a Cloud Endpoints proporcionar características de administración de API. ESPv2 reemplaza al proxy de servicio extensible (ESP) basado en NGINX.

En este documento, se describe cómo migrar una implementación existente de la API de Endpoints desde el ESP a ESPv2.

Antes de comenzar

Antes de comenzar la migración, considera los casos de uso no compatibles y rompe los cambios de la API que se describen a continuación.

Casos de uso no compatibles con ESPv2

  • El entorno flexible de App Engine no es compatible

    El entorno flexible de App Engine tiene compatibilidad con Endpoints integrada que se habilita mediante la configuración de endpoints_api_service en el archivo app.yaml de la aplicación. Esta implementación integrada de Endpoints solo admite el ESP. No se puede migrar a ESPv2.

    Si quieres usar ESPv2 con el entorno flexible de App Engine, inhabilita endpoints_api_service en app.yaml. Puedes implementar el ESPv2 como un servicio independiente de Cloud Run que se usa para administrar tu aplicación en el entorno flexible de App Engine. La implementación funciona de la misma manera en que se usa ESPv2 para admitir el entorno estándar de App Engine.

  • La configuración de NGINX personalizada no es compatible

    El ESPv2 es un proxy basado en Envoy. No puede admitir una configuración personalizada de proxy NGINX. Si tu configuración del ESP usa las marcas -n o --nginx_config, tu implementación puede depender de una configuración NGINX personalizada que no se puede migrar fácilmente a ESPv2.

Cambios rotundos

  • Se cambió el formato de datos del encabezado X-Endpoint-API-UserInfo. Si tu aplicación usa este encabezado, se debe cambiar para que use el formato nuevo. Consulta Controla JWT en el servicio de backend para conocer más detalles.
  • Si se requiere una clave de API para una solicitud, el ESP envía el encabezado X-Endpoint-API-Project-ID con el ID del proyecto del consumidor a la aplicación de backend. El ESPv2 usa dos encabezados diferentes, X-Endpoint-API-Consumer-Type y X-Endpoint-API-Consumer-Number, para enviar los detalles requeridos. Consulta la documentación de referencia de Service Infrastructure para obtener más detalles sobre los Consumer-Type y Consumer-Number enviados con estos encabezados.

  • Se cambia el formato del cuerpo de la respuesta de error HTTP. Cuando el ESPv2 rechaza una solicitud HTTP, genera un cuerpo de la respuesta de error en un formato nuevo. Si tu implementación usa código de cliente para procesar el cuerpo de la respuesta JSON de error HTTP, el código de cliente debe actualizarse. Consulta el formato del cuerpo de respuesta JSON de error HTTP para obtener más detalles.

  • Hay disponibles nuevas marcas de inicio y algunas marcas ESP ya no están disponibles o se reemplazaron en ESPv2. Consulta Cambios en la marca de inicio entre ESP y ESPv2.

Migra tus API de Endpoints para usar ESPv2

Los pasos de migración necesarios para usar ESPv2 con plataformas sin servidores (Cloud Run, funciones de Cloud Run y App Engine) difieren de los pasos necesarios para las plataformas con servidores (Google Kubernetes Engine, Compute Engine y Kubernetes).

A continuación, se describen los pasos de migración necesarios para cada tipo de plataforma:

Plataformas sin servidores: GKE, Compute Engine, Kubernetes

ESPv2 es un reemplazo directo del ESP. Para la mayoría de las configuraciones, solo debes actualizar a la etiqueta de imagen de Docker.

Sin embargo, es posible que debas ajustar las marcas de inicio si configuraste el ESP con lo siguiente:

  • Más de un puerto a través de las marcas --http_port, http2_port o --ssl_port.
  • SSL, DNS, Client IP o alguna otra marca de uso poco frecuente.

Existen nuevos indicadores de inicio disponibles para ESPv2 y algunas marcas del ESP ya no están disponibles o se reemplazaron. Para obtener más detalles, consulta Cambios en la marca de inicio entre ESP y ESPv2.

GKE y Kubernetes

A fin de migrar las configuraciones de Endpoints para GKE y Kubernetes, cambia la etiqueta de la imagen del ESP de :1 a :2 en el archivo yaml de implementación. Por ejemplo:

- name: esp
  image: gcr.io/endpoints-release/endpoints-runtime:2
  args: [
    "--http_port=8081",
    "--backend=127.0.0.1:8080",
    "--service=SERVICE_NAME",
    "--rollout_strategy=managed",
  ]

Compute Engine

Tanto ESP como ESPv2 se implementan en el contenedor de Docker mediante el comando docker run. Para migrar Endpoints para Compute Engine a ESPv2, actualiza la etiqueta de imagen de Docker de :1:2 en el comando. Por ejemplo:

sudo docker run \
    --detach \
    DOCKER_ARGUMENTS \
    gcr.io/endpoints-release/endpoints-runtime:2 \
    --service=SERVICE_NAME \
    --rollout_strategy=managed \
    --backend=YOUR_API_CONTAINER_NAME:8080

Plataformas sin servidores (Cloud Run, Cloud Functions, App Engine)

En el caso de las plataformas sin servidores, ESPv2 se implementa como un servicio de Cloud Run para administrar la aplicación que se ejecuta en Cloud Run, en la función de Cloud Functions o App Engine. Para migrar Endpoints a ESPv2, debes compilar tu configuración de servicio de Endpoints existente en una nueva imagen de Docker de ESPv2 y, luego, implementar la imagen en tu servicio de ESPv2 de Cloud Run.

Los pasos de implementación para el ESP y ESPv2 son idénticos, excepto por los siguientes detalles:

  • La etiqueta de imagen debe cambiarse de :1 a :2 en el ESPv2 cuando implementes ESPv2 en Cloud Run. Por ejemplo:

    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
    --image="gcr.io/endpoints-release/endpoints-runtime-serverless:2" \
    --allow-unauthenticated \
    --platform managed \
    --project=ESP_PROJECT_ID  
  • La secuencia de comandos de gcloud_build_image se descarga desde una ubicación diferente. Usa gcr.io/endpoints-release/endpoints-runtime-serverless:2 como la imagen base.

  • Se usa una variable de entorno para especificar marcas de inicio. El nombre de variable para ESP es ESP_ARGS. El nombre de ESPv2 es ESPv2_ARGS. Consulta las Opciones de inicio del proxy de servicio extensible V2 a fin de obtener más información para configurar ESPv2_ARGS y las marcas de inicio disponibles.

Cambios en la marca de inicio entre ESP y ESPv2

Al igual que con el proxy de servicio extensible, puedes especificar marcas de configuración cuando implementas servicios de ESPv2. Tras el cambio del ESP basado en NGINX por el ESPv2 basado en Envoy, algunas marcas dejaron de estar disponibles o se reemplazaron, y se agregaron marcas nuevas. En esta sección, se usan tres tablas para describir los cambios:

  • En la tabla 1, se describen las marcas nuevas que reemplazan a las marcas obsoletas.
  • En la Tabla 2, se describen las marcas nuevas.
  • En la tabla 3, se describen las marcas obsoletas.

Marcas reemplazadas

Marcas nuevas Marcas reemplazadas Descripción
--listener_port --http_port, --http2_port, --ssl_port Un único puerto del objeto de escucha de Envoy admite http, http2 y ssl en ESPv2. No es necesario especificar puertos diferentes.
--ssl_server_cert_path --ssl_port Cuando se usa --ssl_server_cert_path, el ESPv2 usa certificados de los archivos server.key y server.crt. Con ESPv2, puedes especificar rutas de acceso de certificado de servidores que no sean /etc/nginx/ssl. Esta marca reemplaza a --ssl_port en el ESP, que usa certificados de las rutas de acceso a archivos /etc/nginx/ssl/nginx.key y /etc/nginx/ssl/nginx.crt.
--ssl_backend_client_cert_path --tls_mutual_auth, --enable_grpc_backend_ssl, --grpc_backend_ssl_private_key_file, --grpc_backend_ssl_cert_chain_file Cuando se usa --ssl_backend_client_cert_path, el ESPv2 usa certificados de los archivos client.key y client.crt. Con ESPv2, puedes especificar rutas de acceso de certificados de cliente que no sean /etc/nginx/ssl. Esta marca reemplaza a --tls_mutual_auth en el ESP, que usa certificados de las rutas de acceso a archivos /etc/nginx/ssl/backend.key y /etc/nginx/ssl/backend.crt.
--ssl_backend_client_root_certs_file --grpc_backend_ssl_root_certs_file Con ESPv2, --ssl_backend_client_root_certs_file funciona en todos los backends. Esta marca reemplaza a --grpc_backend_ssl_root_certs_file en el ESP, que solo funciona en backends de gRPC.
--ssl_minimum_protocol,--ssl_maximum_protocol --ssl_protocols Cuando uses --ssl_protocols en el ESP, debes enumerar todos los protocolos ssl deseados. En el ESPv2, puedes especificar un protocolo mínimo y máximo.
--envoy_use_remote_address,--envoy_xff_num_trusted_hops --xff_trusted_proxy_list,--client_ip_header,--client_ip_position Envoy requiere use_remote_address y xff_num_trusted_hops para configurar la extracción de IP del cliente.
--dns_resolver_addresses --dns La marca de reemplazo tiene el mismo comportamiento, pero un valor predeterminado diferente. El ESP usa 8.8.8.8 como agente de resolución de DNS. El ESPv2 usa el agente de resolución de DNS configurado en /etc/resolv.conf.
--service_account_key --non_gcp, --service_account_key En el ESP, la marca --service_account_key permite, de manera implícita, la implementación en plataformas distintas de GCP. Evita que el ESP llame al servidor de metadatos de la instancia. En el ESPv2, este comportamiento implícito se divide en otra marca. Es posible que debas agregar --non_gcp durante la migración; de lo contrario, el ESPv2 no se iniciará en plataformas distintas de GCP.

Marcas nuevas

Marcas nuevas Descripción
--http_request_timeout_s Establece el tiempo de espera para todas las llamadas remotas de http o https, excepto las llamadas de backend y las llamadas del Control de servicios de Google, en segundos.
--service_control_check_timeout_ms Establece el tiempo de espera para las llamadas de Verificación de control de servicio de Google, en milisegundos.
--service_control_report_timeout_ms Establece el tiempo de espera para las llamadas al Informe de control de servicio de Google.
--service_control_quota_timeout_ms Configura el tiempo de espera para las llamadas de la cuota de control de servicio de Google.
--service_control_check_retries Especifica el número de reintento para las llamadas de Control del control de servicios de Google.
--service_control_report_retries Especifica el número de reintento para las llamadas del Informe del control de servicios de Google.
--service_control_quota_retries Especifica el número de reintento para las llamadas de cuota del control de servicios de Google.
--backend_dns_lookup_family La configuración específica de Envoy que se usa para definir la familia de búsqueda de DNS para todos los backends.
--disable_tracing Una marca general que se usa para inhabilitar todos los seguimientos.
--tracing_project_id Se usa para configurar el ID del proyecto que posee los datos de seguimiento.
--tracing_incoming_context Se usa para especificar el contexto de seguimiento entrante.
--tracing_outgoing_context Se usa para especificar el contexto de seguimiento saliente.

Marcas obsoletas

Marcas obsoletas Descripción
--enable_websocket Websocket está habilitado de forma predeterminada en Envoy.
--experimental_proxy_backend_host_header No compatible.
--allow_invalid_headers No compatible. Esta es una configuración de NGINX: ignore_invalid_headers. Si una solicitud HTTP tiene nombres de encabezados no válidos, el ESPv2 rechazará. Los nombres de encabezado válidos están compuestos por letras, dígitos, guiones y guiones bajos en inglés. En el ESPv2, la marca --underscores_in_headers determina si se permiten guiones bajos en los encabezados.
--client_max_body_size La configuración de NGINX, que no es compatible.
--client_body_buffer_size La configuración de NGINX, que no es compatible.
--large_client_header_buffers La configuración de NGINX, que no es compatible.
--keepalive_timeout La configuración de NGINX, que no es compatible.
--client_body_timeout La configuración de NGINX, que no es compatible.
--rewrite No compatible.
--experimental_enable_multiple_api_configs No compatible.
--enable_backend_routing No es necesario. El enrutamiento del backend se habilita automáticamente para las plataformas sin servidores.
--rollout_fetch_throttle_window_in_s No es necesario.
--nginx_config No compatible.

Consulta las Opciones de inicio del proxy de servicio extensible V2 para obtener más detalles sobre las marcas de inicio del ESPv2. Puedes encontrar ejemplos genéricos adicionales y texto de ayuda para las marcas en el repositorio de GitHub.

Ubicaciones de JWT predeterminadas

De forma predeterminada, los JWT se pasan en el encabezado Authorization (con el prefijo “Bearer”), el encabezado X-Goog-Iap-Jwt-Assertion o el parámetro de búsqueda access_token. El ESP y el ESPv2 admiten estas ubicaciones. También puedes pasar un JWT en el encabezado Authorization (sin prefijo) cuando uses el ESP. Sin embargo, esta ubicación no se admite en ESPv2.

Si deseas seguir pasando JWT con el encabezado Authorization (sin prefijo) después de la migración a ESPv2, puedes hacer lo siguiente:

x-google-jwt-locations:
- header: "Authorization"
jwt_locations:
- header: Authorization

Controla JWT en el servicio de backend

Cuando se usan JWT para realizar la autenticación, ESPv2 y ESP envían el resultado de la autenticación en el encabezado X-Endpoint-API-UserInfo a la API de backend. Te recomendamos usar este encabezado en lugar del encabezado Authorization original, ya que el encabezado Authorization original se puede modificar en plataformas sin servidores.

El encabezado X-Endpoint-API-UserInfo contiene un objeto JSON codificado en Base64Url. Sin embargo, su formato cambió de ESP a ESPv2.

Para ESPv2, el encabezado X-Endpoint-API-UserInfo contiene la carga útil del JWT original, sin modificaciones.

En el ESP, el encabezado X-Endpoint-API-UserInfo contiene la carga útil de JWT y algunos campos específicos que agrega el ESP. El ESP agrega los campos id, issuer, email y audiences al objeto JSON. También agrega el campo claims para incluir la carga útil original del JWT.

# ESPv1 X-Endpoint-API-UserInfo header value
{
  "id": "extracted from 'sub' field",
  "issuer": "extracted from 'iss' field",
  "email": "extracted from 'email' field",
  # The following "audiences" is extracted from 'aud' field.
  # The 'aud' field may have multiple audiences delimited by coma. e.g. "aud: aud1,aud2".
  # but the following "audiences" is always a JSON array.
  "audiences": ["aud1", "aud2"],
  "claims": {
     Original JWT payload
   }
}

En el siguiente ejemplo, se ilustran las diferencias, todas las cuales se decodificaron con base64url.

# This is an example of the original JWT payload:
{
  &quotiss&quot: &quothttps://accounts.google.com&quot,
  &quotemail&quot: &quotabcdefg123456@gmail.com&quot,
  &quotsub&quot: &quot1234567890123456789&quot,
  &quotaud&quot: &quotxyz1.example.com,xyz2.example.com&quot,
  &quotfoo&quot: &quotfoo.foo.foo.foo&quot,
  &quotbar&quot: &quotbar.bar.bar.bar&quot,
  &quotazp&quot: &quot98765432109876543210&quot,
  &quotexp&quot: &quot1642809446&quot,
  &quotiat&quot: &quot1642805846&quot
}

# This is an example of the `X-Endpoint-API-UserInfo` header from ESPv2
# extracted from above JWT payload.
{
  &quotiss&quot: &quothttps://accounts.google.com&quot,
  &quotemail&quot: &quotabcdefg123456@gmail.com&quot,
  &quotsub&quot: &quot1234567890123456789&quot,
  &quotaud&quot: &quotxyz1.example.com,xyz2.example.com&quot,
  &quotfoo&quot: &quotfoo.foo.foo.foo&quot,
  &quotbar&quot: &quotbar.bar.bar.bar&quot,
  &quotazp&quot: &quot98765432109876543210&quot,
  &quotexp&quot: &quot1642809446&quot,
  &quotiat&quot: &quot1642805846&quot
}

# This is an example of the `X-Endpoint-API-UserInfo` header from ESP
# extracted from above JWT payload.
{
  &quotid&quot:&quot1234567890123456789&quot,
  &quotissuer&quot: &quothttps://accounts.google.com&quot,
  &quotemail&quot: &quotabcdefg123456@gmail.com&quot,
  &quotaudiences&quot: [
    &quotxyz1.example.com&quot
    &quotxyz2.example.com&quot
  ],
  &quotclaims&quot: {
    &quotiss&quot: &quothttps://accounts.google.com&quot,
    &quotemail&quot: &quotabcdefg123456@gmail.com&quot,
    &quotsub&quot: &quot1234567890123456789&quot,
    &quotaud&quot: &quotxyz1.example.com,xyz2.example.com&quot,
    &quotfoo&quot: &quotfoo.foo.foo.foo&quot,
    &quotbar&quot: &quotbar.bar.bar.bar&quot,
    &quotazp&quot: &quot98765432109876543210&quot,
    &quotexp&quot: &quot1642809446&quot,
    &quotiat&quot: &quot1642805846&quot
  }
}

Consulta Usa un método personalizado para autenticar usuarios y Autenticación entre servicios a fin de obtener más información sobre el uso de JWT con autenticación.

Formato del cuerpo de respuesta JSON de error

Si el ESP o ESPv2 rechaza una solicitud HTTP, el cuerpo de la respuesta contiene un código de estado y un mensaje de error en formato JSON. El formato del cuerpo de la respuesta cambió en ESPv2, como se muestra en los siguientes ejemplos:

El cuerpo de la respuesta de error del ESP

{
 "code": 5,
 "message": "Method does not exist.",
 "details": [
  {
   "@type": "type.googleapis.com/google.rpc.DebugInfo",
   "stackEntries": [],
   "detail": "service_control"
  }
 ]
}

El cuerpo de la respuesta de error del ESPv2

{
 "code": 400,
 "message": "Method does not exist.",
}

Existen dos diferencias principales:

  • En el ESPv2, el campo code contiene un código de estado HTTP, en lugar de un código de estado de RPC que se encuentra en el ESP.
  • El cuerpo de la respuesta de error del ESPv2 no contiene un campo details.

¿Qué sigue?

Obtén más información acerca de los siguientes temas: