Carpe Diem

備忘録

Envoyで重み付き負荷分散を試してみる

概要

christina04.hatenablog.com

の中で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でリクエストが分散されました。

サンプルコード

今回のサンプルコードはこちら

github.com

まとめ

Envoyの重み付き負荷分散を試してみました。