サイドカー
Sidecar ・ さいどかー
アプリの隣に補助コンテナを並走させ、通信代理やログ転送などの共通機能を言語に依らず後付けするパターン。
✦ 30秒で試す — 航海何語で書いたアプリにも、同じ部品を後付けできる本体が処理を終えたあと、プロキシと Pod はどうなる?予想してみる概要
サイドカーは、アプリケーション本体の隣に補助的なプロセスを「並走」させ、ログの収集・通信の代理・証明書の更新といった共通機能を後付けするデザインパターンです。名前の由来はオートバイの側車(サイドカー)で、本体とは別の車体でありながら同じ道を同じ速度で走る — アプリとは別のコンテナでありながら、同じ一生を共にする関係をよく表しています。
実際の姿としては、Kubernetes の Pod(複数のコンテナをまとめる最小のデプロイ単位)の中に、アプリ用のコンテナと補助用のコンテナを同居させる形が典型です。同じ Pod のコンテナはネットワークを共有するため、サイドカーは localhost 越しにアプリと話せ、共有ボリュームに置いたファイルも読めます。アプリからは「すぐ隣にいる小さな相棒」であり、コードを1行も変えずに機能を足せるのがこのパターンの魅力です。
なぜ生まれたか
マイクロサービスの時代になると、すべてのサービスに共通で必要な機能 — リトライ、タイムアウト、ログの転送、TLS の証明書の管理、メトリクスの出力など — をどう配るかが問題になりました。素朴な答えは「共通ライブラリを作って各サービスに組み込む」ですが、サービスが Go・Java・Python・Node.js と多言語で書かれていると、同じ機能を言語ごとに作り直し、言語ごとにバグを直し、全サービスに新しい版を行き渡らせる必要があります。ライブラリの更新は各チームの再ビルド・再デプロイ待ちになり、「全サービスの半分だけ古い実装が残っている」状態が常態化します。
実際、Netflix は Java 向けに作り込んだ回復性やサービス発見のライブラリを、Java 以外のサービスにも使わせるため、2014年ごろ Prana という「隣に置く補助プロセス」を作りました。Airbnb の SmartStack(2013年)も、サービス発見とロードバランシングを各マシンのローカルなプロキシに任せる同じ発想です。2016年には Kubernetes の設計者の Brendan Burns らが、コンテナを組み合わせる設計パターンの論文でこれを「サイドカー」と名付けて整理し、ほかにアンバサダー(外への通信の代理)やアダプター(出力の形式の変換)といった仲間のパターンも挙げました。
サイドカーは、この「言語ごとのライブラリ地獄」をプロセスの分離という発想で断ち切りました。共通機能を独立したプロセス(コンテナ)に切り出して隣に置けば、アプリが何語で書かれていても localhost の通信さえできれば機能を使えます。実装は1つ、更新はサイドカーのイメージの差し替えだけ。ライブラリを「組み込む」から、インフラとして「添える」への転換です。
詳細
Pod の中で何を共有しているか
Kubernetes の Pod では、同居するコンテナ群が同じネットワーク名前空間を共有します。つまりサイドカーとアプリは同じ IP アドレスを持ち、互いに localhost で届きます。ボリュームを両方にマウントすれば、ファイルシステムの一部も共有できます。一方で、それぞれの /(イメージの中身)やプロセスの一覧は既定では分かれているため、依存ライブラリやランタイムが混ざり合うことはありません。「近さは localhost、独立性はコンテナ」という距離感が、このパターンの土台です。
代表的な使い道と、通信の横取り
サイドカーの代表例は大きく3つあります。1つ目はログ・メトリクスの収集で、アプリが書き出したログファイルを Fluent Bit のようなエージェントが読み取り、集約基盤へ転送します。アプリは「ローカルに書くだけ」でよく、転送先が変わっても無関係でいられます。2つ目は証明書やシークレットの取得・更新で、Vault Agent のようなサイドカーが定期的に新しい認証情報を取ってきて、共有ボリューム経由でアプリに渡します。
3つ目がネットワークプロキシで、これがサイドカーの最大の応用先です。アプリの送受信をすべてサイドカーのプロキシ(Envoy が代表格)が仲介し、mTLS による暗号化、リトライやサーキットブレーカー、分散トレーシング用のヘッダの付与などを肩代わりします。アプリは宛先に直接つないでいるつもりですが、Pod の起動時に小さな init コンテナが iptables(Linux のパケット転送の規則)を書き換え、Pod から出入りする通信をすべてプロキシのポートへ流すようにしてあります。アプリのコードを変えずに済むのはこの横取りのおかげで、裏返せば、プロキシがいない瞬間にはアプリの通信はどこにも出られません。この形を全サービスに広げたものがサービスメッシュです。
落とし穴 — リソースと、起動・終了の順番
便利な一方で、代償も明確です。まずリソース。サイドカーは Pod の数だけ増えるため、1つあたり数十 MB のメモリでも、1,000 Pod あれば無視できない総量になります。プロキシ型なら、通信のたびにプロキシを2回(送信側と受信側)通る分のレイテンシも上乗せされます。
次に、起動と終了の順番の問題です。ふつうのコンテナとして並べたサイドカーは、アプリと「同時に」起動し、「同時に」終了の合図(SIGTERM)を受けます。2つ目のコンテナは1つ目の準備が整うのを待たないので、プロキシの準備より先にアプリが外へ通信すると失敗します。終了時にはプロキシのほうが先に終わりやすく、後片付け中のアプリの最後の通信が宙に浮きます。バッチ処理の Job では、アプリが仕事を終えてもサイドカーが動き続け、Pod がいつまでも完了しません。いずれも現場で長く悩みの種でした。
これに応えたのが Kubernetes のネイティブサイドカーです。init コンテナに restartPolicy: Always を指定すると、そのコンテナは「アプリより先に起動し(準備の確認を待ってから次へ進み)、アプリが動いているあいだ動き続け、アプリが終わってから止められる」サイドカーとして扱われます。1.28 でアルファとして導入され、1.29 でベータになって既定で有効になり、1.33(2025年4月)で正式な機能(GA)になりました。Job でも、本体が終われば kubelet がサイドカーを止めるので、Pod はきちんと完了します。
下の部品で、順番の問題を手で確かめてください。時間軸のバーの端をドラッグすると、アプリとプロキシの起動・終了の時刻が動き、プロキシがいない瞬間に出た通信が朱で落ちます。「ネイティブサイドカー」に切り替えると、どう動かしても順番が崩れなくなります。
アプリの外向きの通信は、同じ Pod のプロキシに横取りされて外へ出ます。時間軸のバーの端をドラッグして、起動・終了の順番を入れ替えてみてください。朱の粒は、プロキシがいない瞬間に出て落ちた通信です。
採用の判断軸は、「その機能は言語をまたいで共通か」「アプリと別の頻度で更新したいか」です。単一言語の小さなチームなら普通のライブラリで十分なことも多く、サイドカーは多言語・多サービスの規模で効いてくるパターンです。なお、Pod ごとにプロキシを置く重さを嫌って、ノード単位のプロキシで同じ機能を提供する「サイドカーレス」の方式も広がっています(サービスメッシュの記事で扱います)。
試問
1つの Pod(一緒に動かすコンテナの組)の中で、アプリと、その外向きの通信を必ず横取りして運ぶプロキシが動きます。下の時間軸で、2本のバーの端をドラッグすると起動・終了の時刻が動き、プロキシが受け付けられない瞬間に出た通信は朱の × で落ちます。8秒の赤い線で Pod に終了の合図(SIGTERM)が届き、アプリはその後に後片付けをします。
アプリの外向きの通信は、同じ Pod のプロキシに横取りされて外へ出ます。時間軸のバーの端をドラッグして、起動・終了の順番を入れ替えてみてください。朱の粒は、プロキシがいない瞬間に出て落ちた通信です。
