Migrar a Extensible Service Proxy V2

El proxy de servicios extensible V2 (ESPv2) es un proxy basado en Envoy que permite a Cloud Endpoints proporcionar funciones de gestión de APIs. ESPv2 sustituye al proxy de servicios extensible (ESP) basado en NGINX.

En este documento se describe cómo migrar una implementación de API de Endpoints de ESP a ESPv2.

Antes de empezar

Antes de empezar la migración, ten en cuenta los casos prácticos no admitidos y los cambios de API que suponen un cambio radical que se describen a continuación.

Casos prácticos no admitidos de ESPv2

  • No se admite el entorno flexible de App Engine

    El entorno flexible de App Engine tiene compatibilidad integrada con Endpoints, que se habilita definiendo endpoints_api_service en el archivo app.yaml de la aplicación. Esta implementación de Endpoints integrada solo admite ESP y 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 desplegar ESPv2 como un servicio de Cloud Run independiente que se usa para gestionar tu aplicación en el entorno flexible de App Engine. El despliegue funciona de la misma forma que ESPv2 se usa para admitir el entorno estándar de App Engine.

  • No se admite la configuración personalizada de NGINX

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

Puntos de ruptura

  • Se ha cambiado el formato de los datos del encabezado X-Endpoint-API-UserInfo. Si tu aplicación usa este encabezado, debes cambiarlo para que use el nuevo formato. Consulta más información en Gestionar JWTs en el servicio backend.
  • Si se necesita una clave de API para una solicitud, ESP envía el encabezado X-Endpoint-API-Project-ID con el ID del proyecto del consumidor a la aplicación backend. ESPv2 usa dos encabezados diferentes,X-Endpoint-API-Consumer-Type y X-Endpoint-API-Consumer-Number, para enviar los detalles necesarios. Consulta la documentación de referencia de Service Infrastructure para obtener más información sobre los valores de Consumer-Type y Consumer-Number que se envían con estos encabezados.

  • Se ha cambiado el formato del cuerpo de la respuesta de error HTTP. Cuando ESPv2 rechaza una solicitud HTTP, genera un cuerpo de respuesta de error en un nuevo formato. Si tu implementación usa código de cliente para procesar el cuerpo de la respuesta JSON de error HTTP, debes actualizar el código de cliente. Consulta más detalles en el artículo Cuerpo de la respuesta JSON de error HTTP.

  • Hay nuevas marcas de inicio disponibles y algunas marcas de ESP se han retirado o sustituido en ESPv2. Consulta Cambios en las marcas de inicio entre ESP y ESPv2.

Migrar las APIs de Endpoints para usar ESPv2

Los pasos de migración necesarios para usar ESPv2 con plataformas sin servidor (Cloud Run, funciones de Cloud Run y App Engine) son diferentes de los pasos necesarios para plataformas que no son sin servidor (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 servidor: GKE, Compute Engine y Kubernetes

ESPv2 es un sustituto directo de ESP. En la mayoría de las configuraciones, solo tiene que actualizar la etiqueta de la imagen de Docker.

Sin embargo, es posible que tengas que ajustar las marcas de inicio si has configurado ESP con lo siguiente:

  • Más de un puerto mediante las marcas --http_port, http2_port o --ssl_port.
  • SSL, DNS, Client IP u otra marca que se use con poca frecuencia.

Hay nuevas marcas de inicio disponibles para ESPv2 y algunas marcas de ESP se han retirado o sustituido. Consulta Cambios en las marcas de inicio entre ESP y ESPv2 para obtener más información.

GKE y Kubernetes

Para migrar las configuraciones de Endpoints para GKE y Kubernetes, cambia la etiqueta de imagen de 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 la imagen de Docker de :1 a :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 servidor (Cloud Run, Cloud Functions y App Engine)

En las plataformas sin servidor, ESPv2 se implementa como un servicio de Cloud Run para gestionar la aplicación que se ejecuta en Cloud Run, Cloud Functions o App Engine. Para migrar Endpoints a ESPv2, debes compilar la configuración de tu servicio de Endpoints en una nueva imagen de Docker de ESPv2 y, a continuación, desplegar la imagen en tu servicio de Cloud Run de ESPv2.

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

  • La etiqueta de imagen debe cambiar de :1 a :2 en 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 gcloud_build_image secuencia de comandos se descarga desde otra ubicación. Usa gcr.io/endpoints-release/endpoints-runtime-serverless:2 como imagen base.

  • Se usa una variable de entorno para especificar las marcas de inicio. El nombre de la variable del ESP es ESP_ARGS. El nombre de ESPv2 es ESPv2_ARGS. Para obtener más información sobre cómo definir ESPv2_ARGS y las marcas de inicio disponibles, consulta Opciones de inicio de Extensible Service Proxy V2.

Cambios en las marcas de inicio entre ESP y ESPv2

Al igual que con Extensible Service Proxy, puedes especificar marcas de configuración al desplegar servicios de ESPv2. Con el cambio del ESP basado en NGINX al ESPv2 basado en Envoy, algunas marcas se han retirado o sustituido, y se han añadido otras nuevas. En esta sección se usan tres tablas para describir los cambios:

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

Banderas sustituidas

Nuevas marcas Marcas sustituidas Descripción
--listener_port --http_port, --http2_port, --ssl_port Un único puerto de escucha de Envoy admite http, http2 y ssl en ESPv2. No es necesario especificar puertos independientes.
--ssl_server_cert_path --ssl_port Cuando se usa --ssl_server_cert_path, ESPv2 usa certificados de server.key y archivos server.crt. Con ESPv2, puede especificar rutas de certificados de servidor distintas de /etc/nginx/ssl. Esta marca sustituye a --ssl_port en ESP, que usa certificados de las rutas de archivo /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, ESPv2 usa certificados de client.key y archivos client.crt. Con ESPv2, puede especificar rutas de certificados de cliente distintas de /etc/nginx/ssl. Esta marca sustituye a --tls_mutual_auth en ESP, que usa certificados de las rutas de archivo /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 back-ends. Esta marca sustituye a --grpc_backend_ssl_root_certs_file en ESP, que solo funciona con back-ends de gRPC.
--ssl_minimum_protocol,--ssl_maximum_protocol --ssl_protocols Cuando uses --ssl_protocols en ESP, debes enumerar todos los protocolos SSL que quieras. En ESPv2, puede 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 la IP del cliente.
--dns_resolver_addresses --dns La marca de sustitución tiene el mismo comportamiento, pero un valor predeterminado diferente. El ESP usa 8.8.8.8 como resolvedor de DNS. ESPv2 usa el resolvedor de DNS configurado en /etc/resolv.conf.
--service_account_key --non_gcp, --service_account_key En ESP, la marca --service_account_key permite de forma implícita el despliegue en plataformas distintas de GCP. Evita que el ESP llame al servidor de metadatos de instancias. En ESPv2, este comportamiento implícito se divide en otro indicador. Es posible que tengas que añadir --non_gcp al migrar. De lo contrario, ESPv2 no se iniciará en plataformas que no sean GCP.

Nuevas marcas

Nuevas marcas Descripción
--http_request_timeout_s Define el tiempo de espera de todas las llamadas remotas http/https, excepto las llamadas de backend y las llamadas de Google Service Control, en segundos.
--service_control_check_timeout_ms Define el tiempo de espera de las llamadas de comprobación de control de servicio de Google, en milisegundos.
--service_control_report_timeout_ms Define el tiempo de espera de las llamadas a Google Service Control Report.
--service_control_quota_timeout_ms Define el tiempo de espera de las llamadas a Google Service Control Quota.
--service_control_check_retries Especifica el número de reintentos de las llamadas a Google Service Control Check.
--service_control_report_retries Especifica el número de reintentos de las llamadas a Google Service Control Report.
--service_control_quota_retries Especifica el número de reintentos de las llamadas a Google Service Control Quota.
--backend_dns_lookup_family Configuración específica de Envoy que se usa para definir la familia de búsqueda de DNS de todos los back-ends.
--disable_tracing Una marca general que se usa para inhabilitar todos los rastreos.
--tracing_project_id Se usa para definir el ID del proyecto propietario de los datos de la traza.
--tracing_incoming_context Se usa para especificar el contexto de rastreo entrante.
--tracing_outgoing_context Se usa para especificar el contexto de rastreo saliente.

Marcas obsoletas

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

Consulta más información sobre las marcas de inicio de ESPv2 en Opciones de inicio de Extensible Service Proxy V2. Puedes consultar más ejemplos genéricos y texto de ayuda para las marcas en el repositorio de GitHub.

Ubicaciones predeterminadas de JWT

De forma predeterminada, se envía un JWT en el encabezado Authorization (con el prefijo "Bearer "), en el encabezado X-Goog-Iap-Jwt-Assertion o en el parámetro de consulta access_token. Estas ubicaciones son compatibles con ESP y ESPv2. También puedes enviar un JWT en el encabezado Authorization (sin prefijo) cuando uses ESP. Sin embargo, esta ubicación no se admite en ESPv2.

Si quieres seguir enviando JWTs mediante el encabezado Authorization (sin prefijo) después de migrar a ESPv2, puedes hacer lo siguiente:

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

Gestionar JWTs en el servicio de backend

Cuando se usan JWTs 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 que uses este encabezado en lugar del encabezado original Authorization, ya que este último puede modificarse en plataformas sin servidor.Authorization

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

En ESPv2, el encabezado X-Endpoint-API-UserInfo contiene la carga útil del JWT original, sin ninguna modificación.

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

# 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 muestran las diferencias. Todas las cadenas se han decodificado 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 Autenticar usuarios mediante un método personalizado y Autenticación entre servicios para obtener más información sobre el uso de JWTs con la autenticación.

Formato del cuerpo de la respuesta JSON de error

Si ESP o ESPv2 rechazan 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 ha cambiado en ESPv2, tal como se muestra en los ejemplos siguientes:

Cuerpo de la respuesta de error de ESP

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

Cuerpo de la respuesta de error de ESPv2

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

Hay dos diferencias principales:

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

Siguientes pasos

Puedes informarte sobre lo siguiente: