Kubernetes Gateway API 入門
Gateway API を使用して Kubernetes クラスタへのイングレストラフィックを設定する方法。
Istio やその他のサービスメッシュを使用して Kubernetes アプリケーションサービスを実行している場合でも、Kubernetes クラスタ内の通常のサービスを使用している場合でも、クラスタ外のクライアントにアプリケーションサービスへのアクセスを提供する必要があります。プレーンな Kubernetes クラスタを使用している場合は、おそらく Kubernetes の Ingress リソースを使用して、着信トラフィックを設定していることでしょう。Istio を使用している場合は、推奨される設定リソースである Gateway と VirtualService を使用する可能性が高いでしょう。
Kubernetes Ingress リソースには、特に大規模なアプリケーションのイングレストラフィックを設定する場合や、HTTP 以外のプロトコルを使用する場合に、いくつかの重大な欠点があることが以前から知られていました。1 つの問題は、クライアント側の L4-L6 プロパティ(ポート、TLS など)とサービス側の L7 ルーティングの両方を 1 つのリソースで設定していることです。大規模なアプリケーションの場合、これらの構成は異なるチームが異なる名前空間で管理する必要があります。また、異なる HTTP プロキシ間で共通の分母を描こうとした結果、Ingress は最も基本的な HTTP ルーティングしかサポートできず、最新のプロキシのその他のすべての機能を移植性のないアノテーションに押し込むことになっています。
Ingress の欠点を克服するために、Istio はイングレストラフィック管理用の独自の設定 API を導入しました。Istio の API では、クライアント側の表現は Istio Gateway リソースを使用して定義され、L7 トラフィックは VirtualService に移動されます。これは、メッシュ内のサービス間のトラフィックをルーティングするために使用される同じ構成リソースと偶然にも一致します。Istio API は大規模なアプリケーションのイングレストラフィック管理に適したソリューションを提供しますが、残念ながら Istio 固有の API です。別のサービスメッシュ実装を使用している場合や、サービスメッシュをまったく使用していない場合は、運が悪かったと言えるでしょう。
Gateway API の登場
Gateway API と呼ばれる新しい Kubernetes トラフィック管理 API をめぐって、大きな盛り上がりを見せています。これは最近、ベータ版に昇格されました。Gateway API は、Ingress の欠点を克服する(Istio の API と同様に)イングレストラフィック制御用の Kubernetes 設定リソースのセットを提供しますが、Istio の API とは異なり、広範な業界の合意を得た標準の Kubernetes API です。いくつかの API の実装が進行中で、Istio のベータ版実装も含まれます。したがって、Kubernetes Ingress や Istio Gateway/VirtualService から新しい Gateway API にイングレストラフィック構成を移行することを検討し始めるには、今が良い時期かもしれません。
サービスメッシュの管理に Istio を使用するかどうか、または使用する予定があるかどうかにかかわらず、Istio の Gateway API 実装を簡単に使用して、クラスタのイングレス制御を開始できます。Istio の実装は、Gateway API 自体がまだベータレベルの API であるという事実が主な要因となって、まだベータ版機能ですが、内部では Istio の実績のある同じ内部リソースを使用して構成を実装しているため、非常に堅牢です。
Gateway API のクイックスタート
Gateway API を使用を開始するには、まず CRD をダウンロードする必要があります。ほとんどの Kubernetes クラスタには、少なくともまだデフォルトでインストールされていません。
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl apply -f -; }
CRD がインストールされたら、それらを使用して Gateway API リソースを作成してイングレストラフィックを構成できますが、リソースが機能するためには、クラスタでゲートウェイコントローラーが実行されている必要があります。Istio のゲートウェイコントローラーの実装を有効にするには、最小限のプロファイルで Istio をインストールするだけです。
$ curl -L https://istio.dokyumento.jp/downloadIstio | sh -
$ cd istio-1.24.0
$ ./bin/istioctl install --set profile=minimal -y
これで、クラスタには、`istio.io/gateway-controller` という名前の Istio のゲートウェイコントローラーを介した、すぐに使用できる Gateway API の完全に機能する実装が用意されます。
Kubernetes ターゲットサービスをデプロイする
Gateway API を試すために、Istio の helloworld サンプルをイングレスターゲットとして使用しますが、サイドカーインジェクションを有効にせずに、シンプルな Kubernetes サービスとしてのみ実行します。「Kubernetes クラスタ」へのイングレストラフィックを制御するために Gateway API を使用するだけなので、ターゲットサービスがメッシュの内側と外側のどちらで実行されているかは関係ありません。
helloworld サービスをデプロイするには、次のコマンドを使用します。
$ kubectl create ns sample
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -n sample
helloworld サービスには、異なるバージョン (v1
と v2
) に対応する 2 つのバッキングデプロイメントが含まれています。次のコマンドを使用して、両方が実行されていることを確認できます。
$ kubectl get pod -n sample
NAME READY STATUS RESTARTS AGE
helloworld-v1-776f57d5f6-s7zfc 1/1 Running 0 10s
helloworld-v2-54df5f84b-9hxgww 1/1 Running 0 10s
helloworld イングレストラフィックを構成する
helloworld サービスが起動して実行されたので、Gateway API を使用してイングレストラフィックを構成できます。
イングレスエントリポイントは、Gateway リソースを使用して定義されます。
$ kubectl create namespace sample-ingress
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: sample-gateway
namespace: sample-ingress
spec:
gatewayClassName: istio
listeners:
- name: http
hostname: "*.sample.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
EOF
Gateway を実装するコントローラーは、GatewayClass を参照することで選択されます。機能的な Gateway を持つには、クラスタに少なくとも 1 つの GatewayClass が定義されている必要があります。この場合、Gateway の gatewayClassName: istio
設定で、関連付けられた GatewayClass (istio
という名前) を参照することにより、Istio のゲートウェイコントローラー istio.io/gateway-controller
を選択しています。
Ingress とは異なり、Kubernetes Gateway にはターゲットサービスである helloworld への参照が含まれていないことに注意してください。Gateway API では、サービスへのルートは、トラフィックのサブセットを特定のサービス(この例では helloworld など)に転送するために Gateway に接続される個別の設定リソースで定義されます。この分離により、異なるチームが管理する可能性のある異なる名前空間で Gateway とルートを定義できます。ここでは、クラスタオペレーターの役割を担い、sample-ingress
名前空間で Gateway を適用しています。後で、アプリケーション開発者の代わりに、helloworld サービス自体の隣の sample
名前空間にルートを追加します。
Gateway リソースはクラスタオペレーターが所有しているため、helloworld サービスだけでなく、複数のチームのサービスにイングレスを提供するために使用できます。この点を強調するために、Gateway でホスト名を *.sample.com
に設定し、複数のサブドメインのルートをアタッチできるようにしました。
Gateway リソースを適用したら、外部アドレスを取得する前に、準備が整うのを待つ必要があります。
$ kubectl wait -n sample-ingress --for=condition=programmed gateway sample-gateway
$ export INGRESS_HOST=$(kubectl get -n sample-ingress gateway sample-gateway -o jsonpath='{.status.addresses[0].value}')
次に、parentRefs
フィールドを使用して、HTTPRoute を sample-gateway
にアタッチし、helloworld サービスへのトラフィックを公開およびルーティングします。
$ kubectl apply -n sample -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: helloworld
spec:
parentRefs:
- name: sample-gateway
namespace: sample-ingress
hostnames: ["helloworld.sample.com"]
rules:
- matches:
- path:
type: Exact
value: /hello
backendRefs:
- name: helloworld
port: 5000
EOF
ここでは、クラスタ外部のクライアントに対して、特にホスト helloworld.sample.com
経由で helloworld サービスの /hello
パスを公開しました。curl を使用して、helloworld サンプルにアクセスできることを確認できます。
$ for run in {1..10}; do curl -HHost:helloworld.sample.com http://$INGRESS_HOST/hello; done
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
ルートルールでバージョンのルーティングが設定されていないため、トラフィックはほぼ半分が helloworld-v1
で処理され、残りの半分が helloworld-v2
で処理される、均等な分割が表示されるはずです。
重みベースのバージョンルーティングを構成する
他の「トラフィックシェーピング」機能の中でも、Gateway API を使用して、すべてのトラフィックをいずれかのバージョンに送信したり、リクエストのパーセンテージに基づいてトラフィックを分割したりできます。たとえば、次のルールを使用して、helloworld トラフィックを 90% が v1
、10% が v2
に分散させることができます。
$ kubectl apply -n sample -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: helloworld
spec:
parentRefs:
- name: sample-gateway
namespace: sample-ingress
hostnames: ["helloworld.sample.com"]
rules:
- matches:
- path:
type: Exact
value: /hello
backendRefs:
- name: helloworld-v1
port: 5000
weight: 90
- name: helloworld-v2
port: 5000
weight: 10
EOF
Gateway API は、ルートターゲットである helloworld-v1
および helloworld-v2
のバージョン固有のバックエンドサービス定義に依存しています。helloworld サンプルには、helloworld バージョン v1
と v2
のサービス定義がすでに含まれています。それらを定義するには、次のコマンドを実行するだけです。
$ kubectl apply -n sample -f @samples/helloworld/gateway-api/helloworld-versions.yaml@
これで、前の curl コマンドを再度実行できます。
$ for run in {1..10}; do curl -HHost:helloworld.sample.com http://$INGRESS_HOST/hello; done
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
Hello version: v2, instance: helloworld-v2-54dddc5567-2lm7b
Hello version: v1, instance: helloworld-v1-78b9f5c87f-2sskj
今回は、約 10 件のリクエストのうち 9 件が helloworld-v1
で処理され、約 1 件のみが helloworld-v2
で処理されることがわかります。
内部メッシュトラフィック用の Gateway API
Gateway API について、イングレス構成 API としてのみ(ノースサウストラフィック管理と呼ばれることが多い)であり、クラスタ内のサービス間(別名、イーストウェスト)トラフィック管理用の API ではないということに気付いたかもしれません。
サービスメッシュを使用している場合は、Istio が VirtualService を使用して両方のルートルールを設定する方法と同様に、同じ API リソースを使用してイングレストラフィックルーティングと内部トラフィックの両方を構成できることが非常に望ましいでしょう。幸いなことに、Kubernetes Gateway API はこのサポートを追加するために取り組んでいます。イングレストラフィック用の Gateway API ほど成熟していませんが、メッシュ管理および管理のための Gateway API (GAMMA) イニシアチブと呼ばれる取り組みが、これを実現するために進行中で、Istio は、Gateway API をすべてのトラフィック管理のデフォルトの API にする予定です将来的に。
最初の重要な Gateway 拡張提案 (GEP) が最近承認され、実際に Istio で既に使用できるようになっています。試してみるには、上記でインストールした標準のベータ版ではなく、Gateway API CRD の 実験版 を使用する必要がありますが、それ以外の場合は準備完了です。開始するには、Istio の リクエストルーティングタスク を参照してください。
まとめ
この記事では、Istio の軽量な最小限のインストールを使用して、クラスタイングレストラフィック制御用の新しい Kubernetes Gateway API のベータ品質の実装を提供する方法を見てきました。Istio ユーザーの場合、Istio の実装では、メッシュ内のイーストウェストトラフィック管理の実験的な Gateway API のサポートも試してみることができます。
Istioのドキュメントの多くは、すべてのイングレスに関するタスクや、メッシュ内部のトラフィック管理に関するいくつかのタスクを含め、Gateway APIまたはIstio設定APIのいずれかを使用してトラフィックを設定するための並行した手順が含まれています。IstioでのGateway APIの実装に関する詳細については、Gateway APIのタスクをご覧ください。