TT Lab
はじめる
学ぶ 学習パス コース

Envoyの内部構造

再起動せずに設定を入れ替える

TT Labで続きを見る

目標

静的設定の限界を確認した後、同じプロキシをファイル購読方式に変え、クラスターとリスナーを再起動なしで差し替え、誤った更新が拒否されるところまで見ます。

なぜ重要なのか

サービスメッシュとIngressコントローラーがしていることの本質が、これです。ところが、文書だけで読むと、「コントロールプレーンが死んだらメッシュが死ぬ」のような誤った文が頭に残ります。一度自分で拒否を作ってみれば、拒否された後もトラフィックが流れるという事実と、そのため誰も知らないまま数週間が過ぎうるという事実が、一緒に残ります。その2つを知っている人だけが、update_rejectedにアラートを設定します。

ステップ

  1. アップストリームを2つokで起動してください(8096・8097)。/root/envd-xds/static.yamlに、/がstatic=v1を返す静的設定を置いて起動し(管理9977、リスナー127.0.0.1:10077)、起動したままそのファイルのv1をv2に直してください。直す前と後にそれぞれリクエストして、/root/envd-xds/01-static.txtにbefore=・after_edit=の2行を書いてください(起動し直しません)。
  2. /root/envd-xds/dyn.yamlを作ってください。static_resourcesなしで、node(id envd-xds-1、cluster envd-xds)とdynamic_resourcesだけを置き、lds_configは/root/envd-xds/xds/lds.yamlを、cds_configは/root/envd-xds/xds/cds.yamlを、path_config_sourceで購読します。2つのリソースファイルも作ってください。リスナーは/markerにlds=v1を返し、それ以外はクラスターpoolへ送ります。クラスターpoolのエンドポイントは、8096・8097の2つです。起動してから、/markerと/にリクエストして、/root/envd-xds/02-subscribe.txtにmarker=・upstream_ok=(/のリクエストが200ならyes)の2行を書いてください。
  3. /root/envd-xds/xds/cds.yamlから、エンドポイント8097を外してください(エンドポイントを1つだけ残します)。プロキシはそのままにして、反映されるまで待ってから、8回リクエストして、/root/envd-xds/03-reload.txtにp8096=・p8097=・total=の3行を書いてください。
  4. /config_dumpからクラスターの節だけを取り出して/root/envd-xds/04-dump.jsonに保存し、/root/envd-xds/04-dump.txtにstatic_clusters=(静的クラスターの数)、dynamic_clusters=(動的クラスターの数)、dynamic_name=(動的クラスターの名前)の3行を書いてください。
  5. /root/envd-xds/xds/lds.yamlの/markerの応答を、lds=v1からlds=v2に直してください。プロキシはそのままにして、反映されるまで待ってから、/root/envd-xds/05-lds.txtにmarker_after=(/markerの応答)とupstream_still_ok=(/のリクエストがまだ200ならyes)の2行を書いてください。
  6. /root/envd-xds/xds/cds.yamlで、クラスターのnameの行を削除して、わざと誤った更新を送ってください(名前はスキーマが必須として要求します)。少し待ってから、/root/envd-xds/06-rejected.txtにstill_serving=(/のリクエストがまだ200ならyes)、update_rejected=(cluster_manager.cds.update_rejectedの統計の値)、endpoints=(/clustersに残っているpoolエンドポイントの数)の3行を書いてください。
  7. /root/envd-xds/07-stats.txtにcds_success=・cds_rejected=・lds_success=・cds_reload=の4行を書いてください。それぞれcluster_manager.cds.update_success、cluster_manager.cds.update_rejected、listener_manager.lds.update_success、cluster_manager.cds.config_reloadの統計の値です。
  8. /root/envd-xds/08-report.mdに、static_needs_restart=(ステップ1の結果が「変わらない」ならyes)、reload_count=(ステップ7のcds_reload)、rejected_kept_old=(ステップ6で拒否の後もトラフィックが流れたならyes)、endpoints_after=(ステップ3の後に残ったエンドポイントの数)の4行を書き、その下に学んだことを4行以上書いてください。

参考

静的設定は、ファイルを直しても変わらない

アップストリームを2つokで起動してください(8096・8097)。/root/envd-xds/static.yamlに、/がstatic=v1を返す静的設定を置いて起動し(管理9977、リスナー127.0.0.1:10077)、起動したままそのファイルのv1をv2に直してください。直す前と後にそれぞれリクエストして、/root/envd-xds/01-static.txtにbefore=・after_edit=の2行を書いてください(起動し直しません)。

static_resourcesは、プロセスが起動するときに一度だけ読み込まれます。そのため、ファイルを直しても、起動し直すまでは何も起こりません。これが、プロキシの設定を変えるには再起動が必要だという話の正体であり、サービスメッシュが解こうとした問題でもあります。直すにはsed -iが便利です。起動し直さないように注意してください。このステップの要点は、「変わらない」ことを示すことです。

設定を外から受け取るように変える

/root/envd-xds/dyn.yamlを作ってください。static_resourcesなしで、node(id envd-xds-1、cluster envd-xds)とdynamic_resourcesだけを置き、lds_configは/root/envd-xds/xds/lds.yamlを、cds_configは/root/envd-xds/xds/cds.yamlを、path_config_sourceで購読します。2つのリソースファイルも作ってください。リスナーは/markerにlds=v1を返し、それ以外はクラスターpoolへ送ります。クラスターpoolのエンドポイントは、8096・8097の2つです。起動してから、/markerと/にリクエストして、/root/envd-xds/02-subscribe.txtにmarker=・upstream_ok=(/のリクエストが200ならyes)の2行を書いてください。

ブートストラップにstatic_resourcesがまったくなくてもかまいません。そのときプロキシは、起動するとすぐに購読を始め、リソースが届いて初めて、実際に待ち受けを始めます。リソースファイルの形は、resources:の下に"@type"を示したリストです。リスナーならListener、クラスターならClusterタイプです。本物のコントロールプレーンはこれをgRPCで送りますが、送る内容の形は、ファイルでもgRPCでも同じです。

ファイルを直すと、起動し直さなくても反映される

/root/envd-xds/xds/cds.yamlから、エンドポイント8097を外してください(エンドポイントを1つだけ残します)。プロキシはそのままにして、反映されるまで待ってから、8回リクエストして、/root/envd-xds/03-reload.txtにp8096=・p8097=・total=の3行を書いてください。

ファイル購読方式は、ファイルが変わったことに気づいて、読み直します。すぐにではなく、数秒かかることがあるので、固定のsleepではなく、目的の結果が出るまで回るループを使ってください。これが、サービスメッシュでPodが起動したり停止したりするたびに起きていることです。プロキシを再起動せず、エンドポイントのリストだけを差し替えます。反映されたかどうかは、/clustersでも見られます。注意として、ファイルをその場で上書きすると更新が来ません。新しいファイルに書いてから、mvで差し替えてください。

動的に受け取った設定は、ダンプの別の場所にある

/config_dumpからクラスターの節だけを取り出して/root/envd-xds/04-dump.jsonに保存し、/root/envd-xds/04-dump.txtにstatic_clusters=(静的クラスターの数)、dynamic_clusters=(動的クラスターの数)、dynamic_name=(動的クラスターの名前)の3行を書いてください。

/config_dumpのクラスターの節には、static_clustersとdynamic_active_clustersが別々にあります。ブートストラップに書いたものと、外から受け取ってきたものを区別する必要があるからです。運用で「自分が送った設定が届いたか」を確認するときに見る場所が、まさにこの動的側です。静的側が空で、動的側に入っていれば、購読が正しく動いています。?resource=で節を選んで受け取ることもできますが、このステップでは、全体を受け取ってjqで2か所を一緒に数えるほうが簡単です。

リスナーも無停止で差し替える

/root/envd-xds/xds/lds.yamlの/markerの応答を、lds=v1からlds=v2に直してください。プロキシはそのままにして、反映されるまで待ってから、/root/envd-xds/05-lds.txtにmarker_after=(/markerの応答)とupstream_still_ok=(/のリクエストがまだ200ならyes)の2行を書いてください。

リスナーを差し替えるのは、クラスターより重い作業です。ソケットを開き直すことだからです。Envoyは、新しいリスナーを準備した後で、古いリスナーをドレインしながら入れ替えるので、その間もリクエストが途切れません。そのため、ルート規則を1つ直すためにデプロイをしなくて済むのです。クラスター側の設定には触れていないので、アップストリームへ向かう経路はそのままのはずです。それも一緒に確認してください。

誤った更新は拒否され、古い設定が残る

/root/envd-xds/xds/cds.yamlで、クラスターのnameの行を削除して、わざと誤った更新を送ってください(名前はスキーマが必須として要求します)。少し待ってから、/root/envd-xds/06-rejected.txtにstill_serving=(/のリクエストがまだ200ならyes)、update_rejected=(cluster_manager.cds.update_rejectedの統計の値)、endpoints=(/clustersに残っているpoolエンドポイントの数)の3行を書いてください。

これが、xDSで最も重要な性質です。更新が誤っていれば、プロキシはそれを拒否して、最後に成功した設定をそのまま使います。コントロールプレーンが壊れた設定を送っても、トラフィックは流れ続けます。そのため、「コントロールプレーンが死んだらメッシュが死ぬ」という言い方は正確ではありません。新しい設定を受け取れないだけで、現在の設定では動き続けます。その代わり、誰も知らせてくれないので、拒否の統計とバージョンを監視する必要があります。統計名にupdate_rejectedが入ります。注意点が1つあります。すべての誤りが拒否されるわけではありません。知らない列挙値のように、デフォルトの検証器が警告だけを出して通すものもあります。必須フィールドが抜けたように、スキーマが受け入れられないものだけが、拒否として捕捉されます。

更新が届いたかは、数字で見る

/root/envd-xds/07-stats.txtにcds_success=・cds_rejected=・lds_success=・cds_reload=の4行を書いてください。それぞれcluster_manager.cds.update_success、cluster_manager.cds.update_rejected、listener_manager.lds.update_success、cluster_manager.cds.config_reloadの統計の値です。

コントロールプレーンがある環境で最初に見る数字が、これです。update_successが止まっていれば、設定が来ていないということで、update_rejectedが上がっていれば、来てはいるのに、プロキシが受け入れられないということです。2つはまったく別の問題なので、直す場所も違います。前者は接続や購読の問題で、後者は送る側が作った設定の問題です。このラボでは、前のステップでわざと拒否を作っておいたので、その数字が見えるはずです。

動的設定の運用メモを残す

/root/envd-xds/08-report.mdに、static_needs_restart=(ステップ1の結果が「変わらない」ならyes)、reload_count=(ステップ7のcds_reload)、rejected_kept_old=(ステップ6で拒否の後もトラフィックが流れたならyes)、endpoints_after=(ステップ3の後に残ったエンドポイントの数)の4行を書き、その下に学んだことを4行以上書いてください。

説明の行には、「コントロールプレーンが死ぬと、何が止まり、何が続くのか」を、自分の言葉で書いておいてください。この1文が、メッシュの障害対応で最もよく使われます。値は前のステップのファイルから取ってください。