gokigenmaruのブログ

40から始めるクラウドエンジニア

Azure AutomationでAKSを自動停止させる

AKSクラスター、非運用としてデフォルト(B4ms)3ノード(3VM)で1日動かすと約15ドル、1ドル140円とすると15x140で2100円かかります。
検証用途で使うにしてちょっと止め損ねたとすると、12時間くらいだと1000円くらい簡単に飛んでいきます。
これは痛い…。
ということで、一番最初にコスト対策としてAKS止め忘れた時の保険となる自動停止を作ろうと思います。

要件

まずは要件を考えることにします。
要件は、

  • 毎日自動でAKS停止が実行されること(基本は自分で手動停止するが、忘れたときの保険として動いてほしい)
  • あまりお金がかからないこと(たくさんお金かかるなら本末転倒)
  • 簡単に出来ること!

以下は必須ではないけどやれたらいいなということで、

  • 自動で止めたいAKSだけ止める

AKSを停止するには…

AKSの停止は主にGUI(コンソール)での停止とコマンド(CLI)での停止の2つに分けられます。
GUIの停止はWeb画面で作業ですが、今回のように定期的に実行するには向いていません。
コマンドでの停止はAzureだと主に2つかな?

 az xxxで実行するコマンド、自分はaz loginとかでよくお世話になっています。

 az.xxxで実行するコマンド

どちらでもAKSの制御は出来そうです。

Azureの自動実行

Azureでは自動実行環境としてAzure FunctionとAzure Automationがあります。

  • Azure Functionsはいろんな言語(C#,Java,Python,Powershellなど)が利用でき、Functionsをキックさせるトリガーも結構豊富でAWS Lambdaにかなり近い感じ。
  • Azure Automationは主にPowershell(Pythonも使えます)で、ポータルから手動で実行したり、Webhookやスケジュール実行が出来るようで、お手軽に自動実行するにはいい感じっぽいです。

上記ぱっと見、スケジュール実行やお手軽さなどから今回はAzure Automationを使います。
Azure Automationを使うとなると、言語はPowershellPythonのどちらかに。Azureリソースを制御する機能が豊富に用意されているPowershellにします。

自動実行環境の作成

Azure Automationを設定する

まずは自動実行のプログラムの箱となるAzure Automationを設定します。
AutomationはAutomationアカウント(サーバ?)の中でRunbook(アプリ?)が動くイメージでしょうか。
なので、まずはAutomationアカウントから作成します。

Azure Automationアカウント作成

作成は簡単でした。

  • AzureコンソールからAutomationアカウントを選択
  • 画面左上の作成を選択
account
  • 基本設定でリソースグループとAutomationアカウント名を入力し、確認および作成を選択

これで作成は完了です。基本デフォルトで作成しているので必要に応じて他の設定をしていくといいかと思います。

Runbook作成

アカウントが作成されると作成したアカウントに移動できます。
その中でRunbookを作成していくことになります。

Runbookの作成します。
名前はお好きに、Runbookの種類はPowershellでランタイムのバージョンは7.2(プレビュー)としました。
これはPowershellスクリプト内で使っている「PowerState」のプロパティが5.1では使えなかったためです。

スクリプト作成

スクリプトは以下の通り作成しました。

try
{
    "Logging in to Azure..."
    Connect-AzAccount -Identity
}
catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

# AKS Stop

(Get-AzAksCluster -SubscriptionId xxxxxx | Select-Object -Property Name, ResourceGroupName, Tags, PowerState | Where-Object {($_.Tags.stop -eq "true") -and ($_.PowerState.Code -eq "Running")}) | ForEach-Object {
    stop-AzAksCluster -SubscriptionId xxxxxx -Name $_.Name -ResourceGroupName $_.ResourceGroupName
}

Powershell便利ですね。
Azureリソースを管理する関数がかなり用意されているので、簡単なスクリプトAKSを停止する機能を作れました。

カスタムロール作成

Azure Automationアカウントは実行する権限がどういう権限となるかの設定が必要です。
Automationアカウント画面の左ツリーにある「ID」でどの権限で実行するかの設定が必要です。

ロールの割り当てで「共同作成者」とかの権限を割り当てるなら特に問題はないですが、Automationアカウントで強い権限を渡してしまうとAutomationアカウントにアクセスできる人が何でも出来てしまいます。
お勉強も兼ねて今回はなるべく小さい権限にすることに。
詳しく書きませんが、ここはハマりポイントでした。
まずはaksの管理者系の権限をつけてみて実行を試すことに。
AKSではロールの検索で出てこなかったのでKubernetes系のロールをつけてみる。
つけたのは以下の管理系ロール

Azure Arc Kubernetes クラスター管理者
Azure Kubernetes Service RBAC クラスター管理者
Azure Arc Kubernetes 管理者
Azure Kubernetes Service RBAC 管理者
Azure Kubernetes Service 共同作成者ロール

しかし、実行した結果以下の通りのメッセージが出ました。

Stop-AzAksCluster_Stop: 
Line |
  14 |      stop-AzAksCluster -Name $_.Name -ResourceGroupName $_.ResourceGro …
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The client 'xxxxxxx' with object id 'xxxxxxxx' does not have authorization to perform action 'Microsoft.ContainerService/managedClusters/stop/action' over scope '/subscriptions/xxxxxxx/resourceGroups/testakscluster_group/providers/Microsoft.ContainerService/managedClusters/testakscluster' or the scope is invalid. If access was recently granted, please refresh your credentials.

読んでみると、'Microsoft.ContainerService/managedClusters/stop/action'がないとダメだと。
管理系のロールつけたんすけど…。
ということで、カスタムロールで'Microsoft.ContainerService/managedClusters/stop/action'をつけたロールを作成してアタッチ。
※カスタムロールはサブスクリプションから作成できます。

あとはgetでAKSの情報を取ってくるので、それっぽいロールでClusterのMonitoringのロールをつけたらうまくいきました。

スケジュール作成

Runbookの左側ツリーに「スケジュール」があるので、ここで設定していきます。

スケジュールをRunbookにリンクします を選択し、新しいスケジュールで名前と開始日時、タイムゾーンと繰り返し、間隔と有効期限を設定

自分の場合、18:00以降はあまりやらなそうなので18:00を停止時間としました。定期実行は毎日実行したいので間隔を1日、有効期限は今のところはなしにしました。

完成!

これで要件を満たすことが出来ました。

  • 毎日自動でAKS停止が実行されること(基本は自分で手動停止するが、忘れたときの保険として動いてほしい)

 →RunbookでPowershellAKSを停止するスクリプトを作成し、Runbookのスケジュール設定で毎日スケジュール実行とする

  • あまりお金がかからないこと(たくさんお金かかるなら本末転倒)

 →Automationアカウントのコストは1分で0.283円、しかも1か月あたり無料で500分ついてくる!

  • 簡単に出来ること!

 →AKS停止は3行で書けました!
以下は必須ではないけどやれたらいいなということで、

  • 自動で止めたいAKSだけ止める

 →PowershellでTagsを見ていて、AKSのタグにKeyがstop、Valueがtrueがある場合だけ停止するようにした

今回はAKSの自動停止でしたが、同じような感じでVMとかもできそうです。これは便利。Powershellを使えると結構便利ですねー

もっといいやり方があれば教えてくれると嬉しいです!