Kubernetes 1.28: Revenge of the Sidecars?
#翻訳
原文 https://buoyant.io/blog/kubernetes-1-28-revenge-of-the-sidecars
Star Wars: Episode III – Revenge of the Sith - Wikipedia
Kubernetes v1.28: Planternetes | Kubernetes
k8s 1.28の新機能SidecarContainersの紹介など: Neco Weekly (2023-07-14号)
A guide to Kubernetes sidecars: what they are, why they exist, and what Kubernetes 1.28 changes
Kubernetes を使用しているなら、おそらくサイドカーという用語を聞いたことがあるでしょう。この概念は、クラウド ネイティブ エコシステムにおけるいくつかの重要な構成要素、特にサービス メッシュの基礎です。ただし、驚かれるかもしれませんが、Kubernetes 自体には、少なくとも今のところ、サイドカーの概念が組み込まれていません。この状況は、待望の次期 Kubernetes 1.28 に「サイドカー KEP」が統合され、Kubernetes API にサイドカーが正式に導入されることで、ついに変わりつつあります。
しかし、この KEP は実際には何を意味するのでしょうか?このガイドでは、サイドカーとは何か、何が良いのか、何が悪いのか、そして Kubernetes 1.28 でのサイドカーの変更点など、知っておくべきことをすべて説明します。
Pods, containers, and init containers
サイドカーの説明に入る前に、Kubernetes がアプリケーション コンポーネントを編成する方法の基本を理解していることを確認しましょう。
Kubernetes の実行とアドレス指定の中心となる単位はポッドです。ポッドには 1 つ以上のコンテナが含まれます。各ポッドには一意の IP アドレスが割り当てられ、ポッド内のコンテナーはすべてこの IP アドレスを共有します。コンテナーはそれぞれ異なるポートをリッスンできますが、ポッド内のすべてのコンテナーはその IP にバインドされており、そのポッドの「一部」です。ポッドが停止すると、コンテナーも停止します。
Kubernetes は、基本的な構成要素としてポッドを使用し、その上に構築された膨大な数の構造を提供します。ポッドを複製し、整理し、変更を管理し、名前を付け、相互に通信できるようにするなどの方法があります。しかし、今日の目的のためには、ポッドがどのように使用されるかについてあまり理解する必要はありません。それらは、ほとんどの Kubernetes 構造の中核となる構成要素であるというだけです。
ポッドが異なればプロパティも異なりますが、Kubernetes に関する限り、ポッドに異なる「タイプ」はありません。ポッドはポッドです。コンテナには同じことが当てはまりません。 Kubernetes は、通常のコンテナと init コンテナの 2 種類のコンテナを認識します。
Init コンテナーは、名前が示すように、ポッドがアクションの準備ができる前に、ポッドの初期化時に実行されます。 Init コンテナーは終了することが想定されており、ポッド内ですべての init コンテナーが終了すると、通常の非 init コンテナーが実行されます。通常の (非 init コンテナー) は、init コンテナーがすべて完了した後に開始され、通常はポッド自体が終了するまで永久に実行され続けます。 (完了時に終了することが想定されるジョブなどのワークロードの場合、この動作には例外がいくつかありますが、これが最も一般的なパターンです。)
init コンテナと通常のコンテナのこの区別が、Kubernetes 1.28 でロック解除される新しいサイドカー機能の鍵となります。その話に入る前に、最後にサイドカーについて見てみましょう。
So what is a sidecar?
これまでの Kubernetes の歴史全体を通じて、サイドカーは単にパターンの名前であり、Kubernetes の実際の機能ではありませんでした。サイドカーは、オートバイの横に取り付けられたサイドカーと同様に、メイン アプリケーション コンテナーの「隣」で実行されるコンテナーです。これは単に慣例の問題であり、「サイドカー コンテナ」と他のすべてのコンテナの唯一の違いは、その機能です。
しかし、コンテナが別のコンテナの隣で実行できるというアイデアがなぜこれほど興味深いものであり、特別な名前を付けるに値するのでしょうか?なぜなら、サイドカー パターンは非常に強力なもの、つまり、アプリケーション自体と同じ運用およびセキュリティ コンテキストで実行しながら、コードの変更を必要とせずに実行時にアプリケーションを拡張する方法を提供するからです。このステートメント(※斜体のところ)は、サイドカーの力、そしておそらく Kubernetes のポッド モデルの力を理解するための鍵となります。
コードを変更せずに実行時にアプリケーションを拡張する方法。サイドカーを使用すると、アプリケーションを再コンパイルしたり、新しいライブラリにリンクしたり、何らかの変更をしたりすることなく、アプリケーションに機能を追加することができます。これは、開発者が関与する必要がないだけでなく、サイドカーが任意の言語で記述されたアプリケーションで動作できることを意味します。
→The Service Mesh: What every software engineer needs to know about the world’s most over-hyped technology
アプリケーション自体と同じ運用およびセキュリティコンテキストで実行される。これが本当に強力な部分です。サイドカーは (システム内の他の場所ではなく) 同じポッド内で実行されるため、事実上アプリケーションの一部として扱われます。サイドカーに障害が発生すると、それが実行されているポッドの障害と同じになります。サイドカーにセキュリティ違反がある場合、その違反はポッドに限定されます。サイドカーが異常な量のリソースを消費する場合、アプリケーション自体がそれらのリソースを消費するようなものです。これらの状況を処理するための Kubernetes メカニズムはすべて、変更することなくサイドカー対応アプリケーションに適用できます。
「開発者の関与を必要とせずにアプリケーションを拡張できる」と「最初にアプリケーションを扱うのと同じ方法でこれらの拡張を扱える」というこの組み合わせは、プラットフォーム所有者にとって恩恵となってきました。特に、サービス メッシュのようなサイドカー ベースのプロジェクトが提供する拡張機能のほとんどは、ビジネス ロジックではなくプラットフォーム機能であるためです。
→https://platformengineering.org/blog/what-is-platform-engineering
Kubernetes のサイドカーの一般的な例には、アプリケーション コンテナを計測して中央のメトリクス ストアにデータを報告するメトリクス エージェントや、コンテナのログを取得して別の場所に中継するログ アグリゲータが含まれます。しかし、サイドカーが実際に動作している最大の例は、おそらくサービス メッシュでしょう。
サービス メッシュはサイドカー モデルを使用して、ネットワーク プロキシをすべてのポッドに追加します。これらのサイドカーは、アプリケーションとの間のすべての TCP 接続をインターセプトし、これらの接続上のリクエストを処理して、印象的な機能リストを実現します。これらのプロキシは、ポッド間の相互 TLS、コンポーネントごとのきめ細かい HTTP メトリクスなどの機能を提供できます。リクエストの再試行、透過的なクラスタ間通信など。これらのプロキシが正確に何であるかは、実装によって異なる場合があります。多くのサービス メッシュは人気のある Envoy プロジェクトを使用していますが、たとえば Linkerd は、Rust プログラミング言語で書かれた超軽量の「マイクロプロキシ」を使用しています。これは、複雑さとリソース消費を大幅に削減しながらパフォーマンスとセキュリティを向上させるアプローチです。 (Rust を採用するという私たちの決定について詳しく読むことができます。)
サイドカー モデルの能力は、Linkerd のようなサービス メッシュがこれらの機能を透過的に追加できるだけでなく、アプリケーションに合わせて拡張し、クラスターへの単一障害点の導入を回避できることを意味します。
Do we really need sidecars? Can't, like, the network do this?
人気があるにもかかわらず、サイドカーは常に物議を醸すトピックでした。たとえば、アプリケーションまたはプラットフォーム所有者のバックグラウンドからサービス メッシュにアクセスする人にとって、サイドカー モデルの価値は明らかです。事実上、欠点がまったくなく、共有ライブラリの利点が得られます。これは本質的に私が上で共有した視点です。
ただし、サービス メッシュがネットワーク層であるという見方をしている人にとって、L7 ネットワーク ロジックは「カーネル内」あるいは少なくとも「アプリケーションを見ているときに見えない場所」ではなくアプリケーションの近くに配置されるべきであるという考えは、アプリケーションとネットワークの従来の関係に反します。結局のところ、ポッドを見るたびに、サービス メッシュ サイドカーがあなたを見つめていることになるのです。 ネットワークの観点からすると、これは奇妙で歓迎されない違反のように感じるかもしれません。
実際、この部門は「サイドカーフリー」サービス メッシュの導入によって頂点に達しました。これらのアプローチで提供される息を呑むようなマーケティングはさておき(eBPF や HBONE などの名前の奇跡のテクノロジーを使用して「サービス メッシュを解決」します)、これらのサービス メッシュは最終的には、コア ロジックをノードごとまたは名前空間ごとのプロキシに移動することですべて機能します。サイドカーというより。言い換えれば、プロキシはまだ存在しており、ポッド内に存在していないだけです。
→eBPFとサービスメッシュ
→https://istio.io/latest/blog/2022/introducing-ambient-mesh/
※2023/08 ambient meshはalpha https://istio.io/v1.18/docs/ops/ambient/getting-started/
私たちはこれらのアプローチを注意深く検討しましたが、最終的には Linkerd には採用されませんでした。ここでのトレードオフについては言いたいことがたくさんあります。その特定のトピックに興味がある方は、eBPF とサービス メッシュに対するそのユーティリティの長い評価でその多くを取り上げています。 L7 トラフィックは L4 トラフィックとは異なり、サイドカーで得られる重要な分離とセキュリティの保証が失われ、最終的には運用面とセキュリティ面で大きく後退することになると言えれば十分です。
しかし、この記事の目的上、私の多くの意見はすべて無視して構いません。今回はサイドカーについてお話します!そして、サイドカーの世界ではすべてが完璧ではありません。サイドカーには、実際の欠点や煩わしさがいくつかあります。その理由を見てみましょう。
What are some of the complications of sidecars?
Kubernetes がポッドを提供できるようにする強力なポッド モデルも、サイドカーに関するいくつかの問題の原因です。主なものは次のとおりです。
サイドカーをアップグレードするには、ポッド全体を再起動する必要があります。 Kubernetes ポッドは不変であるため、アプリケーションを含むポッド全体を再起動せずに 1 つのコンテナーを変更することはできません。現在、Kubernetes アプリケーションは任意のポッドの再起動とシャットダウンを処理するように構築されることになっており、Kubernetes はローリング再起動などのあらゆる種類のメカニズムを提供して、これをワークロード全体のダウンタイムなしで実行できるようにしていますが、それでも面倒です。
サイドカーはジョブの終了を妨げる可能性があります。ジョブに関する上記のメモを覚えていますか?ジョブは、完了後に自動的に終了することが期待される Kubernetes ワークロードの 1 つのタイプです。残念ながら、Kubernetes にはサイドカーに終了する必要があることを通知する方法がありません。つまり、デフォルトではジョブ ポッドは永久に実行されます。これを修正する回避策はありますが (私たちの回避策は linkerd-await と呼ばれます)、サービス メッシュの透過性に違反するアプリケーション コンテナへの変更が必要になります。
サイドカーは、起動時にアプリケーションと競合し得ます。 Kubernetes は init コンテナを特定の順序で実行しますが、通常のコンテナの順序は保証されません。これは、アプリケーションの起動中にサイドカーの準備ができていることが保証されていないことを意味します。これは、たとえば外部へのネットワーク接続を行うためにサイドカーが必要な場合に問題になる可能性があります。 (Linkerd ではこれを回避するためのハックがいくつかあります。)
実際には、これらはどれも重大な問題ではありませんが、どれも迷惑であり、場合によってはハッキングや回避策が必要です。
どのようなハックですか?ちょっと試してみると、競合状態を防ぐために、実際にはコンテナ用の postStart フックが存在することがわかりました。これは実際には仕様にはありませんが、フックが完了するまで次のコンテナの起動をブロックします。そのため、Linkerd はプロキシをポッド内の最初のコンテナとして追加し、postStart フックを使用して他のアプリケーションよりも前にプロキシが起動して実行されていることを保証します。競合状態は回避されました!ただし、Linkerd がポッドspecの最初のコンテナーになっているため、kubectl logsなどのツールは、デフォルトでアプリケーション ログではなく Linkerd プロキシ ログを出力します。これはユーザーにとって非常に迷惑です。ただし、心配する必要はありません。Kubernetes 1.27 には、アプリケーション コンテナに設定できるデフォルト コンテナという概念があります。これは、kubectl が正しいことを行うのに役立ちます。しかし、すべてのクラスターが 1.27 にあるわけではありません...など。セットアップ全体が面倒で壊れやすいですが、それが今日の最先端です。
先ほども言いましたが、ハックです。
これまでのところ、これが Kubernetes でのサイドカーの使用状況であり、ほとんどの場合は機能しますが、時には自分自身を傷つける荒削りな部分もあります。しかし、Kubernetes 1.28 がその窮地を救うために登場しました。
What's happening in Kubernetes 1.28?
最後に、Kubernetes 1.28 とサイドカー KEP について話しましょう。この KEP (Kubernetes Enhancement Proposal) は 2019 年に初めて開始され、長年にわたる議論、停滞、再設計、危機一髪に直面してきました。これは Kubernetes の世界ではちょっとした冗談になっています。
4 年が経った今、サイドカー KEP がついに次の 1.28 リリースでアルファ機能になったようです。そして、この KEP によって変更される内容は、実際にはすべて init コンテナーに遡ります。
KEP では、init コンテナの仕様に新しい RestartPolicy フィールドが導入されています。このフィールドの説明は次のとおりです。
RestartPolicy は、ポッド内の個々のコンテナーの再起動動作を定義します。このフィールドはinitコンテナに対してのみ設定でき、許可される値は「Always」のみです。非initコンテナの場合、またはこのフィールドが指定されていない場合、再起動動作はポッドの再起動ポリシーとコンテナ タイプによって定義されます。 init コンテナの RestartPolicy を「Always」に設定すると、次のような影響があります。この init コンテナは、すべての通常のコンテナが終了するまで、終了時に継続的に再起動されます。すべての通常のコンテナが完了すると、restartPolicy が「Always」のすべての init コンテナがシャットダウンされます。このライフサイクルは通常の init コンテナとは異なり、多くの場合「サイドカー」コンテナと呼ばれます。このinitコンテナーは引き続きinitコンテナー シーケンスで開始されますが、コンテナーが完了するのを待ってから次のinitコンテナーに進みます。代わりに、次の init コンテナは、この init コンテナが開始された直後か、startupProbe が正常に完了した直後に開始されます。
これを詳しく見てみましょう:
新しい RestartPolicy: Always 構成を init コンテナーに指定できるようになりました。
新しい構成を追加すると、サイドカー コンテナーが作成されます。
サイドカー コンテナは、すべての通常のコンテナより前に開始され (init コンテナであるため)、これが重要な部分ですが、通常のコンテナがすべて終了した後に終了するようになりました。
通常のコンテナの実行中に何らかの理由でサイドカー コンテナが停止した場合、自動的に再起動されます。 (これは「Always」が意味する部分です。)
最後に、各 init コンテナが順番に完了するのを待ってから次の init コンテナが開始されるのとは異なり、他の init コンテナはサイドカー コンテナの完了を待ってから開始することはありません。それは良いことです。なぜなら、それらはずっと後になるまで完了しないからです。
本質的に、この KEP は、「バックグラウンド コンテナ」 (または古代の用語では「TSR コンテナ」) に近いモードを導入します。これらの新しいサイドカー コンテナは、通常のコンテナより前に開始され、通常のコンテナの後に終了します。これにより、サイドカーの問題点リストの 2 と 3 が一気に解決されます。ジョブの終了時に自動的に終了できるようになり、通常のコンテナに対する起動時の競合状態がなくなり、postStart フックとデフォルトコンテナのすべての愚かさを取り消すことができます。
勝利!この新機能により、サイドカーが再びクールになりました。それとも?
The glorious future that awaits us in Kubernetes 1.28
私はこの記事に「サイドカーの復讐」というタイトルを付けましたが、明らかにそれは少し誇張です。サイドカー KEP は、Kubernetes でのサイドカーの使用に関する 2 つの最大の問題、つまりジョブのサポートとコンテナーの起動に関する競合状態を取り除きます。これらの問題は両方とも現在回避策がありますが、これらの回避策はメッシュ所有者に不幸な結果を課します。 Kubernetes 1.28 以降では、これらの回避策を完全に削除できます。
ということは、サイドカー界ではもうすべてが順調だということでしょうか?個人的には、サイドカーをより一般的に受け入れるには、まだいくつかの課題があると思います。そのうちの最大のものは (皮肉なことに) 可視性に関するものです。すべてのポッドでサイドカーが確認できるため、a) これは従来のネットワーキングの考え方と合わず、b) サイドカーのリソースへの影響が非常に目に見えます。共有ライブラリが 200 メガのメモリと 5% の CPU を使用したとしても、おそらく気付かないでしょう。サイドカーがそれを行うと、非常に目立ちます。 (幸いなことに、Rust の優れたメモリ割り当て制御のおかげで、Linkerd のリソース使用量は非常に最小限です。)
昨年、私は、サイドカーを kubectl の出力から隠すことによって (eBPF を使用して) Linkerd からサイドカーを削除するつもりだという冗談を言いました。私にとって残念なことに、このアイデアに対する反応は非常に熱狂的で興奮していたので、私はジョークを説明するフォローアップツイートを投稿しなければなりませんでした。実際には kubectl をフォークするつもりはありませんでした。しかし、すべての良い (?) ジョークと同様に、そこには真実の核があり、もしサイドカーがそこにあっても単に見えなかったり、旗の後ろに隠れたりした場合、「サイドカーを殺さなければならない」という感情はどれだけ薄れるだろうかと疑問に思います。
そうは言っても、Linkerd での私たちの仕事は、地球上で最も速く、最も軽く、最もシンプルな (つまり、TCO が最も低い) サービス メッシュを提供することであり、サイドカーがそれを実現する最良の方法ではないということを私たちが確信するものはまだありません。したがって、近い将来、少なくとも Linkerd ユーザーを待っている輝かしい未来は、サイドカーが増え、いぼが減るということです。そして願わくば、kubectl のフォークがないことを願っています。
Get mesh-y with Linkerd!
サービス メッシュを検討している場合は、Linkerd を試してみてください。 Adidas、Plaid、Microsoft (Xbox Cloud) などの企業は、重要な本番インフラストラクチャを強化するために Linkerd に依存しています。私たちは、純粋なオープンソース手段を通じて、または商業パートナーとして、皆様のスタートを喜んでお手伝いいたします。私たちは、世界中の企業が誇大広告を打ち破り、ゼロトラスト セキュリティ ポリシー、相互 TLS、FIPS-140-2 準拠などの堅牢なサービス メッシュを本番環境に導入できるよう支援してきました。今すぐご連絡ください。
#Linkerd #ServiceMesh