Extensible Service Proxy V2로 마이그레이션

Extensible Service Proxy V2(ESPv2)는 Cloud Endpoints에 API 관리 기능을 제공하는 Envoy 기반 프록시입니다. ESPv2는 NGINX 기반 Extensible Service Proxy(ESP)를 대체합니다.

이 문서에서는 기존 Endpoints API 배포를 ESP에서 ESPv2로 마이그레이션하는 방법을 설명합니다.

시작하기 전에

마이그레이션을 시작하기 전에 지원되지 않는 사용 사례 및 아래에 설명된 주요 API 변경사항을 고려하세요.

ESPv2가 지원되지 않는 사용 사례

  • App Engine 가변형 환경은 지원되지 않습니다.

    App Engine 가변형 환경에는 Endpoints 지원이 내장되어 있으며 애플리케이션의 app.yaml 파일에 endpoints_api_service를 설정하여 사용 설정합니다. 이 기본 제공 Endpoints 구현은 ESP만 지원하며, ESPv2로 마이그레이션할 수 없습니다.

    App Engine 가변형 환경에 ESPv2를 사용하려면 app.yaml에서 endpoints_api_service를 사용 중지합니다. App Engine 가변형 환경에서 애플리케이션을 관리하기 위해 ESPv2를 별도의 Cloud Run 서비스로 배포할 수 있습니다. 배포는 App Engine 표준 환경 지원을 위해 ESPv2가 사용되는 것과 동일한 방법으로 작동합니다.

  • 커스텀 NGINX 구성은 지원되지 않습니다.

    ESPv2는 Envoy 기반 프록시입니다. 커스텀 NGINX 프록시 구성은 지원할 수 없습니다. ESP 구성에 -n 또는 --nginx_config 플래그가 사용될 경우 ESPv2로 쉽게 마이그레이션할 수 없는 커스텀 NGINX 구성이 구현에 사용될 수 있습니다.

브레이킹 체인지

  • X-Endpoint-API-UserInfo 헤더 데이터 형식이 변경되었습니다. 애플리케이션에서 이 헤더가 사용되는 경우 새 형식을 사용하도록 변경해야 합니다. 자세한 내용은 백엔드 서비스에서 JWT 처리를 참조하세요.
  • API 키가 요청에 필요한 경우 ESP는 소비자 프로젝트 ID가 있는 X-Endpoint-API-Project-ID 헤더를 백엔드 애플리케이션에 보냅니다. ESPv2는 서로 다른 두 헤더 X-Endpoint-API-Consumer-TypeX-Endpoint-API-Consumer-Number를 사용하여 필요한 세부정보를 보냅니다. 이 헤더와 함께 전송된 Consumer-TypeConsumer-Number에 대한 자세한 내용은 서비스 인프라 참조 문서를 참조하세요.

  • HTTP 오류 응답 본문 형식이 변경되었습니다. ESPv2는 HTTP 요청을 거부할 때 새 형식으로 오류 응답을 생성합니다. HTTP 오류 JSON 응답 본문을 처리하기 위해 클라이언트 코드가 구현에 사용될 경우, 클라이언트 코드를 업데이트해야 합니다. 자세한 내용은 HTTP 오류 JSON 응답 본문을 참조하세요.

  • 새 스타트업 플래그를 사용할 수 있으며 일부 ESP 플래그는 ESPv2에서 지원 중단되었거나 대체되었습니다. ESP 및 ESPv2 간의 스타트업 플래그 변경사항을 참조하세요.

ESPv2를 사용하도록 Endpoints API 마이그레이션

서버리스 플랫폼(Cloud Run, Cloud Functions, App Engine)에서 ESPv2를 사용하는 데 필요한 마이그레이션 단계는 비서버리스 플랫폼(Google Kubernetes Engine, Compute Engine, Kubernetes)에 필요한 단계와 다릅니다.

각 플랫폼 유형에 필요한 마이그레이션 단계는 다음과 같습니다.

비서버리스 플랫폼: GKE, Compute Engine, Kubternetes

ESPv2는 ESP에 대한 삽입형 대체 기능입니다. 대부분의 구성에서는 docker 이미지 태그만 업데이트하면 됩니다.

그러나 다음과 같이 ESP를 구성한 경우에는 시작 플래그를 조정해야 할 수 있습니다.

  • --http_port, http2_port 또는 --ssl_port 플래그를 통한 두 개 이상의 포트
  • SSL, DNS, Client IP 또는 거의 사용되지 않는 다른 플래그

새 시작 플래그는 ESPv2에서 사용할 수 있으며 일부 ESP 플래그는 지원 중단되었거나 대체되었습니다. 자세한 내용은 ESP 및 ESPv2 간의 시작 플래그 변경사항을 참조하세요.

GKE 및 Kubernetes

GKE 및 Kubernetes용 엔드포인트 구성을 마이그레이션하려면 yaml 배포 파일에서 ESP 이미지 태그를 :1에서 :2로 변경합니다. 예를 들면 다음과 같습니다.

- 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

ESP 및 ESPv2는 docker run 명령어를 사용하여 Docker 컨테이너에 배포됩니다. Compute Engine용 Endpoints를 ESPv2로 마이그레이션하려면 명령어의 Docker 이미지 태그를 :1에서 :2로 업데이트합니다. 예를 들면 다음과 같습니다.

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

서버리스 플랫폼(Cloud Run, Cloud Functions, App Engine)

서버리스 플랫폼에서 ESPv2는 Cloud Run 서비스로 배포되어 Cloud Run, Cloud Function, App Engine에서 실행되는 애플리케이션을 관리합니다. Endpoints를 ESPv2로 마이그레이션하려면 새 ESPv2 Docker 이미지에 기존 Endpoints 서비스 구성을 빌드한 다음 ESPv2 Cloud Run 서비스에 이미지를 배포해야 합니다.

ESP 및 ESPv2의 배포 단계는 동일하지만 아래의 세부정보는 제외됩니다.

  • ESPv2를 Cloud Run에 배포할 때 이미지 태그를 ESPv2의 :1에서 :2로 변경해야 합니다. 예를 들면 다음과 같습니다.

    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
    --image="gcr.io/endpoints-release/endpoints-runtime-serverless:2" \
    --allow-unauthenticated \
    --platform managed \
    --project=ESP_PROJECT_ID
  • gcloud_build_image 스크립트는 다른 위치에서 다운로드됩니다. 여기에는 gcr.io/endpoints-release/endpoints-runtime-serverless:2가 기본 이미지로 사용됩니다.

  • 시작 플래그를 지정하기 위해 환경 변수가 사용됩니다. ESP의 변수 이름은 ESP_ARGS입니다. ESPv2의 이름은 ESPv2_ARGS입니다. ESPv2_ARGS 설정 및 사용 가능한 시작 플래그에 대한 자세한 내용은 Extensible Service Proxy V2 시작 옵션을 참조하세요.

ESP 및 ESPv2 간의 스타트업 플래그 변경사항

Extensible Service Proxy에서와 같이 ESPv2 서비스를 배포할 때 구성 플래그를 지정할 수 있습니다. NGINX 기반 ESP에서 Envoy 기반 ESPv2로의 변경에 따라 일부 플래그가 지원 중단되었거나 대체되었고, 새 플래그가 추가되었습니다. 이 섹션에서는 3개의 표를 통해 이러한 변경사항을 설명합니다.

  • 표 1은 지원이 중단된 플래그를 대체하는 새로운 플래그를 설명합니다.
  • 표 2는 새로운 플래그를 설명합니다.
  • 표 3은 지원이 중단된 플래그를 설명합니다.

대체된 플래그

새로운 플래그 대체된 플래그 설명
--listener_port --http_port, --http2_port, --ssl_port 단일 Envoy 리스너 포트는 ESPv2에서 http, http2, ssl을 지원합니다. 포트를 별도로 지정할 필요가 없습니다.
--ssl_server_cert_path --ssl_port --ssl_server_cert_path를 사용하면 ESPv2가 server.keyserver.crt 파일의 인증서를 사용합니다. ESPv2를 사용하면 /etc/nginx/ssl 이외의 서버 인증서 경로를 지정할 수 있습니다. 이 플래그는 ESP에서 --ssl_port를 대체하며 /etc/nginx/ssl/nginx.key/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 --ssl_backend_client_cert_path를 사용하면 ESPv2가 client.keyclient.crt 파일의 인증서를 사용합니다. ESPv2를 사용하면 /etc/nginx/ssl 이외의 클라이언트 인증서 경로를 지정할 수 있습니다. 이 플래그는 ESP에서 --tls_mutual_auth를 대체하며 /etc/nginx/ssl/backend.key/etc/nginx/ssl/backend.crt 파일 경로의 인증서를 사용합니다.
--ssl_backend_client_root_certs_file --grpc_backend_ssl_root_certs_file ESPv2를 사용하면 --ssl_backend_client_root_certs_file이 모든 백엔드에 작동합니다. 이 플래그는 ESP의 --grpc_backend_ssl_root_certs_file을 대체하며 gRPC 백엔드에만 작동합니다.
--ssl_minimum_protocol,--ssl_maximum_protocol --ssl_protocols ESP의 --ssl_protocols를 사용할 때는 원하는 모든 ssl 프로토콜을 나열해야 합니다. ESPv2에서는 최소 및 최대 프로토콜을 지정할 수 있습니다.
--envoy_use_remote_address,--envoy_xff_num_trusted_hops --xff_trusted_proxy_list,--client_ip_header,--client_ip_position 클라이언트 IP 추출을 구성하려면 Envoy에 use_remote_addressxff_num_trusted_hops가 필요합니다.
--dns_resolver_addresses --dns 대체 플래그는 동작이 동일하지만 기본값이 다릅니다. ESP는 DNS 리졸버로 8.8.8.8을 사용합니다. ESPv2는 /etc/resolv.conf에 구성된 DNS 리졸버를 사용합니다.
--service_account_key --non_gcp, --service_account_key ESP에서 --service_account_key 플래그를 사용하면 GCP 이외의 플랫폼에 암시적으로 배포할 수 있습니다. ESP가 인스턴스 메타데이터 서버를 호출하지 못하도록 합니다. ESPv2에서 이 암시적 동작은 다른 플래그로 분할됩니다. 마이그레이션 시 --non_gcp를 추가해야 할 수 있습니다. 그러지 않으면 ESPv2가 GCP 이외의 플랫폼에서 시작되지 않습니다.

새로운 플래그

새로운 플래그 설명
--http_request_timeout_s 백엔드 호출 및 Google Service Control 호출을 제외한 모든 http/https 원격 호출의 시간 제한을 초 단위로 설정합니다.
--service_control_check_timeout_ms Google Service Control Check 호출의 시간 제한을 밀리초 단위로 설정합니다.
--service_control_report_timeout_ms Google Service Control Quota 호출의 시간 제한을 설정합니다.
--service_control_quota_timeout_ms Google Service Control Quota 호출의 시간 제한을 설정합니다.
--service_control_check_retries Google Service Control Check 호출의 재시도 횟수를 지정합니다.
--service_control_report_retries Google Service Control Report 호출의 재시도 횟수를 지정합니다.
--service_control_quota_retries Google Service Control Quota 호출의 재시도 횟수를 지정합니다.
--backend_dns_lookup_family 모든 백엔드의 DNS 조회 모음을 정의하는 데 사용되는 Envoy 관련 구성입니다.
--disable_tracing 모든 trace를 사용 중지하기 위해 사용되는 전체 플래그입니다.
--tracing_project_id trace 데이터를 소유한 프로젝트의 ID를 설정하는 데 사용됩니다.
--tracing_incoming_context 수신 trace 컨텍스트를 지정하는 데 사용됩니다.
--tracing_outgoing_context 발신 trace 컨텍스트를 지정하는 데 사용됩니다.

지원 중단된 플래그

지원 중단된 플래그 설명
--enable_websocket 웹소켓은 Envoy에서 기본적으로 사용 설정됩니다.
--experimental_proxy_backend_host_header 지원되지 않음
--allow_invalid_headers 지원되지 않음 NGINX 구성 ignore_invalid_headers입니다. HTTP 요청에 잘못된 헤더 이름이 있으면 ESPv2에서 거부됩니다. 올바른 헤더 이름은 영문자, 숫자, 하이픈, 밑줄로 구성됩니다. ESPv2에서 --underscores_in_headers 플래그는 헤더에 밑줄이 허용되는지 여부를 결정합니다.
--client_max_body_size NGINX 구성, 지원되지 않음
--client_body_buffer_size NGINX 구성, 지원되지 않음
--large_client_header_buffers NGINX 구성, 지원되지 않음
--keepalive_timeout NGINX 구성, 지원되지 않음
--client_body_timeout NGINX 구성, 지원되지 않음
--rewrite 지원되지 않음
--experimental_enable_multiple_api_configs 지원되지 않음
--enable_backend_routing 필요하지 않음. 백엔드 라우팅은 서버리스 플랫폼에서 자동으로 사용 설정됩니다.
--rollout_fetch_throttle_window_in_s 필요하지 않음.
--nginx_config 지원되지 않음

ESPv2 시작 플래그에 대한 자세한 내용은 Extensible Service Proxy V2 시작 옵션을 참조하세요. 플래그에 대한 추가적인 일반 예시 및 도움말 텍스트는 GitHub 저장소에서 찾을 수 있습니다.

기본 JWT 위치

기본적으로 JWT는 Authorization 헤더('Bearer' 프리픽스 포함), X-Goog-Iap-Jwt-Assertion 헤더 또는 access_token 쿼리 매개변수로 전달됩니다. 이 위치는 ESP 및 ESPv2에서 지원됩니다. ESP를 사용할 때 Authorization 헤더(프리픽스 없음)에 JWT를 전달할 수도 있습니다. 그러나 이 위치는 ESPv2에서 지원되지 않습니다.

ESPv2로 마이그레이션한 후 Authorization 헤더(프리픽스 없음)를 사용하여 JWT를 계속 전달하려면 다음을 수행할 수 있습니다.

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

백엔드 서비스에서 JWT 처리

JWT를 사용하여 인증을 수행할 때 ESPv2 및 ESP는 X-Endpoint-API-UserInfo 헤더의 인증 결과를 백엔드 API에 전송합니다. 원본 Authorization 헤더가 서버리스 플랫폼에서 수정될 수 있으므로 원본 Authorization 헤더 대신 이 헤더를 사용하는 것이 좋습니다.

X-Endpoint-API-UserInfo 헤더에는 Base64Url로 인코딩된 JSON 객체가 포함됩니다. 하지만 형식이 ESP에서 ESPv2로 변경되었습니다.

ESPv2의 경우 X-Endpoint-API-UserInfo 헤더에는 수정 없이 원본 JWT 페이로드가 포함됩니다.

ESP에서 X-Endpoint-API-UserInfo 헤더는 JWT 페이로드와 ESP에서 추가한 일부 특정 필드를 포함합니다. ESP는 id, issuer, email, audiences 필드를 JSON 객체에 추가합니다. 또한 원본 JWT 페이로드를 포함하도록 claims 필드를 추가합니다.

# 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
   }
}

다음 예시는 모두 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
  }
}

인증과 함께 JWT 사용에 대한 자세한 내용은 커스텀 메서드를 사용하여 사용자 인증서비스 간 인증을 참조하세요.

오류 JSON 응답 본문 형식

ESP 또는 ESPv2에서 HTTP 요청을 거부하면 응답 본문에 상태 코드와 JSON 형식의 오류 메시지가 포함됩니다. 응답 본문 형식은 아래 예시와 같이 ESPv2에서 변경되었습니다.

ESP의 오류 응답 본문

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

ESPv2의 오류 응답 본문

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

여기에는 두 가지 주요 차이점이 있습니다.

  • ESPv2에서는 ESP에 있는 RPC 상태 코드가 아닌 http 상태 코드가 code 필드에 포함됩니다.
  • ESPv2의 오류 응답 본문에는 details 필드가 포함되지 않습니다.

다음 단계

다음 사항에 대해 알아보세요.