Gateway API は、Kubernetes でのルーティングとロードバランシングのための次世代 API を提供する公式の Kubernetes プロジェクトです。このトピックでは、Gateway API を使用して Gateway with Inference Extension でサポートされる基本機能を構成する方法について説明します。
仕組み
Gateway with Inference Extension は、Envoy Gateway プロジェクト上に構築されたコンポーネントです。すべての基本的な Gateway API の機能とオープンソースの Envoy Gateway 拡張リソースをサポートします。
Envoy Gateway のアーキテクチャには、以下が含まれます。
コントロールプレーン: クラスター内のトラフィックルールを監視する Envoy Gateway コンポーネントで構成されます。コントロールプレーンは、Envoy プロキシインスタンスを動的に作成および管理し、その転送ルールをリアルタイムで更新します。コントロールプレーンは、サービストラフィックを直接転送しません。
データプレーン: 実行中の Envoy プロキシインスタンスで構成され、サービストラフィックを処理および転送して、効率的で信頼性の高い通信を保証します。
シナリオ
ACK マネージドクラスター または ACS クラスター、バージョン 1.30 以降。クラスターのスペックアップ方法の詳細については、「クラスターを手動でスペックアップする」をご参照ください。
Gateway with Inference Extension コンポーネントがインストールされていること。
準備
backend と backend-2 のテストアプリケーションを作成します。次の YAML コンテンツを backend.yaml として保存し、
kubectl apply -f backend.yamlコマンドを実行します。説明backend-2 アプリケーションを作成するには、YAML ファイル内の
backendのすべてのインスタンスをbackend-2に置き換えます。apiVersion: v1 kind: ServiceAccount metadata: name: backend --- apiVersion: v1 kind: Service metadata: name: backend labels: app: backend service: backend spec: ports: - name: http port: 3000 targetPort: 3000 selector: app: backend --- apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 1 selector: matchLabels: app: backend version: v1 template: metadata: labels: app: backend version: v1 spec: serviceAccountName: backend containers: - image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/envoygateway-echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: - containerPort: 3000 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespaceGateway with Inference Extension をインストールすると、デフォルトで GatewayClass が作成されます。次のコマンドを実行して GatewayClass を表示します。
kubectl get gatewayclass NAME CONTROLLER ACCEPTED AGE ack-gateway gateway.envoyproxy.io/gatewayclass-controller True 2m31sGatewayClass リソースが見つからない場合は、手動で作成できます。
Gateway リソースを作成します。次の YAML コンテンツを gateway.yaml として保存し、
kubectl apply -f gateway.yamlコマンドを実行します。apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: ack-gateway spec: gatewayClassName: ack-gateway listeners: - name: http protocol: HTTP port: 80Gateway with Inference Extension コンポーネントのコントロールプレーンは、Gateway リソースに基づいて EnvoyProxy デプロイメントと対応する `LoadBalancer` サービスを作成します。このサービスは、指定されたポートでリッスンします。Server Load Balancer インスタンスの課金の詳細については、「Server Load Balancer の課金」をご参照ください。
また、EnvoyProxy デプロイメントの仕様をカスタマイズしたり、サービスパラメーターをカスタマイズしたり、ゲートウェイの Horizontal Pod Autoscaling (HPA) を有効にしたりすることもできます。
ゲートウェイアドレスを取得します。
export GATEWAY_HOST=$(kubectl get gateway/ack-gateway -o jsonpath='{.status.addresses[0].value}')
パスプレフィックスマッチングに基づく HTTP ルーティング
次の例では、HTTPRoute を構成して /get パスプレフィックスに一致させ、構成をテストする方法を示します。
HTTPRoute リソースを作成します。次の YAML コンテンツを httproute.yaml として保存し、
kubectl apply -f httproute.yamlコマンドを実行します。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 matches: - path: type: PathPrefix value: /getアクセスをテストします。
curl -H "Host: www.example.com" http://$GATEWAY_HOST/get予期される出力:
{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": [ "*/*" ], "User-Agent": [ "curl/8.9.1" ], "X-Envoy-External-Address": [ "115.XX.XXX.55" ], "X-Forwarded-For": [ "115.XX.XXX.55" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "953b2f8f-26d3-4ba9-93ba-a482b197b1ff" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
リクエストヘッダーを追加する
HTTPRoute 構成を更新して、ルーティングされたリクエストにヘッダーを追加します。
HTTPRoute リソースを更新します。次の YAML コンテンツを httproute.yaml として保存し、
kubectl apply -f httproute.yamlコマンドを実行します。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: "added-header" value: "foo"アクセスをテストします。
curl -H "Host: www.example.com" http://$GATEWAY_HOST/get期待される出力: サンプルアプリケーションは、その応答でリクエスト情報を返します。応答に追加された
added-headerが表示され、操作が成功したことを示します。{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": [ "*/*" ], "Added-Header": [ "foo" ], "User-Agent": [ "curl/8.9.1" ], "X-Envoy-External-Address": [ "115.XX.XXX.55" ], "X-Forwarded-For": [ "115.XX.XXX.55" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "d37f19e5-25c1-45cf-90e5-51453e7ae3ed" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
重みによるトラフィックの分割
HTTPRoute 構成を更新して、backend-2 サービスにルーティングルールを追加し、backend と backend-2 サービスのトラフィックの重みを構成します。
Gateway API では、backendRef の重みの合計が 100 である必要はありません。単一サービスのトラフィック比率は、次のように計算されます:
HTTPRoute リソースを更新します。次の YAML コンテンツを httproute.yaml として保存し、
kubectl apply -f httproute.yamlコマンドを実行します。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 8 - group: "" kind: Service name: backend-2 port: 3000 weight: 220 回連続でリクエストを送信してアクセスをテストし、2 つのサービス間のトラフィック比率を確認します。
次のコマンドには、出力に
backendとbackend-2のみを表示するための追加処理が含まれています。for i in $(seq 1 20); do curl -sS -H "Host: www.example.com" http://$GATEWAY_HOST/get |grep backend; done | \ sed -E 's/".*"(backend(-2)?)-[0-9a-zA-Z]*-.*/\1/'期待される出力: トラフィックは、2 つのサービス間で約 80% 対 20% の比率で分割されます。
backend-2 backend backend backend backend backend backend backend backend backend backend-2 backend-2 backend backend backend-2 backend backend backend backend
TLS トラフィックを処理する
証明書を構成し、TLS リスナーを追加して Gateway リソースを更新し、TLS トラフィックが正しく処理されることを確認します。
証明書を生成し、Secret を作成します。
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization" openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crtGateway リソースを更新します。TLS リスナーを追加し、前のステップで作成した証明書を参照します。
kubectl patch gateway ack-gateway --type=json --patch ' - op: add path: /spec/listeners/- value: name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - kind: Secret group: "" name: example-cert '変更が有効になったかどうかを確認します。
kubectl get gateway/ack-gateway -o yaml | grep spec: -A 20期待される出力:
spec: gatewayClassName: ack-gateway listeners: - allowedRoutes: namespaces: from: Same name: http port: 80 protocol: HTTP - allowedRoutes: namespaces: from: Same name: https port: 443 protocol: HTTPS tls: certificateRefs: - group: "" kind: Secret name: example-cert mode: Terminate status:出力は、変更が有効であることを示しています。
アクセスをテストします。
curl -H Host: www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ --cacert example.com.crt https://www.example.com/get予期される出力:
{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": [ "*/*" ], "User-Agent": [ "curl/8.9.1" ], "X-Envoy-External-Address": [ "115.XX.XXX.55" ], "X-Forwarded-For": [ "115.XX.XXX.55" ], "X-Forwarded-Proto": [ "https" ], "X-Request-Id": [ "ac539756-3826-474b-be2f-5e57fdd49dac" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }