GAになったGKE Gateway controller を改めて検証してみた
こんにちは、クラウドエースの阿部です。
こちらの記事では、2022/11/09に一般提供(GA)になった GKE Gateway controller について検証していこうと思います。
GKE Gateway controller の概要
GKE Gateway controller は、GKE における Kubernetes Gateway API の実装になります。
Kubernetes Gateway API は、 Ingress API で実現していた汎用的なAPIと様々なプラットフォーム上での実装仕様を持っていた特性を引き継ぎつつ、
Ingress API の課題を改善するためにNetwork-SIGによって開発されたAPIです。
なお、こちらのFAQにもありますが、Gateway APIはIngress APIの置き換えを目指しているわけではありません。
Kubernetes Gateway API について
Kubernetes Gateway API は以下のような仕様です。
-
GatewayClass
,Gateway
,HTTPRoute
といった複数のリソース定義を使って複数のサービスのトラフィックを管理します。 -
Gateway
とHTTPRoute
を分離して管理することで、クラスタ管理者とアプリケーション開発者のロールを分離することができます。 - Ingress ではできなかった、Namespaceを跨いだ構成も可能です。
GKE Gateway controller について
GKE の Gateway controller は Gateway API をGKE上で実現するための実装になるため、基本的には Kubernetes Gateway API の仕様に準じます。
ただし、Kubernetes Gateway API は、 TCPRoute
や UDPRoute
といったリソース定義が存在し、L7だけでなくL4のトラフィックも管理可能ですが、2022/12現在のGKE Gateway controllerはL7トラフィックのみ管理可能です。
GKE Gateway controller を使用するためには、最低限以下の要件を満たす必要があります。
- GKEクラスタのバージョンがv1.24以降であること
- GKEクラスタがVPCネイティブクラスタであること
また、Istioや内部負荷分散を使用したい場合は追加の要件を満たす必要があります。
詳細は「GKE Gateway コントローラの要件」のドキュメントを参照してください。
Gateway API のリソース
GKEがサポートするGateway APIのリソースは下記の表の通りです。
リソース(kind) | 説明 |
---|---|
GatewayClass | Gateway APIを使って構築する負荷分散・トラフィック制御機能の種類を定義するリソースです。GKE Gateway controllerでは4つのGatewayClassが事前定義されており、ユーザーが追加で作成する必要はありません。 |
Gateway | IPアドレスや受信プロトコル、TLS暗号の有無等、フロントエンド設定を定義するリソースです。 |
HTTPRoute | ホスト名やパスに従って1つ以上のサービスにトラフィックを振り分ける設定を定義するリソースです。Cloud Load Balancing で言うところのURL Mapを設定します。複数の HTTPRoute を設定でき、Gateway API側で1つの負荷分散設定としてマージされます。 |
xxPolicy | Gateway controllerで管理するCloud Load Balancingに追加設定を行うためのリソースです。記事執筆時点(2022/12)では、LBPolicyとHealthCheckPolicyの2種類が使用可能です。ドキュメントはこちらを参照してください。 |
GKE Gateway controller が定義する GatewayClass について
本記事執筆時点(2022年12月)における、GKE Gateway controller の GatewayClass は以下の通りです。
GatewayClass名 | リリース段階 | ロケーション | クラスタタイプ | ネットワーク到達性 | 高度なトラフィック管理 |
---|---|---|---|---|---|
gke-l7-gxlb | GA | グローバル | シングルクラスタ | インターネット | なし |
gke-l7-rilb | GA | リージョン | シングルクラスタ | VPC内部 | トラフィック分割、ミラーリング等 |
gke-l7-gxlb-mc | Preview | グローバル | マルチクラスタ | インターネット | なし |
gke-l7-rilb-mc | Preview | リージョン | マルチクラスタ | VPC内部 | トラフィック分割、ミラーリング等 |
上記以外の機能の違いについては、下記のGatewayClassに関するドキュメントをご確認ください。
参考情報
GKE Gateway controller が作成する Cloud Load Balancing について
本記事執筆時点(2022年12月)における GKE Regular チャンネルのバージョン(v1.24.5-gke.600
)では、実際にデプロイされるCloud Load Balancingとして「グローバル外部 HTTP(S) ロードバランサ」ではなく「グローバル外部 HTTP(S) ロードバランサ(従来)」を使用します。
そのためかは分かりませんが、 gke-l7-gxlb
やgke-l7-gxlb-mc
では高度なトラフィック管理機能を使う事ができません。
GKE Gateway controller の基本的な使い方
ここでは、GKE Gateway controller の基本的な使い方を説明していきたいと思います。
GKE Gateway controllerでは、外部負荷分散と内部負荷分散の両方を作成することができますが、この記事では外部負荷分散であるgke-l7-gxlb
の使い方を説明します。
GKEクラスタのセットアップ
静的IPアドレスの予約
以下のコマンドでグローバル パブリック IP アドレス な静的IPアドレスを予約します。
ここでは、gke-gateway-vip
という名前でIPアドレスリソースを作成します。
PROJECT_ID
はお使いの Google Cloud プロジェクトIDに置き換えて下さい。
gcloud compute addresses create gke-gateway-vip --global --project=PROJECT_ID
コマンド実行後、以下のコマンドで予約したIPアドレスを確認します。後で使います。
gcloud compute addresses describe gke-gateway-vip --global --format="get(address)"
検証用ドメインの予約
次に、予約したIPアドレスにドメインを設定します。
今回の検証ではSSLを設定したいので、ドメインを設定します。検証用のドメインを持っている人はそちらを使って頂いてよいと思います。
ここでは、Google Cloud プロジェクトで無料で利用できるCloud Endpointsドメインを使います。
まず、以下のようなYAMLファイルを用意します。ファイル名は openapi.yaml
とします。
openapi.yaml
swagger: '2.0'
info:
title: 適当なタイトル
version: 1.0.0
host: "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog"
x-google-endpoints:
- name: "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog"
target: "予約したIPアドレス"
paths: {}
- title: 設定ファイルのタイトルを記述します。「Test project」のようなものでOKです。
- host: ドメイン(FQDN)になります。
SERVICENAME
の部分は数字・英小文字・ハイフンで構成された最大60文字程度の単語で置き換えてください。
PROJECT_ID
はお使いのGoogle Cloud プロジェクトIDに置き換えてください。 - name: hostと同じにしてください。
- target: 先の手順で予約したIPアドレスを記述してください。
次に、Cloud Endpoints APIが有効になっているかを確認します。
gcloud services list --enabled --filter=name:endpoints.googleapis.com
上記コマンドで、 Listed 0 items.
と表示された場合はまだ Cloud Endpoints API が有効になっていませんので、以下のコマンドを実行します。
gcloud services enable endpoints.googleapis.com
Cloud Endpoints APIが有効な状態で、以下のコマンドを実行します。
※PROJECT_ID
は、お使いのGoogle Cloud プロジェクトIDに置き換えて下さい。
gcloud endpoints services deploy openapi.yaml --project=PROJECT_ID
特にエラーがでなければ、openapi.yaml
に記述した内容でドメインを使うことが使う事ができると思います。
Google Managed SSL 証明書の作成
ドメインを予約した後は、ドメインに対応するGoogle Managed SSL証明書を作成します。
ここでは、gke-gateway-cert
という名前で証明書リソースを作成します。
--domains
オプションには、先ほどCloud Endpointsで設定したhost名を記述します。
以下のコマンドを実行します。
gcloud compute ssl-certificates create gke-gateway-cert \
--domains="{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog" \
--global
GKEクラスタの作成
本題のGKEクラスタを作成します。2022年12月時点では、Cloud consoleからはGateway controllerを有効化できないため、コマンドラインで作成する必要があります。
基本的な作成方法は通常のGKE Standardクラスタと同様ですが、 --gateway-api=standard
オプションを付ける必要があります。また、クラスタのバージョンは1.24以降である必要があります。
最初に、以下のコマンドで、現在REGULARチャンネルで選択できるバージョンを確認します。
gcloud container get-server-config --region=asia-northeast1 | grep -A5 "channel: REGULAR"
このとき、1.24以降でなるべく新しいバージョンを確認します。記事執筆時点では、 1.24.5-gke.600
が選択可能でした。
以下のコマンドを実行します。 --cluster-version
で指定するバージョンは、前述のコマンドで確認したものに適宜置き換えてください。
また、以下のコマンドラインでは、検証費用を抑えるための --spot
オプションを付与していますので、検証の目的に応じて外してください。
gcloud container clusters create "gke-gateway-cluster" --region "asia-northeast1" \
--cluster-version "1.24.5-gke.600" --release-channel "regular" \
--machine-type "e2-medium" --disk-size "50" --spot --num-nodes "1" \
--enable-ip-alias --gateway-api=standard
しばらくするとGKEクラスタが作成されます。(最近のgcloudコマンドは認証も設定してくれますが)GKEクラスタの認証設定も行います。
gcloud container clusters get-credentials gke-gateway-cluster --region asia-northeast1
GKEクラスタでGateway APIが有効化されているかを確認します。以下のコマンドを実行します。
kubectl get gatewayclass
以下のように gke-l7-gxlb
とgke-l7-rilb
が表示されれば問題ありません。
NAME CONTROLLER ACCEPTED AGE
gke-l7-gxlb networking.gke.io/gateway True 158m
gke-l7-rilb networking.gke.io/gateway True 158m
同じ Namespace の Service へのルーティング
Gateway
と HTTPRoute
、および、 Service
と Pod
が同じ Namespace
に配置するケースでk8sマニフェストを記述してみます。
デモアプリケーションのデプロイ
まず、Google公式リファレンスにあるデモアプリケーションをデプロイします。
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
以下のように、default Namespace にstore-v1
、store-v2
、store-german
サービスとDeploymentがデプロイされます。
表示例
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
store-german-7dbb4b97cd-fr7hn 1/1 Running 0 21s
store-german-7dbb4b97cd-x4zst 1/1 Running 0 21s
store-v1-6d8d58d78-8s64q 1/1 Running 0 22s
store-v1-6d8d58d78-qlz96 1/1 Running 0 22s
store-v2-5d66fbc946-dxnr2 1/1 Running 0 21s
store-v2-5d66fbc946-llclw 1/1 Running 0 21s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.8.0.1 <none> 443/TCP 171m
store-german ClusterIP 10.8.9.176 <none> 8080/TCP 24s
store-v1 ClusterIP 10.8.6.220 <none> 8080/TCP 24s
store-v2 ClusterIP 10.8.0.250 <none> 8080/TCP 24s
Gateway をデプロイ
次に、Gateway リソースをデプロイします。
下記のk8s YAMLを記述します。
クラスタ作成のセクションで、IPアドレスをgke-gateway-vip
、証明書リソースをgke-gateway-cert
で作成しています。別名で作成している方は、YAMLファイルの該当箇所も読み替えて下さい。
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: external-https
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: gke-gateway-cert
addresses:
- type: NamedAddress
value: gke-gateway-vip
記述のポイントとしては以下の通りです。
-
metadata.name
にはGatewayリソースの名前を記述します。 -
spec.gatewayClassName
には定義済みのGatewayClassを指定します。 - HTTPSを有効化する場合、
spec.listeners.tls
を設定します。証明書リソースは、options
にnetworking.gke.io/pre-shared-certs
を追加します。 - IPアドレスを固定したい場合は、
spec.addresses
にIPアドレスリソース名を追加します。
HTTPSではなく、HTTPでよい場合は公式ドキュメントのサンプルを参考にしてください。
GatewayリソースのYAMLファイルを作成したら、以下のコマンドで反映します。
kubectl apply -f gateway.yaml
この段階で、GatewayリソースによるCloud Load Balancingは作成されます。ただし、作成されるのはIPアドレスと証明書リソースを使ったフロントエンドと、k8sデフォルトバックエンド(404ページ)へのルートのみです。
HTTPRoute をデプロイ
HTTPRoute
リソースをデプロイします。
ほぼGoogle公式リファレンスにある記載内容と同じですが、 spec.hostnames
の部分をCloud Endpointsで取得したドメインに変更しています。
また、 spec.parentRefs
に指定するGatewayリソースの名称を external-https
に変更しています。
store-route.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: store
spec:
parentRefs:
- kind: Gateway
name: external-https
hostnames:
- "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog"
rules:
- backendRefs:
- name: store-v1
port: 8080
- matches:
- headers:
- name: env
value: canary
backendRefs:
- name: store-v2
port: 8080
- matches:
- path:
value: /de
backendRefs:
- name: store-german
port: 8080
作成したら、以下のコマンドを実行して反映します。
kubectl apply -f store-route.yaml
各リソースの作成状況について
リソースの作成状況は以下のコマンドで確認することができます。
Gatewayの作成状況
kubectl get gateway
※READY列がTrueならひとまず作成できたことが確認できる
kubectl describe gateway external-https
※StatusやEventsから作成状況を確認できる
HTTPRouteの作成状況
kubectl describe httproute store
※Eventsからなんとなく判断する
HTTPRouteリソースのEventsのメッセージはちょっと分かりにくいです。
Managed SSL証明書の作成状況確認
今回の作成方法ではManaged SSL証明書を使用しており、Gatewayが実際のCloud Load Balancingを作成した後、証明書リソースがIPアドレスとドメインの紐付けをチェックして証明書のセットアップが完了するまで時間がかかります。(公式には30分~1時間程度)
作成状況は以下のコマンドで確認できます。
gcloud compute ssl-certificates describe gke-gateway-cert --format="get(managed)"
※Status=ACTIVEになっていれば作成完了と判断できる
Gatewayへのアクセステスト
では、実際にアクセスしてみます。
curlコマンドでアクセス確認します。
store-v1 (デフォルトパス)へのアクセス
store-v1のcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "store-v1",
"pod_name": "store-v1-6d8d58d78-qlz96",
"pod_name_emoji": "🎅🏽",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-07T06:47:20",
"zone": "asia-northeast1-a"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
store-v2 (Canaryリリース)へのアクセス
store-v2のcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog -H "env: canary"
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "store-v2",
"pod_name": "store-v2-5d66fbc946-llclw",
"pod_name_emoji": "🦶🏼",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-07T06:50:25",
"zone": "asia-northeast1-c"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
store-german (別パス)へのアクセス
store-germanのcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog/de
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "Gutentag!",
"pod_name": "store-german-7dbb4b97cd-fr7hn",
"pod_name_emoji": "🧗🏻♂️",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-07T06:51:28",
"zone": "asia-northeast1-a"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
HTTPRouteリソースで定義したパスやヘッダルーティングの通りにトラフィックが制御されたことが分かります。
検証用リソースのクリーンアップ
以下のコマンドを実行して、リソースをクリーンアップしておきましょう。
kubectl delete -f store-route.yaml
kubectl delete -f gateway.yaml
kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
別 Namespace の Service へのルーティング
別の設定方法として、GatewayとHTTPRoute、Serviceを別のNamespaceで管理するケースで設定します。
Ingressリソースによる負荷分散設定では、IngressとServiceは全て同一のNamespaceで管理しなければならず、ルーティング先のサービス毎に別Namespace管理するような設定が困難でした。
Gateway APIは、Gateway,HTTPRoute,Serviceを別のNamespaceに配置する事が可能なため、非常に柔軟なリソース配置が可能になっています。
ここでは、GatewayとHTTPRouteは同じNamespaceで管理し、別NamespaceのServiceと連携するような構成を想定します。
この手順を始める前に、前セクションの「同じ Namespace の Service へのルーティング」で設定したGatewayとHTTPRouteは事前に削除しておきましょう。
また、扱うサンプルはGoogleのリファレンスで提供されているstoreデモアプリケーションのNamespaceを修正したものを流用します。
Namespace のセットアップ
今回デプロイするNamespaceは以下の3つにします。
Namespace名 | デプロイするリソース | ラベル |
---|---|---|
gateway | Gateway | 不要 |
store | store-v1とstore-v2デモアプリ、及び、HTTPRoute | shared-gateway-access: "true" |
store-de | store-germanデモアプリ、及び、HTTPRoute | shared-gateway-access: "true" |
実際に作成するYAMLファイルは以下の通りです。
namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: gateway
---
apiVersion: v1
kind: Namespace
metadata:
name: store
labels:
shared-gateway-access: "true"
---
apiVersion: v1
kind: Namespace
metadata:
name: store-german
labels:
shared-gateway-access: "true"
このとき、 store
Namespace と store-german
Namespace には必ず shared-gateway-access: "true"
というラベルを付与します。
このラベルは後ほどGatewayリソース設定時に使用します。
以下のコマンドで反映します。
kubectl apply -f namespace.yaml
store デモアプリケーションのデプロイ
store デモアプリケーションをデプロイします。Googleリファレンスのstore.yaml
を以下のように修正します。
基本的には、 各リソース定義に metadata.namespace
を追加しただけです。
store.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: store-v1
namespace: store
spec:
replicas: 2
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.11
ports:
- containerPort: 8080
env:
- name: METADATA
value: "store-v1"
---
apiVersion: v1
kind: Service
metadata:
name: store-v1
namespace: store
spec:
selector:
app: store
version: v1
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: store-v2
namespace: store
spec:
replicas: 2
selector:
matchLabels:
app: store
version: v2
template:
metadata:
labels:
app: store
version: v2
spec:
containers:
- name: whereami
image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.11
ports:
- containerPort: 8080
env:
- name: METADATA
value: "store-v2"
---
apiVersion: v1
kind: Service
metadata:
name: store-v2
namespace: store
spec:
selector:
app: store
version: v2
ports:
- port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: store-german
namespace: store-german
spec:
replicas: 2
selector:
matchLabels:
app: store
version: german
template:
metadata:
labels:
app: store
version: german
spec:
containers:
- name: whereami
image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.11
ports:
- containerPort: 8080
env:
- name: METADATA
value: "Gutentag!"
---
apiVersion: v1
kind: Service
metadata:
name: store-german
namespace: store-german
spec:
selector:
app: store
version: german
ports:
- port: 8080
targetPort: 8080
以下のコマンドで反映します。
kubectl apply -f store.yaml
Gateway のデプロイ
Gatewayリソースをデプロイします。基本的な設定は「同じ Namespace の Service へのルーティング」と同じですが、2点異なる部分があります。
1点目は、external-https
リソースを配置するmetadata.namespace
の指定、もう1点はlistenersの指定にallowRoutes
を追加したことです。
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: external-https
namespace: gateway
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: gke-gateway-cert
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
addresses:
- type: NamedAddress
value: gke-gateway-vip
allowRoutes はGatewayとHTTPRouteを別のNamespaceに配置する場合のどのNamespaceとの連携を許可するかの設定になります。
デフォルトは allowRoutes.namespaces.from: Same
であり、同一のNamespaceのみ許可する設定になっています。
今回の設定は、Selector
を指定し、 matchLabels
によって特定のラベルを持つNamespaceに限定する設定しています。
以下のコマンドで反映します。
kubectl apply -f gateway.yaml
HTTPRoute のデプロイ
HTTPRouteをデプロイします。HTTPRouteはデモアプリケーションを管理しているNamespaceに寄せてデプロイする設定です。
下記の様に2つのHTTPRouteリソースを作成します。
store
HTTPRouteリソースは store-v1
、store-v2
Deploymentを配置している store
Namespaceに配置し、store-german
HTTPRouteリソースは store-german
Namespaceに配置します。
その他のルーティング条件については基本的に「同じ Namespace の Service へのルーティング」のときと同じにしています。
store-route.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: store
namespace: store
spec:
parentRefs:
- kind: Gateway
name: external-https
namespace: gateway
hostnames:
- "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog"
rules:
- backendRefs:
- name: store-v1
port: 8080
- matches:
- headers:
- name: env
value: canary
backendRefs:
- name: store-v2
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: store-german
namespace: store-german
spec:
parentRefs:
- kind: Gateway
name: external-https
namespace: gateway
hostnames:
- "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog"
rules:
- matches:
- path:
value: /de
backendRefs:
- name: store-german
port: 8080
以下のコマンドで反映します。
kubectl apply -f store-route.yaml
Gatewayへのアクセステスト
しばらく待ってから、動作確認を行います。確認コマンドは「同じ Namespace の Service へのルーティング」と同じcurlコマンドです。
store-v1 (デフォルトパス)へのアクセス
store-v1のcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "store-v1",
"pod_name": "store-v1-6d8d58d78-ttzgl",
"pod_name_emoji": "✍🏼",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-08T08:03:32",
"zone": "asia-northeast1-c"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
store-v2 (Canaryリリース)へのアクセス
store-v2のcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog -H "env: canary"
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "store-v2",
"pod_name": "store-v2-5d66fbc946-z6lfh",
"pod_name_emoji": "🏃🏾♂️",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-08T08:03:43",
"zone": "asia-northeast1-a"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
store-german (別パス)へのアクセス
store-germanのcurlコマンド結果
$ curl https://{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog/de
{
"cluster_name": "gke-gateway-cluster",
"host_header": "{SERVICENAME}.endpoints.{PROJECT_ID}.cloud.goog",
"metadata": "Gutentag!",
"pod_name": "store-german-7dbb4b97cd-h9s26",
"pod_name_emoji": "👨🏻🚀",
"project_id": "{PROJECT_ID}",
"timestamp": "2022-12-08T08:03:47",
"zone": "asia-northeast1-c"
}
※{SERVICENAME}
と{PROJECT_ID}
の箇所は実際のサービス名やプロジェクトIDで表示されます。
Gateway controller の課題点
ここからは、Gateway API(GKE Gateway controller)を使ってみて感じた課題について述べていきたいと思います。
Google Cloud Load Balancing 機能のサポート
こちらの制限事項に記載されているとおり、Ingressリソースでサポートされていた下記の機能は、 Gateway controller ではサポートされていません。
- Cloud CDN
- Identity-Aware Proxy
- Google Cloud Armor
- SSL ポリシー
- HTTP から HTTPS へのリダイレクト
また、それ以外にも幾つか制限事項が存在していますので、詳細は制限事項のページをご確認ください。
このあたりの機能は負荷分散としては必須の機能なので(特にCloud Armor, SSLポリシーあたり)、今後のGateway controllerの開発に期待です。
Gateway API リソース削除後の Google Cloud リソースが残ることがある
Ingress と同様ですが、検証等でクラスタを削除したい場合に、クラスタ削除前に Gateway API のリソース(Gateway
やHTTPRoute
、Service
)を削除しておかないと、実体であるCloud Load Balancingのリソースが残ってしまいます。
少々面倒ですが、k8s管理リソースを丁寧に削除してからクラスタを削除しましょう。
また、綺麗に消してからクラスタ削除しても、 Network Endpoint Group や Health Check といったリソースも残ってしまう場合があるようです。
エラーメッセージが分かりづらい
GatewayやHTTPRouteの設定に誤りがあったとき、APIスキーマとして設定箇所に誤りがある場合は比較的する分かるのですが、スキーマ自体は問題無いものの設定に誤りがある(もしくは何らか別の原因がある)場合のメッセージが非常に分かりにくいです。
以下は、検証している中でHTTPRouteリソースの設定が上手く反映されなかったケースで kubectl describe httproute
コマンドで確認した際のメッセージです。
HTTPRoute作成失敗時のエラーメッセージ
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 62s sc-gateway-controller store/store
Normal SYNC 19s sc-gateway-controller Bind of HTTPRoute "store/store" to ParentRef {Group: "gateway.networking.k8s.io",
Kind: "Gateway",
Namespace: "gateway",
Name: "external-https",
SectionName: nil,
Port: nil} was a success
Warning SYNC 19s sc-gateway-controller ReconciliationFailed: Reconciliation of HTTPRoute "store/store" bound to ParentRef {Group: "gateway.networking.k8s.io",
Kind: "Gateway",
Namespace: "gateway",
Name: "external-https",
SectionName: nil,
Port: nil} failed: error cause: gceSync: generic::not_found: 2 errors occurred: Update: The resource 'projects/******/global/backendServices/gkegw1-lofr-store-german-s
tore-german-8080-6z7zjb560but' was not found; Insert: The resource 'projects/******/zones/asia-northeast1-c/networkEndpointGroups/k8s1-ac924807-store-german-store-german-8080-
3f5a19b0' was not found
なんとなく、Gateway controller が Cloud Load Balancing のリソースであるバックエンドサービスとネットワークエンドポイントのリソースの作成に失敗しているのですが、これを見てどうすればよいか分からなかったです。
結局、このときはいったん GatewayとHTTPRouteのリソースを全部削除してから再作成することで対処できました。
こうしたエラーメッセージがもっと分かりやすくなってくれればなと思います。
Terraform Google Provider でサポートされていない
まだ Terraform Google Provider では Gateway API の有効化がサポートされていないようです。
下記のIssueで提案されているようですので、気になる方は 👍 を押しましょう。
まとめ
GAになったとは言え、すぐ商用環境で使えるかというと微妙な部分がいくつかあるなという印象でした。
しかし、Ingressでは構成できなかった柔軟な設定が可能になっている点は将来的な可能性を感じます。
現在Ingressで負荷分散を使っている方は、まずはお試し頂くのがよいかなと思います。
Discussion