はじめに
Azure Kubernetes Service(AKS)は柔軟なスケーリング機能を備えていますが、開発環境やテスト環境では業務時間外にクラスターを停止してコストを削減したいというケースが多いでしょう。
本記事では、Azure Automation と PowerShell Runbook を用いて、AKS クラスターを自動的に起動・停止する仕組みを構築します。
ポイントは、以下の3つです:
- セキュリティを意識した構成(Managed Identity + 最小権限)
- タグによる柔軟な制御(AutoShutdown=true で対象限定)
- スケジュールによる完全自動化(業務時間外の停止・翌朝の自動起動)
想定されるコスト削減効果
業務時間帯(平日8:00~20:00)では年間3120時間分の消費
- 24時間フル稼働:年間8,760時間分のコスト消費
- 平日のみ稼働(8:00-20:00):年間約3120時間 月間約260時間のコスト消費
- 削減率:約64%のコスト削減が可能
前提条件
本手順を実施するには、以下の環境と権限が必要です。
必要な環境
- Azure サブスクリプション
- 停止・起動対象の AKS クラスター
- Azure Cloud Shell または Azure PowerShell がインストールされた環境
必要な権限
実行者には以下の権限が必要です:
- Automation アカウントを作成できる権限(Contributor 以上)
- AKS クラスターへのロール割り当て権限(User Access Administrator または Owner)
- リソースグループへの書き込み権限
必要な知識
- Azure の基本的な操作
- PowerShell の基礎知識
- AKS の基本概念
全体構成
本手順では、以下のステップで実装を進めます。
| ステップ | 内容 |
|---|---|
| 1 | タグで制御対象を定義 |
| 2 | Automation アカウントの作成 |
| 3 | Automation アカウントに最小権限を付与 |
| 4 | 停止用 Runbook の作成と公開 |
| 5 | 起動用 Runbook の作成と公開 |
| 6 | スケジュールの設定 |
複数のAKSクラスターを管理する場合
本手順では1つのリソースグループ内の複数クラスターに対応しています。
異なるリソースグループのクラスターを管理する場合は、以下のいずれかの方法を選択してください:
- リソースグループごとに個別のRunbookとスケジュールを作成
- スクリプトを修正して複数のリソースグループをループ処理
- サブスクリプションレベルで権限を付与(セキュリティ上推奨されません)
実装手順
1. タグで制御対象を定義
まず、対象となる AKS クラスターにタグを付与しておきます。このタグを Runbook 側で参照し、停止・起動対象を限定します。
| キー | 値 | 説明 |
|---|---|---|
| AutoShutdown | true | 自動停止・起動対象を示す |
設定方法
- Azure ポータルで対象の AKS クラスターを開く
- 左メニューから「タグ」を選択
- 以下のタグを追加
- 名前:
AutoShutdown - 値:
true
- 名前:
- 「適用」をクリック
補足:AKSクラスターの状態について
タグの設定作業は、Azure Kubernetes Service を起動した状態で行ってください。
停止された状態で作業を行うと、以下のエラーが発生します:
Operations are not allowed when the managed cluster is not in the Running power state. (コード: BadRequest)
2. Automation アカウントの作成(Managed Identity 有効)
次に、Automation アカウントを作成します。ここでは Managed Identity を有効化しておくことで、Runbook から安全に Azure リソースへアクセスできるようにします。
Cloud Shell の PowerShell で実行
# 変数の設定
$automationAccountName = "aks-auto-control"
$resourceGroupName = "<RESOURCE_GROUP_NAME>"
$location = "japaneast"
# Azure Automation アカウント作成(Managed Identity 有効)
New-AzAutomationAccount `
-Name $automationAccountName `
-ResourceGroupName $resourceGroupName `
-Location $location `
-AssignSystemIdentity
Write-Output "Automation Account created successfully: $automationAccountName"
作成後の確認
- Azure ポータルで作成した Automation アカウントを開く
- 左メニューから「ID」を選択
- 「システム割り当て済み」タブで状態が「オン」になっていることを確認
3. Automation アカウントに権限を付与(最小権限)
Managed Identity を使う場合でも、必要最小限の権限を明示的に付与する必要があります。ここでは AKS クラスタースコープに限定した Contributor ロールを割り当てます。
PowerShell で実行
# 変数の設定
$automationAccountName = "aks-auto-control"
$automationResourceGroupName = "<AUTOMATION_RESOURCE_GROUP_NAME>"
$aksResourceGroupName = "<AKS_RESOURCE_GROUP_NAME>"
$aksClusterName = "<AKS_CLUSTER_NAME>"
$subscriptionId = "<SUBSCRIPTION_ID>"
# Automation アカウント情報を取得
$automationAccount = Get-AzAutomationAccount `
-ResourceGroupName $automationResourceGroupName `
-Name $automationAccountName
# Managed Identity の PrincipalId を確認
$principalId = $automationAccount.Identity.PrincipalId
Write-Output "Automation Managed Identity PrincipalId: $principalId"
# 対象 AKS クラスタースコープ
$aksScope = "/subscriptions/$subscriptionId/resourceGroups/$aksResourceGroupName/providers/Microsoft.ContainerService/managedClusters/$aksClusterName"
# Contributor ロールを付与(必要最小限)
New-AzRoleAssignment `
-ObjectId $principalId `
-RoleDefinitionName "Contributor" `
-Scope $aksScope
Write-Output "Role assignment completed successfully"
確認方法
- Azure ポータルで対象の AKS クラスターを開く
- 左メニューから「アクセス制御 (IAM)」を選択
- 「ロールの割り当て」タブで Automation アカウントの Managed Identity が Contributor(共同作成者) として登録されていることを確認
セキュリティ補足
- サブスクリプション全体ではなく、対象 AKS のみにスコープを限定
- 管理者アカウントではなく、Automation の Managed Identity を利用
- 必要最小限の権限(Contributor)のみを付与
4. PowerShell Runbook(停止用)の作成
Runbook 概要
| 項目 | 値 |
|---|---|
| 名前 | Stop-AKS |
| 種類 | PowerShell |
| ランタイムバージョン | 7.2 |
| 説明 | AKS クラスターを自動停止 |
作成手順
- Azure ポータルで Automation アカウントを開く
- 左メニューから「Runbook」を選択
- 「+ Runbook の作成」をクリック
- 以下の情報を入力
- 名前:
Stop-AKS - Runbook の種類:
PowerShell - ランタイム バージョン:
7.2 - 説明:
AKS クラスターを自動停止
- 名前:
- 「作成」をクリック
スクリプト内容
以下のスクリプトを Runbook エディタに貼り付けます。
param(
[string]$ResourceGroupName = "<AKS_RESOURCE_GROUP_NAME>",
[string]$TagKey = "AutoShutdown",
[string]$TagValue = "true"
)
try {
# Managed Identity で認証
Connect-AzAccount -Identity -ErrorAction Stop
Write-Output "Successfully authenticated with Managed Identity"
# 特定リソースグループ内のタグ付きクラスターを取得
$clusters = Get-AzAksCluster -ResourceGroupName $ResourceGroupName -ErrorAction Stop |
Where-Object { $_.Tags[$TagKey] -eq $TagValue }
if ($clusters.Count -eq 0) {
Write-Output "No AKS clusters found with tag $TagKey=$TagValue in resource group $ResourceGroupName"
return
}
Write-Output "Found $($clusters.Count) AKS cluster(s) to stop"
foreach ($cluster in $clusters) {
Write-Output "Processing AKS Cluster: $($cluster.Name)"
# クラスターの現在の状態を確認
if ($cluster.PowerState.Code -eq "Stopped") {
Write-Output " Status: Already stopped. Skipping."
continue
}
Write-Output " Status: Running. Stopping cluster..."
Stop-AzAksCluster -Name $cluster.Name -ResourceGroupName $cluster.ResourceGroupName -ErrorAction Stop
Write-Output " Successfully stopped: $($cluster.Name)"
}
Write-Output "Stop operation completed successfully"
}
catch {
Write-Error "Error occurred during stop operation: $_"
Write-Error $_.Exception.Message
throw
}
保存と公開
- スクリプトを貼り付けたら「保存」をクリック
- 「公開」をクリック
- 確認メッセージで「はい」をクリック
重要:公開しないとスケジュール登録ができません
テスト実行
公開前にテストして動作を確認することをお勧めします。
- Runbook 画面で「テスト ウィンドウ」をクリック
- パラメーター
ResourceGroupNameに対象のリソースグループ名を入力 - 「開始」をクリック
- 出力ログで正常に停止されたことを確認
- 実行結果が表示されない場合は「ジョブ ストリームを更新します」をクリック
注意:Test Job 実行時は同時実行制御に注意してください。実行中のジョブがある場合、エラーになることがあります
5. PowerShell Runbook(起動用)の作成
Runbook 概要
| 項目 | 値 |
|---|---|
| 名前 | Start-AKS |
| 種類 | PowerShell |
| ランタイムバージョン | 7.2 |
| 説明 | AKS クラスターを自動起動 |
作成手順
停止用 Runbook と同様の手順で作成します。
- 「+ Runbook の作成」をクリック
- 以下の情報を入力
- 名前:
Start-AKS - Runbook の種類:
PowerShell - ランタイム バージョン:
7.2 - 説明:
AKS クラスターを自動起動
- 名前:
- 「作成」をクリック
スクリプト内容
param(
[string]$ResourceGroupName = "<AKS_RESOURCE_GROUP_NAME>",
[string]$TagKey = "AutoShutdown",
[string]$TagValue = "true"
)
try {
# Managed Identity で認証
Connect-AzAccount -Identity -ErrorAction Stop
Write-Output "Successfully authenticated with Managed Identity"
# タグ付きクラスターを取得
$clusters = Get-AzAksCluster -ResourceGroupName $ResourceGroupName -ErrorAction Stop |
Where-Object { $_.Tags[$TagKey] -eq $TagValue }
if ($clusters.Count -eq 0) {
Write-Output "No AKS clusters found with tag $TagKey=$TagValue in resource group $ResourceGroupName"
return
}
Write-Output "Found $($clusters.Count) AKS cluster(s) to start"
foreach ($cluster in $clusters) {
Write-Output "Processing AKS Cluster: $($cluster.Name)"
# PowerState.Code で状態確認
if ($cluster.PowerState.Code -eq "Running") {
Write-Output " Status: Already running. Skipping."
continue
}
if ($cluster.ProvisioningState -ne "Succeeded") {
Write-Output " Status: Cluster is not in Succeeded state. Current state: $($cluster.ProvisioningState). Skipping."
continue
}
Write-Output " Status: Stopped. Starting cluster..."
Start-AzAksCluster -Name $cluster.Name -ResourceGroupName $cluster.ResourceGroupName -ErrorAction Stop
Write-Output " Successfully started: $($cluster.Name)"
}
Write-Output "Start operation completed successfully"
}
catch {
Write-Error "Error occurred during start operation: $_"
Write-Error $_.Exception.Message
throw
}
保存と公開
- 「保存」をクリック
- 「公開」をクリック
- 確認メッセージで「はい」をクリック
6. スケジュールの設定
スケジュールを設定して、定期実行を自動化します。
重要:1つのスケジュールは1つの Runbook しか紐付けできません。そのため、停止用と起動用は別スケジュールを作成します。
スケジュール設定の概要
| Runbook | スケジュール名 | 実行時間 | 説明 |
|---|---|---|---|
| Stop-AKS | Stop-AKS-Daily | 平日 20:00(JST) | タグ付き AKS を停止 |
| Start-AKS | Start-AKS-Daily | 平日 08:00(JST) | タグ付き AKS を起動 |
停止用スケジュールの作成
- Automation アカウントを開く
- 左メニューから「スケジュール」を選択
- 「+ スケジュールの追加」をクリック
- 以下の情報を入力
- 名前:
Stop-AKS-Daily - 説明:
平日夜間の AKS 停止スケジュール - 開始:任意の日付、時間 20:00
- タイムゾーン:
Japan - Japan Time - 繰り返し:
定期的 - 間隔:
1週 - 設定する曜日:月曜日、火曜日、水曜日、木曜日、金曜日
- 有効期限の設定:任意
- 名前:
- 「作成」をクリック
停止用 Runbook とスケジュールの紐付け
- Runbook「Stop-AKS」を開く
- 左メニューから「スケジュール」を選択
- 「+ スケジュールの追加」をクリック
- 「スケジュールを Runbook にリンクします」をクリック
- 先ほど作成した「Stop-AKS-Daily」を選択
- 「OK」をクリック
- パラメーターと実行設定で以下を入力
-
ResourceGroupName:対象のリソースグループ名を入力 -
TagKey:AutoShutdown(デフォルト値のまま) -
TagValue:true(デフォルト値のまま)
-
- 「OK」をクリック
起動用スケジュールの作成
同様の手順で起動用のスケジュールを作成します。
- 「+ スケジュールの追加」をクリック
- 以下の情報を入力
- 名前:
Start-AKS-Daily - 説明:
平日朝の AKS 起動スケジュール - 開始:任意の日付、8:00
- タイムゾーン:
Japan - Japan Time - 繰り返し:
定期的 - 間隔:
1週 - 設定する曜日:月曜日、火曜日、水曜日、木曜日、金曜日
- 有効期限の設定:任意
- 名前:
- 「作成」をクリック
起動用 Runbook とスケジュールの紐付け
- Runbook「Start-AKS」を開く
- 左メニューから「スケジュール」を選択
- 「+ スケジュールの追加」をクリック
- 「Start-AKS-Daily」を選択
- パラメーターを設定して「OK」をクリック
動作確認
設定完了後、以下の方法で動作を確認します。
1. 手動実行での確認
スケジュール実行を待たずに、手動で Runbook を実行して動作を確認できます。
2. スケジュール実行の確認
- Automation アカウントを開く
- 左メニューから「ジョブ」を選択
- スケジュール実行されたジョブの状態を確認
- ジョブをクリックして詳細ログを確認
3. AKS クラスターの状態確認
- Azure ポータルで AKS クラスターを開く
- 概要画面で「電源の状態」を確認
- 停止後:
Stopped - 起動後:
Running
- 停止後:
トラブルシューティング
よくあるエラーとその対処法をまとめます。
エラー1:権限不足エラー
エラーメッセージ例:
The client with object id 'xxx' does not have authorization to perform action 'Microsoft.ContainerService/managedClusters/stop/action'
原因: Managed Identity に適切な権限が付与されていない
対処法:
- AKS クラスターの「アクセス制御 (IAM)」を確認
- Automation アカウントの Managed Identity に Contributor ロールが付与されているか確認
- 権限付与のスクリプトを再実行
エラー2:認証エラー
エラーメッセージ例:
Connect-AzAccount: No certificate was found for Managed Identity
原因: Managed Identity が有効化されていない
対処法:
- Automation アカウントの「ID」タブで「システム割り当て済み」が「オン」になっているか確認
- オフの場合は「オン」に変更して保存
エラー3:モジュールが見つからない
エラーメッセージ例:
The term 'Get-AzAksCluster' is not recognized
原因: 必要な PowerShell モジュールがインストールされていない
対処法:
- Automation アカウントの「モジュール」を開く
- 「ギャラリーを参照」をクリック
-
Az.Aksモジュールを検索してインストール -
Az.Accountsモジュールもインストールされているか確認
補足:
- PowerShell 7.2 ランタイムを使用する場合、モジュールのバージョン互換性に注意してください
-
Az.AksモジュールはAz.Accountsモジュールに依存しているため、両方がインストールされている必要があります - モジュールのインストール後、Runbook を再公開する必要はありませんが、既存のジョブは新しいモジュールを使用しません
エラー4:同時実行エラー
エラーメッセージ例:
Cannot start the job because a test job is already running
原因: テストジョブが実行中
対処法:
- 実行中のテストジョブを停止
- しばらく待ってから再実行
エラー5:クラスターが起動しない
症状: 起動用 Runbook は成功するが、クラスターが起動しない
原因: クラスターの ProvisioningState が Succeeded ではない
対処法:
- AKS クラスターの状態を確認
- エラーがある場合は Azure ポータルで詳細を確認
- クラスターが正常な状態になってから再実行
まとめ
本記事では、Azure Automation を用いた安全かつ効率的な AKS の自動起動・停止構成を構築しました。
この構成の特徴
| 特徴 | 内容 |
|---|---|
| セキュリティ | Managed Identity + 最小権限スコープで安全に運用 |
| 柔軟性 | タグによる制御で対象クラスターを限定可能 |
| 運用効率 | スケジュール実行で完全自動化、手動操作不要 |
| コスト最適化 | 不要な時間帯の稼働を抑制し、約60%のコスト削減が可能 |
導入効果
この構成を導入することで:
- コスト削減: 業務時間外のリソース稼働を抑制し、大幅なコスト削減を実現
- セキュリティ向上: Managed Identity による認証で、資格情報の管理が不要
- 運用負荷軽減: 自動化により、手動での起動・停止作業が不要
- 柔軟な制御: タグによる制御で、複数のクラスターを個別に管理可能
今後の拡張案
さらに以下のような拡張も検討できます:
-
通知機能の追加
- Azure Monitor や Logic Apps と連携して、起動・停止の結果を通知
- 失敗時のアラート送信
-
複数環境への展開
- 開発、ステージング、本番など、環境ごとに異なるスケジュールを設定
- タグの値を変更して柔軟に制御
-
コスト可視化
- Azure Cost Management と連携して、削減効果を可視化
- レポートの自動生成
-
条件付き起動・停止
- 祝日カレンダーと連携して、祝日は停止したままにする
- 特定のメトリクスに基づいて起動・停止を判断










