Azureの仮想マシンで、泥臭くも、お手軽なスケールアウトを考える

オートスケールとか高度なスケールアウトの仕組みをAzureは備えていますが、今日はそんな話は全く縁が無い仮想マシンの泥臭いスケールアウトです。

Azureの2リージョン間 BCDR-災害対策と待機系フェイルオーバでも触れましたが、Azureは停止中のVM料金は取られません

つまり、スケールアウトするのであれば、あらかじめ構築しておいて、必要に合わせて起動、停止すれば良いのです。

仮想マシンで作るスケールアウト

ある程度の許容限界は想定できてないといけませんが、以下の図ように予め仮想マシンを作っておけばよいのです。作っておけば、あとは起動するだけ。

手動でポータルからポチポチでも良いし、スクリプトを使っても良いでしょう。
Azureでは、メトリックをポータルでとる事ができるので、CPUの負荷が閾値を超えたら、Azure Automationに設定したスクリプトのWebhookをキックするとか、Zabbixあたりで検知したら、スクリプトを叩くなどをトリガーに起動しても良いと思います。

こうしておけば、スケールアウトの為にインスタンスを立てるところから始めるなんて馬鹿なことをせずに済みます。大事なことなので、二度言いますが。

停止中のVMの料金は取られませんしストレージも使った分の請求

ですので、ストレージ分だけ払って作っておけば良いですし、停止しているVM3~VM5は仮想ハードディスクの実容量分を支払えばいいことになりますので、起動しっぱなしよりは全然安いです。

lb.png

スクリプトを使って少し便利に

この例では、5台程度ですので最悪手動でポチポチしても良いとは思いますが、台数が増えてくると、この作業は単調でとても骨です。

台数を指定したら手っ取り早く起動してくれたらと思いますよね?

以下は、UbuntuのVMを上の図と同じようにAzure Resouce Managerを使い、5台起動したものです。名前はVM0からVM4までの5台としました。

capture20160712141503068.png

やっつけでサンプルスクリプトを作りました、行っているのは、以下の項目の通りです。
既に書いてて想定できるBUGがありますが、TargetInstancesの最大数が台数超えるとかwそのあたりはサンプルなので、改良して使ってくださいませね。

  1. 変数TargetInstancesには、起動しておきたい台数を記述
  2. リソースグループのVMの一覧を取得して、VMの名前の配列を得る
  3. 目的の台数まで、VMを起動し、その後は停止を行います
    • 起動を行う場合
      既に起動されている場合は、そのままスキップ、停止の場合は起動
    • 停止の場合
      既に停止している場合は、そのままスキップ、起動の場合は停止

と、やっつけで作ったので、知性のかけらもありません。今回はあくまでサンプルスクリプトなので、わかりやすさを重視して同期実行で記述をしています。
もう少し工夫すると、非同期で実行ができます。
もし、大量のVMの操作を行う場合ですが、非同期処理を検討する事をお勧めします。


Login-AzureRmAccount
Get-AzureRmSubscription
Select-AzureRmSubscription -SubscriptionName 'internal'

# RGとVM名
$ResouceGroupName='handscaleout'

# 全数中起動したい台数
$TargetInstances=2

## function
# VMのステータス確認と起動
function Start-Vm($TgtRgName, $VmName) {
    $VmDetail = Get-AzureRmVM -ResourceGroupName $TgtRgName -Name $VmName -Status -ErrorAction 'SilentlyContinue' -WarningAction 'SilentlyContinue'| Select-Object -ExpandProperty Statuses| Select-Object -ExpandProperty Code
    $VmState = $VmDetail[-1]
    if ($VmState -like 'PowerState/deallocated'){
        Start-AzureRmVM -ResourceGroupName $TgtRgName -Name $VmName
    }
}
function Stop-Vm($TgtRgName, $VmName) {
    $VmDetail = Get-AzureRmVM -ResourceGroupName $TgtRgName -Name $VmName -Status -ErrorAction 'SilentlyContinue' -WarningAction 'SilentlyContinue'| Select-Object -ExpandProperty Statuses| Select-Object -ExpandProperty Code
    $VmState = $VmDetail[-1]
    if ($VmState -like 'PowerState/running'){
        Stop-AzureRmVM -ResourceGroupName $TgtRgName -Name $VmName -Force 
    }
}
## Main
$VMList = Get-AzureRmVM -ResourceGroupName $ResouceGroupName|Select-Object -ExpandProperty Name
$counter=0
Foreach ( $VM in $VMList ) {
    if($counter -ge $TargetInstances){
        Stop-VM $ResouceGroupName $VM
    }else{
        Start-VM $ResouceGroupName $VM    
    }
    $counter++
}
exit