マイクロサービスの CI/CD

マイクロサービス アーキテクチャの主な利点は、リリース サイクルの短縮です。 信頼性の高い継続的インテグレーションと継続的デリバリー (CI/CD) プロセスがないと、マイクロサービスによって提供される機敏性が失われます。 この記事では、マイクロサービス アーキテクチャにおける一般的な CI/CD の課題について概説し、サービスを個別に構築、検証、セキュリティで保護、デプロイする方法を推奨します。

CI/CD とは何でしょうか?

CI/CD とは、継続的インテグレーション、継続的デリバリー、継続的デプロイなど、いくつかの関連プロセスを指します。

  • 継続的インテグレーション (CI): コードの変更は、多くの場合、メイン ブランチにマージされます。 ビルドとテストの自動化されたプロセスにより、メイン ブランチのコードは常に運用環境の品質になります。

  • 継続的デリバリー (CD): CI プロセスを渡すコード変更は、運用環境に似た環境に自動的に発行されます。 ライブ運用環境へのデプロイには手動による承認が必要になる場合がありますが、それ以外の場合は自動化されます。 目標は、コードが常に運用環境にデプロイする 準備ができている ということです。

  • 継続的デプロイ: 前の 2 つの手順に合格したコード変更は、運用環境 に自動的にデプロイされます。

マイクロサービス アーキテクチャの堅牢な CI/CD プロセスの次の目標を検討してください。

  • 各チームは、他のチームに影響を与えたり妨害したりすることなく、独立に所有するサービスを構築およびデプロイできます。

  • 新しいバージョンのサービスが運用環境にデプロイされる前に、検証のために開発/テストおよび QA 環境にデプロイされます。 品質ゲートは、各段階で適用されます。

  • サービスの新しいバージョンは、以前のバージョンと並行してデプロイできます。

  • 十分なアクセス制御ポリシーが用意されています。 パイプラインは、有効期間の長いシークレットではなく、フェデレーションされた有効期間の短い資格情報を使用してAzureに対して認証を行います。

  • コンテナー化されたワークロードの場合は、運用環境にデプロイされているコンテナー イメージを信頼できます。 その信頼は、署名されたイメージ、ソフトウェア部品表 (SBOM) 構成証明、およびパイプラインに適用される脆弱性スキャンによって確立されます。

堅牢な CI/CD パイプラインが重要な理由

従来のモノリシック アプリケーションでは、1 つのビルド パイプラインによってアプリケーション実行可能ファイルが生成されます。 開発作業はすべて、このパイプラインにフィードされます。 チームが優先度の高いバグを見つけた場合は、修正プログラムを統合、テスト、公開する必要があります。この場合、新機能のリリースが遅れる可能性があります。 これらの問題を軽減するには、十分に考慮されたモジュールと機能分岐を使用して、コード変更の影響を制限します。 しかし、アプリケーションがより複雑になり、機能が追加されるにつれて、モノリスのリリース プロセスがより複雑になり、失敗する可能性が高くなります。

マイクロサービスの理念によると、すべてのチームが列に並ぶ必要がある長いリリース トレーニングは決してありません。 サービス A をビルドするチームは、選択した時点で更新プログラムをリリースでき、サービス B の変更がマージ、テスト、デプロイされるまで待つ必要はありません。

モノリスアーキテクチャとマイクロサービス アーキテクチャの CI/CD を比較した図。

高いリリース速度を実現するには、リスクを最小限に抑えるために、リリース パイプラインを自動化し、信頼性を高める必要があります。 運用環境に 1 日に 1 回以上リリースする場合、回帰やサービスの中断はまれである必要があります。 同時に、不適切な更新プログラムをデプロイする場合は、以前のバージョンのサービスにすばやくロールバックまたはロールフォワードするための信頼性の高い方法が必要です。

Challenges

  • 多数の小さな独立したコード ベース: 各チームは、独自のビルド パイプラインを使用して独自のサービスを構築する責任があります。 組織によっては、チームが個別のコード リポジトリを使用する場合があります。 個別のリポジトリを使用すると、チーム間でシステムを構築する方法に関する知識を分散させることができます。 その結果、組織内の誰もアプリケーション全体をデプロイする方法を知りません。

    緩和: 統合された自動化されたパイプラインまたは少なくとも一般的なパイプライン インフラストラクチャを用意して、サービスを構築してデプロイし、この知識が各チーム内に隠されないようにします。 再利用可能なパイプライン テンプレート (GitHub Actions再利用可能なワークフローAzure Pipelines テンプレート など) は、すべてのサービスでビルド、テスト、スキャン、デプロイの手順を標準化するのに役立ちます。

  • 複数の言語とフレームワーク: 各チームは独自のテクノロジを組み合わせて使用するため、ワークロード全体で動作する 1 つのビルド プロセスを作成するのは困難な場合があります。 ビルド プロセスは、すべてのチームが選択した言語またはフレームワークに合わせて調整できる十分な柔軟性を備えている必要があります。

    緩和: ビルド システムがコンテナーを実行するだけで済むように、各サービスのビルド プロセスをコンテナー化します。 GitHub Actions、Azure Pipelines、Azure Container Registry タスクなどのプラットフォームは、ソース言語に関係なく、コンテナー イメージを一貫してビルドして発行できます。

  • 統合とロード テスト: Teams は独自のペースで更新プログラムをリリースするため、サービスが他のサービスに依存している場合は特に、堅牢なエンドツーエンドのテストを設計するのは困難な場合があります。 完全な運用クラスターの実行にはコストがかかる可能性があるため、すべてのチームがテスト専用の実稼働スケールで独自のフル クラスターを実行する可能性は低くなります。

    Mitigation: 必要に応じて作成される Kubernetes または Azure Container Apps 環境 のプル要求ごとの名前空間など、エフェメラル プレビュー環境を使用します。 コントラクト テストを使用して、運用環境の完全な複製を必要とせずに、統合の問題を早期に解決できるようにします。

  • リリース管理: すべてのチームは、運用環境に更新プログラムをデプロイできる必要があります。 この要件は、すべてのチーム メンバーがデプロイするアクセス許可を持っていることを意味するわけではありません。 一元化されたリリース マネージャー ロールを使用すると、展開速度を低下させることができます。

    緩和: CI/CD プロセスが自動化され、信頼性が高いほど、中央機関は必要なくなります。 主要な機能更新プログラムのリリースと軽微なバグ修正に関して、引き続き異なるポリシーが適用される場合があります。 分散化されたアプローチは、ガバナンスがゼロを意味するわけではありません。 Azure Pipelines環境と承認またはGitHub Actions展開環境と必要なレビュー担当者を使用して承認を適用し、Azure Kubernetes Service (AKS)にAzure Policyを使用してクラスター側ポリシーを体系化します または OPA Gatekeeper

  • サービスの更新: サービスを新しいバージョンに更新する場合、更新によって、それに依存する他のサービスが失敗しないようにする必要があります。

    緩和策: 後方互換性を損なわない変更には、ブルーグリーンデプロイやカナリアリリースなどのデプロイ手法を用います。 API の破壊的変更については、新しいバージョンを以前のバージョンと並行してデプロイします。 この方法では、以前の API を使用するサービスを更新し、新しい API についてテストできます。 詳細については、「サービスの 更新」を参照してください。

  • パイプライン ID とシークレット管理: パイプラインに格納されている有効期間の長いサービス プリンシパル シークレットは、侵害と運用作業の頻繁な原因です。 サービス プリンシパル シークレットの有効期限が切れ、リークする可能性があり、多数の独立したマイクロサービス パイプライン間でローテーションが必要になる可能性があります。

    Mitigation: OpenID Connect (OIDC) を使用するワークロード ID フェデレーションでAzureするようにパイプラインを認証するため、クライアント シークレットはパイプラインに格納されません。 詳細については、Azure Pipelines のワークロード ID および GitHub Actions のための Azure での OpenID Connect の構成 を参照してください。 残りのシークレットを Azure Key Vault に格納し、実行時に参照します。

  • サプライ チェーンのセキュリティ: 運用環境に出荷するものはすべて、それがビルドされたコードと依存関係まで追跡可能である必要があります。 マイクロサービスにより、イメージ、レジストリ、パイプラインの数が増え、サプライ チェーン攻撃対象領域が増加します。

    軽減策:Notation と Key Vault を使用してコンテナー イメージに署名し、AKS image integrity または Ratify を使用してアドミッション時に署名を検証します。 ビルド成果物として SBOM を生成します。 Microsoft Defender for Cloud DevOps セキュリティおよび GitHub Advanced Security を使用して、コード、依存関係、パイプラインをスキャンします。 Microsoft Defender for Containers を使用してランタイム イメージをスキャンします。 リリースを続行する前に、すべてのスキャンを成功させる必要があります。

Monorepo と multirepo

CI/CD ワークフローを作成する前に、次のようなコード ベースの構造と管理方法を把握しておく必要があります。

  • チームが別々のリポジトリで作業するか、モノレポで作業するか。
  • 分岐戦略。
  • 運用環境にコードをプッシュできるユーザーと、リリース マネージャーが存在するかどうか。

Teams は、運用環境で両方のアプローチを広く使用しています。 選択は、チーム トポロジ、ツールの成熟度、サービス間で共有されるコードの量によって異なります。

  モノレポ 複数のリポジトリ
利点 - コード共有

- コードとツールの標準化が容易

- コードのリファクタリングが簡単

- 検出可能性 (コードの単一ビュー)
- チームごとの所有権のクリア

- マージ競合が減る可能性がある

- マイクロサービスの分離を強制するのに役立ちます
課題 - 共有コードの変更が複数のマイクロサービスに影響する可能性があります

- マージ競合の可能性が高い

- ツールは大規模なコード ベースにスケーリングする必要があります

- アクセス制御

- より複雑なデプロイ プロセス
- コードを共有するのが難しい

- コーディング標準の適用が困難

- 依存関係の管理

- 拡散コード ベース、検出可能性が低い

- 共有インフラストラクチャの不足

どのモデルを選択する場合でも、パイプラインでは、GitHub Actions のパス フィルターAzure Pipelines のトリガー パス など、パス スコープのトリガーを使用してください。 パス スコープトリガーは、影響を受けるマイクロサービスのみが各コミットで再構築および再デプロイされるようにするのに役立ちます。

サービスを更新する

ローリング アップデート、ブルーグリーン デプロイ、カナリア リリースなど、既に運用環境にあるサービスを更新するためのさまざまな戦略があります。 これらのパターンは、多くの場合、GitOps ワークフローを通じて調整されます。 詳細については、「 GitOps とプログレッシブ 配信」を参照してください。

ローリングアップデート

ローリング アップデートでは、サービスの新しいインスタンスをデプロイすると、新しいインスタンスは要求の受信をすぐに開始します。 新しいインスタンスの準備ができたら、前のインスタンスが削除されます。

Kubernetes の例: Kubernetes では、 デプロイのポッド 仕様を更新するときの既定の動作はローリング更新です。 デプロイ コントローラーは、更新されたポッドの新しい ReplicaSet を作成します。 次に、新しい ReplicaSet をスケールアップし、前の ReplicaSet をスケールダウンして目的のレプリカ数を維持します。 新しいポッドの準備ができるまで、以前のポッドは削除されません。 Kubernetes は更新プログラムの履歴を保持するため、必要に応じて更新プログラムをロールバックできます。

Container Apps の例: Container Apps では 、リビジョン を使用してローリング更新プログラムを管理します。 新しいリビジョンをデプロイすると、Container Apps はトラフィック分割ルールを使用して、以前のリビジョンから新しいリビジョンにトラフィックを徐々にシフトできます。 新しいリビジョンで問題が発生した場合は、トラフィックを以前のリビジョンにリダイレクトすることでロールバックできます。 複数のアクティブなリビジョンを同時に構成し、各リビジョンが受信するトラフィックの割合を制御できます。

ローリングアップデートの課題の 1 つは、更新処理中に旧バージョンと新バージョンが混在したまま稼働し、トラフィックを処理することです。 この期間中、システムは任意の要求をいずれかのバージョンにルーティングできます。

API の破壊的変更については、前のバージョンのすべてのクライアントが更新されるまで、両方のバージョンを並行してサポートすることをお勧めします。 詳細については、「API の バージョン管理」を参照してください。

ブルーグリーンデプロイメントとは、環境Aと環境Bを交互に使用して新しいソフトウェアをリリースする手法です。

青緑色のデプロイでは、以前のバージョンと共に新しいバージョンをデプロイします。 新しいバージョンを検証したら、すべてのトラフィックを以前のバージョンから新しいバージョンに一度に切り替えます。 スイッチの後、アプリケーションで問題が発生した場合は監視します。 問題が発生した場合は、トラフィックを以前のバージョンに切り替えることができます。 問題がない場合は、以前のバージョンを削除できます。

従来のモノリシックまたは N 層アプリケーションでは、ブルーグリーン デプロイは通常、同じ 2 つの環境を作成することを意味します。 新しいバージョンをステージング環境にデプロイし、仮想 IP アドレスをスワップするなどの方法で、クライアント トラフィックをその環境にリダイレクトします。 マイクロサービス アーキテクチャでは、更新はマイクロサービス レベルで行われるため、通常は同じ環境に更新プログラムをデプロイし、サービス検出メカニズムを使用してトラフィックを切り替えます。

Kubernetes の例: Kubernetes では、ブルーグリーンデプロイを行うために別のクラスターを作成する必要はありません。 代わりに、セレクターを利用できます。 新しいポッド スペックと別のラベル セットを使用して、新しい デプロイ リソースを作成します。 このデプロイを作成しますが、以前のデプロイを削除したり、それを指すサービスを変更したりしないでください。 新しいポッドが実行されたら、新しいデプロイに合わせてサービスのセレクターを更新できます。

ブルーグリーンデプロイの欠点の 1 つは、更新中に、サービスのポッドの 2 倍の数 (現在と次のポッド) を実行することです。 ポッドで大量の CPU またはメモリ リソースが使用されている場合は、より高いリソース需要を満たすためにクラスターを一時的にスケールアウトすることが必要になる場合があります。

カナリアリリース

カナリア リリースでは、更新されたバージョンをクライアントの小さなサブセットに展開し、すべてのクライアントに展開する前に新しいサービスの動作を監視します。 このアプローチでは、制御された方法で段階的にロールアウトし、実際のデータを監視し、問題がすべての顧客に影響を与える前に特定することができます。

カナリア リリースは、異なるバージョンのサービスに要求を動的にルーティングする必要があるため、ブルーグリーンまたはローリング 更新プログラムよりも管理が複雑です。

Kubernetes の例: Kubernetes では、2 つのレプリカ セット (バージョンごとに 1 つ) にまたがる サービス を構成し、レプリカ数を手動で調整できます。 ただし、Kubernetes がポッド間で負荷分散を行う方法により、この方法は粒度が粗くなります。 たとえば、合計 10 個のレプリカがある場合は、10% 増分でのみトラフィックをシフトできます。 サービス メッシュを使用する場合は、サービス メッシュ ルーティング規則を使用して、より高度なカナリア リリース戦略を実装できます。

Container Apps の例: Container Apps では、 トラフィック分割 を使用して、定義された割合のトラフィックを新しいリビジョンに送信し (10% を v2 し、90% は v1に留まります)、信頼度が高まるにつれて重みをシフトできます。外部サービス メッシュは必要ありません。

プログレッシブ配信と GitOps

Kubernetes で多数のマイクロサービスを運用するチームの場合、GitOps プルベースモデルは、以前のプッシュベースの例を補完します。 目的のクラスターの状態は Git に存在し、クラスター内オペレーターはクラスターをその状態に調整します。 CI は、イメージのビルド、テスト、スキャン、署名、プッシュを行います。 CD は、クラスターをマニフェストに調整します。 この分離により、監査証跡とディザスター リカバリー (DR) が容易になります。 また、CI ランナーが直接クラスター資格情報を保持する必要がなくなります。

次のステップ