サイドカーはタダではない
一言でいうと
サイドカーを1つ付けると、Podのリクエスト量が加算され、起動時間が延び、障害点が1つ増えます。その代償を上回るメリットがあるときだけ付けます。
なぜ必要なのか
「機能をもう1つ追加しよう」という理由でサイドカーを増やすと、いつの間にかPodがコンテナ5つ入りになります。そのとき起きることは次のとおりです。
リソースが加算されます: Podのリクエスト量はコンテナの合計です。サイドカーにrequests.cpu: 100mを指定すると、Pod 200個で20コアが予約されます。スケジューラーはその合計を見て配置先を探すため、ノードの密度が下がります。実際に使っていなくても予約は確保されます。
起動が遅くなります: 正式なサイドカー(restartPolicy: Alwaysのinitコンテナ)は本体より先に起動します。プロキシの起動に3秒かかれば、すべてのPodの起動が3秒延びます。ローリングアップデートでは、それがPodの数だけ掛け算されます。
障害点が増えます: サイドカーがOOMで落ちると、そのコンテナが再起動している間Podは準備状態を失い、繰り返されるとCrashLoopBackOffでPod全体が使えなくなります。ログコレクターがバッファーをメモリにためる設定なら、トラフィックが集中したときにまさにそれが起きます。
どう動くのか
リソースを決めるときの基準はシンプルです。
| コンテナ | requests | limits |
|---|---|---|
| 本体 | 実使用量のp50 | p99 + 余裕 |
| サイドカー | とても小さく(10–50m) | 余裕を持たせる |
サイドカーのlimitsを絞ると、本体まで一緒に落ちます。requestsは小さく、limitsは余裕を持たせるのが正解です。これは本体とは逆の向きなので、混同しやすいところです。
終了順序も重要です。本体がまだリクエストを処理している最中にプロキシが先に落ちると、それらのリクエストが失敗します。正式なサイドカーは本体が終わったあとに終了するためこの問題は解決しましたが、それ以前はpreStopフックで数秒間持ちこたえさせる回避策がよく使われていました。
よくある勘違い
「サイドカーが落ちても本体は生きている」: Podは再起動の1つの単位です。restartPolicyはPodレベルの設定で、コンテナ1つが落ち続けるとPod全体がCrashLoopBackOffになります。
「リソースを指定しなければ使われない」: requestsを指定しないとQoSがBestEffortになり、メモリ圧迫時に真っ先に落とされます。サイドカーが先に落ちると、本体も巻き込まれます。
起動と終了の順序の問題
サイドカーの昔からの悩みの種は順序でした。メインコンテナが先に起動してサイドカー(プロキシ)がまだ存在しないと最初のリクエストが失敗し、終了時にはサイドカーが先に落ちて最後のリクエストとログが失われます。
❌ 옛 동작
시작: 모든 컨테이너 동시 → 프록시가 늦으면 초기 요청 실패
종료: 모든 컨테이너 동시 → 프록시가 먼저 죽으면 하류 호출 실패
✅ 네이티브 사이드카 (k8s 1.29+)
initContainers 에 restartPolicy: Always 를 주면
시작: 사이드카가 Ready 가 된 뒤에 메인이 시작
종료: 메인이 끝난 뒤에 사이드카가 종료
spec:
initContainers:
- name: proxy
image: envoyproxy/envoy:v1.31
restartPolicy: Always # ← 이 한 줄이 네이티브 사이드카로 만든다
containers:
- name: app
image: myapp:1.0
以前は、アプリケーションにプロキシを待つコードを入れたり、preStopにsleepを置く回避策を使ったりしていました。今は不要です。クラスターのバージョンを先に確認してから使うことが、この機能の唯一の条件です。
Jobが終了しない問題
バッチ処理のPodにサイドカーがあると、メインが終わってもサイドカーが動き続け、JobがずっとRunningのままになります。CronJobが毎日たまっていく事故はここで起きます。
ネイティブサイドカーはこれも解決します。メインが終わるとKubernetesがサイドカーにSIGTERMを送ります。1.29より前なら、メインが終わるときにサイドカーへシグナルを送るスクリプトを自分で入れる必要があります。
リソースを二重に数えない
サイドカーごとにリクエスト量と上限に余裕を持たせると、Pod 1つが実際の必要量の2倍を予約してしまいます。ノードには半分しか入りません。
| サイドカー | よくあるリクエスト量 | 実際の必要量 |
|---|---|---|
| ログコレクター | 100m / 128Mi | たいてい20m / 64Mi |
| プロキシ(Envoy) | 500m / 512Mi | トラフィックに応じて50–200m |
| メトリクスエクスポーター | 100m / 128Mi | 10m / 32Mi |
実測して減らします。Pod数百個に100mずつ余分に確保すると、数十コアが遊んでしまいます。kubectl top pod --containersでコンテナごとの実使用量を確認します。
実務で本当に大切なこと
サイドカーを入れる前に問うべきことは1つです。DaemonSetではだめなのかということです。
ノードごとに1つあれば足りる作業(ログ収集、ノードのメトリクス)にPodごとのコンテナを付けると、プロセス数がPodの数だけ増えます。サイドカーが妥当な場合は次の3つだけです。
- Podのネットワークネームスペースが必要です(プロキシ、mTLS)
- Podのボリュームが必要です(特定パスのファイル)
- テナントごとに分離する必要があります(設定がPodごとに異なる)
3つのどれにも当てはまらなければ、DaemonSetのほうが安上がりです。