サービス メッシュ: Istio 対 Linkerd、mTLS およびトラフィック管理
Kubernetes 上のマイクロサービス アーキテクチャでは、各サービスが他の数十のサービスと通信します。 これらの通信が暗号化されていることを誰が保証しますか?自動再試行をいつ管理するか サービスが一時的にアクセスできなくなっていますか?レイテンシとレートのメトリクスを提供するのは誰ですか 各送信元と宛先のペアのエラーの割合は?サービス メッシュを使用しない場合は、次の質問に答えてください 質問には各サービスのカスタム コードが必要です。
Un サービスメッシュ これらの問題をインフラストラクチャレベルで解決し、 アプリケーションに対して透過的です。 Kubernetes 環境の主要なプレーヤーは次の 2 つです。 イスティオ、最も機能が豊富で、 リンカード、 シンプルさとオーバーヘッドを最小限に抑えるように設計されています。この記事ではインストール方法を説明します 両方とも、自動 mTLS の構成、カナリア展開によるトラフィックの管理、 サーキット ブレーカー、およびどちらかを選択するタイミング。
何を学ぶか
- サービス メッシュの仕組み: データ プレーン (サイドカー) とコントロール プレーン
- 自動 mTLS: 意味、確認方法、例外の処理方法
- Istio: インストール、VirtualService、DestinationRule、Canary、Blue/Green
- Linkerd: 軽量インストール、SMI TrafficSplit、拡張機能
- Istio OutlierDetection による回線遮断
- インフラストラクチャレベルでの再試行とタイムアウト
- 可観測性: サービス メッシュからのゴールデン シグナル メトリクス
- Istio と Linkerd: どちらを選択するか
サービスメッシュの仕組み
サービス メッシュは、 サイドカープロキシ 各ポッドの (Istio の場合は Envoy、Linkerd の場合は Linkerd2-proxy)。サイドカーがすべてを横取りする 変更を必要とせずに、アプリケーションコンテナに出入りするトラフィック コードに。
Il データプレーン トラフィックを処理するすべてのプロキシ サイドカーのセット 効果的です。の コントロールプレーン (Istio の場合は Istiod、Linkerd の場合は linkerd-control-plane) 構成をプロキシに配布し、mTLS の証明書を管理し、テレメトリを収集します。
Istio と Linkerd の比較
| 特性 | イスティオ | リンカード |
|---|---|---|
| サイドカープロキシ | Envoy (C++、50 ~ 100 MB) | linkerd2-proxy (Rust、10 ~ 20 MB) |
| ポッドのメモリ オーバーヘッド | 100~200MB | 20~30MB |
| レイテンシのオーバーヘッド P99 | 2~5ミリ秒 | 0.5~1ms |
| 自動mTLS | はい (cert-manager または組み込み) | あり(24時間自動回転) |
| 交通管理 | フル (仮想サービス、DR) | 基本 (HTTPRoute、TrafficSplit) |
| L7 ポリシー | HTTP、gRPC、TCP | HTTP、gRPC |
| 入り口 | APIゲートウェイ + Istioゲートウェイ | APIゲートウェイ |
| 学習曲線 | 急な | 適度 |
| 生産の成熟度 | 高 (Google、Airbnb) | 高 (Shopify、Microsoft) |
Istio: 基本的なインストールと構成
istioctl を使用したインストール
# Scarica e installa istioctl
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.0 sh -
export PATH=$PWD/istio-1.22.0/bin:$PATH
# Installa Istio con profilo di produzione
istioctl install --set profile=production -y
# Il profilo production abilita:
# - HA con multiple repliche del control plane
# - Affinity rules per distribuire su nodi diversi
# - Risorse CPU/memoria adeguate
# - Solo le feature necessarie (no addon come Kiali, Jaeger)
# Abilita l'iniezione automatica del sidecar nel namespace
kubectl label namespace production istio-injection=enabled
# Verifica lo stato del mesh
istioctl proxy-status
# Analizza la configurazione per possibili problemi
istioctl analyze --namespace production
Istio を使用した mTLS: PeerAuthentication と DestinationRule
Istio は、挿入されたすべてのサイドカー ポッド間に自動 mTLS を実装します。と PeerAuthentication は mTLS 経由で実行できます 厳しい (必須) 名前空間またはメッシュレベル全体:
# mtls-strict.yaml
# Abilita mTLS STRICT per tutto il namespace production
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: production
spec:
mtls:
mode: STRICT # DISABLE, PERMISSIVE, STRICT
---
# Eccezione: un servizio legacy che non ha sidecar
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: legacy-service-exception
namespace: production
spec:
selector:
matchLabels:
app: legacy-service
mtls:
mode: PERMISSIVE # accetta anche connessioni plain-text
# Verifica mTLS
kubectl exec -n production frontend-pod -c istio-proxy -- \
pilot-agent request GET /config_dump | grep -A5 "tls_context"
# Visualizza lo stato mTLS con istioctl
istioctl x describe pod frontend-pod.production
VirtualService: ルーティングとトラフィック分割
VirtualService は、サービスへのトラフィックがどのようにルーティングされるかを定義します。 HTTP ヘッダー、重み、パスの一致に基づくルールを使用します。
# virtual-service-canary.yaml
# Canary deployment: 90% traffico a v1, 10% a v2
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-service-vs
namespace: production
spec:
hosts:
- api-service # nome del Kubernetes Service
http:
# Routing per header: dev e QA ricevono sempre v2
- match:
- headers:
x-user-group:
exact: "beta-testers"
route:
- destination:
host: api-service
subset: v2
# Traffico generale: 90/10 split
- route:
- destination:
host: api-service
subset: v1
weight: 90
- destination:
host: api-service
subset: v2
weight: 10
# Timeout e retry a livello di infrastruttura
timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure,retriable-4xx"
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: api-service-dr
namespace: production
spec:
host: api-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
loadBalancer:
simple: LEAST_CONN # ROUND_ROBIN, RANDOM, LEAST_CONN
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
外れ値検出機能付きサーキットブレーカー
サーキット ブレーカーは、「異常な」ホストをロード バランシングから一時的に削除します。 定義されたエラーしきい値を超えた場合にプールします。
# destination-rule-circuit-breaker.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-service-circuit-breaker
namespace: production
spec:
host: payment-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
connectTimeout: 3s
http:
http1MaxPendingRequests: 100
http2MaxRequests: 500
maxRetries: 3
outlierDetection:
# Rimuovi un host se in 10 secondi riceve 5 errori 5xx
consecutiveGatewayErrors: 5
consecutive5xxErrors: 5
interval: 10s
# Tienilo fuori per 30 secondi
baseEjectionTime: 30s
# Massimo 50% degli host puo essere rimosso
maxEjectionPercent: 50
# Analizza solo richieste con 100ms o piu di latenza
minHealthPercent: 50
イングレストラフィック用の Istio ゲートウェイ
# istio-gateway.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: wildcard-tls-cert # Secret con cert TLS
hosts:
- "*.federicocalo.dev"
- port:
number: 80
name: http
protocol: HTTP
tls:
httpsRedirect: true # redirect tutto HTTP a HTTPS
hosts:
- "*.federicocalo.dev"
---
# Collega il Gateway al VirtualService
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-gateway-vs
namespace: production
spec:
hosts:
- "api.federicocalo.dev"
gateways:
- istio-system/production-gateway
- mesh # anche per traffico interno al mesh
http:
- route:
- destination:
host: api-service
port:
number: 8080
認可ポリシー: アクセス制御
# authorization-policy.yaml
# Solo il frontend puo chiamare il backend
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: backend-access-policy
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/production/sa/frontend-service-account"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
---
# Blocca tutto il resto (default deny)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec:
action: DENY
# Nessun selector = si applica a tutti i Pod nel namespace
# Nessuna rule = blocca tutto
Linkerd: インストールと構成
Linkerd は操作のシンプルさとパフォーマンスを重視します。 Rustで書かれたプロキシ P99 レイテンシが約 1ms のオーバーヘッドと、ポッドあたり約 20MB のメモリがあり、理想的です。 多くのマイクロサービスやリソースの制約があるクラスターの場合。
リンカードのインストール
# Installa Linkerd CLI
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
export PATH=$HOME/.linkerd2/bin:$PATH
# Prerequisiti: verifica che il cluster sia compatibile
linkerd check --pre
# Installa il control plane
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
# Verifica installazione
linkerd check
# Abilita injection sul namespace
kubectl annotate namespace production linkerd.io/inject=enabled
# Installa l'estensione Viz per osservabilita
linkerd viz install | kubectl apply -f -
linkerd viz check
linkerd viz dashboard &
Linkerd と HTTPRoute を使用した Canary (ゲートウェイ API)
# linkerd-canary-httproute.yaml
# Linkerd usa la Gateway API per il traffic splitting
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-service-canary
namespace: production
spec:
parentRefs:
- name: api-service
kind: Service
group: core
port: 80
rules:
- backendRefs:
- name: api-service-v1
port: 80
weight: 90
- name: api-service-v2
port: 80
weight: 10
# Monitora il canary con linkerd viz
linkerd viz stat httproute/api-service-canary -n production
linkerd viz routes deploy/api-service-v2 -n production
Linkerdで監視可能
# Visualizza metriche golden signals per tutti i deployment
linkerd viz stat deploy -n production
# Output tipico:
# NAME MESHED SUCCESS RPS LATENCY_P50 LATENCY_P99 TCP_CONN
# api-service 4/4 99.8% 245 1ms 12ms 42
# backend-service 3/3 98.2% 180 3ms 45ms 28
# payment-service 2/2 100.0% 65 8ms 89ms 12
# Visualizza il traffico per un singolo Pod
linkerd viz tap pod/api-service-xyz -n production
# Genera un report di osservabilita
linkerd viz check --proxy -n production
Istio テレメトリ: メトリクス、トレース、ロギング
Istio が自動的に発行する 黄金の信号 (遅延、トラフィック、エラー、 飽和)を送信元と宛先のペアごとに設定します。メトリクスは形式で公開されます Prometheus と公式 Istio ダッシュボードを備えた Grafana で表示されます。
# telemetry-config.yaml
# Configura il sampling per il distributed tracing
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-tracing
namespace: istio-system
spec:
tracing:
- providers:
- name: tempo # o jaeger, zipkin
randomSamplingPercentage: 1.0 # campiona 1% del traffico in produzione
---
# Metriche custom per un servizio specifico
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: payment-service-metrics
namespace: production
spec:
selector:
matchLabels:
app: payment-service
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
destination_version:
value: "request.headers['x-version'] | 'unknown'"
# Importa le dashboard Grafana ufficiali Istio
# Dashboard ID: 7639 (Mesh Overview), 11829 (Service), 12378 (Workload)
Service Mesh と Cilium eBPF: いつ使用するか
Cilium の出現により、サイドカーなしで (カーネル内の eBPF 経由で) mTLS および L7 ポリシーを提供します。 選択は複雑です。実用的なガイドは次のとおりです。
| シナリオ | 推奨される選択肢 | 理由 |
|---|---|---|
| 高度なトラフィック管理を備えたマイクロサービス (カナリア、ヘッダーベースのルーティング) | イスティオ | VirtualService/DestinationRule は置き換えられません |
| オーバーヘッドを最小限に抑えた mTLS セキュリティ | リンカードまたは繊毛 | Rust プロキシまたは最小限の eBPF |
| 数百のマイクロサービスを含むクラスター、限られたリソース | Linkerd または Cilium mTLS | サイドカーのオーバーヘッドに各ポッドを乗算 |
| マルチクラスターまたはマルチクラウド | イスティオ | メッシュフェデレーション内蔵 |
| サービス メッシュを初めて使用するチーム | リンカード | 学習曲線を大幅に短縮 |
サービスメッシュのベストプラクティス
実稼働環境でのサービス メッシュのチェックリスト
- PERMISSIVE モードで開始します。 mTLS を SRICT にする前に PERMISSIVE で有効にして、サイドカーがまだないサービスを識別します。
- すべての VirtualServices にタイムアウトを設定します。 タイムアウトがないと、依存関係が遅いため呼び出しチェーン全体がブロックされます。
- 各外部依存関係のサーキット ブレーカー: データベース、外部 API、決済サービス
- 冪等エラーの場合にのみ再試行を使用します。 冪等性キーを使用せずに POST で自動再試行を行わないでください。そうしないと、重複した注文が作成されます。
- CPU/メモリサイドカーを監視: 多くの Pod を含むクラスターでは、サイドカーのオーバーヘッドの合計がかなり大きくなる可能性があります
- フェイルオーバーのテスト: ポッドを手動で無効にし、サーキット ブレーカーと再試行が期待どおりに動作することを確認します。
- メッシュを最新の状態に保ちます。 Istio および Linkerd のバージョンのライフサイクルは短い (6 ~ 12 か月)。定期的なアップグレードを計画する
一般的なアンチパターン
- 増幅を伴う無限の再試行: A が 3 回の再試行で B をリコールし、B が 3 回の再試行で C をリコールした場合、1 つのエラーにより C への 9 回の試行が生成されます (リトライ ストーム)
- タイムアウトが多すぎる: 重要な API での 60 秒のタイムアウトは、停止中にすべてのアプリケーション スレッド/ゴルーチンが 60 秒間ブロックされることを意味します。
- コントロールプレーンのオーバーヘッドを無視します。 Istiod は、接続されたプロキシごとに大量の CPU/メモリを消費します。 1000 以上のポッドを含むクラスターでは、専用ノードが必要です
- 平面を使用しない選択的注入: 一部の Pod にのみサイドカーがある場合、mTLS STRICT はサイドカーのない Pod への通信に失敗します
結論と次のステップ
サービス メッシュは「あれば便利」ではなくなり、次の要件になりました。 深刻なマイクロサービス アーキテクチャ。自動 mTLS、きめ細かな可観測性、 サーキット ブレークと宣言型トラフィック管理により、問題を解決することなく実際の問題を解決できます。 サービス メッシュでは、各サービスにカスタム コードが必要になります。
Istio と Linkerd のどちらを選択するかは、ニーズによって異なります。複雑なシナリオには Istio を使用します。 高度なマルチクラスタ トラフィック管理、Linkerd による運用の簡素化とオーバーヘッド 最小限。どちらの場合も、学習とセットアップへの初期投資がかかります。 アプリケーションのインフラストラクチャ コードの削減と可視性によって成果が得られました。 クラスタ内トラフィックに対する前例のない影響。
Kubernetes at Scale シリーズの今後の記事
以前の記事
関連シリーズ
- Kubernetes ネットワーキング: eBPF を使用した Cilium — mTLS のサービス メッシュの代替
- 可観測性と OpenTelemetry — Istio と統合された分散トレーシング
- プラットフォームエンジニアリング — 内部プラットフォームとしてのサービス メッシュ







