サイドカー パターン: コードを変更せずにマイクロサービスを拡張する

サイドカー パターン: コードを変更せずにマイクロサービスを拡張する

最新のクラウドネイティブ システムでは、マイクロサービスはビジネス ロジックを実行する以上のことを行うことが期待されています。ログの処理、SSL/TLS 証明書の管理、メトリクスの収集、再試行メカニズムの実装、および他のサービスとの安全な通信の調整を行う必要があります。

この横断的な機能をすべて各アプリケーションのコードベース内に直接埋め込むと、コードの肥大化、密結合、言語のロックインが発生します。

ここで、サイドカー パターンが登場します。このガイドでは、サイドカー パターンとは何か、それが最新のマイクロサービス アーキテクチャに不可欠である理由、および簡単な例えと Kubernetes 構成例を使用してそれがどのように機能するかを詳しく説明します。


現実世界の例え: オートバイのサイドカー

このパターンを理解する最も簡単な方法は、サイドカー付きのオートバイを考えることです。

ポッド内のアプリケーションとサイドカー コンテナを示すサイドカー パターン アーキテクチャ図

あなたが高性能のオートバイを持っていると想像してください。この車両は、1 人のライダーを迅速に輸送するという 1 つのことを非常にうまく実行するように設計されています。ここで、乗客の手荷物を運ぶ必要があるか、追加の座席を追加する必要があるとします。

オートバイのフレーム、エンジン、ホイールを完全に再設計して車に変えることができます。しかし、それには多大な労力が必要で、バイクのシンプルさが損なわれ、メンテナンスが難しくなります。

代わりに、サイドカーを接続します。

サイドカーは、オートバイに接続する独立した自己完結型ユニットです。バイクの移動を共有し、バイクの行くところならどこへでも移動し、緊密に連携して動作します。しかし、オートバイの核となるエンジンは手つかずのままです。

ソフトウェア アーキテクチャでは:

  • Motorcycle は、主要なアプリケーション コンテナです (チェックアウトやユーザー認証などのコア ビジネス ロジックを実行します)。
  • サイドカーは、別個のヘルパー コンテナーです (SSL 終了、監視、ログ配布などのユーティリティ タスクを実行します)。
  • ジャーニー は、デプロイメント (Kubernetes ポッドなど) のライフサイクルです。

問題: 分野横断的な懸念とコードの肥大化

サイドカーが登場する前は、開発者はアプリケーション コードにヘルパー ライブラリを直接組み込む必要がありました。たとえば、ログを中央サーバーに送信する場合は、ログ ライブラリをインポートします。メトリクスが必要な場合は、メトリクス SDK を追加しました。

このライブラリベースのアプローチでは、いくつかの重大な課題が生じました。

  • 言語ロックイン: 監視ライブラリが Go でのみ記述されている場合、Python や Java マイクロサービスで簡単に使用することはできません。スタック内のすべての言語のライブラリを検索または構築する必要があります。
  • コード汚染: ビジネス ロジックは、再試行、サービス検出、暗号化、ロギングのためのインフラストラクチャ固有のコードで乱雑になります。
  • 複雑なアップグレード: 通信ライブラリにセキュリティの脆弱性が見つかった場合、すべてのマイクロサービスは依存関係を更新し、再コンパイルし、再デプロイする必要があります。
  • リソース競合: ヘルパー コードはメイン アプリケーションと同じランタイム プロセスで実行されます。つまり、ロガーのメモリ リークにより、コア アプリケーション全体がクラッシュする可能性があります。

解決策: サイドカー パターン

サイドカー パターン は、ヘルパー タスクをメイン アプリケーション プロセスから移動し、アプリケーションのすぐ隣で実行される別個の独立したプロセスに配置することで、これらの問題を解決します。

Kubernetes のようなコンテナ化された環境では、アプリケーション コンテナとサイドカー コンテナは同じ Pod 内で実行されます。同じポッドを共有しているため、次のようになります。

  • 同じネットワーク名前空間: 同じ IP アドレスとネットワーク ポートを共有します。実質的に待ち時間がゼロで、localhost を介して相互に即座に通信できます。
  • 共有ストレージ ボリューム: まったく同じディスク ストレージにアクセスできるため、サイドカーはログ ファイルを読み取ったり、メイン アプリケーションによって書き込まれた構成ファイルを読み込んだりできます。
  • 同一のライフサイクル: サイドカーは、プライマリ アプリケーションと一緒にデプロイ、開始、停止、スケーリングされます。

サイドカー パターンの主な使用例

サイドカーは信じられないほど多用途です。最も一般的なアプリケーションには次のようなものがあります。

1. サービス メッシュ プロキシ (Envoy、Linkerd など)

アプリケーションは他のサービスに直接 HTTP 呼び出しを行う代わりに、ローカルのサイドカー プロキシにリクエストを送信します。サイドカー プロキシは、ルーティング、再試行、ロード バランシング、サーキット ブレーク、および相互 TLS (mTLS) 暗号化を処理し、リクエストを転送します。アプリケーションは、こうしたネットワークの複雑さをまったく認識しません。

2. ログの収集と転送 (例: Fluent Bit)

アプリケーションはログ ステートメントを標準出力またはローカル ログ ファイルに書き込むだけです。サイドカー コンテナはそのファイルを監視し、ログを解析して、Elasticsearch や Datadog などの中央分析エンジンに転送します。

3. 設定とシークレットのリロード

サイドカーは、構成の更新や暗号キーのローテーションについてリモート サーバー (Consul や Vault など) を監視できます。変更が検出されると、新しいファイルを共有ボリュームにダウンロードし、再起動することなく、メイン アプリケーションにファイルを再ロードするように通知します。


Kubernetes の実装例

Kubernetes では、サイドカーのセットアップは簡単です。以下は、共有ボリュームにログを書き込むアプリケーション コンテナと、それらのログを読み取って送信する Fluent Bit サイドカー コンテナを示す簡単な YAML 構成です。

apiVersion: v1
kind: Pod
metadata:
  name: app-with-logging-sidecar
  labels:
    app: billing-service
spec:
  containers:
    # 1. Primary Application Container
    - name: web-app
      image: node:18-alpine
      command: ["/bin/sh", "-c"]
      args:
        - >
          while true; do
            echo "$(date) [INFO] Transaction processed successfully" >> /var/log/app/output.log;
            sleep 5;
          done
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app

    # 2. Sidecar Container (Log Shipper)
    - name: log-shipper
      image: fluent/fluent-bit:latest
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app
      # In a real setup, Fluent Bit config would read /var/log/app/output.log
      # and forward it to an external logging system.

  # Shared disk storage accessible by both containers
  volumes:
    - name: shared-logs
      emptyDir: {}

サイドカー パターンの長所と短所

他のデザイン パターンと同様、サイドカーには次のようなトレードオフがあります。

アドバンテージ (プロ) デメリット(短所)
言語に依存しない: サイドカーは独自の環境で実行されます。同じサイドカー ヘルパーを Go、Java、Python、または Ruby アプリの隣で使用できます。 リソース オーバーヘッド: ポッドごとに複数のコンテナを実行すると、CPU とメモリの消費量が増加します。
分離されたライフサイクル: インフラストラクチャ チームは、アプリケーション コードに触れることなく、サイドカーのセキュリティ パッチを更新できます。 複雑さの増加: 2 倍の数のコンテナを管理することにより、デプロイメント構成、デバッグ、およびスケジュール設定が複雑になります。
独立した障害分離: サイドカー コンテナーがクラッシュした場合、Kubernetes はメイン アプリケーションを停止せずにサイドカー コンテナーを自動的に再起動できます。 わずかなネットワーク遅延: ローカル プロキシ サイドカーを介したトラフィック ルーティングにより小さなホップが追加されますが、通常は無視できる程度です (< 1ms)。

## 結論

サイドカー パターンは、最新のクラウドネイティブ アーキテクチャの基本的な構成要素です。ネットワーク プロキシ、セキュリティ、ロギング、構成管理などの横断的な問題を別の付随プロセスに分離することで、開発者はビジネス価値の構築に純粋に集中できるようになります。

追加のリソース オーバーヘッドが発生し、効果的に管理するには Kubernetes などのコンテナ オーケストレーション プラットフォームが必要ですが、よりクリーンなコードベース、言語の柔軟性、独立したスケーリングの利点により、エンタープライズ マイクロサービスにとって不可欠なパターンとなっています。


Ghaznix ブログでソフトウェア開発とバックエンド エンジニアリングの洞察をさらに詳しく見る→