KubernetesへのLinkerdサービスメッシュのデプロイ:軽量なZero-Trust mTLSと高ネットワークパフォーマンスの実現

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

サービスメッシュのアプローチ:マイクロサービスに最適なレイヤーの選定

Kubernetesクラスタ内のマイクロサービス間におけるEast-Westトラフィックの保護では、アーキテクチャの複雑さとパフォーマンスのトレードオフに直面することが少なくありません。コンプライアンス監査でZero-Trust相互TLS(mTLS)、エンドツーエンドのテレメトリ、厳格なトラフィックポリシーが求められる場合、主に以下の3つの標準パターンが考えられます。

  • アプリケーションレベルの暗号化(SDK / コード内実装): Spring BootでのJava KeyStore設定やGoのgRPCダイヤルオプションへのX.509キーペア読み込みなど、開発者がランタイム内で直接TLSハンドシェイクを管理します。プロキシによるレイテンシを完全に排除できる反面、証明書のローテーションロジックが多数のコードベースに分散し、言語固有のバグが発生しやすく、暗号化処理のメンテナンス負荷が開発者に重くのしかかります。
  • 重量級のEnvoyベースのメッシュ(Istioなど): すべてのPodにEnvoyサイドカーを配置し、高度なレイヤー7トラフィックルーティングやプロトコル解析を提供します。しかし、リソース消費が課題となります。標準的なEnvoyサイドカーはPodあたり50MB〜150MBのRAMを消費し、高負荷時にはテールレイテンシが2ms〜6ms増加することがあります。また、複雑なコントロールプレーンの運用負荷も高くなります。
  • 専用マイクロプロキシ型メッシュ(Linkerd): Linkerdは、Rustで専用設計されたプロキシであるlinkerd2-proxyを採用しています。データプレーンにあらゆるルーティングフィルターを詰め込むのではなく、マイクロサービスのコアトラフィックに特化しています。設定不要ですぐに利用可能なmTLSを提供し、サイドカーあたりのRAM消費量はわずか15MB〜30MBに抑えられ、p99レイテンシのオーバーヘッドも1.5ms未満に抑えられます。

数百のマイクロサービスを実行するクラスタにおいて、マイクロプロキシはクラウドインフラコストを跳ね上げることなく、暗号化と可観測性をもたらします。

長所と短所:本番環境に向けたLinkerdの評価

メリット

  • 最小限のメモリ・CPUフットプリント: Rustのメモリ安全性保証に基づいて構築されており、ガベージコレクションによる一時停止(GCポーズ)が発生しません。Podあたりのアイドル時消費量は通常20MB未満のRAMと10m CPUに収まります。
  • ゼロタッチの相互TLS(mTLS): Linkerdはメッシュ化されたPodを検出すると、自動的に認証付きのTLS 1.3トンネルを確立します。アクティブなTCP接続を切断することなく、短期間のワークロード証明書を24時間ごとにローテーションします。
  • サブミリ秒単位のp99レイテンシ: 重いLuaランタイムの評価や汎用フィルターグラフを排除しているため、秒間35,000リクエストの高負荷時でもp99ジッターを1.5ms未満に維持します。
  • シンプルで洗練されたポリシーモデル: 膨大なCRDの学習を強いることなく、Server、AuthorizationPolicy、MeshTLSAuthenticationといった必要十分なポリシープリミティブに焦点を絞っています。

トレードオフ

  • 特化されたプロトコルサポート: LinkerdはHTTP/1.x、HTTP/2、gRPC、およびraw TCPを処理します。アーキテクチャがDubboなどのレガシーなエンタープライズプロトコルに依存している場合や、プロキシレイヤーでのカスタムペイロード解析が必要な場合は、Envoyの方が依然として柔軟です。
  • 組み込みの拡張性がない: Linkerdはデータプレーン内でのWebAssembly(Wasm)やカスタムLuaフィルターチェーンをサポートしていません。独自のペイロード変換は、Ingress Gatewayやアプリケーションミドルウェアで処理する必要があります。

本番環境アーキテクチャと前提条件

本番環境では、Linkerd CLIのデフォルトである自己署名証明書を決して使用しないでください。これらの証明書は365日で有効期限が切れ、自動更新フックも備わっていません。代わりに、外部の公開鍵基盤(PKI)をcert-managerに統合して、証明書の自動ローテーションを構成します。

アーキテクチャトポロジー

  • Trust Anchor(信頼の起点): HashiCorp VaultやAWS KMSなどの安全なシークレットストアに保存される、長期間有効(5〜10年間)なルートCA証明書。
  • Identity Issuer(ID発行者): cert-managerによってKubernetes内部で管理され、30〜60日ごとにローテーションされる中間CA。
  • 高可用性(HA)コントロールプレーン: ノード障害に耐えられるよう、Podアンチアフィニティルールを適用した各3レプリカ構成のlinkerd-destinationおよびlinkerd-identity。
  • 名前空間レベルのインジェクション: 新しくスケジュールされたすべてのPodが自動的にプロキシサイドカーを受け取れるように、Kubernetesの名前空間に直接アノテーションを付与。

この構成により、コントロールプレーン全体のメモリ使用量を1.5GB未満に保ちながら、秒間50,000リクエストを超える本番ワークロードを安定して処理できます。

ステップ別実装ガイド

ステップ 1: Linkerd CLIのインストールとクラスタ互換性の検証

ワークステーションにLinkerd CLIをダウンロードし、クラスタがカーネル、CNI、およびiptablesの前提条件を満たしていることを確認します。

# Linkerd CLIのダウンロードとインストール
curl -fsL https://run.linkerd.io/install | sh
export PATH=$PATH:$HOME/.linkerd2/bin

# インストール前にクラスタの適合性を検証
linkerd check --pre

次のステップに進む前に、すべての事前チェックが正常(グリーン)であることを確認してください。

ステップ 2: step-cliとcert-managerを使用したPKI基盤の構築

step CLIを使用して、ルートTrust Anchorと中間Issuer証明書を生成します。

# ルートTrust Anchorの生成(有効期間10年)
step certificate create root.linkerd.cluster.local root.crt root.key \
  --profile root-ca \
  --no-password --insecure \
  --not-after=87600h

# 中間Issuer証明書の生成(有効期間1年)
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
  --profile intermediate-ca \
  --ca root.crt --ca-key root.key \
  --no-password --insecure \
  --not-after=8760h

LinkerdのIDコントローラーがPod用の短命な24時間証明書に署名できるように、中間Issuer証明書ペアをKubernetes Secretとして保存します。

# Linkerd用の名前空間を作成
kubectl create namespace linkerd

# Issuer証明書をSecretとして保存
kubectl create secret tls linkerd-identity-issuer \
  --cert=issuer.crt \
  --key=issuer.key \
  --namespace=linkerd

ステップ 3: 高可用性(HA)モードでのLinkerdコントロールプレーンのデプロイ

最初にカスタムリソース定義(CRD)をインストールし、続いてコアコントロールプレーンコンポーネントをデプロイします。

# 1. Linkerd CRDのインストール
linkerd install --crds | kubectl apply -f -

# 2. HAフラグとリソース制約を指定してコントロールプレーンをインストール
linkerd install \
  --ha \
  --identity-trust-anchors-file=root.crt \
  --identity-issuer-certificate-file=issuer.crt \
  --identity-issuer-key-file=issuer.key \
  --proxy-cpu-request="50m" \
  --proxy-memory-request="32Mi" \
  --proxy-cpu-limit="500m" \
  --proxy-memory-limit="128Mi" \
  | kubectl apply -f -

# 3. コントロールプレーンの健全性を確認
linkerd check

ステップ 4: アプリケーション名前空間での自動プロキシインジェクションの有効化

個々のPodスペックを手動で編集する必要はありません。対象のアプリケーション名前空間全体でMutating Admission Webhookを有効にします。

# アプリケーション用の名前空間を作成
kubectl create namespace payments-service

# 自動プロキシインジェクションを有効化
kubectl annotate namespace payments-service linkerd.io/inject=enabled

ワークロードをデプロイするか、ローリング再起動をトリガーして、Linkerdにlinkerd2-proxyサイドカーコンテナを挿入させます。

# 既存のDeploymentに対してローリング再起動をトリガー
kubectl rollout restart deployment -n payments-service

ステップ 5: Zero-Trust mTLSとリアルタイムネットワークテレメトリの検証

Linkerdには、暗号化ステータスの監査とレイテンシ分布の追跡を行うためのオンクラスタメトリクスエンジンが含まれています。

可視化拡張機能をインストールします。

# Linkerd Vizのインストール
linkerd viz install | kubectl apply -f -
linkerd check

ターミナルから直接、実行中のワークロード間のリアルタイムmTLSステータスを確認します。

# payments-service内の稼働中mTLSエッジを検査
linkerd viz edges deployment -n payments-service

出力結果により相互TLSの検証が確認され、SPIFFE準拠の正確なワークロードIDが表示されます。

SRC          DST             SRC_EU_ID                                                                   DST_EU_ID                                                                   SECURED
api-gateway  payment-worker  api-gateway.payments-service.serviceaccount.identity.linkerd.cluster.local  payment-worker.payments-service.serviceaccount.identity.linkerd.cluster.local  yes (TLS 1.3)

アプリケーションコードに計測処理を追加することなく、リアルタイムのレイテンシパーセンタイル、スループット、およびエラー率を確認できます。

# ゴールデンメトリクス(成功率、RPS、p50/p95/p99レイテンシ)の確認
linkerd viz stat deployment -n payments-service

ステップ 6: 厳格なZero-Trust認可ポリシーの適用

LinkerdはデフォルトでPermissive(許容)モードで動作し、トラフィックを暗号化しつつも非認証の接続を許可します。厳格なZero-Trust分離を強制するには、プロキシ境界で未承認の呼び出し元をブロックするServerおよびAuthorizationPolicyリソースを定義します。

apiVersion: policy.linkerd.io/v1beta1
kind: Server
metadata:
  name: payment-server-port
  namespace: payments-service
spec:
  port: 8080
  proxyProtocol: HTTP/2
  podSelector:
    matchLabels:
      app: payment-worker
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
  name: allow-api-gateway-only
  namespace: payments-service
spec:
  targetRef:
    group: policy.linkerd.io
    kind: Server
    name: payment-server-port
  requiredAuthenticationRefs:
    - group: policy.linkerd.io
      kind: MeshTLSAuthentication
      name: api-gateway-identity
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
  name: api-gateway-identity
  namespace: payments-service
spec:
  identities:
    - "api-gateway.payments-service.serviceaccount.identity.linkerd.cluster.local"

このポリシーが有効になると、api-gateway IDを持たないPodからの通信は、アプリケーションコードに到達する前に即座にHTTP 403またはTCPリセットで遮断されます。

Share: