負荷試験

負荷試験 #

負荷試験の目的 #

Docker SwarmからKubernetesに移行するにあたり、移行前のスペックを移行後に同等以上のスペックを発揮することを試験する必要があります。 したがって、アプリケーション自体の詳細な性能テストではなく、クラスターとして同等の性能が発揮できていることが大雑把でも確認できればよい、というのがここでのゴールとなります。

評価するためにはPrometheusやDataDog Agentなどから収集したデータをGrafanaやDataDog Dashboardで確認しつつ再現性を持った試験を実施する必要があります。

何を試験するか #

実際に試験して確認した内容を次の表にまとめました。

試験内容目的
経路上の Proxy を最小台数にしたときに想定するrpsを処理ことができるか確かめるConnection Pool や TCP ESTABLISHED に余裕があるか確認する
Runtime(nodejs)やライブラリの処理可能なrpsを計測する同じ Runtime やライブラリを使用しているアプリケーションの CPU/MEM リソースの基準値を見積もる
Pod をスケールアウトしたときの rps に対するリソースの変化を確認するPod 数に対するリソース使用量と rps の関係を把握する
連続的にリクエストを投げることでほかサービスに影響がないか確認する負荷試験の対象は挙動に問題ないが、同じ Gateway を使っている場合や同じマシンに乗っている他のサービスに影響がないことを確かめる

基本的に「性能限界」と「リソースの見積」のための試験になります。 これらの情報を元に、常設のreplicasの見積りや、Horizontal Pod AutoscalerのためのCPUのlimit設定、 共倒れを防ぐためのRate Limit設定を割り出していきます。

合わせてリソースの値をどうやって決めるかを確認してみてください。

試験方法 #

他のマイクロサービスと連携していないHTTPサーバーを用意する #

Kubernetesの一連の動作検証も含め以下のようなサーバーを用意しておくと検証が捗ります。

import * as express from "express";

const app = express();

app.get("/", (req: express.Request, res: express.Response) => {
  res.send("ok");
});

const httpServer = server.listen(3000, "0.0.0.0");

process.on("SIGTERM", () => {
  httpServer.close();
});

このサーバーをコンテナ化してKubernetes上で稼働させ、疎通確認や負荷試験の対象として扱います。

負荷試験ツール #

使用したツールで簡易で便利だったのがtsenart/vegetaでした。 Binaryで手に入るためセットアップが容易で適当なサーバーから直接実行したり、docker-composeでローカルに環境を作り、その中で動作確認ができるのは非常に作業効率が高いです。

例えば1rpsのテストを実施したい場合は次のようなShellを実行するだけで済みます。

echo "GET http://test-server:3000" | vegeta attack -rate 1/1s > /dev/null

DataDogでの1rps

これをistio-proxyから収集されたMetricsをGrafanaで可視化することで、まずは集計クエリが正しいことを確認していきます。 ある程度高いrpsで負荷をかけ続けると、パラメーターで指定したrpsよりも低い値で可視化されることがありますが、 負荷試験用のクライアントの性能だったり、常に均質なネットワークを提供できるわけではなかったりするためです。

とはいえ負荷試験時のrps目標値があるため、観測されるrpsが目標値になるまでクライアント側のrpsを上げるか、 クライアントを分散して負荷を高めるなど工夫をします。

ProxyからリクエストをMirroringする #

いきなり移行対象のクラスターやサーバーに対してトラフィックを100%向けるのはかなり危険です。 見積もりが正しくともそれが確実かどうかはやってみなければわかりません。 安全に取るなら同じ流量のリクエストを移行後の機材に向けて検証した後に徐々にTraffic Weightを調整していくのが無難でしょう。

一番手っ取り早いのはリクエストをミラーリングして実際のリクエストを受け付けることです。 BFFのサーバーの場合、リクエストのほとんどがGETであるためアクセスログを出力するロードバランサーより後方でミラーリングを実施することが可能です。

実際に使用したミラーリングはnginxの機能によるものを利用しています。

実際には次のような経路でミラーリングを実施しました。

リクエストのミラーリング概略図

移行後のクラスターに対してGETリクエストをミラーリングし、CPU/MEMなどのリソース使用量、エラー率をモニタリングツールで監視しました。 この結果と単純な負荷試験による見積もりの誤差を把握した上で移行に備えました。