概要
の中でconfig.route.v3.RouteActionに重み付き負荷分散(weighted load balancing)の設定がありました。
これを利用することで
- カナリアリリース
- リクエストのサンプリング
- 一部だけ詳細なログやstatsを出す
- Mountebankのようなリクエストをレコードしてリプレイできるモックサーバに流す
といったことが容易に実現できます。
今回はこの機能を試してみます。
環境
- v1.24.0
Weighted load balancing
設定
Listener
設定は簡単で、weighted_clusters.clusters
に対象とするclusterとリクエストを振り分けする重みの設定を行うだけです。
以前はtotal_weight
で重みの合計を指定する必要がありましたが、現在はdeprecatedとなり自動で行ってくれます。
route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - name: default match: { prefix: "/" } route: weighted_clusters: clusters: - name: base weight: 80 - name: canary weight: 20 timeout: 30s
今回は8:2でリクエストを分散するようにしています。
Cluster
今回は簡単のためclusterの名前は別ですが中身のエンドポイントは同じになってます。
実際のカナリアリリースではエンドポイントをカナリア用のサーバに向けます。
clusters: - name: base connect_timeout: 1s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: base endpoints: - lb_endpoints: - endpoint: address: socket_address: address: httpbin.org port_value: 80 - name: canary connect_timeout: 1s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: canary endpoints: - lb_endpoints: - endpoint: address: socket_address: address: httpbin.org port_value: 80
動作検証
k6を用いて10rpsを定常的にかけてみます。
import http from "k6/http"; import { check } from "k6"; export const options = { scenarios: { open_model: { executor: "constant-arrival-rate", rate: 10, timeUnit: "1s", duration: "2m", preAllocatedVUs: 20, }, }, }; export default function () { const res = http.get("http://localhost:8080/get"); check(res, { "is status 200": (r) => r.status === 200, }); }
結果
期待通り8:2でリクエストが分散されました。
サンプルコード
今回のサンプルコードはこちら
まとめ
Envoyの重み付き負荷分散を試してみました。