前の記事 k8s-Service Mesh Practice-Istio の概要では、Istio をインストールしてデプロイする方法が紹介されており、Istio を使用して gRPC ロード バランシングを実装できます。 今日はさらに一歩進んで、Istio の機能の使い方について詳しく見ていきます。 Istio トラフィック モデルから、Istio はクラスターのイングレス リクエストとエグレス リクエスト (ゲートウェイ) の管理をサポートしているだけでなく、クラスター内のメッシュ トラフィック、つまりクラスター内のサービス間のリクエストの管理もサポートしていることがわかります。 今回は、まずクラスター内のリクエストについて説明し、以下の2つの機能を実装します。 - グレースケールリリース(指定されたリクエストを異なるサービスにルーティングする)
- サービスのリクエストの重みを設定する
グレースケールリリース開始前に、2 つのデプロイメントと 1 つのサービスがデプロイされます。同時に、これら 2 つのデプロイメントに関連付けられた Pod は、グレースケール中にグループ化されるため、2 つの異なるラベルに対応します。 この yaml を使用すると、必要なデプロイメントとサービスがデプロイされます。 kubectl apply -f https://raw.githubusercontent.com/crossoverJie/k8s-combat/main/deployment/istio-mesh.yaml まず、グレースケールのリリースが必要な場合を想像してみましょう。通常、主要機能のテストであり、内部テストにエントリーした一部のユーザーのみ入場可能です。 アプリを作成していると仮定すると、内部テスト パッケージを受け取ったユーザーのすべてのリクエスト ヘッダーにバージョン番号を追加できます。 たとえば、versinotallow=200 は新しいバージョンを示し、versinotallow=100 は古いバージョンを示します。同時に、このバージョン番号はサーバー上に出力され、リクエストが期待される Pod に入ったかどうかを区別します。 // Client version := r.URL.Query().Get("version") name := "world" ctx, cancel := context.WithTimeout(context.Background(), time.Second) md := metadata.New(map[string]string{ "version": version, }) ctx = metadata.NewOutgoingContext(ctx, md) defer cancel() g, err := c.SayHello(ctx, &pb.HelloRequest{Name: name}) // Server func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { md, ok := metadata.FromIncomingContext(ctx) var version string if ok { version = md.Get("version")[0] } log.Printf("Received: %v, version: %s", in.GetName(), version) name, _ := os.Hostname() return &pb.HelloReply{Message: fmt.Sprintf("hostname:%s, in:%s, version:%s", name, in.Name, version)}, nil } グループ化サービスグレースケール テストを実行する場合、多くの場合、v2 (上図の Pod2) と呼ばれる新しいグレースケール サービスをデプロイする必要があります。 同時に、v1 と v2 をグループ化する必要があります。 apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: k8s-combat-service-ds spec: host: k8s-combat-service-istio-mesh subsets: - name: v1 labels: app: k8s-combat-service-v1 - name: v2 labels: app: k8s-combat-service-v2 ここでは、Istio の DestinationRule を使用してサブセットを定義します。つまり、サービス下の Pod を v1/v2 に分割します。 ラベルアプリを使ってグループ化する
ここでのホスト: k8s-combat-service-istio-mesh は通常、サービス名で構成されます。 apiVersion: v1 kind: Service metadata: name: k8s-combat-service-istio-mesh spec: selector: appId: "12345" type: ClusterIP ports: - port: 8081 targetPort: 8081 name: app - name: grpc port: 50051 targetPort: 50051 これはサービスの名前です。ホストとしての構成もサポートされています: k8s-combat-service-istio-mesh.default.svc.cluster.local。略語が使用されている場合、Istio は現在指定されている名前空間に従ってそれを解決します。 Istio では、誤操作を避けるために、ここでは省略形ではなく完全修飾名を使用することをお勧めします。
もちろん、DestinationRule で負荷分散戦略を構成することもできますが、ここでは省略します。 apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: k8s-combat-service-ds spec: host: k8s-combat-service-istio-mesh trafficPolicy: loadBalancer: simple: ROUND_ROBIN そこで、次の 2 つのグループを定義しました。 - v1: アプリ: k8s-combat-service-v1
- v2: アプリ: k8s-combat-service-v2
その後、ルーティング ルールを構成して、トラフィックを 2 つの異なるグループに割り当てることができます。ここでは、構成に VirtualService を使用します。 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: k8s-combat-service-vs spec: gateways: - mesh hosts: - k8s-combat-service-istio-mesh # match this host http: - name: v1 match: - headers: version: exact: '100' route: - destination: host: k8s-combat-service-istio-mesh subset: v1 - name: v2 match: - headers: version: exact: '200' route: - destination: host: k8s-combat-service-istio-mesh subset: v2 - name: default route: - destination: host: k8s-combat-service-istio-mesh subset: v1 このルールはとてもシンプルです。 http プロトコル ヘッダーのバージョン フィールド値を検出します。 100 の場合は、subset=v1 グループ内の Pod にルーティングされます。同様に、200 の場合は、subset=v2 グループ内の Pod にルーティングされます。 一致するヘッダーがない場合、デフォルトのサブセット: v1が入力されます gRPC も http プロトコルに基づいており、そのメタデータは http プロトコルのヘッダーに対応します。
ヘッダー=100 Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=100" Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=100" Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=100" Greeting: hostname:k8s-combat-service-v1-5b998dc8c8-hkb72, in:world, version:100istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=100" ヘッダー=200 Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" 上記のテスト リクエストによれば、リクエスト ヘッダーに指定されたバージョンが含まれている限り、指定された Pod にルーティングされます。 この機能を使用すると、グレースケール検証中に Deployment のグレースケール バージョンを別途送信し、クライアントが指定したバージョンと組み合わせてグレースケール機能を実装できます。 重みの設定VirtualService に基づいて、異なるサブセット グループの重みを構成することもできます。 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: k8s-combat-service-vs spec: gateways: - mesh hosts: - k8s-combat-service-istio-mesh # match this host http: - match: - uri: exact: /helloworld.Greeter/SayHello route: - destination: host: k8s-combat-service-istio-mesh subset: v1 weight: 10 - destination: host: k8s-combat-service-istio-mesh subset: v2 weight: 90 timeout: 5000ms ここで説明されているのは、SayHello インターフェースの重み設定です (もちろん、一致するルールは複数あります)。トラフィックの 90% は v2 サブセット、つまり k8s-combat-service-istio-mesh サービスの下にあるアプリ: k8s-combat-service-v2 Pod に入ります。 Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-**v1**-5b998dc8c8-hkb72, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ curl "http://127.0.0.1:8081/grpc_client?name=k8s-combat-service-istio-mesh&versinotallow=200" Greeting: hostname:k8s-combat-service-v2-5db566fb76-xj7j6, in:world, version:200istio-proxy@k8s-combat-service-v1-5b998dc8c8-hkb72:/$ テストの結果、ほとんどのリクエストは予想どおり v2 グループに入ることがわかりました。 もちろん、次のこともできます。 - タイムアウト
- フォールト注入
- 再試行の詳細な設定については、Istio の公式ドキュメントを参照してください。
- もちろん、一部のクラウド プラットフォームでは、より直感的に使用できるビジュアル ページも提供されています。
上記はAlibaba Cloudのスクリーンショットです
しかし、管理するリソースは主にKubernetesであり、通常は運用やDevOpsによって構成されるため、開発や使用には不便です。したがって、クラウド ベンダーと開発者の間で、開発者がプロジェクトの次元でこれらの機能を管理および保守できるようにする管理およびリリース プラットフォームが必要です。 この記事のすべてのソースコードは、https://github.com/crossoverJie/k8s-combat からアクセスできます。 |