DUICUO

Istio は Gateway API を使用してトラフィック管理を実装します。

Gateway APIは、SIG-NETWORKコミュニティが管理するオープンソースプロジェクトであり、https://gateway-api.sigs.k8s.io/ から利用可能です。開発の主な理由は、Ingressリソースオブジェクトがネットワーク要件を十分に満たせないことです。多くのシナリオにおいて、IngressコントローラーはアノテーションやCRDを定義して拡張する必要があり、これは標準的な使用方法やサポートに悪影響を及ぼします。新たにリリースされたGateway APIは、拡張可能なロール指向インターフェースを通じてサービスネットワーキングを強化することを目的としています。

Gateway API は、GatewayClass、Gateway、HTTPRoute、TCPRoute、Service などを含む Kubernetes の API リソースのコレクションです。これらのリソースは連携して、さまざまなネットワーク ユース ケースのモデルを構築します。

ゲートウェイAPI

Gateway APIは当初、外部クライアントからクラスタ内のサービスへのトラフィック(IngressまたはNorth/Southシナリオ)を管理するために設計されました。その後、サービスメッシュユーザーからの関心が高まり、同一クラスタ内のサービス間トラフィックやEast/WestトラフィックにGateway APIをどのように活用できるかを定義するGAMMA(Gateway API for Service Mesh)イニシアチブが設立されました。

Gateway API の改善により、現在の Ingress リソース オブジェクトよりも優れた設計機能が数多く追加されました。

  • ロール指向ゲートウェイは、Kubernetes サービス ネットワークで使用および構成されるロールに応じてモデル化されたさまざまな API リソースで構成されます。
  • 普遍性 - Ingressと同様に、Gateway APIは多数の実装を持つユニバーサル仕様です。多くの実装でサポートされるように設計された仕様標準です。
  • より表現力豊かに - Gateway API リソースは、ヘッダーベースのマッチングやトラフィックの重み付けなどのコア機能をサポートします。これらは、Ingress ではカスタム アノテーションを通じてのみ実現できます。
  • スケーラビリティ - ゲートウェイ API を使用すると、カスタム リソースを API のさまざまなレイヤーにリンクできるため、API 構造の適切なポイントでよりきめ細かなカスタマイズが可能になります。

他にも注目すべき機能がいくつかあります。

  • GatewayClasses は、負荷分散実装の種類を形式化し、Kubernetes リソースを通じて利用できる機能をユーザーが簡単に理解できるようにします。
  • 共有ゲートウェイとクロスネームスペースのサポート - これにより、ロードバランサとVIPを共有し、独立したルーティングリソースを同じゲートウェイにバインドできるようになります。これにより、チームは直接的な調整を必要とせずに、インフラストラクチャ(複数のネームスペース間を含む)を安全に共有できます。
  • 標準化されたルーティングとバックエンド - Gateway API は、型付きルーティング リソースとさまざまな種類のバックエンドをサポートしているため、API はさまざまなプロトコル (HTTP や gRPC など) とさまざまなバックエンド サービス (Kubernetes サービス、バケット、関数など) を柔軟にサポートできます。
  • サービス メッシュのサポート - ゲートウェイ API は、ルーティング リソースをサービス リソースに関連付けて、サービス メッシュとイングレス コントローラーを構成することをサポートします。

キャラクター重視のデザイン

道路、電力、データセンター、Kubernetesクラスターなど、インフラは共有のために構築されています。しかし、共有インフラには共通の課題があります。それは、インフラ利用者に柔軟性を提供しつつ、所有者のコントロールを維持することです。

Gateway APIは、Kubernetesサービスネットワークにロール指向の設計を採用することでこれを実現し、柔軟性と集中管理のバランスをとっています。これにより、共有ネットワークインフラストラクチャ(ハードウェアロードバランサー、クラウドネットワーク、クラスターホスト型エージェントなど)を、クラスター運用によって設定された様々なポリシーと制約に従いながら、複数の異なるチームで利用できるようになります。

ゲートウェイAPIデモ

クラスタ運用エンジニアは、GatewayClassに基づいてGatewayリソースを作成します。このGatewayは、それが表す基盤となるネットワークリソースで構成されます。クラスタ運用チームと各チームは、アプリケーションを公開するために、このGatewayに何を接続できるかについて話し合う必要があります。TLSなどの集中管理されたポリシーは、クラスタ運用チームがGatewayに適用できます。一方、ストアアプリケーションとサイトアプリケーションはそれぞれ独自の名前空間で実行されますが、ルートは同じ共有ゲートウェイに接続されるため、ルーティングロジックを個別に制御できます。

この関心の分離設計により、集中戦略と制御をクラスター操作に任せながら、さまざまなチームが独自のトラフィックを管理できます。

コンセプト

ゲートウェイAPIには、インフラストラクチャプロバイダー、クラスタ管理者、アプリケーション開発者の3つの役割が関係します。シナリオによっては、アプリケーション管理者も関与する場合があります。ゲートウェイAPIは、GatewayClass、Gateway、およびRouteという3つの主要なリソースモデルを定義します。

ゲートウェイクラス

GatewayClassは、同じ設定とアクションを共有するゲートウェイのセットを定義します。各GatewayClassはコントローラーによって処理され、クラスター全体のリソースであるため、少なくとも1つのGatewayClassを定義する必要があります。

これはIngressのIngressClassに似ています。Ingress v1beta1では、ingress-classアノテーションはGatewayClassに似ていましたが、Ingress V1では最も近いのはIngressClassリソースオブジェクトです。

ゲートウェイ

ゲートウェイは、トラフィックがクラスター内のサービスにどのように変換されるかを記述します。言い換えれば、Kubernetes に関連しないソースからのトラフィックをクラスター内のサービスにリダイレクトするリクエストを定義します。これには、クラウドロードバランサー、クラスター内プロキシ、または外部ハードウェアロードバランサーから Kubernetes サービス宛てのトラフィックが含まれます。

これは、GatewayClassの設定と動作仕様を実装する特定のロードバランサー設定へのリクエストを定義します。このリソースは、管理者が直接作成することも、GatewayClassを処理するコントローラーによって作成することもできます。

ゲートウェイは 1 つ以上のルート参照に接続することができ、これによりトラフィックのサブセットが特定のサービスに誘導されます。

ルートリソース

ルートリソースは、ゲートウェイからのリクエストをKubernetesサービスにマッピングするための特定のルールを定義します。バージョンv1alpha2以降、APIには4種類のルートリソースが含まれています。

HTTPルート

HTTPRoute は、HTTP または HTTPS 接続に使用され、ルーティングに HTTP ヘッダーを使用したり、リクエスト処理中に HTTP ヘッダーを変更したりするなど、HTTP リクエストを検査してルーティングまたは変更するシナリオに適しています。

TLSルート

TLSRouteはTLS接続に使用され、SNIによって区別されます。SNIを主要なルーティング方法として使用し、HTTPなどの上位プロトコルの特性を気にしない場所に適しています。接続のバイトストリームは、検査なしでバックエンドにプロキシされます。

TCPルートとUDPRoute

TCPRoute(およびUDPRoute)は、1つまたは複数のポートを単一のバックエンドにマッピングするように設計されています。この場合、同じポートに対して異なるバックエンドを選択するための識別子がないため、各TCPRouteはリスナー上で異なるポートを必要とします。TLSを使用する場合は、暗号化されていないバイトストリームがバックエンドに配信されます。TLSを使用しない場合は、暗号化されたバイトストリームがバックエンドに配信されます。

GRPCRoute

GRPCRoute は gRPC トラフィックのルーティングに使用されます。GRPCRoute をサポートするゲートウェイは HTTP/2 をサポートしている必要があります。HTTP/1 からの初期アップグレードは不要であるため、gRPC トラフィックは正常に処理されます。

組み合わせ

GatewayClass、Gateway、xRoute、Serviceの組み合わせにより、実装可能なロードバランサーが定義されます。次の図は、さまざまなリソース間の関係を示しています。

組み合わせ関係

リバース プロキシを使用して実装されたゲートウェイの一般的なクライアント/ゲートウェイ API 要求フローを以下に示します。

  • クライアントは http://foo.example.com にリクエストを送信します。
  • DNS はドメイン名をゲートウェイ アドレスに解決します。
  • リバース プロキシはリスナーでリクエストを受信し、ホスト ヘッダーを使用して HTTPRoute と一致させます。
  • (オプション) リバース プロキシは、HTTPRoute 一致ルールに従ってルーティングできます。
  • (オプション) リバース プロキシは、HTTPRoute のフィルタリング ルールに基づいてリクエストを変更できます (つまり、ヘッダーを追加または削除します)。
  • 最後に、リバース プロキシは、HTTPRoute の forwardTo ルールに従って、クラスター内の 1 つ以上のオブジェクト (サービス) に要求を転送します。

Istio APIとの違い

このセクションでは、主にサービスメッシュにおけるGateway APIの使用について説明します。まず、Gateway APIとIstio APIの違いを理解しましょう。

Gateway APIは、GatewayやVirtualServiceなどのIstio APIと多くの類似点を持っています。メインリソースは同じGateway名を使用し、同様の目的で使用されます。

新しいGateway APIは、Istioを含む様々なKubernetes Ingress実装の経験を活かし、標準化されたベンダー非依存のAPIを構築することを目的としています。これらのAPIは、Istio GatewayやVirtualServiceと基本的に同じ目的を果たしますが、いくつかの違いもあります。

  • Istio API のゲートウェイは、既存のデプロイ済みのゲートウェイ デプロイメント/サービスのみを構成しますが、ゲートウェイ API のゲートウェイ リソースはゲートウェイを構成するだけでなく、デプロイも行います。
  • Istio VirtualService では、すべてのプロトコルが単一のリソースで構成されますが、Gateway API では、HTTPRoute や TCPRoute など、プロトコル タイプごとに独自のリソースがあります。
  • Gateway API は豊富なルーティング機能を提供しますが、Istio のすべての機能をカバーしているわけではありません。

成し遂げる

次に、Istio zでGateway APIを使用する方法を学びます。Gateway APIはKubernetesクラスターにデフォルトでインストールされていないため、まずGateway API CRDをインストールする必要があります。

 $ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created

`standard-install.yaml` ファイルには、GatewayClass、Gateway、HTTPRoute、ReferenceGrant など、GA またはベータ版にアップグレードされたすべてのリソースが含まれています。Istio はすでに Gateway API をサポートしているため、直接使用できます。例えば、以下に示すように、`istio` GatewayClass リソースオブジェクトが自動的に作成されます(`istio-remote` という名前のオブジェクトも存在します)。

 $ kubectl get gatewayclass NAME CONTROLLER ACCEPTED AGE istio istio.io/gateway-controller True 106s istio-remote istio.io/unmanaged-gateway True 106s $ kubectl get gatewayclass istio -oyaml apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: istio spec: controllerName: istio.io/gateway-controller description: The default Istio GatewayClass

ほとんどのシナリオではIstioクラスターは1つだけなので、デフォルトのistio GatewayClassを直接使用できます。複数のIstioクラスターがある場合は、複数のGatewayClassを作成して、異なるクラスターを区別することができます。

例えば、Gateway APIを使ってhttpbinアプリケーションを外部に公開してみましょう。まず、httpbinアプリケーションをデプロイする必要があります。

 kubectl apply -f samples/httpbin/httpbin.yaml

次に、次に示すように、外部ロードバランサからクラスタ内のサービスにトラフィックを転送するための Gateway リソース オブジェクトもデプロイする必要があります。

 # default-gateway.yaml apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway namespace: istio-ingress # 网关资源对象所在的命名空间spec: gatewayClassName: istio # 使用默认的istio GatewayClass listeners: # 监听器- name: default hostname: "*.example.com" port: 80 protocol: HTTP allowedRoutes: # 允许的路由namespaces: from: All # 允许所有命名空间

ゲートウェイは論理ロードバランサーのインスタンス化を表します。Istio GatewayClassに基づいてテンプレート化されています。ゲートウェイはポート80でHTTPトラフィックをリッスンします。このGatewayClassには、デプロイ後に自動的にIPアドレスが割り当てられ、Gateway.statusに表示されます。

使用している名前空間を istio-ingress として宣言している点に注意してください。これは、Istio Gateway が、デフォルトで istio-system 名前空間にデプロイされている Istio Ingress Gateway Deployment を直接使用できるためです。istio-ingress 名前空間に Gateway リソースオブジェクトを別途作成すると、デフォルトの Istio Ingress Gateway と区別するために、この名前空間にゲートウェイコントローラーが自動的にデプロイされます。

したがって、Istio Ingress Gateway が Gateway リソース オブジェクトを通じて構成を取得できるように、istio-ingress 名前空間にこの Gateway リソース オブジェクトを作成する必要があります。

 kubectl create namespace istio-ingress

次に、このリソース オブジェクトを直接適用できます。

 $ kubectl apply -f default-gateway.yaml $ kubectl get gateway -n istio-ingress NAME CLASS ADDRESS PROGRAMMED AGE gateway istio False 8m23s $ kubectl get deploy -n istio-ingress NAME READY UP-TO-DATE AVAILABLE AGE gateway-istio 1/1 1 1 8m35s $ kubectl get svc -n istio-ingress NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gateway-istio LoadBalancer 10.100.103.86 <pending> 15021:31509/TCP,80:32530/TCP 9m38s

また、上記で生成したgateway-istio を Istio のデフォルトの istio-ingressgateway デプロイメントと比較することもできます。それらの構成はほぼ同じです。

次に、VirtualServiceと同様に、httpbinアプリケーションへのアクセス方法を定義するルーティングルールを作成する必要があります。このルーティングルールは、以下に示すように、HTTPRouteリソースオブジェクトを使用して定義できます。

 # httpbin-route.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin namespace: default spec: parentRefs: # 引用定义的Gateway 对象- name: gateway namespace: istio-ingress hostnames: ["httpbin.example.com"] # 域名rules: # 具体的路由规则- matches: - path: type: PathPrefix value: /get # 匹配/get 的请求backendRefs: # 引用的后端服务- name: httpbin port: 8000

上記のHTTPRouteオブジェクトでは、parentRefsフィールドで接続先のゲートウェイを指定しています。これにより、ゲートウェイが接続を許可している場合、ルートは親ゲートウェイからのトラフィックを受信できるようになります。backendRefsフィールドは、トラフィックを送信するバックエンドを定義します。ただし、ここでは/getパスに一致するリクエストのみを定義し、ホスト名でアクセスするドメイン名を定義している点に注意してください。

リソース オブジェクトを直接使用することもできます。

 $ kubectl apply -f httpbin-route.yaml $ kubectl get httproute NAME HOSTNAMES AGE httpbin ["httpbin.example.com"] 5s

次に、httpbin.example.com 経由で httpbin アプリケーションにアクセスします。

 # $ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsnotallow='{.status.addresses[0].value}') export GATEWAY_URL=$(kubectl get po -l istio.io/gateway-name=gateway -n istio-ingress -o 'jsnotallow={.items[0].status.hostIP}'):$(kubectl get svc gateway-istio -n istio-ingress -o 'jsnotallow={.spec.ports[?(@.name=="default")].nodePort}')

クラスターがLoadBalancerを正常に使用できる場合、デプロイ後にゲートウェイコントローラーにIPアドレスが自動的に割り当てられ、Gateway.statusに表示されます。ここではこの機能をサポートしていないため、NodePort経由でアクセスすることは可能です。その後、curlコマンドを使用してhttpbinサービスにアクセスできます。

 $ curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/get" HTTP/1.1 200 OK server: istio-envoy date: Mon, 18 Dec 2023 07:29:11 GMT content-type: application/json content-length: 494 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 2

-H フラグを使用すると、Host HTTP ヘッダーが httpbin.example.com に設定されることに注意してください。HTTPRoute は httpbin.example.com へのリクエストを処理するように設定されているため、この手順は必須です。ただし、テスト環境ではこのホストには DNS バインディングがなく、リクエストは単に入力 IP に送信されます。

明示的に公開されていない他の URL にアクセスすると、通常は HTTP 404 エラーが表示されます。

 $ curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST/headers" HTTP/1.1 404 Not Found date: Mon, 18 Dec 2023 07:31:51 GMT server: istio-envoy transfer-encoding: chunked

同様に、gateway-istio ログを確認すると、次のようなログが表示されます。

 $ kubectl -n istio-ingress logs -f gateway-istio-7474cd4d9b-8dw2k # ...... 2023-12-18T07:04:33.164968Z info cache returned workload trust anchor from cache ttl=23h59m59.835033638s 2023-12-18T07:04:33.621616Z info Readiness succeeded in 813.201909ms 2023-12-18T07:04:33.621946Z info Envoy proxy is ready [2023-12-18T07:29:11.177Z] "HEAD /get HTTP/1.1" 200 - via_upstream - "-" 0 0 2 2 "10.244.1.1" "curl/7.29.0" "68f51e89-8125-4d9e-be36-e0cdc6e6ead8" "httpbin.example.com" "10.244.1.131:80" outbound|8000||httpbin.default.svc.cluster.local 10.244.1.132:46066 10.244.1.132:80 10.244.1.1:55626 - default.httpbin.0 [2023-12-18T07:31:52.051Z] "HEAD /headers HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "10.244.1.1" "curl/7.29.0" "a9a1002f-d65c-40d8-861d-ec99d4a4a442" "httpbin.example.com" "-" - - 10.244.1.132:80 10.244.1.1:53583 - -

これは、ルーティング ルールが有効になったことを証明します。

同様に、`/headers` ルートに正しくアクセスできるようにするには、`HTTPRoute` オブジェクトを更新します。

 # httpbin-route.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin namespace: default spec: parentRefs: # 引用定义的Gateway 对象- name: gateway namespace: istio-ingress hostnames: ["httpbin.example.com"] # 域名rules: # 具体的路由规则- matches: - path: type: PathPrefix value: /get # 匹配/get 的请求- path: type: PathPrefix value: /headers # 匹配/headers 的请求filters: - type: RequestHeaderModifier # 添加一个修改请求头的过滤器requestHeaderModifier: add: # 添加一个标头- name: my-added-header value: added-value backendRefs: # 引用的后端服务- name: httpbin port: 8000

ルールに「/headers」に一致するルールを追加しただけでなく、「RequestHeaderModifier」フィルターを追加してヘッダーメッセージを追加しました。リソースオブジェクトを更新し、「/headers」に再度アクセスすると、リクエストに「My-Added-Header」ヘッダーが追加されていることが分かりました。

 $ curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/headers" { "headers": { "Accept": "*/*", "Host": "httpbin.example.com", "My-Added-Header": "added-value", # 添加了一个Header头"User-Agent": "curl/7.29.0", "X-Envoy-Attempt-Count": "1", "X-Envoy-Internal": "true", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=11fc66a1c6c9fc44e65ec67f7f8b16d06fbaa73d9729e141e0bd91134dc59db3;Subject=\"\";URI=spiffe://cluster.local/ns/istio-ingress/sa/gateway-istio" } }

上記の例では、ゲートウェイを構成する前にIngressゲートウェイのデプロイメントをインストールしませんでした。これは、デフォルト構成ではゲートウェイの構成に基づいてゲートウェイのデプロイメントとサービスが自動的に配布されるためです。ただし、より高度なシナリオでは、手動によるデプロイメントが必要になる場合があります。

自動展開

デフォルトでは、各ゲートウェイは同じ名前のサービスとデプロイメントを自動的に提供します。ゲートウェイが変更された場合(例:新しいポートが追加された場合)、これらの設定は自動的に更新されます。これらのリソースは、いくつかの方法で定義できます。

  • ゲートウェイからサービスとデプロイメントにアノテーションとタグをコピーします。これにより、内部ロードバランサーの設定など、上記のフィールドから読み取った内容を設定できます。Istioは、生成されたリソースを設定するための追加のアノテーションを提供します。
  • networking.istio.io/service-type: Service.spec.type フィールドを制御します。例えば、ClusterIP を設定してサービスを外部に公開しないようにすると、デフォルトで LoadBalancer が使用されます。
  • Service.spec.loadBalancerIP フィールドは、アドレス フィールドを構成することによって明示的に設定できます。
 apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: gateway spec: addresses: - value: 192.0.2.0 # 仅能指定一个地址type: IPAddress

手動展開

自動デプロイメントを使用しない場合は、デプロイメントとサービスを手動で設定できます。このオプションの設定が完了したら、ゲートウェイをサービスに手動でリンクし、ポート設定を同期させる必要があります。

ゲートウェイをサービスにリンクするには、アドレス フィールドを単一のホスト名を指すように構成する必要があります。

 apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: gateway spec: addresses: - value: ingress.istio-gateways.svc.cluster.local type: Hostname

もちろん、これは非常に単純な例に過ぎません。Gateway APIのその他の機能については、今後のレッスンで詳しくご紹介していきます。

リクエストルーティングを構成する

次に、Gateway API を使用して、マイクロサービスの複数のバージョンにリクエストを動的にルーティングする方法を学びましょう。

同様に、Bookinfo の例 (Bookinfo アプリケーションを最初にデプロイする必要があります) を使用すると、最初にすべてのトラフィックがマイクロサービス v1 (バージョン 1) にルーティングされ、次にアプリケーション ルールによって HTTP リクエスト ヘッダーの値に基づいてトラフィックがルーティングされます。

まず、以下に示すように、Bookinfo アプリケーション専用の Gateway リソース オブジェクトを作成します。

 # bookinfo-gateway.yaml apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: bookinfo-gateway spec: gatewayClassName: istio listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: Same

上記の Gateway リソース オブジェクトは前の例と似ていますが、ここでは allowedRoutes を Same に設定しています。つまり、同じ名前空間内のすべてのルート リソース オブジェクトがこのゲートウェイに接続できるようになります。

次に、次に示すように、Productpage アプリケーションの HTTPRoute リソース オブジェクトを作成します。

 # productpage-route.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: bookinfo spec: parentRefs: - name: bookinfo-gateway # 引用上面定义的Gateway 对象rules: - matches: - path: type: Exact value: /productpage - path: type: PathPrefix value: /static - path: type: Exact value: /login - path: type: Exact value: /logout - path: type: PathPrefix value: /api/v1/products backendRefs: - name: productpage # 引用的后端服务port: 9080

前回のVirtualServiceと同様に、Productpageアプリケーションにいくつかのルーティングルールを設定し、ページ上でアプリケーションに通常通りアクセスできるようにしました。上記の2つのリソースマニフェストファイルを適用するだけです。

 kubectl apply -f bookinfo-gateway.yaml kubectl apply -f productpage-route.yaml

同様に、Gateway オブジェクトを作成すると、gateway-istio デプロイメントとそれに対応するサービスがデフォルトの名前空間に自動的にデプロイされます。

 $ kubectl get pods -l istio.io/gateway-name=bookinfo-gateway NAME READY STATUS RESTARTS AGE bookinfo-gateway-istio-548556df95-kggs2 1/1 Running 0 112s $ kubectl get svc bookinfo-gateway-istio NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE bookinfo-gateway-istio LoadBalancer 10.111.86.147 <pending> 15021:30357/TCP,80:30749/TCP 2m19s

通常、上記の NodePort 30749 を介して Productpage アプリケーションにアクセスできます。

書籍情報

バージョン1へのルーティング

同じページのコメントエリアには、3つの異なるバージョンのコメントサービスが稼働しているため、3つの異なる状態が表示されます。まずトラフィックをバージョンv1にルーティングするために、以下のようにHTTPRouteリソースオブジェクトを作成します。

 # route-reviews-v1.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reviews spec: parentRefs: # 这里我们引用的是reviews 这个Service 对象- group: "" kind: Service name: reviews port: 9080 rules: - backendRefs: - name: reviews-v1 port: 9080

上記のリソースオブジェクトでは、Gatewayオブジェクトではなく、`parentRefs`フィールドを介して`reviews`サービスオブジェクトを参照していることに注意してください。これは、トラフィックがGatewayから直接ではなく、Productpageを介してレビューサービス(サービスオブジェクト)にアクセスしているためです。その後、すべてのトラフィックをレビューサービスのv1バージョンである`reviews-v1`にルーティングします。

ここで、上記のリソース オブジェクトを再度適用してみましょう。

 kubectl apply -f route-reviews-v1.yaml

ただし、DestinationRules のサブセットを使用してサービスバージョンを定義する Istio API とは異なり、Kubernetes Gateway API ではバックエンドサービスを使用してサービスバージョンを定義する点に注意してください。そのため、reviews サービスの 3 つのバージョンに対応するバックエンドサービス定義を作成するには、以下のコマンドを実行する必要があります。

 kubectl apply -f samples/bookinfo/platform/kube/bookinfo-versions.yaml

Bookinfoアプリを再度更新します。これで、何度更新しても、ページのコメントセクションに評価の星が表示されなくなります。これは、コメントサービスからのすべてのトラフィックを、星評価サービスにアクセスしないバージョンreviews:v1にルーティングするようにIstioを設定しているためです。

レビュー v1

ユーザーIDベースのルーティング

次に、特定のユーザーからのすべてのトラフィックを特定のサービスバージョンにルーティングするようにルーティング設定を変更します。例えば、Jasonというユーザーからのすべてのトラフィックは、サービスreviews:v2(星評価機能を含むバージョン)にルーティングされます。

以下に示すように、HTTPRoute リソース オブジェクトを作成します。

 # route-reviews-jason-v2.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reviews spec: parentRefs: - group: "" kind: Service name: reviews port: 9080 rules: - matches: - headers: # 匹配请求头end-user: jason - name: end-user value: jason backendRefs: - name: reviews-v2 port: 9080 - backendRefs: - name: reviews-v1 port: 9080

上記のHTTPRouteリソースオブジェクトでは、reviewsへのトラフィックを2つのルールに分割しています。最初のルールは、リクエストヘッダー end-user: jason に一致し、トラフィックをreviews-v2サービスにルーティングします。2つ目のルールは、一致しない場合はトラフィックをreviews-v1サービスにルーティングします。

次に、このリソース オブジェクトを再度適用します。

 kubectl apply -f route-reviews-jason-v2.yaml

次に、Bookinfoページでユーザーjasonとしてログインします。ログイン後は、ブラウザを何度更新しても、ページに黒い星の評価が表示されます。これはレビューのv2バージョンです。

ジェイソンは

別のユーザー アカウントに切り替えたり、ログインせずにブラウザを更新したりすると、星評価は表示されなくなります。

重み付けルーティング

次に、重み付けベースのルーティングをテストしてみましょう。マイクロサービスのあるバージョンから別のバージョンへトラフィックを段階的に移行する必要があることがよくありますが、Gateway APIを使えば非常に簡単に移行できます。

次に、トラフィックの50%をreviews:v1に、残りの50%をreviews:v3に送信します。その後、トラフィックの100%をreviews:v3に送信して移行を完了します。

まず、次のコマンドを再実行して、すべてのトラフィックをレビュー サービスのバージョン v1 にルーティングします。

 kubectl apply -f route-reviews-v1.yaml

次に、トラフィックの 50% を reviews:v1 から reviews:v3 に転送するための、以下に示すリソース オブジェクトを作成します。

 # route-reviews-50-v3.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reviews spec: parentRefs: - group: "" kind: Service name: reviews port: 9080 rules: - backendRefs: - name: reviews-v1 port: 9080 weight: 50 - name: reviews-v3 port: 9080 weight: 50

上記のオブジェクトでは、backendRefs の weight フィールドを使用して重みを設定しました。ここでは、reviews-v1 と reviews-v3 の重みを 50 に設定しています。これは、トラフィックがこれら 2 つのサービス バージョンに均等に分散されることを意味します。

次に、このリソース オブジェクトを使用できます。

 kubectl apply -f route-reviews-50-v3.yaml

新しいルールがプロキシに反映されるまで数秒お待ちください。その後、ブラウザで商品ページを更新してください。ページに赤い星が付いたレビューが表示される確率は約50%です。これは、レビューバージョン3は星付きレビューにアクセスできますが、バージョン1はアクセスできないためです。

reviews:v3 マイクロサービスが安定していると思われる場合は、トラフィックの 100% を reviews:v3 にルーティングできるようになりました。

 # route-reviews-v3.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reviews spec: parentRefs: - group: "" kind: Service name: reviews port: 9080 rules: - backendRefs: - name: reviews-v3 port: 9080

次に、このリソース オブジェクトを再度適用します。

 kubectl apply -f route-reviews-v3.yaml

これで、Bookinfo アプリにアクセスすると、赤い星の評価が付いた書籍レビューが常に表示されます。

TLSを使用してサービスを公開する

次に、TLS経由でサービスを公開する方法を見てみましょう。ここでは、httpbinの例を使って説明します。

まず、httpbin の例をデプロイします。

 kubectl apply -f samples/httpbin/httpbin.yaml

次に、openssl ツールを使用してクライアントとサーバーの証明書とキーを生成します。

まず、サービス署名用のルート証明書と秘密キーを作成します。

 $ mkdir example_certs1 $ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs1/example.com.key -out example_certs1/example.com.crt

httpbin.example.com の証明書と秘密鍵を作成します。

 $ openssl req -out example_certs1/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization" $ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 0 -in example_certs1/httpbin.example.com.csr -out example_certs1/httpbin.example.com.crt

次のステップは、Ingress ゲートウェイの Secret を作成することです。

 kubectl create -n istio-system secret tls httpbin-credential \ --key=example_certs1/httpbin.example.com.key \ --cert=example_certs1/httpbin.example.com.crt

ここでは、スタンドアロンの Kubernetes ゲートウェイを作成します。

 # httpbin-gateway.yaml apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: mygateway namespace: istio-system spec: gatewayClassName: istio listeners: - name: https hostname: "httpbin.example.com" port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: httpbin-credential allowedRoutes: namespaces: from: Selector selector: matchLabels: kubernetes.io/metadata.name: default

上記のオブジェクトでは、HTTPSプロトコルを設定し、TLSをTerminateモードに設定しました。これは、ゲートウェイでTLS接続を終了することを意味します。次に、`certificateRefs`で、以前に作成したSecretオブジェクトを参照してゲートウェイの認証情報を設定しました。最後に、`allowedRoutes`フィールドを使用して許可されたルートを設定しました。ここでは、`default`名前空間内のすべてのルートリソースオブジェクトにトラフィックをルーティングするように設定しました。

次に、対応する HTTPRoute を定義して、ゲートウェイの受信トラフィック ルーティングを構成します。

 # httpbin-route.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin spec: parentRefs: - name: mygateway namespace: istio-system hostnames: ["httpbin.example.com"] rules: - matches: - path: type: PathPrefix value: /status - path: type: PathPrefix value: /delay backendRefs: - name: httpbin port: 8000

ここで最も重要なことは、parentRefs フィールドが以前に作成された Gateway オブジェクトを参照することです。

次に、上記の 2 つのリソース オブジェクトを直接適用できます。

 kubectl apply -f httpbin-gateway.yaml kubectl apply -f httpbin-route.yaml

同様に、適用後、gateway-istio デプロイメントと対応するサービスが istio-system 名前空間に自動的にデプロイされます。

 $ kubectl get pods -n istio-system NAME READY STATUS RESTARTS AGE mygateway-istio-64676bfc88-q8nft 1/1 Running 0 32s $ kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mygateway-istio LoadBalancer 10.111.175.36 <pending> 15021:31206/TCP,443:32597/TCP 74s

次に、NodePort 32597 を介して httpbin サービスに HTTPS リクエストを送信できます。

 $ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:32597:192.168.0.100" --cacert example_certs1/example.com.crt "https://httpbin.example.com:32597/status/418" * Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: example_certs1/example.com.crt CApath: none * SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * Server certificate: * subject: O=httpbin organization,CN=httpbin.example.com * start date: Dec 22 07:13:47 2023 GMT * expire date: Dec 21 07:13:47 2024 GMT * common name: httpbin.example.com * issuer: CN=example.com,O=example Inc. # ...... -=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""` * Connection #0 to host httpbin.example.com left intact

通常、ティーポット出力が表示されるはずです。これは、TLS 経由でサービスが正常に公開されたことを意味します。

TCPルーティング

Gateway APIは、HTTPルーティングに加えて、TCPおよびUDPルーティングもサポートしています。TCPルーティングルールを設定するには、別のリソースオブジェクトを使用する必要があります。   TCPRoute以下のようになります。

 apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: tcp-echo-gateway spec: gatewayClassName: istio listeners: - name: tcp-31400 protocol: TCP port: 31400 allowedRoutes: # 只允许TCPRoute 资源对象连接到这个网关kinds: - kind: TCPRoute --- apiVersion: v1 kind: Service metadata: name: tcp-echo-v1 spec: ports: - port: 9000 name: tcp selector: app: tcp-echo version: v1 --- apiVersion: v1 kind: Service metadata: name: tcp-echo-v2 spec: ports: - port: 9000 name: tcp selector: app: tcp-echo version: v2 --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute # TCPRoute 资源对象metadata: name: tcp-echo spec: parentRefs: # 引用定义的Gateway 对象- name: tcp-echo-gateway sectionName: tcp-31400 rules: - backendRefs: - name: tcp-echo-v1 port: 9000 weight: 80 - name: tcp-echo-v2 port: 9000 weight: 20

その他の用途

フォールト インジェクションやサーキット ブレーキングなどのその他のトラフィック管理機能は、Gateway API ではまだサポートされていません。

ただし、リクエストのタイムアウトはサポートされています。例えば、レビューサービスの呼び出しに0.5秒のタイムアウトを追加するには、次のリソースオブジェクトを使用します。

 apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reviews spec: parentRefs: - group: "" kind: Service name: reviews port: 9080 rules: - backendRefs: - name: reviews-v2 port: 9080 timeouts: request: 500ms

リクエストのタイムアウト期間を設定するために、上記のオブジェクトに timeouts フィールドを追加しました。

次のリソース オブジェクトでは、トラフィック ミラーリングもサポートされています。

 apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin spec: parentRefs: - group: "" kind: Service name: httpbin port: 8000 rules: - filters: - type: RequestMirror requestMirror: backendRef: name: httpbin-v2 port: 80 backendRefs: - name: httpbin-v1 port: 80

在上面的资源对象中我们添加了一个 RequestMirror 过滤器,该过滤器用于将流量镜像到另外的服务上去。