誰も語らないサイドカーの隠れたコスト
従来のIstioメッシュでは、すべてのPodにサイドカーが付き——アプリケーションコンテナと並んで自動的に注入されるEnvoyプロキシです。小規模なら問題ありません。しかし200以上のPodが存在すると、それぞれが50〜100 MBのRAMとCPUを常時消費する200個のEnvoyプロセスが走ることになります。メッシュのオーバーヘッドがクラウド費用の明確な項目として現れてきます。
問題はIstioではなく、サイドカーモデルにあります。Pod1つにつき1プロキシということは、N個のPodにN個のプロキシが必要で、共有はできません。メッシュはトラフィック量ではなく、ワークロード数に対して線形にスケールしていきます。
Istio Ambient Meshはサイドカーを完全に排除することでこの問題を解決します。トラフィックの傍受とmTLSは、そのノード上のすべてのPodが共有するztunnelという軽量コンポーネントによってノードレベルで処理されます。私は50〜300以上のPodを持つクラスタで本番運用してきましたが、初日からプロキシ関連のメモリが目に見えて減少し、Podの起動も速くなり、ローリングデプロイ中のサイドカー注入失敗も過去のものになりました。
このガイドではAmbientモデルを実際に体験します。5分以内で動作するインストールを行い、ウェイポイントプロキシを使ったL7トラフィックポリシーまで解説します。
クイックスタート:5分でAmbient Meshを構築
Kubernetesクラスタ(1.28以上)とkubectlの設定が必要です。クリーンなクラスタから始めましょう——AmbientモードとSidecarモードは共存できますが、同一Namespace内で混在させると学習時に混乱が生じます。
ステップ1:istioctlのインストール
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.0 sh -
cd istio-1.22.0/
export PATH=$PWD/bin:$PATH
istioctl version
ステップ2:AmbientプロファイルでIstioをデプロイ
ambientプロファイルは、コントロールプレーンに加えて2つの新しいコンポーネントをインストールします:istio-cni(トラフィックリダイレクト用DaemonSet)とztunnel(L4 mTLS用DaemonSet)。
istioctl install --set profile=ambient --skip-confirmation
# すべてのPodがRunning状態になるまで待機
kubectl get pods -n istio-system -w
1〜2分後の出力例:
NAME READY STATUS RESTARTS
istio-cni-node-xxxxx 1/1 Running 0
istio-ingressgateway-xxxxxxxxx-xxxxx 1/1 Running 0
istiod-xxxxxxxxx-xxxxx 1/1 Running 0
ztunnel-xxxxx 1/1 Running 0
ステップ3:NamespaceをMeshに追加
Namespaceをメッシュに追加するには、ラベルを1つ付けるだけです——Podの再起動も、注入Webhookも不要です。
kubectl create namespace demo
kubectl label namespace demo istio.io/dataplane-mode=ambient
# サンプルアプリをデプロイ
kubectl apply -n demo -f https://raw.githubusercontent.com/istio/istio/release-1.22/samples/bookinfo/platform/kube/bookinfo.yaml
kubectl get pods -n demo
Podが起動してもistio-proxyコンテナは表示されません。Namespaceはメッシュに参加しており、ztunnel経由でPod間のmTLSはすでに有効になっています。
# Ambientがトラフィックを処理していることを確認
istioctl experimental ztunnel-config workload -n demo
詳細解説:Ambient Meshの実際の動作原理
Ambientは、サイドカーが担っていた機能を2つの独立したレイヤーに分割します。それぞれが任意であり、独立したスコープを持ちます。
レイヤー1 — ztunnel(L4、常時有効)
ztunnelはDaemonSetとして動作し、ノードごとに1つのPodが配置されます。担当する処理は以下のとおりです:
- そのノード上のすべてのPod間トラフィックに対する相互TLS
- L4認可ポリシー(IP、ポート、SPIFFE ID)
- 接続レベルのテレメトリ(送受信バイト数、接続数)
トラフィックのリダイレクトはistio-cniが担当し、アプリケーションコンテナをrootで実行することなく、PodのネットワークNamespace内にiptablesルールを設定します。アプリはこれらについて何も知る必要がありません——通常通りポートをバインドし、カーネルがztunnel経由でトラフィックを透過的にルーティングします。
内部的には、ztunnelインスタンスはHBONE(HTTP-Based Overlay Network Encapsulation)——相互TLSを使用したHTTP/2 CONNECTトンネリング——を用いて通信します。送信元IPを保持し、既存のネットワークポリシーとも問題なく動作します。
レイヤー2 — ウェイポイントプロキシ(L7、オプション)
HTTPルーティング、リトライ、サーキットブレーカー、ヘッダー操作が必要ですか?それがウェイポイントプロキシの出番です——NamespaceまたはServiceAccountにスコープされた専用のEnvoyインスタンスです。L7処理が必要なトラフィックはウェイポイントを経由し、それ以外はztunnelのL4レイヤーで処理されます。
これが真の価値です:L7機能が必要な場所にのみEnvoyのオーバーヘッドが発生し、デフォルトですべてのPodに組み込まれることはありません。
応用:ウェイポイントプロキシとトラフィックポリシー
ウェイポイントプロキシのデプロイ
# demoネームスペース全体にウェイポイントを作成
istioctl experimental waypoint apply -n demo --enroll-namespace
# 動作確認
kubectl get pods -n demo -l istio.io/gateway-name=waypoint
AuthorizationPolicyの適用
L7が利用可能になることで、ポリシーはHTTPメソッドやパスをターゲットにできます——ztunnel単体では実現できない機能です。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-reviews-get
namespace: demo
spec:
targetRefs:
- kind: Service
group: ""
name: reviews
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
paths: ["/reviews/*"]
kubectl apply -f authz-policy.yaml
VirtualServiceによるトラフィック管理
ウェイポイントが配置されると、標準のIstio VirtualServiceおよびDestinationRuleオブジェクトは、サイドカーモードとまったく同じように動作します。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
namespace: demo
spec:
hosts:
- reviews
http:
- match:
- headers:
x-user:
exact: canary-tester
route:
- destination:
host: reviews
subset: v3
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
サイドカーモードからの段階的な移行
既存のサイドカーベースのNamespaceがある場合、ダウンタイムなしで移行できます:
# 1. サイドカー注入ラベルを削除
kubectl label namespace my-app istio-injection-
# 2. Ambientラベルを追加
kubectl label namespace my-app istio.io/dataplane-mode=ambient
# 3. 既存のサイドカーコンテナを取り除くためにローリング再起動
kubectl rollout restart deployment -n my-app
# 4. istio-proxyコンテナがなくなったことを確認
kubectl get pods -n my-app -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{" "}{end}{"\n"}{end}'
Ambientを本番運用して得た実践的なヒント
移行前にリソース削減量を計測する
負荷の高いNamespaceを移行する前に、現在の使用状況をスナップショットしておきましょう:
# 移行前のコンテナごとのCPUとメモリ
kubectl top pods -n my-app --containers | grep istio-proxy
# 移行後——ノードごとのztunnel使用量(共有コスト)
kubectl top pods -n istio-system -l app=ztunnel
私のクラスタでは、20以上のPodを持つNamespaceでサイドカーを削除した後、プロキシ関連のメモリが常に60〜70%削減されました。ztunnel DaemonSetはPod数に関係なくノードあたり約30〜50 MBを使用します——これはワークロードごとではなく、固定コストです。
L7が必要なときだけウェイポイントを追加する
「念のため」とあらゆる場所にウェイポイントを追加したくなる誘惑があります。抵抗してください。ztunnel単体でmTLS、ピア認証、L4ポリシーが得られ——セキュリティ要件の大部分をカバーします。具体的なニーズが現れたときだけウェイポイントを追加してください:ヘッダーベースのルーティング、HTTPフォールト注入、パスレベルの認可など。各ウェイポイントはあなたが管理するDeploymentです。
Ambientトラフィックフローのデバッグ
# ztunnelが認識しているワークロードを確認
istioctl experimental ztunnel-config workload
# 特定ノード上のztunnelの内部Envoy設定を検査
istioctl experimental ztunnel-config all -n istio-system
# ウェイポイントプロキシがサービスをインターセプトしているか確認
istioctl experimental waypoint status -n demo
# ノード上のztunnelのライブアクセスログ
kubectl logs -n istio-system -l app=ztunnel -f --tail=50
互換性チェックリスト
- CNIプラグイン:Calico、Cilium(eBPF kube-proxyの置き換えなし)、Flannel、AWS VPC CNIがテスト済みでサポートされています。
- Kubernetesバージョン:1.28以上を推奨。1.26でも動作しますが、一部のノードフィーチャーゲートが不足しています。
- HostNetworkのPod:Ambientメッシュではサポートされていません——そのワークロードには特別にサイドカーモードを使用してください。
- 既存のNetworkPolicy:Ambientメッシュは追加型です。NetworkPolicyオブジェクトはカーネルレベルで引き続き機能し、ztunnelはその上で動作します。
Ambient Meshがチームにもたらす変化
Ambientは日常的なプロキシ管理の考え方を変えます。サイドカーのアップグレードは、すべてのDeploymentにわたるローリング再起動の調整を意味していました——10のワークロードなら管理可能ですが、200では苦痛です。Ambientでは、ztunnelのアップグレードはクラスタ全体で単一のDaemonSetロールアウトで完了します。L7ポリシーはすべてのPodが黙って抱えるものではなく、特定のサービスにスコープされた意図的な選択になります。
サイドカーのオーバーヘッドがIstioを棚上げした理由であれば、Ambientはその中心的な不満に対処しています。ztunnelはほぼゼロの設定でmTLSと観測可能性のベースラインを提供します。ウェイポイントはL7が実際に必要な場所にのみ現れ——メッシュはそれが常に必要だとは想定しません。
Istio 1.22はAmbientを本番対応として宣言し、ツール群もそれを反映しています。移行ドキュメントは充実しており、デバッグ機能は改善され続け、アーキテクチャはいくつかのマイナーリリースにわたって驚きなく持続しています。ステージングで重要でないNamespaceを選び、ラベルを切り替えて、プロキシメモリに何が起きるかを計測してみましょう。数字が決断を後押ししてくれるはずです。

