Azure DevOpsと Helm を使用して Kubernetes 上のマイクロサービス用の CI/CD パイプラインを構築する

マイクロサービス アーキテクチャの信頼性の高い継続的インテグレーションと継続的デリバリー (CI/CD) プロセスの作成は困難な場合があります。 各チームは、他のチームを中断したり、アプリケーション全体を不安定にしたりすることなく、迅速かつ確実にサービスをリリースする必要があります。

この記事では、マイクロサービスを Azure Kubernetes Service (AKS) にデプロイするための CI/CD パイプラインの例について説明します。 すべてのチームやプロジェクトはそれぞれ異なるので、この記事を一連の厳格な規則としては考えないでください。 代わりに、独自の CI/CD プロセスを設計するための開始点として使用してください。

次の一覧は、Kubernetes でホストされるマイクロサービスの CI/CD パイプラインの目標をまとめたものです。

  • チームは、サービスを個別に構築およびデプロイすることができます。
  • CI プロセスを渡すコード変更は、運用環境に似た環境に自動的にデプロイされます。
  • パイプラインの各ステージでは、品質ゲートが適用されます。
  • サービスの新しいバージョンは、以前のバージョンと並行してデプロイできます。

詳細については、 マイクロサービス アーキテクチャの CI/CD を参照してください。

前提条件

この例では、開発チームとコード ベースに関するいくつかの前提条件を次に示します。

  • コード リポジトリは単一リポジトリであり、フォルダーがマイクロサービス別に整理されています。
  • チームのブランチ戦略は、トランクベース開発に基づいています。
  • チームは、リリース ブランチを使用してリリースを管理します。 マイクロサービスごとに個別のリリースが作成されます。
  • CI/CD プロセスでは、Azure Pipelines を使用して、マイクロサービスをビルド、テスト、および AKS にデプロイします。
  • すべてのマイクロサービスのコンテナー イメージは、1 つの共有Azure Container Registry インスタンスに格納され、マイクロサービスごとに個別のリポジトリが用意されています。 Container Registry Azure ABAC リポジトリのアクセス許可を使用して、各パイプライン ID のスコープを独自のリポジトリに設定するか、より強力な信頼境界が必要な場合は個別のレジストリを使用します。
  • チームは、Helm chart を使用して各マイクロサービスをパッケージ化します。
  • プッシュ デプロイ モデルが使用されます。Azure Pipelinesおよび関連付けられているエージェントは、AKS クラスターに直接接続してデプロイを実行します。

これらの想定によって、CI/CD パイプラインの特定の詳細の多くが設定されます。 ただし、ここで説明する基本的なアプローチは、GitHub Actions、Jenkins、Docker Hubなど、他のプロセス、ツール、サービスに合わせて調整できます。

Alternatives

AKS で CI/CD 戦略を選択する場合は、次の一般的な代替手段を検討してください。

  • Helm をパッケージ管理およびデプロイ ツールとして使用する代わりに、 Kustomize (Kubernetes ネイティブ構成管理ツール) を使用して、アプリケーション構成をカスタマイズおよびパラメーター化するためのテンプレートなしの方法を導入できます。

  • Git リポジトリとパイプラインにAzure DevOpsを使用する代わりに、プライベート Git リポジトリとパブリック Git リポジトリにGitHub リポジトリを使用し、CI/CD パイプラインにGitHub Actionsできます。

    GitHub Actionsは、AKS とスターター ワークフローの統合を提供し、OpenID Connect (OIDC) をサポートして、Azureに対するセキュリティで保護されたシークレットレス認証を実現します。

  • プッシュ デプロイ モデルを使用する代わりに、 GitOps (プル デプロイ モデル) を使用して Kubernetes 構成を大規模に管理することを検討してください。 FluxArgo CD などのクラスター内 Kubernetes オペレーターは、Git リポジトリに格納されている構成に基づいてクラスターの状態を同期します。 GitOps を使用すると、パイプラインが直接クラスターにアクセスする必要がなくなり、攻撃対象領域が減少し、自己復旧機能とドリフト検出機能が提供されます。

    Tip

    プッシュベースのデプロイ モデルとプルベース (GitOps) デプロイ モデルを評価する場合は、ワークロードの要件を考慮してください。 プッシュベースのデプロイでは、確定的な更新と直接パイプライン制御が提供されます。これは、安全なデプロイプラクティスに適しています。 プルベース (GitOps) デプロイでは、整合性、監査可能性、自己復旧が提供されるため、クラスターがパイプラインからクラスターへの直接アクセスなしで目的の状態に対して調整する必要がある環境に最適です。

検証ビルド

開発者が Delivery Service というマイクロサービスに取り組んでいるとします。 新しい機能を開発する場合、開発者はコードを機能ブランチにチェックインします。 慣例により、機能ブランチは feature/* と名付けられます。

機能ブランチ ワークフローの図。

この図は、2 本の水平 Git 分岐線と、その下にビルド パイプラインを示しています。 上部にはメインブランチがあり、水平線として表されます。 機能/8150 ブランチはメインから分岐します。 このブランチには、3 つのドットが配置され、まとめてラベル付けされたコミットがあります。 3 つのコミットのそれぞれから、図の下部にあるボックスに向かって下向きの矢印が表示されます。 ボックスには [ビルド パイプライン] というラベルが付き、パイプライン名 ci-delivery-validation が含まれています。 3 つの破線の矢印はすべて、この単一のビルド パイプライン ボックスに収束し、機能/8150 ブランチへの各コミットによって ci-delivery-validation パイプラインの実行がトリガーされることを示します。

ビルド定義ファイルには、次のように、ブランチ名とソース パスでフィルター処理するトリガーが含まれます。

trigger:
  batch: true
  branches:
    include:
    # for new release to production: release flow strategy
    - release/delivery/v*
    - refs/release/delivery/v*
    - main
    - feature/delivery/*
    - topic/delivery/*
  paths:
    include:
    - /src/shipping/delivery/

このアプローチを使用する場合、各チームは独自のビルド パイプラインを持つことができます。 /src/shipping/delivery フォルダーにチェックインされたコードのみが配信サービスのビルドをトリガーします。 フィルターに一致するブランチにコミットをプッシュすると、CI のビルドがトリガーされます。 ワークフローのこの時点で、CI ビルドでは、いくつかの最小限のコードの検証が実行されます。

  1. コードをビルドする。
  2. 単体テストを実行する。

ビルド時間を短くして、開発者がすばやくフィードバックを取得できるようにすることが目標です。 この機能をメインにマージする準備ができたら、開発者は PR を開きます。 この操作は、いくつかの追加のチェックを実行する別の CI ビルドをトリガーします。

  1. コードをビルドする。
  2. 単体テストを実行する。
  3. ソース コードで静的アプリケーション セキュリティ テスト (SAST) を実行します。
  4. ランタイム コンテナー イメージをビルドする。
  5. イメージに対して脆弱性スキャンを実行する。

ビルドパイプライン内の ci-delivery-full を示す図。

この図は、2 本の水平 Git 分岐線と、その下にビルド パイプラインを示しています。 上部にはメインブランチがあり、水平線として表されます。 その下には、機能/8150 ブランチが並列に実行され、コミットを表す 3 つのドットがあります。 機能/8150 分岐の右端では、破線の矢印がメイン ブランチ上のポイントに接続されます。 このポイントには、PR というラベルが付いた別のドットが付いています。これは、プル要求がメインに対して開かれたことを示します。 メイン ブランチの PR ポイントから、パイプライン名 ci-delivery-full を含む [ビルド パイプライン] というラベルのボックスを下方向に破線で示します。 この行は、機能ブランチからメインにプル要求を開くと ci-delivery-full パイプラインがトリガーされ、CI チェックの拡張セットが実行されることを示しています。

Azure DevOpsのサービスの 1 つであるAzure Reposでは、ブランチを保護するポリシーを定義できます。 たとえば、ポリシーでは、メインにマージする前に、CI ビルドの成功と承認者からのサインオフが必要になる場合があります。

完全な CI/CD ビルド

チームが新しいバージョンの Delivery Service をデプロイする準備ができたら、リリース マネージャーは、 release/<microservice name>/<semver>という名前付けパターンを使用して、メイン ブランチからブランチを作成します。 たとえば、「 release/delivery/v1.0.2 」のように入力します。

ビルド パイプラインをトリガーするリリース ブランチとリリース パイプラインを示す図。

この図は、3 つの水平 Git 分岐線とその下に 2 つのパイプラインを示しています。 中央にはメインブランチがあり、水平線として表されます。 主な機能/8150 ブランチの下には、コミットを表す 3 つのドットがあります。 feature/8150 ブランチは、マージというラベルが付いたポイントでメイン ブランチに接続され、フィーチャー ブランチがメインにマージされていることを示します。 メイン ブランチの上と右側に、release/delivery/v1.0.2 というラベルが付いた新しいブランチが右側に拡張されます。 このリリース ブランチは、マージの右側にある main から開始されます。 リリース/配信/v1.0.2 ブランチから、破線は ci-delivery-full というラベルが付いたボックス (ビルド パイプラインの上) を下向きにします。 ci-delivery-full の右側にある水平矢印は、cd-delivery というラベルが付いた 2 つ目のボックスを指し示します。これは、Release パイプラインというラベルの上にあります。

このブランチを作成すると、前のすべての手順と次の手順を実行する完全な CI ビルドがトリガーされます。

  1. コンテナー イメージをコンテナー レジストリにプッシュします。 イメージには、ブランチ名のバージョン番号がタグ付けされます。
  2. helm package を実行して、サービス用の Helm chart をパッケージ化する。 この chart にもバージョン番号がタグ付けされます。
  3. Helm パッケージを Container Registry にプッシュする。

このビルドが成功すると、Azure Pipelinesリリース パイプラインを使用してデプロイ (CD) プロセスがトリガーされます。 このパイプラインには、次の手順が含まれています。

  1. Helm chart を QA 環境にデプロイする。
  2. パッケージが運用環境に移動される前に、承認者がサインオフする。 「Release deployment control using approvals (承認を使用したリリース デプロイ制御)」をご覧ください。
  3. Container Registry で運用名前空間の Docker イメージにタグを付け直します。 たとえば、現在のタグが myrepo.azurecr.io/delivery:v1.0.2 の場合、運用タグは myrepo.azurecr.io/prod/delivery:v1.0.2 になります。
  4. Helm chart を運用環境にデプロイする。

モノレポでも、チームが個別にデプロイできるように、これらのタスクのスコープを個々のマイクロサービスに設定します。 このプロセスには、PR の承認、リリース ブランチの作成、運用クラスターへのデプロイの承認など、いくつかの手動手順が含まれています。 ワークロード チームは、必要に応じてこれらの手順を自動化できます。

環境の分離

開発、スモーク テスト、統合テスト、ロード テスト、運用環境などの複数の環境にサービスをデプロイします。 これらの環境には、あるレベルの分離が必要です。 Kubernetes では、物理的な分離と論理的な分離のどちらかを選択できます。 物理的分離は、個別のクラスターにデプロイされます。 論理的な分離では、名前空間とポリシーが使用されます。

開発/テスト環境用の個別のクラスターと共に専用の運用クラスターを作成することをお勧めします。 開発/テスト クラスター内の環境を分離するには、論理的な分離を使用します。 開発/テスト クラスターにデプロイされたサービスには、ビジネス データを保持するデータ ストアへのアクセス権を与えるべきではありません。

クラスター内で分離を強制するには、次の手順を実行します。

認証と承認

マイクロサービスをデプロイするパイプラインと、それらのパイプラインがデプロイするワークロードの両方に、可能な限りシークレットレス認証を使用します。

  • パイプラインのワークロード ID フェデレーション: Azure Pipelinesの場合は、ワークロード ID フェデレーション サービス接続を使用して、有効期間の長いサービス プリンシパル シークレットを格納せずにAzureに対する認証を行います。 GitHub Actionsの場合は、同じシークレットレス認証を実現するように OIDC を構成します。
  • デプロイされたワークロードのMicrosoft Entra ワークロード ID : マニフェスト、Helm 値、または Kubernetes シークレットを介して資格情報を挿入するのではなく、Microsoft Entra ワークロード ID を使用するようにパイプラインがデプロイするマイクロサービスを構成します。 ワークロード ID は Kubernetes サービス アカウントを Microsoft Entra ID とフェデレーションし、パイプラインでシークレットを管理することなく、ポッドがAzure サービス (Azure Key Vault、Container Registry、Azure SQL など) に対して認証できるようにします。

シークレットの管理

ソース コード、Dockerfile、Helm 値ファイル、またはパイプライン定義にシークレット (接続文字列、API キー、データベース パスワード) を直接埋め込むことはありません。 その代わりに:

Important

有効期間の長い資格情報 (クライアント シークレット、証明書、またはパスワード) は、パイプライン変数、環境変数、または Kubernetes シークレットに格納しないでください。 代わりに、マネージド ID とフェデレーション資格情報を使用して、資格情報のローテーションの負担と攻撃対象領域を減らします。

ビルドプロセス

可能であれば、ご自分のビルド プロセスを Docker コンテナーにパッケージ化します。 この構成により、各ビルド マシンでビルド環境を構成することなく、Docker を使用してコード成果物をビルドできます。 コンテナー化されたビルド プロセスでは、新しいビルド エージェントを追加することで CI パイプラインのスケールアウトが簡略化されます。 また、チームの開発者は、ビルド コンテナーを実行してコードをビルドできます。

Docker でマルチステージ ビルドを使用すると、ビルド環境とランタイム イメージを 1 つの Dockerfile で定義できます。 たとえば、次の Dockerfile は、.NET 10 アプリケーションをビルドします。

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
USER app
WORKDIR /app
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src/Fabrikam.Workflow.Service

COPY Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.csproj

COPY Fabrikam.Workflow.Service/. .
RUN dotnet build Fabrikam.Workflow.Service.csproj -c Release -o /app/build --no-restore

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

FROM build AS publish
RUN dotnet publish Fabrikam.Workflow.Service.csproj -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Fabrikam.Workflow.Service.dll"]

この Dockerfile では、いくつかのビルド ステージが定義されます。 baseという名前のステージでは、.NET 10 ASP.NET ランタイム イメージが使用されますが、build という名前のステージでは完全な .NET 10 SDK が使用されていることに注意してください。 build ステージは、.NET プロジェクトをビルドします。 しかし、最終的なランタイム コンテナーは base から作成されます。これは、ランタイムしか含まないので、完全な SDK イメージよりかなり小さくなっています。

Important

.NET 8 以降、公式の Linux ベースの.NET コンテナー イメージには、appという非ルート ユーザーが含まれています。 Dockerfile の USER app 命令は、最小特権の原則に従って、この非特権ユーザーとしてコンテナーを実行します。 コンテナー イメージ ASP.NET Core、既定のリッスン ポートも 80 から 8080 に変更されました。

テストランナーの構築

もう 1 つのおすすめできる方法は、コンテナー内で単体テストを実行することです。 たとえば、次のコードは、テスト ランナーを構築する Dockerfile の一部を示しています。

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

開発者は、次の Dockerfile を使用してテストをローカルで実行できます。

docker build . -t delivery-test:1 --target=testrunner
docker run delivery-test:1

また、CI パイプラインでは、ビルド検証手順の一環としてテストが実行される必要があります。

このファイルでは、Docker RUN コマンドではなく Docker ENTRYPOINT コマンドを使用してテストを実行します。

  • RUN コマンドを使用した場合は、イメージをビルドするたびにテストが実行されます。 ENTRYPOINTを使用する場合、テストはオプトインされます。 testrunner ステージを明示的にターゲットとした場合に限り、テストが実行されます。
  • テストの失敗により、Docker の build コマンドが失敗することはありません。 この動作により、コンテナービルドの失敗とテストエラーを区別できます。
  • テストの結果は、マウントされたボリュームに保存できます。

コンテナーのベスト プラクティス

コンテナーについて考慮すべきその他のベスト プラクティスを次に示します。

  • クラスターにデプロイされたリソース (ポッドやサービスなど) のコンテナー タグ、バージョン管理、名前付け規則に関する組織全体の規則を定義します。 これらの規則を使用すると、デプロイの問題を簡単に診断できます。
  • 開発とテストのサイクル中に、CI/CD プロセスによって多数のコンテナー イメージがビルドされます。 これらのイメージの一部のみがリリースの候補であり、それらのリリース候補の一部のみが運用環境に昇格します。 現在運用環境にデプロイされているイメージを把握し、必要に応じて以前のバージョンに簡単にロールバックできるように、明確なバージョン管理戦略を用意します。
  • latest ではなく、特定のバージョン タグを常にデプロイしてください。
  • Container Registry の 名前空間を 使用して、運用環境で承認されたイメージを、まだテスト中のイメージから分離します。 運用環境にデプロイする準備ができるまで、イメージを運用名前空間に移動しないでください。 このプラクティスとコンテナー イメージのセマンティック バージョン管理を組み合わせると、リリースが承認されていないバージョンを誤ってデプロイする可能性が低くなります。
  • コンテナーを特権のないユーザーとして実行して、最小特権の原則に従います。 Kubernetes では、 ポッド セキュリティ標準ポッド セキュリティ アドミッション (Kubernetes 1.25 の非推奨のポッド セキュリティ ポリシーに代わる) を使用して、コンテナーがルートとして実行されないようにするなどの制限を適用します。 運用環境のワークロードには、 restricted プロファイルを使用します。
  • コンテナー イメージの攻撃対象領域を減らすには、最小限またはディストリビューションレスの基本イメージ (Alpine ベースのイメージ、linux ベースイメージまたはディストリビューションレス イメージAzure、.NETイメージなど) を使用します。
  • Premium レジストリの場合は、タグ付けされていないマニフェストを削除するように Container Registry アイテム保持ポリシー を構成します。 タグを年齢または名前で消去するには、 acr purge を実行する Container Registry タスクをスケジュールします。 アクティブなデプロイとロールバック 計画が参照するイメージを保持します。

Helm チャート

Helm を使用してサービスの構築やデプロイを管理することを考慮してください。 次の Helm 機能は、CI/CD パイプラインをサポートしています。

  • 1 つのマイクロサービスは、多くの場合、複数の Kubernetes オブジェクトによって定義されます。 Helm を使用すると、これらのオブジェクトを 1 つの Helm チャートにパッケージ化できます。
  • 一連の kubectl コマンドではなく、1 つの Helm コマンドを使用してグラフをデプロイできます。
  • グラフは明示的にバージョン管理されます。 Helm を使用して、バージョンのリリース、リリースの表示、および以前のバージョンへのロールバックを行います。 Helm では、セマンティック バージョン管理を使用して更新とリビジョンを追跡します。
  • Helm chart では、多数のファイルにわたる情報の複製 (ラベルやセレクターなど) を回避するためにテンプレートが使用されます。
  • Helm では、chart 間の依存関係を管理できます。
  • コンテナー レジストリなどの Helm リポジトリにグラフを格納し、それらをビルド パイプラインに統合できます。

詳細については、「 アプリケーション グラフの Helm リポジトリとしてコンテナー レジストリを使用する」を参照してください

1 つのマイクロサービスに複数の Kubernetes 構成ファイルが必要な場合があります。 サービスを更新するには、セレクター、ラベル、およびイメージ タグを更新するために、これらのファイルをすべて編集する必要がある場合があります。 Helm は、これらのファイルを グラフ と呼ばれる 1 つのパッケージとして扱い、変数を使用して YAML ファイルを簡単に更新できるようにします。 Helm では、パラメーター化された YAML 構成ファイルを記述できるテンプレート言語 (Go テンプレートに基づく) を使用します。

たとえば、デプロイを定義する YAML ファイルの一部を次に示します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "package.fullname" . | replace "." "" }}
  labels:
    app.kubernetes.io/name: {{ include "package.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

...

spec:
  template:
    spec:
      containers:
      - name: &package-container_name fabrikam-package
        image: {{ .Values.dockerregistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        - name: LOG_LEVEL
          value: {{ .Values.log.level }}

デプロイ名、ラベル、コンテナー スペックはすべて、デプロイ時に指定したテンプレート パラメーターを使用していることがわかります。 たとえば、コマンドラインから次を実行します。

helm install <release-name> oci://<registry>/<repository>/<package-chart-name> --version <desiredVersion> \
     --set image.tag=0.1.0 \
     --set image.repository=package \
     --set dockerregistry=$ACR_SERVER \
     --namespace backend

CI/CD パイプラインでは、Kubernetes にグラフを直接インストールできますが、グラフ アーカイブ (.tgz ファイル) を作成し、コンテナー レジストリなどの Helm リポジトリにグラフをプッシュします。 詳細については、「 Helm チャートのパッケージ化とデプロイ (HelmDeploy タスク)」を参照してください。

改訂

Helm グラフには、 セマンティック バージョン管理を使用する必要があるバージョン番号が常に含まれます。 チャートにはappVersionを追加することもできます。 このフィールドは省略可能であり、グラフのバージョンに関連付ける必要はありません。 一部のチームでは、グラフの更新とは別にアプリケーションのバージョン管理を行う必要がある場合があります。 より簡単な方法は、1 つのバージョン番号を使用することです。そのため、グラフのバージョンとアプリケーションのバージョンの間には 1 対 1 の関係があります。 そうすれば、リリースごとに 1 つの chart を格納して、必要なリリースを簡単にデプロイすることができます。

helm install <package-chart-name> --version <desiredVersion>

もう 1 つ、次のようにデプロイ テンプレート内に change-cause 注釈を指定することをお勧めします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "delivery.fullname" . | replace "." "" }}
  labels:
     ...
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

この注釈を使用すると、 kubectl rollout history コマンドを使用して、各リビジョンの変更原因フィールドを表示できます。 前の例では、変更原因は Helm チャート パラメーターとして提供されています。

kubectl rollout history deployments/delivery-v010 -n backend
deployment.apps/delivery-v010
REVISION  CHANGE-CAUSE
1         Initial deployment

helm list コマンドを使用して、次のようにリビジョン履歴を表示することもできます。

helm list -n backend
NAME              NAMESPACE   REVISION    UPDATED                                 STATUS      CHART               APP VERSION
delivery-v0.1.0   backend     1           2024-04-07 00:25:30.000000 +0000 UTC    deployed    delivery-v0.1.0     v0.1.0

Azure Pipelines

Azure Pipelines、Azure DevOpsのサービスには、ビルド パイプラインとリリース パイプラインという 2 種類のパイプラインがあります。 ビルド パイプラインでは、CI プロセスが実行され、ビルド成果物が作成されます。 Kubernetes 上のマイクロサービス アーキテクチャの場合、これらの成果物は、各マイクロサービスを定義するコンテナー イメージと Helm chart です。 リリース パイプラインは、マイクロサービスをクラスターにデプロイする CD プロセスを実行します。

この記事で前述した CI フローに基づいて、ビルド パイプラインは次のタスクで構成される可能性があります。

  1. Docker タスクを使用してテスト ランナー コンテナーをビルドします。
  2. Docker タスクを使用して、テスト ランナー コンテナーに対してdocker runを呼び出してテストを実行します。
  3. PublishTestResults タスクを使用してテスト結果を発行します。 詳細については、「 イメージのビルド」を参照してください。
  4. ソース コードで SAST を実行します。
  5. ローカル docker buildDocker タスクを使用するか、Container Registry ビルドと AzureCLI タスクを使用して、ランタイム コンテナーをビルドします。 たとえば、Microsoft SBOM ツールを使用して、イメージのソフトウェア部品表 (SBOM) を生成し、イメージ ダイジェストに関連付けられたパイプライン成果物として発行するか、Container Registry のイメージにアタッチします。
  6. コンテナー イメージの脆弱性スキャン (たとえば、コンテナーのMicrosoft Defenderや Trivy などのMicrosoft以外のツールを使用して) を実行して、イメージが公開される前に既知の脆弱性を検出します。
  7. DockerまたはAzureCLI タスクを使用して、コンテナー イメージを Container Registry (または別のコンテナー レジストリ) にプッシュします。
  8. 変更できないダイジェストによってプッシュされたイメージに署名し、その整合性と信頼性を確保します。 Azure Pipelinesについては、表記署名のガイダンスに従ってください。
  9. HelmDeploy タスクを使用して Helm チャートをパッケージ化します。
  10. HelmDeploy タスクを使用して、Helm パッケージを Container Registry (または別の Helm リポジトリ) にプッシュします。

CI パイプラインからの出力は、実稼働可能なコンテナー イメージと、マイクロサービスの更新された Helm chart です。 この時点では、リリース パイプラインが管理を引き継ぎます。 マイクロサービスごとに一意のリリース パイプラインがあります。 リリース パイプラインは、成果物を発行した CI パイプラインにトリガー ソースが設定されるように構成されます。 このパイプラインを使用すると、各マイクロサービスを個別にデプロイできます。 リリース パイプラインは、次のステップを実行します。

  1. Helm チャートを開発/QA/ステージングの環境にデプロイします。 helm upgrade コマンドを --install フラグと共に使用して、最初のインストール以降のアップグレードをサポートできます。
  2. 承認者がデプロイを承認または却下するのを待機する。
  3. リリース用にコンテナー イメージにタグを付け直します。
  4. リリース タグをコンテナー レジストリにプッシュする。
  5. 運用環境クラスターに Helm chart をデプロイする。 ratify とAzure Policyを使用して、受付中にイメージ署名を検証し、イメージを信頼されたレジストリに制限するように許可イメージ ポリシーを個別に構成します。

個別のイメージ プル シークレットを使用せずに AKS が Container Registry からイメージをプルできるようにするには、レジストリ全体の RBAC を使用するレジストリに 対して AKS 間のContainer-Registry 統合 を使用します。 ABAC 対応レジストリの場合、この統合はサポートされていません。 代わりに、クラスターの kubelet マネージド ID に Container Registry Repository Reader ロールを割り当てます。

リリース パイプラインの作成の詳細については、「Release pipelines, draft releases, and release options」 (リリース パイプライン、ドラフト リリース、およびリリース オプション) を参照してください。

次の図に、この記事で説明したエンドツーエンドの CI/CD プロセスを示します。

エンド ツー エンドの CI/CD パイプラインの図。

この図は、開発者コミットから運用環境のデプロイまでの完全な CI/CD パイプラインを示しています。 左側では、開発者が Git リポジトリにコミットをプッシュすることから始まります。 Git リポジトリによって、最初の CI パイプラインがトリガーされます。 CI パイプラインには、ビルド コード、単体テストの実行、ビルド イメージ、プッシュ イメージ、Helm パッケージ、プッシュ チャートの 6 つの順次ステップが含まれています。 最初の 3 つの各手順の右側には、対応する出力ボックスがあります。ビルド コードはコード成果物を生成し、単体テストを実行するとテスト結果が生成され、ビルド イメージはコンテナー イメージを生成します。 [イメージのプッシュ] ステップでは、イメージがコンテナー レジストリにプッシュされます。 Helm パッケージ ステップでは、グラフ アーカイブ ファイルが生成されます。 グラフのプッシュ ステップでは、Helm リポジトリにグラフがプッシュされます。 2 番目の CI パイプラインは、最初の CI パイプラインの下にあります。 QA へのデプロイ、統合テスト、イメージの再タグ付け、イメージのプッシュ、運用環境へのデプロイの 5 つのシーケンシャルな手順が含まれています。 「QA へのデプロイ」ステップから、Helm アップグレードというラベルが付いた行が、テスト/QA クラスターというラベルの付いた Kubernetes クラスターに導きます。 左側の開発者の下には、QA 承認者アイコンから実稼働へのデプロイステップへの行が表示されます。 この行には承認というラベルが付けられます。 [デプロイから運用] ステップでは、Helm アップグレードというラベルが付いた行が、運用クラスターというラベルの付いた 2 つ目の Kubernetes クラスター アイコンにつながります。

代替GitHub Actions

チームがソース管理にGitHubを使用している場合、GitHub Actionsは同等の CI/CD プラットフォームを提供します。 前に説明したスターター ワークフローと OIDC 認証に加えて、AKS を対象とする場合は、次のGitHub固有の機能を検討してください。

  • 環境と保護規則。 GitHubプランとリポジトリの可視性でサポートされている場合は、必要なレビュー担当者、待機タイマー、デプロイ ブランチを含むGitHub環境を使用して承認ゲートを実装します。
  • コンテナーのスキャン。 Trivy、Microsoft Defender for DevOps、または同様のツールに対して、GitHub Actionsマーケットプレース アクションを使用して、ワークフロー内でコンテナー イメージを直接スキャンします。

可観測性と監視

CI/CD パイプラインとランタイム環境全体で可観測性を実装します。

  • パイプラインの監視。 ビルド期間、テスト 合格率、デプロイ頻度、および失敗率を追跡します。 Azure DevOpsでは、組み込みの分析が提供されます。 GitHub Actionsは、Microsoft以外のダッシュボードを使用できます。
  • ランタイムの監視。 Prometheus と Azure Managed Grafana Azure Monitorマネージド サービスを使用して、AKS クラスターの正常性とワークロードのメトリックを監視します。
  • アプリケーション テレメトリ。 分散トレース、要求ログ、依存関係の追跡のために、Azure Monitor Application Insights を使用してマイクロサービスをインストルメント化します。
  • アラート。 デプロイエラー、ポッドの再起動、高いエラー率、リソースの飽和に関するアラートを構成して、迅速なインシデント対応を可能にします。

Well-Architected Framework の配置

Kubernetes 上のマイクロサービス用に CI/CD パイプラインを設計する場合は、Azure Well-Architected Framework の柱を考慮してください。

Considerations
信頼性 自動ロールバック戦略、デプロイに関する正常性プローブ、ブルーグリーンまたはカナリア リリース戦略、ポッドの中断予算。
Security シークレットレス認証 (ワークロード ID、OIDC)、イメージ署名、サプライ チェーン セキュリティ、最小特権 RBAC、ネットワーク ポリシー。
コストの最適化 ビルド エージェントの適切なサイズ設定、エフェメラルセルフホステッド ランナーの使用、Container Registry イメージの保持ポリシーの実装、中断に耐え得る非運用ワークロードに対してのみスポット ノード プールの使用。
オペレーショナル エクセレンス 宣言型デプロイ用の GitOps、コードとしてのインフラストラクチャ、コードとしてのパイプライン (YAML)、可観測性、Runbook の自動化。
パフォーマンス効率 並列パイプライン ステージ、ビルド キャッシュ (Docker レイヤー キャッシュ、依存関係キャッシュ)、ポッドの水平自動スケーリング。

貢献者達

Microsoft では、この記事を保持しています。 この記事を書いたのは、以下の寄稿者です。

主要著者:

  • Ray Kao |プリンシパル ソリューション エンジニア

公開されていない LinkedIn プロフィールを見るには、LinkedIn にサインインしてください。

次のステップ