Gateway API は、Kubernetes におけるルーティングと負荷分散のための次世代 API を提供する公式の Kubernetes プロジェクトです。Gateway API を使用して、トラフィックルールを設定できます。このトピックでは、Gateway with Inference Extension でサポートされている基本的な Gateway API の機能の設定方法について説明します。
仕組み
Gateway with Inference Extension コンポーネントは、Envoy Gateway プロジェクト上に構築されています。これは、Gateway API のすべての基本機能と、オープンソースの Envoy Gateway 拡張リソースをサポートしています。
Envoy Gateway のアーキテクチャには、次のコンポーネントが含まれます。
コントロールプレーン:Envoy Gateway コンポーネントで構成されます。クラスター内のトラフィックルールをリッスンし、Envoy プロキシインスタンスを動的に作成・管理し、その転送ルールをリアルタイムで更新します。コントロールプレーンは、サービストラフィックを直接転送しません。
データプレーン:実行中の Envoy プロキシインスタンスで構成されます。サービストラフィックを処理・転送し、効率的で信頼性の高い通信を保証します。
適用範囲
ご利用の Container Service for Kubernetes (ACK) マネージドクラスター のバージョンが 1.30 以降であること。クラスターをアップグレードするには、「ACK クラスターの手動アップグレード」をご参照ください。
Gateway with Inference Extension コンポーネントがインストールされていること。
事前準備
backend と backend-2 のテストアプリケーションを作成します。次の YAML コンテンツを backend.yaml として保存し、
kubectl apply -f backend.yamlコマンドを実行します。説明backend-2 アプリケーションを作成するには、backend アプリケーションの 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 の Deployment と対応する LoadBalancer タイプの Service を作成します。また、指定されたポートでリスナーを開始します。Server Load Balancer (SLB) インスタンスの課金の詳細については、「SLB の課金」をご参照ください。
また、EnvoyProxy の Deployment の仕様と Service のパラメーターをカスタマイズしたり、ゲートウェイの 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 サービスの重みを設定します。
すべての backendRef エントリの重みの合計は 100 である必要はありません。Service にルーティングされるトラフィックの割合は、次の数式を使用して計算されます:
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: 22 つのサービス間のトラフィックの割合を確認するために、20 回連続でアクセスをテストします。
次のコマンドは、出力に
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 backend-2 backend-2 backend backend backend-2 backend backend backend backend
TLS トラフィックの処理
Gateway リソースを更新し、証明書を設定し、TLS リスナーを追加して、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" }