WEBで表題の件を検索していても記事があまり見つからなかったので、備忘録も兼ねて執筆してみました。
※2026年1月時点での情報を基に記事を作成しています。
本記事で紹介すること
AKSのプライベートクラスターに対して、どのようなリソースをどのように使用してCI/CDを実施するのか、アーキテクチャの概要感を記載します。
本記事で紹介しないこと
使用した各Azureリソースについて、細かな設定値までは記載しません。
使用したAzureリソース
-
Azure Repos
Gitベースのソースコード管理サービスです。Azureが提供するGitサービスとなります。 -
Azure Pipeline
CI/CDを自動化するサービスで、コードのビルド・テスト・デプロイを一貫したパイプラインとして構成できます。 -
Service Connections(Azure DevOps)
Azure PipelinesとAzureリソース間の認証済み接続を管理する機能です。サービスプリンシパルやマネージドIDを使用して、パイプラインからAKSなどのAzureサービスへ安全にアクセスできます。 -
Azure Managed DevOps Pools
Microsoftが管理するセルフホステッドエージェントプールで、カスタムイメージやプライベートネットワークへのアクセスが可能です。プライベートAKSクラスターへのデプロイに必要なネットワーク接続(VNET統合)を提供し、かつAzureが提供するマネージドサービスのため、インフラ管理の負担を軽減します。 -
AKS(Azure Kubernetes Serive)
Azureが提供するマネージドなKubernetesサービスです。今回はプライベートクラスターを前提にしています。クラスターのセキュリティ構成は「Azure RBAC を使用した Microsoft Entra ID 認証」を想定しています。
構成図
Azureリソース構築時の注意点
細かい部分は他の記事やMS Learnがあるので省きますが、少しハマりそうな箇所や注意点についてのみ記載していきます。Reposは非常にシンプルなAzureリソースであり、説明は不要と判断し、特に注意点を記載していないので、各ドキュメントを参照いただければと思います。
AKS Private Cluster
Azure DevOps上で作成したService Connectionを、AKSのIAMで権限を付与(RBACロールに割り当てる)必要があります。
Service ConnectionへのRBAC割り当ては、Service ConnectionsのObject IDを使用するようにします。
- ワークロードIDを有効にしておく
Service Connectionsと接続する際のService Connections側のCredentialをWorkload identity federationにするため、クラスター作成時にワークロードIDは有効化しておきます。
- 権限の割り当て方法
Entra ID>エンタープライズアプリケーション>すべてのアプリケーション>フィルターをすべて外して、Service ConnectionのIDを検索窓に入力します。表示されたIDにObject IDが表記されています。
推奨ロール : Azure Kubernetes Service RBAC Cluster Admin
※「Azure Kubernetes Service RBAC Writer」ロールを使用すると、マニフェストファイルで記載されたnamespaceスコープのリソースはデプロイ可能ですが、PersistentVolume等のクラスタースコープのリソースは権限不足によりデプロイできなかったです。
az role assignment create \
--assignee-object-id <object-id> \
--assignee-principal-type ServicePrincipal \
--role "Azure Kubernetes Service RBAC Cluster Admin" \
--scope <aks-resource-id>
ロールの割り当てが完了したら、ロールが割当たっているか確認してみます。
az role assignment list --assignee <Object ID> --scope /subscriptions/<Subscription ID>/resourceGroups/<Resource Group>/providers/Microsoft.ContainerService/managedClusters/<AKS Cluster Name> --output table
Managed Devops pools
Azure Pipleline Agentの一種であるManaged Devops poolsですが、Managed Devops poolsとはなんぞや。という内容については以下の記事がとても分かりやすかったです。
ポイントとしては、AKSクラスターが配置されている同VNET上にデプロイすることです。これはManaged Devops poolsが提供しているVNET統合機能を使用します。
また、VNET統合する際に、Managed Devops poolsをデプロイするサブネット側で設定が必要な注意点があります。
- サブネットをMicrosoft.DevOpsInfrastructure/pools に委任する
- サブネットのアクセス制御(IAM)で以下のロールを付与する
閲覧者:DevOpsInfrastructure
ネットワーク共同作成者:DevOpsInfrastructure
Service Connections
Service Connectionsの種類はAzure Resource Managerを選択します。Kubernetesは選択しないように。
また、AKSの項目でも説明しましたが、CredentialをWorkload identity federationにすることです。

Azure Pipelines
まず初めに、(詳細は省きますが)予備知識として「並列ジョブ」は意識した方が良いかと思います。Pipelines 動かしてみたけど、並列ジョブの制限に引っかかってPipelines が動かない。ということもあり得ます。並列ジョブについては、以下を参照ください。
続いてPipelinesで使用するYAMLファイルの全体像を記載します。
Pipelines を設定する流れで作成する以下のYAMLファイル自体は、トリガー対象となるレポジトリ(今回はRepos)にファイルが格納されます。
trigger:
- main
variables:
dockerRegistryServiceConnection: '<service-connection-guid>'
imageRepository: '<image-repository-name>'
containerRegistry: '<acr-name>.azurecr.io'
dockerfilePath: '**/Dockerfile'
tag: '$(Build.BuildId)'
vmImageName: 'ubuntu-latest'
subscriptionId: '<subscription-id>'
resourceGroup: '<resource-group-name>'
aksClusterName: '<aks-cluster-name>'
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: Docker@2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
latest
- stage: Deploy
displayName: Deploy stage
dependsOn: Build
jobs:
- deployment: Deploy
displayName: Deploy
pool:
name: '<managed-devops-pool-name>'
environment: '<environment-name>'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- script: |
sudo apt-get update
sudo apt-get install -y unzip
displayName: Install unzip
- task: kubeloginInstaller@0
displayName: Install kubelogin
inputs:
kubeloginVersion: 'latest'
- task: KubernetesManifest@1
displayName: Deploy to AKS
inputs:
action: 'deploy'
connectionType: 'azureResourceManager'
azureSubscriptionConnection: '<azure-subscription-service-connection-guid>'
azureResourceGroup: '$(resourceGroup)'
kubernetesCluster: '$(aksClusterName)'
namespace: 'default'
manifests: |
'<manifestsfile-name>'
以下より、YAMLファイル記載内容の解説です。
まずvariablesについて説明します。こちらはYAMLファイル内で使用する値を変数化している項目です。
variables:
# ACRへのService Connection ID(Azure DevOpsのProject Settings > Service connectionsで作成)
dockerRegistryServiceConnection: '<service-connection-guid>'
# ACRに格納するコンテナイメージのリポジトリ名
imageRepository: '<image-repository-name>'
# Azure Container RegistryのログインサーバーURL
containerRegistry: '<acr-name>.azurecr.io'
# Dockerfileの配置パス(**はワイルドカードでリポジトリ内を再帰的に検索)
dockerfilePath: '**/Dockerfile'
# コンテナイメージのタグ(ビルドIDを使用して一意性を確保)
tag: '$(Build.BuildId)'
# BuildステージでDockerイメージをビルドする際に使用するMicrosoft-hostedエージェントのイメージ
vmImageName: 'ubuntu-latest'
# AzureサブスクリプションID
subscriptionId: '<subscription-id>'
# AKSクラスターが配置されているリソースグループ名
resourceGroup: '<resource-group-name>'
# デプロイ対象のAKSクラスター名
aksClusterName: '<aks-cluster-name>'
BuildステージではManaged Devops poolsを使用せずに、Microsoft-hostedをエージェントとして使用するため、variablesにてMicrosoft-hostedで使用するVMイメージを定義しています。
また、**/Dockerfile は「リポジトリ内のどこかにあるDockerfileを検索する」という意味ですが、Buildステージの「Docker@2 タスク」では、最初に見つかった1つのDockerfileのみをビルドします。
この設定で**/Dockerfile は以下の動作をしますので、必要に応じてdockerfileは個々のプロジェクトに合わせたファイルパスを設定してください(筆者の環境ではdockerfileはレポジトリ内に1つのみなのでこの設定にしています)。
- リポジトリのルートから再帰的に検索
- 最初にマッチした1つのDockerfileのみをビルド
- 複数のDockerfileが存在する場合、どれが選ばれるかは不確定
続いてBuildステージについてです。
tags: |
$(tag)
latest
この設定は、ビルドしたDockerイメージに 2つのタグを同時に付与 してACRにプッシュすることを意味します。プルしたいイメージを指定する際に、常に「latest」を指定することでdockerfile側の運用負荷を下げたいことと、バージョン管理も並行して実施したい目的があります。
開発向けな設定ではあるので、厳密にデプロイ管理をしたい場合は、バージョン指定のみでデプロイできるよう、「latest」は記載から除外することを推奨します。
最後にDeployステージです。
pool:
name: '<managed-devops-pool-name>'
Azure Managed DevOps Poolsの名前を指定します。
environment: '<environment-name>'
「environment(環境)」は、アプリケーションのデプロイ先となるVMやKubernetesクラスターなどのリソースを論理的にまとめたグループです。グルーピングしておくことで、DevOps画面上でデプロイ履歴などが簡単に追えるようになります。
strategy:
runOnce:
deploy:
steps:
デプロイ戦略を記載しています。上記ではrunOnce戦略と呼ばれるシンプルなデプロイ戦略を設定しています。**canary(カナリアデプロイ)**等に変更したい場合は、上記の表記を適宜変更してください。
steps:
- checkout: self
リポジトリのチェックアウトを実施しています。
パイプラインが定義されているリポジトリをエージェント上にクローンすることで、マニフェストファイルにアクセスできるようになります。
- script: |
sudo apt-get update
sudo apt-get install -y unzip
displayName: Install unzip
unzipのインストールを実施しています。後述するkubeloginInstallerタスクがダウンロードしたzipファイルを展開するために使用します。
※エージェントイメージに既に含まれている場合は不要です。
- task: kubeloginInstaller@0
displayName: Install kubelogin
inputs:
kubeloginVersion: 'latest'
Azure AD認証をkubectlで使用可能にするプラグインをインストールします。これをインストールすることで、AKSクラスターへの認証をAzure ADベースで実行できるようになります。
今回AKSのセキュリティ構成は「Azure RBAC を使用した Microsoft Entra ID 認証」となっているため必要な設定です。
- task: KubernetesManifest@1
displayName: Deploy to AKS
inputs:
action: 'deploy'
connectionType: 'azureResourceManager'
azureSubscriptionConnection: '<azure-subscription-service-connection-guid>'
azureResourceGroup: '$(resourceGroup)'
kubernetesCluster: '$(aksClusterName)'
namespace: 'default'
manifests: |
'<manifestsfile-name>'
KubernetesマニフェストファイルをAKSクラスターにデプロイするタスクです。内部的に kubectl apply を実行します。
以下より、上記コード部分を細分化して説明します。
action: 'deploy'
アクションには複数の種類があるようで、いくつか例を記載しておきます。
- 'deploy': マニフェストをデプロイ(kubectl apply 相当)
- 'promote': カナリアデプロイの昇格
- 'reject': カナリアデプロイの拒否
- 'scale': レプリカ数の変更
- 'delete': リソースの削除
- 'patch': リソースの部分更新
connectionType: 'azureResourceManager'
Azure Service Connection経由でAKSに接続するように設定しています。値はService Connections のIDを記載してください。
manifests: |
<manifestsfile-name>
デプロイするKubernetesマニフェストファイルのパスです。改行区切りをすることで、複数ファイルを指定することも可能です。
マニフェストファイルは対象となるレポジトリ(今回はRepos)に事前に格納しておきます。
最後に
実際の運用環境で本構成(プライベートなAKSクラスター+CI/CD環境)を採用する方も少なくないのではと思います。
備忘録として記載した程度ですが、皆様に少しでも参考になれば幸いです。

