五百個の数字から必要なものだけ取り出す
目標
統計名の構造を3つの系統に分けて見て、取り出し方・分割する規則・削り方を順に身につけた後、名前を変えたときに何が消えるかを自分で確認します。
なぜ重要なのか
統計は、ダッシュボードやアラートが立っている土台です。ところがその土台は名前でできているので、名前の規則を知らないと、/statsで見た値をダッシュボードのクエリに移せず、名前を気軽に変えて、グラフをまるごと空にしてしまいます。これに加えて、カウンターとゲージを区別できないと「リセットしたのに変わらない」で行き詰まり、除外リストの性質を知らないと「必要になったときに有効にしよう」と先送りして、いざ必要な瞬間に過去の値がないことに気づきます。
ステップ
- アップストリームを2つ起動してください。
8093はok、8094はfailです。/root/envd-stats/stats.yamlに、stat_prefixがshopのリスナーとクラスターgood・badを置いて起動してください(管理9971、リスナー127.0.0.1:10071)。/helloを5回、/bad/xを1回リクエストしてから、/root/envd-stats/01-names.txtにcluster=・http=・listener=の3行を書いてください。それぞれcluster.good.upstream_rq_total、http.shop.downstream_rq_total、そのリスナーのdownstream_cx_totalの統計の名前全体です。 /statsにfilterを付けてupstream_rq_totalを含む統計だけを取り出し、format=jsonも一緒に付けて、/root/envd-stats/02-filter.jsonに保存してください。そして/root/envd-stats/02-filter.txtにtotal_stats=(フィルターなしで受け取った行数)とmatched=(フィルターで絞った統計の個数)の2行を書いてください。/stats/prometheusを取得して、/root/envd-stats/03-prom.txtにcluster.good.upstream_rq_totalに該当する行だけを保存してください。そして/root/envd-stats/03-prom.mapにenvoy_name=(Prometheusでのメトリクス名)、label_key=(クラスター名を持つラベルのキー)、value=(その値)の3行を書いてください。/reset_countersをPOSTしてから、2つの統計を読み直して、/root/envd-stats/04-reset.txtにcounter_before=・counter_after=(cluster.good.upstream_rq_total)、gauge_before=・gauge_after=(cluster.good.membership_total)の4行を書いてください。/root/envd-stats/stats-tags.yamlを作ってください。stats.yamlと同じで、最上位にstats_config.stats_tagsを置き、タグ名envd_clusterを正規表現^cluster\.((.+?)\.)で取り出します。起動して/helloを2回リクエストしてから、/stats/prometheusからenvd_clusterラベルが付いた行を1つ、/root/envd-stats/05-tags.txtに保存してください。/root/envd-stats/stats-trim.yamlを作ってください。stats_config.stats_matcher.exclusion_listで、プレフィックスがcluster.bad.の統計を除外します。起動してから、/root/envd-stats/06-trim.txtにbefore=(ステップ5の設定での全統計の行数)、after=(この設定での行数)、bad_stats=(この設定でcluster.bad.で始まる行数)の3行を書いてください。/root/envd-stats/stats-rename.yamlを作ってください。ステップ1の設定から、stat_prefixだけをshopからcheckoutに変えたものです。起動して/helloを2回リクエストしてから、/root/envd-stats/07-rename.txtにold_prefix_stats=(http.shop.で始まる統計の行数)、new_prefix_stats=(http.checkout.で始まる行数)、new_rq_total=(http.checkout.downstream_rq_totalの値)の3行を書いてください。/root/envd-stats/08-report.mdに、counter_after_reset=・gauge_after_reset=(ステップ4)、prom_label=(ステップ5で追加したタグ名)、trim_removed=(ステップ6のbeforeからafterを引いた値)、renamed_lost=(ステップ7で古いプレフィックスの統計が消えたならyes)の5行を書き、その下に学んだことを4行以上書いてください。
参考
- 管理ポートのアドレスに
?や&が入る場合は、アドレス全体を引用符で囲んでください。囲まないと、シェルがその後ろを切り落とします。 - Envoyを起動し直す前には
pkill -x envoyで片付け、起動は/readyがLIVEを返すまで回るループで待ってください。 /reset_countersや/quitquitquitのような管理コマンドはPOSTです。curl -X POSTを使います。- 統計の値は
이름: 값(プレースホルダーは名前と値です)の形式なので、grep -m1 '^이름:' | awk '{print $2}'(プレースホルダーは名前です)で取り出します。 - よくある間違い: フィールド名を
stat_tagsと書いてしまうことです。正しい名前はstats_tagsで、間違えると「そのようなフィールドはない」と設定がまるごと拒否されます。
名前は3つの系統で始まる
アップストリームを2つ起動してください。8093はok、8094はfailです。/root/envd-stats/stats.yamlに、stat_prefixがshopのリスナーとクラスターgood・badを置いて起動してください(管理9971、リスナー127.0.0.1:10071)。/helloを5回、/bad/xを1回リクエストしてから、/root/envd-stats/01-names.txtにcluster=・http=・listener=の3行を書いてください。それぞれcluster.good.upstream_rq_total、http.shop.downstream_rq_total、そのリスナーのdownstream_cx_totalの統計の名前全体です。
Envoyの統計名は、何についての数字かをプレフィックスで示します。cluster.はアップストリーム側、http.はそのHTTPコネクションマネージャーが処理したリクエスト側、listener.はソケット側です。同じリクエスト1つが3か所でそれぞれ数えられるので、3つの数字がずれたとき、その差がそのまま手がかりになります。リスナー名にはアドレスとポートが入りますが、ドットの代わりにアンダースコアが使われる場所があるので、自分で確認してください。
500個の中から必要なものだけを取り出す
/statsにfilterを付けてupstream_rq_totalを含む統計だけを取り出し、format=jsonも一緒に付けて、/root/envd-stats/02-filter.jsonに保存してください。そして/root/envd-stats/02-filter.txtにtotal_stats=(フィルターなしで受け取った行数)とmatched=(フィルターで絞った統計の個数)の2行を書いてください。
統計は、デフォルトの設定でも500個を超えます。そのため、管理ポートにはクエリパラメーターがあります。?filter=は正規表現で、?format=jsonは機械が読める形に変えます。2つは&で一緒に使えます。シェルでは?と&が特殊文字なので、アドレス全体を引用符で囲んでください。JSON側の個数はjq '.stats | length'で数えます。
同じ値が別の名前で出力される
/stats/prometheusを取得して、/root/envd-stats/03-prom.txtにcluster.good.upstream_rq_totalに該当する行だけを保存してください。そして/root/envd-stats/03-prom.mapにenvoy_name=(Prometheusでのメトリクス名)、label_key=(クラスター名を持つラベルのキー)、value=(その値)の3行を書いてください。
Prometheusには「ドットでつないだ長い名前」という概念がありません。メトリクス名とラベルの集合で表現します。そのためEnvoyは、エクスポートするときに名前を分割します。cluster.good.upstream_rq_totalは、メトリクス名1つと、クラスター名を持つラベルに分かれます。この規則を知っていてはじめて、/statsで見た名前をダッシュボードのクエリに移せます。ラベルは波括弧の中に열쇠="값"(プレースホルダーはキーと値です)の形で入っています。
リセットするボタンは半分にしか効かない
/reset_countersをPOSTしてから、2つの統計を読み直して、/root/envd-stats/04-reset.txtにcounter_before=・counter_after=(cluster.good.upstream_rq_total)、gauge_before=・gauge_after=(cluster.good.membership_total)の4行を書いてください。
統計には種類があります。カウンターは増え続けるだけの累積値で、ゲージはこの瞬間の状態であり、ヒストグラムは値の分布です。/reset_countersは名前のとおり、カウンターだけを0に戻します。ゲージは「いま健全なサーバーが何台か」のような現在の状態なので、戻すものがありません。この違いを知らないと、「リセットしたのに値が変わらない」で行き詰まります。POSTはcurl -X POSTで送ります。
名前を分割する規則を自分で決める
/root/envd-stats/stats-tags.yamlを作ってください。stats.yamlと同じで、最上位にstats_config.stats_tagsを置き、タグ名envd_clusterを正規表現^cluster\.((.+?)\.)で取り出します。起動して/helloを2回リクエストしてから、/stats/prometheusからenvd_clusterラベルが付いた行を1つ、/root/envd-stats/05-tags.txtに保存してください。
デフォルトのタグ規則は、Envoyがすでに複数持っています(クラスター名・リスナーアドレスなど)。そこに規則を追加すれば、自分の組織の命名規則をラベルとして取り出せます。たとえば、クラスター名にチーム名をプレフィックスとして付けてあるなら、その部分だけを別にラベルにでき、そうすればダッシュボードでチームごとにまとめて見られます。正規表現の1つ目の括弧が名前から切り取る部分で、2つ目の括弧がラベルの値です。フィールド名はstats_tagsです(stat_tagsではありません)。
エクスポートしないものを選ぶ
/root/envd-stats/stats-trim.yamlを作ってください。stats_config.stats_matcher.exclusion_listで、プレフィックスがcluster.bad.の統計を除外します。起動してから、/root/envd-stats/06-trim.txtにbefore=(ステップ5の設定での全統計の行数)、after=(この設定での行数)、bad_stats=(この設定でcluster.bad.で始まる行数)の3行を書いてください。
統計はメモリを消費し、Prometheusへエクスポートすると、時系列の数だけ保存コストになります。クラスターが数百あるプロキシでは、この数字がすぐに手に負えなくなります。そのため、エクスポートするものを選ぶ仕組みがあります。除外リストや包含リストで、プレフィックス・正確な名前・正規表現を指定します。注意すべき点は、除外された統計は画面から消えるのではなく、まったく記録されないことです。必要になった後で復活させても、その間の値はありません。
言葉を1つ変えると、ダッシュボードが空になる
/root/envd-stats/stats-rename.yamlを作ってください。ステップ1の設定から、stat_prefixだけをshopからcheckoutに変えたものです。起動して/helloを2回リクエストしてから、/root/envd-stats/07-rename.txtにold_prefix_stats=(http.shop.で始まる統計の行数)、new_prefix_stats=(http.checkout.で始まる行数)、new_rq_total=(http.checkout.downstream_rq_totalの値)の3行を書いてください。
stat_prefixは名前のための値なので、トラフィックには何の影響もありません。そのため、リファクタリングの途中で気軽に変えやすいのですが、その瞬間にそのプレフィックスを使っていたすべてのダッシュボードとアラートが、空のグラフになります。しかも、値が0に落ちるのではなく時系列そのものが消えるので、「データなし」を障害として扱わないアラートなら、誰も気づきません。名前はインターフェースです。変えるときは、使う側を先に探す必要があります。
統計運用のメモを残す
/root/envd-stats/08-report.mdに、counter_after_reset=・gauge_after_reset=(ステップ4)、prom_label=(ステップ5で追加したタグ名)、trim_removed=(ステップ6のbeforeからafterを引いた値)、renamed_lost=(ステップ7で古いプレフィックスの統計が消えたならyes)の5行を書き、その下に学んだことを4行以上書いてください。
このメモは、次にダッシュボードを作るときやプロキシの設定をリファクタリングするときに、自分が読む文章です。特に最後の行は、「名前はインターフェースである」という規則として書いておくとよいです。値は、前のステップで作ったファイルから取ってください。