Kubernetesはコンテナオーケストレーションを一変させ、Google Kubernetes Engine (GKE)はコンテナアプリのデプロイとスケーリングを支える強力なマネージドプラットフォームを提供しています。GKEはサービスディスカバリやロードバランシングで優れた機能を備える一方、workloadsに到達する前のトラフィックに独自の処理ロジックを適用するには、依然として制約があります。
そこで力を発揮するのが Service Extensions です。GKE Gateway APIと組み合わせてCloud Load Balancingをカスタマイズ・拡張できる、有力な選択肢といえます(注:これはKubernetesの機能であり、Google CloudのAPI Gatewayサービスとは別物です)。
GCPのService Extensionsとは?
Service Extensionsを使うと、データパスに直接カスタムロジックを差し込み、ロードバランサーを通過するトラフィックを高度に加工できます。バックエンドに手を加えることなく、リクエストやレスポンスを操作するコードをパイプラインの各段階に挿入するイメージです。
Service Extensionsには大きく2種類があります。
Plugins: ネットワークデータパス内に独自コードをインラインで挿入できます。WebAssembly (Wasm)とProxy-Wasm ABIをベースに構築され、Googleが管理するサンドボックス基盤上でWasmモジュールとして動作します。低レイテンシを前提に設計されており、データプレーンのすぐそばで実行したい軽量ロジックに最適です。
Callouts: Cloud Load Balancingから外部サービス(Googleが管理するサービス、ユーザーが管理するサービスのいずれも対象。GKE Pod上で動くものも含みます)へgRPC呼び出しを行えるようにします。Calloutsは既存のソフトウェア資産を再利用でき、ランタイムの制約も少ないため柔軟性が高く、外部データや状態を必要とする複雑なロジックに向いています。
GKEチームは先日、Gateway APIでのService Extensionsプレビューサポートを発表しました。これにより、リクエスト/レスポンスのHTTPヘッダーやペイロードの加工はもちろん、トラフィックルーティングの制御まで、既存のバックエンドサービス選定やセキュリティポリシーに影響を与えずに行えるようになります。
GKE Gateway API Service Extensionsの種類
GKE Gatewayコントローラーは現在、Calloutsタイプとして2種類のService Extensionsをサポートしており、それぞれ用途が分かれています。
GCPRoutingExtension:トラフィックルーティングの制御に特化したタイプです。異なるバックエンドサービスへトラフィックを振り分けたり、独自のルーティングロジックを適用したりするケースに最適です。
GCPRoutingExtensionとGatewayの連携イメージ
GCPTrafficExtension:リクエストやレスポンスのヘッダー・ペイロードを書き換えるタイプです。バックエンドサービスの選定やセキュリティポリシーには影響を与えないため、データ変換やエンリッチメントの用途にぴったりです。
GCPTrafficExtensionとGatewayの連携イメージ
GKE Gateway APIでService Extensionsを構成する
GKEのService Extensions機能を試すには、バージョン1.33以降のGKEクラスターと、有効化されたGateway APIが必要です。検証に着手する前に、GKEにおけるGateway Service Extensionsの最新の制限事項にも必ず目を通してください。
Gatewayをデプロイする
Service Extensionを構成するには、まずGatewayリソースをデプロイするか、既存のGatewayリソースがサポート対象のGatewayClassを使っていることを確認します。対応するロードバランサーの詳細は、Google Cloud Service ExtensionとGatewayClassesの互換性を参照してください。
- 以下のマニフェストを適用し、シンプルなリージョナル外部アプリケーションロードバランサーGatewayをデプロイします。
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: gke-l7-regional-external-managed
spec:
gatewayClassName: gke-l7-regional-external-managed
listeners:
- name: http
protocol: HTTP
port: 80
サンプルのstoreバックエンドアプリケーションをデプロイする
- 以下のマニフェストを適用して、サンプルバックエンドアプリケーションとHTTPRouteリソースをデプロイします。HTTPRouteは、GatewayリスナーからバックエンドアプリケーションへHTTPリクエストをどうルーティングするかを定義します。
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: store-v1
spec:
replicas: 1
selector:
matchLabels:
app: store
version: v1
template:
metadata:
labels:
app: store
version: v1
spec:
containers:
- name: whereami
image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
ports:
- containerPort: 8080
env:
- name: METADATA
value: "store-v1"
---
apiVersion: v1
kind: Service
metadata:
name: store-v1
spec:
selector:
app: store
version: v1
ports:
- port: 8080
targetPort: 8080
------
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: store
spec:
parentRefs:
- kind: Gateway
name: gke-l7-regional-external-managed
hostnames:
- "store.example.com"
rules:
- backendRefs:
- name: store-v1
port: 8080
- Gateway APIのIPアドレスにサンプルリクエストを送って、バックエンドのレスポンスを確認します。
curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
出力は次のようになります。
{
"cluster_name": "gateway-api-service-extensio-demo",
"gce_instance_id": "2936941014208025864",
"gce_service_account": "chimbuc-playground.svc.id.goog",
"host_header": "store.example.com",
"metadata": "store-v1",
"pod_name": "store-v1-796c8ff75-mnssb",
"pod_name_emoji": "🧑🏿⚖",
"project_id": "chimbuc-playground",
"timestamp": "2025-07-30T12:21:44",
"zone": "us-central1-a"
}
バックエンドのcalloutサービスをデプロイする
calloutサービスは、GKEのGateway Service Extensionsにおけるカスタムロジックの実装本体です。ロードバランサーはGCPTrafficExtensionまたはGCPRoutingExtensionの設定にもとづいてバックエンドアプリケーションを呼び出し、トラフィックを書き換えたりルーティングしたりします。
GKEクラスター上にcalloutサービスをデプロイする場合は、制限事項に記載された要件をすべて満たす必要があります。
- mkcertなどを使って、calloutサービスのバックエンド用に自己署名証明書を発行します。
appProtocolとしてHTTP2を使う必要があり、エンドツーエンドのTLSが前提となるため、これは欠かせません。
mkcert internal
- 自己署名証明書からK8sのSecretを作成します。
kubectl create secret tls extension-service-app-secret \
--cert=internal.pem \
--key=internal-key.pem
- 以下のマニフェストを適用して、サンプルcalloutアプリケーションをデプロイします。さらに多くのコードサンプルは、service-extensionsのGitHubリポジトリを参照してください。
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: extension-service-app
spec:
selector:
matchLabels:
app: store
replicas: 1
template:
metadata:
labels:
app: store
spec:
containers:
- name: serviceextensions
image: us-docker.pkg.dev/service-extensions-samples/callouts/python-example-basic:main
ports:
- containerPort: 8080
- containerPort: 443
volumeMounts:
- name: certs
mountPath: "/etc/certs/"
readOnly: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: TLS_SERVER_CERT
value: "/etc/certs/tls.crt"
- name: TLS_SERVER_PRIVKEY
value: "/etc/certs/tls.key"
resources:
requests:
cpu: 10m
volumes:
- name: certs
secret:
secretName: "extension-service-app-secret"
optional: false
---
apiVersion: v1
kind: Service
metadata:
name: extension-service
spec:
ports:
- port: 443
targetPort: 443
appProtocol: HTTP2
selector:
app: store
- このサンプルアプリは、リクエストとレスポンスの両方に対して基本的なヘッダー書き換えを行います。詳細はservice_callout_example.pyを参照してください。これをベースに、自社の業務要件に合わせた独自アプリを開発できます。
Service Extensionsを構成する
トラフィックフローのカスタマイズには、GCPRoutingExtensionとGCPTrafficExtensionのいずれかを構成します。
- 以下のマニフェストを適用して
GCPRoutingExtensionリソースを作成します。routeextensionパスへのリクエストに対し、ロードバランサーがextension serviceアプリを呼び出したうえで、バックエンドのstoreアプリへ転送します。
---
kind: GCPRoutingExtension
apiVersion: networking.gke.io/v1
metadata:
name: my-gateway-extension
namespace: default
spec:
targetRefs:
- group: "gateway.networking.k8s.io"
kind: Gateway
name: gke-l7-regional-external-managed
extensionChains:
- name: chain1
matchCondition:
celExpressions:
- celMatcher: request.path.contains("routeextension")
extensions:
- name: routeextension
authority: "store.example.com"
timeout: 1s
backendRef:
group: ""
kind: Service
name: extension-service
port: 443
- calloutサービスはstoreアプリへリクエストを転送する前にホストヘッダーを書き換えるため、
HTTPRouteリソースにservice-extensions.comホストを追加して更新します。
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: store
spec:
parentRefs:
- kind: Gateway
name: gke-l7-regional-external-managed
hostnames:
- "store.example.com"
- "service-extensions.com"
rules:
- backendRefs:
- name: store-v1
port: 8080
- Gateway APIコントローラーが変更を反映するまで数分かかる場合があります。
kubectl describe gateway GATEWAY_NAMEを実行し、GCPRoutingExtensionがGatewayにバインドされていることを確認してください。
Name: gke-l7-regional-external-managed
Namespace: default
Labels: <none>
Annotations: networking.gke.io/addresses:
/projects/269684357132/regions/us-central1/addresses/gkegw1-jorz-default-gke-l7-regional-external-manag-8wyhl317c00c
networking.gke.io/backend-services:
/projects/269684357132/regions/us-central1/backendServices/gkegw1-jorz-default-extension-service-443-e1aovl10z449, /projects/269684357132/...
networking.gke.io/firewalls: /projects/269684357132/global/firewalls/gkegw1-jorz-l7-default-us-central1
networking.gke.io/forwarding-rules:
/projects/269684357132/regions/us-central1/forwardingRules/gkegw1-jorz-default-gke-l7-regional-external-manag-5s86aj5tzcoj
networking.gke.io/health-checks:
/projects/269684357132/regions/us-central1/healthChecks/gkegw1-jorz-default-extension-service-443-e1aovl10z449, /projects/269684357132/reg...
networking.gke.io/last-reconcile-time: 2025-07-30T12:46:15Z
networking.gke.io/lb-route-extensions:
projects/269684357132/locations/us-central1/lbRouteExtensions/gkegw1-jorz-default-gke-l7-regional-external-manag-xivagz6clt0t
networking.gke.io/lb-traffic-extensions:
projects/269684357132/locations/us-central1/lbTrafficExtensions/gkegw1-jorz-default-gke-l7-regional-external-manag-lu8d7n5p4kbs
networking.gke.io/ssl-certificates:
networking.gke.io/target-http-proxies:
/projects/269684357132/regions/us-central1/targetHttpProxies/gkegw1-jorz-default-gke-l7-regional-external-manag-kaecv0bs2nyx
networking.gke.io/target-https-proxies:
networking.gke.io/url-maps:
/projects/269684357132/regions/us-central1/urlMaps/gkegw1-jorz-default-gke-l7-regional-external-manag-kaecv0bs2nyx
API Version: gateway.networking.k8s.io/v1
Kind: Gateway
Metadata:
Creation Timestamp: 2025-07-30T07:45:42Z
Finalizers:
gateway.finalizer.networking.gke.io
Generation: 1
Resource Version: 1753879575407087021
...
- 出力されるアノテーションは、GKEがGatewayと裏側のGoogle Cloudリソースとの紐付けを保持するために使われます。
networking.gke.io/lb-route-extensionsアノテーションが、GatewayとGCPRoutingExtensionのバインドを示しています。 - 続いて、
GATEWAY_IP_ADDRESSを置き換えてrouteextensionパスへのトラフィックを試します。
curl -v http://store.example.com/routeextension --resolve store.example.com:GATEWAY_IP_ADDRESS
- 出力は次のようになり、レスポンス内の
host_headerが書き換わっていることが確認できます。
{
"cluster_name": "gateway-api-service-extensio-demo",
"gce_instance_id": "2936941014208025864",
"gce_service_account": "chimbuc-playground.svc.id.goog",
"host_header": "service-extensions.com",
"metadata": "store-v1",
"pod_name": "store-v1-796c8ff75-mnssb",
"pod_name_emoji": "🧑🏿⚖",
"project_id": "chimbuc-playground",
"timestamp": "2025-07-30T12:51:06",
"zone": "us-central1-a"
}
GCPTrafficExtensionを使えば、リクエスト/レスポンスのカスタムロジック、高度なルーティング、データ変換、セキュリティポリシーなどを実装できます。
- 以下のマニフェストを適用して
GCPTrafficExtensionリソースを作成します。trafficetensionパスへのリクエストに対し、ロードバランサーがextension serviceアプリを呼び出します。supportedEventsを変更すれば、ロードバランサーからcalloutアプリケーションへの呼び出しを細かく制御できます。
---
kind: GCPTrafficExtension
apiVersion: networking.gke.io/v1
metadata:
name: my-traffic-extension
namespace: default
spec:
targetRefs:
- group: "gateway.networking.k8s.io"
kind: Gateway
name: gke-l7-regional-external-managed
extensionChains:
- name: chain1
matchCondition:
celExpressions:
- celMatcher: request.path.contains("trafficeextension")
extensions:
- name: trafficeextension
authority: "store.example.com"
timeout: 1s
supportedEvents: ["RequestHeaders", "RequestBody", "ResponseHeaders", "ResponseBody", "RequestTrailers", "ResponseTrailers"]
backendRef:
group: ""
kind: Service
name: extension-service
port: 443
- 続いて、
GATEWAT_IP_ADDRESSを置き換えてtrafficextensionパスへのトラフィックを試します。
curl -v http://store.example.com/trafficeextension --resolve store.example.com:GATEWAY_IP_ADDRESS
- 出力は次のようになります。
helloというカスタムレスポンスヘッダーが追加され、レスポンスボディが取り除かれていることが確認できます。
* Request completely sent off
< HTTP/1.1 200 OK
< server: Werkzeug/2.3.7 Python/3.11.3
< date: Wed, 30 Jul 2025 12:58:00 GMT
< content-type: application/json
< access-control-allow-origin: *
< hello: service-extensions
< via: 1.1 google
< transfer-encoding: chunked
<
Podログのサンプル:
GKE Gateway API向けのGCP Service Extensionsは、プラットフォームチームがイングレス層でトラフィックを管理・整形・保護する手段を大きく前進させます。カスタム認証の適用、ヘッダーの加工、トラフィックシェーピング、外部システムとの連携など、どのユースケースでも、宣言的かつスケーラブルに実現する手段としてService Extensionsが活躍します。
まだプレビュー段階ではありますが、いまこそService Extensionsを試し、非本番環境で検証しながら、自社プラットフォームに合わせた再利用可能な拡張サービスを開発する好機です。
PoCをお考えなら、ぜひDoiTにお任せください。ビジネス成果を起点とした評価・計画・移行までを一貫してご支援します。カスタムクラウドソリューションの設計を専門とするシニアクラウドエキスパートを100名以上擁するチームが、プロセスをスムーズに進めるとともに、コンプライアンスを担保しつつ、将来の需要にも効率よく応えられるインフラへと最適化します。
戦略的なアドバイスから技術的な深い知見まで、当社の専門家があらゆるフェーズでお客様に伴走します。このポリシー適用フェーズで御社にとって最適な打ち手は何か、ぜひ一度ご相談ください。堅牢でコンプライアンスに準拠し、成果につながるクラウドインフラの実現をお手伝いします。今すぐお問い合わせください。