【GKE再入門】GKE Autopilotクラスタ上にNginxをデプロイしてGlobal external Application Load Balancer経由で外部からアクセスしてみた

【GKE再入門】GKE Autopilotクラスタ上にNginxをデプロイしてGlobal external Application Load Balancer経由で外部からアクセスしてみた

GKE Autopilotクラスタ上にNginxをデプロイし、Gateway APIとGlobal ALBで外部公開してGKEへ再入門してみました。
2026.08.17

はじめに

こんにちは。
コンサルティング部の渡邉です。

Google Kubernetes Engine (GKE) を久しぶりに触る機会があるため、GKE Autopilotクラスタ上にNginxをデプロイし、Global external Application Load Balancer経由で外部からアクセスできる環境を構築して再入門しようと思います。

GKEでWebアプリケーションを外部に公開する際、KubernetesのGateway API(Gateway + HTTPRoute)リソースを作成すると、GKE Gatewayコントローラーが自動的にGoogle CloudのApplication Load Balancerを構成してくれます。私がGKEの運用をしていたときはIngressが標準でしたが、Gateway APIは従来のIngressの後継としてKubernetesコミュニティが策定した次世代の標準であり、GKEでも新規構築では Gateway APIの使用が推奨されています。特にAutopilotクラスタでは Container-native load balancing(NEG ベース) がデフォルトで有効になっており、ロードバランサーからPodに直接トラフィックを送信する効率的な構成が手軽に実現できます。

本記事では、構築の過程で登場するGKEやKubernetesの各種コンポーネントについても解説しています。

全体アーキテクチャ

今回構築する構成の全体像は以下の通りです。

上の図では、左側がクライアントからロードバランサーへのアクセスの流れ、右側がGKE Autopilotクラスタ内のKubernetesリソースとPodの関係を表しています。
Kubernetesリソースの一部は、GKE Autopilot上に作成すると、対応するGoogle Cloudのリソースも同時に作成されます。

  • Gatewaynginx-gateway)を作成すると、GKE GatewayコントローラーがGoogle Cloud上のLoad BalancerリソースであるForwarding Rule・Target HTTP Proxy・URL Map・Backend Service・Health Checkを自動的に作成・構成します。
  • HTTPRoutenginx-httproute)が Gatewayにアタッチされ、トラフィックのルーティング先(Service)を定義します。
  • Servicenginx-service)をバックエンドとして、対応する NEG が自動作成されます。
  • Deploymentnginx-deployment)がNginx Podのレプリカを管理し、NEGが各 Podのエンドポイント(IP:port)を追跡します。
  • クライアントからのトラフィックはForwarding Rule → Target HTTP Proxy → URL Map → Backend Service → NEG → Podという経路で流れます。

GKE Autopilot とは

GKE Autopilotとは、Googleが推奨するGKEの運用モードです。ノードの管理をGoogleに任せることで、ユーザーはアプリケーションのデプロイに集中できます。

GKEにはAutopilotStandardの2つの運用モードがあります。

項目 Autopilot Standard
ノード管理 Google が自動管理(プロビジョニング・スケーリング・アップグレード・修復) ユーザーが管理(ノードプールの作成・サイズ変更・アップグレードなど)
スケーリング Pod 数に応じてノードが自動スケール(ワークロードがない場合はゼロノードまでスケールダウン) Cluster Autoscaler を有効化すればノード自動スケール可能。ただしノードプールの設定はユーザーが管理
セキュリティ デフォルトで強化されたセキュリティ設定が適用(特権コンテナの制限、ホストネットワーク使用不可など) ユーザーが個別に設定。特権コンテナやホストネットワークも利用可能
ネットワーク VPC ネイティブクラスタのみ。Container-native load balancing がデフォルトで有効 VPC ネイティブ / ルートベースを選択可能
料金 Pod が要求したリソース(CPU・メモリ)に基づく課金 ノード(VM)のリソースに対して課金。Pod の有無に関わらずノードが起動していれば課金
カスタマイズ性 制限あり(マシンタイプの直接指定不可、DaemonSet に制約ありなど) ノードプール単位でマシンタイプ・GPU・ローカル SSD 等を自由に選択可能
SLA コントロールプレーンと Pod の計算容量の両方をカバーする SLA コントロールプレーンのみ SLA 対象(Pod の可用性はユーザーの設計に依存)
適したケース 運用負荷を最小化したい場合、標準的なワークロード ノードレベルの細かい制御が必要な場合、GPU / TPU ワークロード、特殊な要件がある場合

GoogleはAutopilotを推奨運用モードとしています。特にノード管理の運用負荷を減らしたい場合や、標準的なWebアプリケーションのデプロイではAutopilotが適しています。
一方で、GPU を使用した機械学習ワークロードやノードの細かいチューニングが必要な場合はStandardが適しています。

Global external Application Load Balancer とは

Global external Application Load Balancer は、Google Cloudが提供する HTTP(S) ロードバランサーの一種です。GFE(Google Front End)上に実装されたグローバルなマネージドサービスであり、世界中に分散配置されたエッジロケーションでトラフィックを終端します。

項目 内容
動作モード グローバル(Premium Tier)
実装 Google Front End(GFE) + Envoy プロキシ
対応プロトコル HTTP/1.1、HTTP/2、WebSocket
主な機能 Cloud CDN 統合、Cloud Armor 統合、トラフィック管理(ミラーリング・重み付け分割)
GKE 連携 Gateway API(推奨)、Ingress、または Standalone NEG(手動オーケストレーション)

GKEではGatewayリソースを作成すると、GKE Gatewayコントローラーが自動的にGlobal ALBを構成してくれるため、ユーザーが個々のロードバランサーコンポーネントを手動で作成する必要はありません。

Container-native load balancing(NEG)

GKE Autopilotクラスタでは、Gateway APIやIngress経由でサービスを公開する際にContainer-native load balancingがデフォルトで有効になります。これは Network Endpoint Group(NEG) を使用して、ロードバランサーからPodのIPアドレスに直接トラフィックを送信する仕組みです。

NEG を使用することで以下のメリットがあります。

  • パフォーマンス向上: kube-proxy のネットワーキングをバイパスし、Podに直接トラフィックを送信するため、レイテンシとスループットが改善。
  • ヘルスチェックの強化: Pod readiness gateにより、ロードバランサーの観点からPodの正常性を判断。
  • 可視性の向上: ロードバランサーから各Podへのレイテンシが個別に確認可能

Autopilot クラスタでは、Gateway APIを使用する場合、GKE Gatewayコントローラーが HTTPRouteのbackendRefsで参照されたServiceに対して自動的にNEGを作成・管理します。

Kubernetes リソースの基本

本記事で使用する主要なKubernetesリソース(Pod・Deployment・Service・Gateway・HTTPRoute)について解説します。

Pod

Pod は、Kubernetesにおけるデプロイの最小単位です。1つ以上のコンテナをまとめたグループであり、同じPod内のコンテナはネットワーク名前空間とストレージボリュームを共有します。

Podは障害やスケーリングによって削除・再作成されるリソースであるため、Podを直接作成するのではなく、次に説明するDeploymentなどの上位リソースを通じて管理するのが一般的です。

Deployment

Deploymentは、Podのレプリカ数などを宣言的に管理するリソースです。「この Pod を何個維持するか」を定義すると、Kubernetesが常にその状態を維持するように動作します。

Deploymentの主な機能は以下のとおりです。

機能 説明
レプリカ管理 replicas フィールドで指定した数の Pod を常に維持。Pod が異常終了した場合は自動的に新しい Pod を起動
ローリングアップデート コンテナイメージの変更時に、Pod を段階的に新バージョンへ入れ替え。maxSurge(超過可能な Pod 数)と maxUnavailable(停止可能な Pod 数)で更新速度を制御
ロールバック 更新に問題があった場合、kubectl rollout undo で以前の ReplicaSet へ即座に戻せる
スケーリング kubectl scale コマンドや HPA(Horizontal Pod Autoscaler)と連携して、レプリカ数を動的に変更可能

Deploymentは内部でReplicaSetを自動作成し、ReplicaSetが実際のPodを管理します。更新が発生すると新しいReplicaSetが作成され、古いReplicaSetのPodを段階的に縮小しながら新しいReplicaSet のPodを拡大することで、ダウンタイムのない更新を実現します。

本記事では以下のように Deployment を定義しています。

Deploymentのサンプルマニフェストファイル
spec:
  replicas: 2            # Pod を 2 つ維持
  selector:
    matchLabels:
      app: nginx          # このラベルを持つ Pod を管理対象とする
  template:
    metadata:
      labels:
        app: nginx        # Pod に付与するラベル(selector と一致させる)
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

selector.matchLabelstemplate.metadata.labels は一致させる必要があります。Deployment はこのラベルを使って管理すべきPodを識別します。

Service

Service は、動的に変化するPodのセットに対して安定したネットワークエンドポイントを提供するリソースです。

PodはスケーリングやアップデートのたびにIPアドレスが変わるため、他のサービスやロードバランサーがPodに直接アクセスするのは困難です。Serviceはラベルセレクターで対象のPodを動的に追跡し、一つの安定した仮想IP(ClusterIP)とDNS 名でアクセスできるようにします。

Service には複数のタイプがあり、用途に応じて使い分けます。

タイプ 説明 用途
ClusterIP クラスタ内部のみからアクセス可能な仮想 IP を割り当て。デフォルトのタイプ クラスタ内のサービス間通信、Gateway API + NEG 構成
NodePort 各ノードの指定ポートで外部からアクセス可能にする。ClusterIP も自動作成される 開発・テスト環境での簡易的な外部公開
LoadBalancer クラウドプロバイダーのロードバランサー(L4)を自動作成。NodePort と ClusterIP も自動作成される L4 ロードバランサーによる外部公開

本記事では ClusterIP を使用しています。従来のロードバランシングではNodePortが必要でしたが、Autopilotクラスタでは Container-native load balancing(NEG)がデフォルトで有効なため、ロードバランサーがPod IPに直接トラフィックを送信します。そのためNodePortを経由する必要がなく、ClusterIPで十分です。

本記事の Service 定義のポイントは以下の通りです。

spec:
  type: ClusterIP
  selector:
    app: nginx        # app=nginx ラベルを持つ Pod にトラフィックを転送
  ports:
  - port: 80          # Service が受け付けるポート
    targetPort: 80    # Pod 内コンテナのポートへ転送

selector.app: nginx は、Deploymentの template.metadata.labels で定義した app: nginx と一致します。これにより、ServiceはDeploymentが管理するPodを自動的にバックエンドとして認識します。

Gateway API(Gateway + HTTPRoute)

Gateway APIは、クラスタ外部からのHTTP(S)トラフィックをクラスタ内のServiceにルーティングするためのKubernetes標準APIです。従来のIngressの後継として登場しました。LoadBalancerタイプのServiceがTCP/UDPレベルのL4ロードバランシングを提供するのに対し、Gateway APIはアプリケーション層のL7で動作し、URLパスやホスト名に基づいたルーティングが可能です。

Gateway APIでは、従来Ingressが1つのリソースで担っていた役割を GatewayHTTPRoute の2つのリソースに分離しています。

リソース 役割
Gateway ロードバランサーのポート・プロトコル・リスナーなどのフロントエンド定義。GatewayClass を指定することでロードバランサーの種類を決定
HTTPRoute トラフィックのパス・ホスト名に基づく振り分けなどのルーティングルールを定義。Gateway にアタッチして使用

GKE ではGKE Gateway コントローラーがデフォルトで有効になっており、Gatewayリソースを作成すると自動的に Google CloudのApplication Load Balancerを構成します。使用する GatewayClass によって作成されるロードバランサーの種類が決まります。

GatewayClass ロードバランサー
gke-l7-global-external-managed Global external Application Load Balancer(推奨)
gke-l7-regional-external-managed Regional external Application Load Balancer
gke-l7-rilb Internal Application Load Balancer
gke-l7-gxlb Classic Application Load Balancer

Ingress との比較

Gateway API はIngressの上位互換であり、GKEでは新規構築にGateway APIの使用が推奨されています。

観点 Ingress Gateway API
リソース構造 1 つのリソースにフロントエンドとルーティングが混在 Gateway(フロントエンド)と HTTPRoute(ルーティング)に分離
マルチテナンシー 制限的 Gateway と Route を異なるチーム・Namespace で管理可能
ルーティング機能 パス・ホストベース パス・ホストベースに加えて、トラフィック分割(重み付け)、ヘッダーマッチ、リダイレクトなど
拡張性 アノテーション依存(実装ごとに異なる) Policy リソースによる標準化された拡張
Kubernetes 標準 レガシー標準 SIG-Network が策定した次世代標準

本記事では以下のようにシンプルな構成で Gateway APIを使用しています。

# Gateway: ロードバランサーのフロントエンド定義
spec:
  gatewayClassName: gke-l7-global-external-managed  # Global ALB を使用
  listeners:
  - name: http
    protocol: HTTP
    port: 80
---
# HTTPRoute: ルーティングルール
spec:
  parentRefs:
  - name: nginx-gateway       # この Gateway にアタッチ
  rules:
  - backendRefs:
    - name: nginx-service      # すべてのリクエストをこの Service に転送
      port: 80

GKE Gatewayコントローラーは、この定義をもとにForwarding Rule・Target HTTP Proxy・URL Map・Backend Service・Health Checkを自動作成し、Global ALBを構成します。

実際に試してみる

前提条件

  • Google Cloud プロジェクトが作成済みであること
  • gcloud CLI がインストール・認証済みであること
  • kubectl がインストール済みであること
  • 課金が有効なプロジェクトであること

手順の流れ

1. 環境変数の設定

まず、作業で使用する環境変数を設定します。
プロジェクトIDに関しては、自身の検証するプロジェクトIDに修正してください。

# プロジェクトIDとリージョンを設定
export PROJECT_ID=YOUR_PROJECT_ID
export REGION=asia-northeast1
export CLUSTER_NAME=nginx-autopilot-cluster
export NETWORK_NAME=nginx-demo-network
export SUBNET_NAME=nginx-demo-subnet
export ROUTER_NAME=nginx-demo-router
export NAT_NAME=nginx-demo-nat

2. API の有効化

VPC やサブネットの作成に Compute Engine API、GKE クラスタの作成に Kubernetes Engine API が必要なので、先に有効化しておきます。

# 必要な API を有効化
gcloud services enable compute.googleapis.com \
  container.googleapis.com \
  --project=$PROJECT_ID

Operation "operations/acf.p2-xxxxxxxxxxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" finished successfully.

3. VPC ネットワークとサブネットの作成

GKE クラスタを作成するには、VPC ネットワークとサブネットが必要です。
GKEではノードへのIPアドレスはプライマリIP範囲から、Podやサービスに対するIPアドレスはセカンダリIP範囲から割り当てるため、合わせて作成します。

# VPC ネットワークを作成
gcloud compute networks create $NETWORK_NAME \
    --subnet-mode=custom \
    --project=$PROJECT_ID

Created [https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/global/networks/nginx-demo-network].
NAME: nginx-demo-network
SUBNET_MODE: CUSTOM
BGP_ROUTING_MODE: REGIONAL
IPV4_RANGE: 
GATEWAY_IPV4: 
INTERNAL_IPV6_RANGE: 

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network nginx-demo-network --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network nginx-demo-network --allow tcp:22,tcp:3389,icmp

# サブネットを作成(Pod・サービス用のセカンダリ範囲を含む)
gcloud compute networks subnets create $SUBNET_NAME \
    --network=$NETWORK_NAME \
    --region=$REGION \
    --range=10.0.0.0/20 \
    --secondary-range=pods=10.4.0.0/14,services=10.8.0.0/20 \
    --project=$PROJECT_ID

Created [https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/regions/asia-northeast1/subnetworks/nginx-demo-subnet].
NAME: nginx-demo-subnet
REGION: asia-northeast1
NETWORK: nginx-demo-network
RANGE: 10.0.0.0/20
STACK_TYPE: IPV4_ONLY
IPV6_ACCESS_TYPE: 
INTERNAL_IPV6_PREFIX: 
EXTERNAL_IPV6_PREFIX: 

各 IP 範囲の用途は以下のとおりです。

IP 範囲 CIDR 用途
プライマリ範囲 10.0.0.0/20 ノードの IP アドレス
セカンダリ範囲 pods 10.4.0.0/14 Pod の IP アドレス
セカンダリ範囲 services 10.8.0.0/20 Service の ClusterIP

4. Cloud Router と Cloud NAT の作成

本記事ではノードに外部IPを付与しないプライベートクラスタを構成します。プライベートノードからインターネットへ通信するために、Cloud Router と Cloud NATを作成します。
Cloud NAT は、外部 IP を持たないノードがコンテナイメージの取得などインターネットへの通信を行うために必要です。--nat-all-subnet-ip-ranges を指定することで、VPC内のすべてのサブネットのプライマリ・セカンダリIP 範囲がNATの対象になります。

# Cloud Router を作成
gcloud compute routers create $ROUTER_NAME \
    --network=$NETWORK_NAME \
    --region=$REGION \
    --project=$PROJECT_ID

Creating router [nginx-demo-router]...done.                                                                                                                                                   
NAME: nginx-demo-router
REGION: asia-northeast1
NETWORK: nginx-demo-network

# Cloud NAT を作成
gcloud compute routers nats create $NAT_NAME \
    --router=$ROUTER_NAME \
    --region=$REGION \
    --auto-allocate-nat-external-ips \
    --nat-all-subnet-ip-ranges \
    --project=$PROJECT_ID

Creating NAT [nginx-demo-nat] in router [nginx-demo-router]...done. 

5. GKE Autopilot クラスタの作成

GKE Autopilotクラスタを作成します。先ほど作成したVPCネットワークとサブネットを指定し、--enable-private-nodes でノードに外部IPを付与しない構成にします。

# GKE Autopilot クラスタの作成
gcloud container clusters create-auto $CLUSTER_NAME \
    --location=$REGION \
    --network=$NETWORK_NAME \
    --subnetwork=$SUBNET_NAME \
    --cluster-secondary-range-name=pods \
    --services-secondary-range-name=services \
    --enable-private-nodes \
    --project=$PROJECT_ID

Note: This cluster has private nodes. If you need connectivity to the public internet, for example to pull public containers, you must configure Cloud NAT. To enable NAT for the network of this cluster, run the following commands: 
gcloud compute routers create my-router --region asia-northeast1 --network default --project=YOUR_PROJECT_ID 
gcloud beta compute routers nats create nat --router=my-router --region=asia-northeast1 --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --project=YOUR_PROJECT_ID
Creating cluster nginx-autopilot-cluster in asia-northeast1... Cluster is being health-checked (Kubernetes Control Plane is healthy)...done.                                                  
Created [https://container.googleapis.com/v1/projects/YOUR_PROJECT_ID/zones/asia-northeast1/clusters/nginx-autopilot-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/asia-northeast1/nginx-autopilot-cluster?project=YOUR_PROJECT_ID
kubeconfig entry generated for nginx-autopilot-cluster.
NAME: nginx-autopilot-cluster
LOCATION: asia-northeast1
MASTER_VERSION: 1.35.6-gke.1641000
MASTER_IP: xx.xxx.xx.xxx
MACHINE_TYPE: ek-standard-8
NODE_VERSION: 1.35.6-gke.1641000
NUM_NODES: 3
STATUS: RUNNING
STACK_TYPE: IPV4

Autopilot クラスタの作成には10分~20分くらいかかります。--enable-private-nodes を指定すると、ノードにはプライベートIPのみが割り当てられ、外部IPは付与されません。作成完了後、新しいクラスタではワークロードをデプロイするまでノードが0の状態となる場合があります。最初のワークロードデプロイ時にノードがプロビジョニングされるため、スケジューリングに通常より時間がかかることがあります。

クラスタが作成されたら、kubectl でクラスタを操作するための認証情報を取得します。

# kubectl の認証情報を取得
gcloud container clusters get-credentials $CLUSTER_NAME \
    --location=$REGION \
    --project=$PROJECT_ID

Fetching cluster endpoint and auth data.
kubeconfig entry generated for nginx-autopilot-cluster.

このコマンドは、kubectl がクラスタと通信するために必要な情報を kubeconfig ファイル(デフォルトでは ~/.kube/config)に書き込みます。具体的には以下の情報が設定されます。

設定項目 内容
cluster GKE クラスタの API サーバーのエンドポイント(IP アドレス)と CA 証明書
user 認証情報(GKE では gke-gcloud-auth-plugin を使用した OAuth トークンベースの認証)
context cluster と user の組み合わせに名前を付けたもの。kubectl が「どのクラスタに」「どのユーザーとして」接続するかを定義

get-credentials を実行すると、対象クラスタの context が自動的に current-context として設定されるため、以降の kubectl コマンドはこのクラスタに対して実行されます。

# 現在の context を確認
kubectl config current-context

gke_YOUR_PROJECT_ID_asia-northeast1_nginx-autopilot-cluster

複数のクラスタを扱う場合は kubectl config get-contexts で一覧を確認し、kubectl config use-context <context名> で切り替えることができます。

最後に、クラスタがAutopilotモードで作成されていることを確認します。

# Autopilot モードの確認
gcloud container clusters describe $CLUSTER_NAME \
    --location=$REGION \
    --project=$PROJECT_ID \
    --format="value(autopilot.enabled)"

True

6. Nginx Deployment の作成

Nginx をデプロイする Deploymentマニフェストを作成・適用します。

cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
EOF

Warning: autopilot-default-resources-mutator:Autopilot updated Deployment default/nginx-deployment: defaulted unspecified 'cpu' resource for containers [nginx] (see http://g.co/gke/autopilot-defaults).
deployment.apps/nginx-deployment created

readinessProbeを設定しておくと、GKE Gateway コントローラーがその設定をもとにGoogle Cloudのヘルスチェックを自動構成します。ヘルスチェックのパス(/)やポート(80)が readinessProbeから推論されるため、Nginxの場合は特別なHealthCheckPolicyの設定なしでヘルスチェックが正常に動作します。

なお、KubernetesにはreadinessProbelivenessProbeの2種類の主要なヘルスチェックがあります。

Probe 役割 失敗時の動作
readinessProbe Pod がトラフィックを受け入れる準備ができているかを確認 Service のエンドポイントから除外(トラフィックが送られなくなる)
livenessProbe Pod 内のプロセスが正常に動作しているかを確認 Pod を再起動(コンテナを kill して再作成)

本記事では readinessProbeのみ設定しています。本番環境では、アプリケーションの特性に応じてlivenessProbeの追加も検討してください。

Pod がRunningになっていることを確認します。

kubectl get pods -l app=nginx

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6fddd4d468-2cqwx   1/1     Running   0          70s
nginx-deployment-6fddd4d468-85m9l   1/1     Running   0          70s

7. Service の作成

Nginx Podを公開するServiceを作成します。

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
EOF

service/nginx-service created

前述のとおり、Autopilot クラスタでは Container-native load balancing(NEG)がデフォルトで有効なため、Serviceタイプは ClusterIP で十分です。

Gateway API を使用する場合、GKE GatewayコントローラーがHTTPRouteのbackendRefsで参照されたServiceに対して自動的にNEG を作成・管理します。

8. Gateway と HTTPRoute の作成

Gateway APIリソースを作成して、Global ALBを構成します。まずGatewayを作成し、次にHTTPRouteを作成します。

cat <<'EOF' | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: nginx-gateway
  namespace: default
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
EOF

gateway.gateway.networking.k8s.io/nginx-gateway created

gatewayClassName: gke-l7-global-external-managed を指定することで、GKE Gateway コントローラーが Global external Application Load Balancer を作成します。allowedRoutes.namespaces.from: Same により、同じNamespaceのHTTPRouteのみがこのGatewayにアタッチできます。

次に、HTTPRouteを作成してトラフィックのルーティングルールを定義します。

cat <<'EOF' | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: nginx-httproute
  namespace: default
spec:
  parentRefs:
  - name: nginx-gateway
  rules:
  - backendRefs:
    - name: nginx-service
      port: 80
EOF

httproute.gateway.networking.k8s.io/nginx-httproute created

parentRefsで先ほど作成したGatewayを参照し、backendRefs ですべてのトラフィックを nginx-service に転送するルールを定義しています。

Gateway の作成後、GKE Gateway コントローラーが以下のリソースを自動的に作成します。

  • 外部 IP アドレス
  • 転送ルール(Forwarding Rule)
  • ターゲット HTTP プロキシ
  • URL マップ
  • バックエンドサービス
  • ヘルスチェック

ロードバランサーが完全に構成されるまで数分かかる場合があります。構成が完了するまで HTTP 404 や HTTP 500 エラーが返ることがあります。

9. 動作確認

Gateway のステータスを確認し、外部 IP アドレスが割り当てられていることを確認します。

kubectl get gateway nginx-gateway

NAME            CLASS                            ADDRESS          PROGRAMMED   AGE
nginx-gateway   gke-l7-global-external-managed   xxx.xxx.xxx.xxx                2m3s

Gateway の Programmed 条件が True になるまで待ちます。

kubectl wait --for=condition=Programmed gateway/nginx-gateway --timeout=300s

gateway.gateway.networking.k8s.io/nginx-gateway condition met

kubectl get gateway nginx-gateway
NAME            CLASS                            ADDRESS          PROGRAMMED   AGE
nginx-gateway   gke-l7-global-external-managed   xxx.xxx.xxx.xxx   True         4m12s

外部 IP アドレスが割り当てられたら、curl でアクセスしてみます。

NginxのデフォルトのウェルカムページのHTMLが取得できました。

# Gateway の外部 IP を取得
GATEWAY_IP=$(kubectl get gateway nginx-gateway -o jsonpath='{.status.addresses[0].value}')

# curl でアクセス
curl http://${GATEWAY_IP}/

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, nginx is successfully installed and working.
Further configuration is required for the web server, reverse proxy, 
API gateway, load balancer, content cache, or other features.</p>

<p>For online documentation and support please refer to
<a href="https://nginx.org/">nginx.org</a>.<br/>
To engage with the community please visit
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/>
For enterprise grade support, professional services, additional 
security features and capabilities please refer to
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

ブラウザ上から正常にアクセスできれば、Nginx のデフォルトのウェルカムページ(Welcome to nginx!)が表示されます。

alt text

また、ロードバランサーの構成も確認できます。
Gateway APIにより各種ロードバランサーのコンポーネントも自動作成されていることが確認できました。

# バックエンドサービスの一覧を確認
gcloud compute backend-services list \
  --project=$PROJECT_ID

NAME: gkegw1-vac7-default-gw-serve404-80-8zjp3d8cqfsu
BACKENDS: 
PROTOCOL: HTTP

NAME: gkegw1-vac7-default-gw-serve500-80-iuaooq9vq8f6
BACKENDS: 
PROTOCOL: HTTP

NAME: gkegw1-vac7-default-nginx-service-80-6nogpxd8beyn
BACKENDS: asia-northeast1-b/networkEndpointGroups/k8s1-245b1ac3-default-nginx-service-80-0f49dc9e
PROTOCOL: HTTP

# NEG の一覧を確認
gcloud compute network-endpoint-groups list \
  --project=$PROJECT_ID

NAME: k8s1-245b1ac3-default-nginx-service-80-0f49dc9e
LOCATION: asia-northeast1-b
ENDPOINT_TYPE: GCE_VM_IP_PORT
SIZE: 2

# ヘルスチェックのステータスを確認
gcloud compute backend-services get-health gkegw1-vac7-default-nginx-service-80-6nogpxd8beyn \
  --global \
  --project=$PROJECT_ID

backend: https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/zones/asia-northeast1-b/networkEndpointGroups/k8s1-245b1ac3-default-nginx-service-80-0f49dc9e
status:
  healthStatus:
  - healthState: HEALTHY
    instance: https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/zones/asia-northeast1-b/instances/gk3-nginx-autopilot-cluster-pool-1-xxxxxxxx-xxxx
    ipAddress: 10.4.0.5
    port: 80
  - healthState: HEALTHY
    instance: https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/zones/asia-northeast1-b/instances/gk3-nginx-autopilot-cluster-pool-1-xxxxxxxx-xxxx
    ipAddress: 10.4.0.13
    port: 80
  kind: compute#backendServiceGroupHealth

まとめ

本記事では、GKE Autopilotクラスタ上に Nginx をデプロイし、Gateway API(Gateway + HTTPRoute)を使ってGlobal external Application Load Balancer経由でアクセスする手順を紹介しました。

IngressよりもGateway APIが推奨になっていたこと以外は、基本的に昔に構築したような形ですんなり構築することができました。

今回はNginxをGKE上にデプロイするシンプルな構成でしたが、Kubernetesはかなり奥が深く、様々なコンポーネントがたくさんあります。
さらにGoogle Cloudの各種リソースが絡み合ったりもするため、今回の構成をベースに以下のような追加の検証を行ってより理解を深めたいと思います。

  • HTTPS 対応: Gateway に Google マネージド SSL 証明書を設定し、HTTPS でのアクセスを有効化
  • Cloud Armor 統合: WAF ルールを適用して DDoS 防御やアクセス制御を追加
  • HPA(Horizontal Pod Autoscaler): CPU やカスタムメトリクスに基づく Pod の自動スケーリング
  • パスベースルーティング: HTTPRoute で複数の Service にパスベースでトラフィックを振り分け
  • トラフィック分割: HTTPRoute の backendRefs に重みを設定し、カナリアデプロイを実現

この記事が誰かの助けになれば幸いです。

以上、コンサルティング部の渡邉でした!

この記事をシェアする

関連記事