클라우드 환경에서는 사용하지 않는 리소스를 중지하는 것만으로도 상당한 비용 절감 효과를 얻을 수 있습니다.

이러한 작업을 수동으로 하게 된다면 비효율적일 뿐만 아니라 누락되기 쉽습니다.
 Azure Automation을 이용하여 반복 작업을 자동화함으로써, 시간 또는 정책 기반으로 리소스를 안정적으로 제어할 수 있습니다.

이 문서에서는 Azure Automation을 이용해 주요 Azure 리소스를 On/Off 하는 방법을 살펴봅니다.

 

Azure VM의 경우 기본적으로 자동종료 기능을 제공합니다.

하지만 이 기능은 종료만 지원하기 때문에 매번 VM을 켜서 사용해야하는 번거로움이  있습니다.

이를 대체하고 더 나아가 효율적인 운영을 위해 Azure Automation을 이용해 주요 Azure 리소스를 On/Off 합니다.

 

1.Automation 계정 생성

Azure Automation 계정 리소스를 생성합니다.

 

2.새 Runbook 을 작성합니다.

Runbook은 직접 작성하거나 사용자들이 직접 작성하여 게시하는 런북갤러리에서 적절한 스크립트를 찾아 적용할 수 있습니다.

 

 

이 문서에서는 Managed Identity를 사용한 스크립트로 작성했습니다.

Managed Identity를 사용하면 별도의 자격증명 관리가 필요 없어 보안성이 높습니다.

이를 위해 Automation을 만드는 과정에서 관리ID 사용을 체크합니다.

 

구분

시스템 할당 (System-assigned)

사용자 할당 (User-assigned)

생명주기

Automation 계정과 함께 생성/삭제

독립적으로 존재 (별도 리소스)

개수

Automation 계정당 1개만 가능

여러 개 생성 가능

재사용성

해당 Automation 계정만 사용

여러 리소스에서 공유 가능

삭제 시

Automation 삭제 시 자동 삭제됨

Automation 삭제해도 ID는 유지됨

권한 관리

각 Automation마다 개별 설정

한 번 설정하면 모든 곳에 적용

설정 복잡도

간단 (토글 하나)

약간 복잡 (먼저 ID 생성 필요)

비용

무료

무료

적합한 경우

단일 Automation 전용 권한

여러 리소스가 동일 권한 필요

 

 

런북을 생성하면 바로 편집 화면으로 넘어갑니다.

오른쪽에 코드를 입력하고 저장 후 게시까지 누릅니다.

게시를 누르지 안으면 초안으로 간주되고 실제 적용은 되지 않은 상태이므로 반드시 게시까지 눌러줍니다.


Param(
    [parameter(Mandatory = $true)]
    [String] $ResourceGroupName,
    [parameter(Mandatory = $true)]
    [ValidateSet('start', 'stop')]
    [String] $Operation
)
 
# Verify if the Resource Group and Application Gateway exists
try {
    Disable-AzContextAutosave -Scope Process
        
    #System Managed Identity
    Write-Output "Logging into Azure using System Managed Identity"
    $AzureContext = (Connect-AzAccount -Identity).context
    $AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
}
catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

Write-Output "Performing $Operation operation on Resource Group: $ResourceGroupName"

switch -CaseSensitive ($Operation) {
    'start' {
        # VM Start
        Write-Output "Starting all VMs in Resource Group $ResourceGroupName"
        $VMs = Get-AzVM -ResourceGroupName $ResourceGroupName
        
        # VM 존재 여부 확인
        if ($VMs.Count -eq 0) {
            Write-Warning "No VMs found in Resource Group $ResourceGroupName"
            exit
        }
        
        Write-Output "Found $($VMs.Count) VM(s) to start"
        $Jobs = @()
        
        # 에러 핸들링과 Job 수집
        foreach ($VM in $VMs) {
            try {
                Write-Output "Initiating start for VM: $($VM.Name)"
                $Jobs += Start-AzVM -ResourceGroupName $ResourceGroupName -Name $VM.Name -AsJob -ErrorAction Stop
            }
            catch {
                Write-Error "Failed to initiate start for VM $($VM.Name): $($_.Exception.Message)"
            }
        }
        
        # 작업 완료 대기 및 결과 로깅
        if ($Jobs.Count -gt 0) {
            Write-Output "Waiting for all start operations to complete..."
            $Jobs | Wait-Job | Out-Null
            
            Write-Output "`n--- Start Operation Results ---"
            foreach ($Job in $Jobs) {
                $Result = Receive-Job -Job $Job
                if ($Job.State -eq 'Completed') {
                    Write-Output "✓ SUCCESS: $($Job.Name) started successfully"
                } 
                else {
                    Write-Error "✗ FAILED: $($Job.Name) - State: $($Job.State)"
                }
            }
            
            # 정리
            $Jobs | Remove-Job
            
            # 요약 통계
            $SuccessCount = ($Jobs | Where-Object {$_.State -eq 'Completed'}).Count
            $FailedCount = $Jobs.Count - $SuccessCount
            Write-Output "`n=== Summary ==="
            Write-Output "Total VMs: $($Jobs.Count) | Successful: $SuccessCount | Failed: $FailedCount"
        }
    }
    
    'stop' {
        # VM Stop
        Write-Output "Stopping all VMs in Resource Group $ResourceGroupName"
        $VMs = Get-AzVM -ResourceGroupName $ResourceGroupName
        
        # VM 존재 여부 확인
        if ($VMs.Count -eq 0) {
            Write-Warning "No VMs found in Resource Group $ResourceGroupName"
            exit
        }
        
        Write-Output "Found $($VMs.Count) VM(s) to stop"
        $Jobs = @()
        
        # 에러 핸들링과 Job 수집
        foreach ($VM in $VMs) {
            try {
                Write-Output "Initiating stop for VM: $($VM.Name)"
                $Jobs += Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VM.Name -Force -AsJob -ErrorAction Stop
            }
            catch {
                Write-Error "Failed to initiate stop for VM $($VM.Name): $($_.Exception.Message)"
            }
        }
        
        # 작업 완료 대기 및 결과 로깅
        if ($Jobs.Count -gt 0) {
            Write-Output "Waiting for all stop operations to complete..."
            $Jobs | Wait-Job | Out-Null
            
            Write-Output "`n--- Stop Operation Results ---"
            foreach ($Job in $Jobs) {
                $Result = Receive-Job -Job $Job
                if ($Job.State -eq 'Completed') {
                    Write-Output "✓ SUCCESS: $($Job.Name) stopped successfully"
                } 
                else {
                    Write-Error "✗ FAILED: $($Job.Name) - State: $($Job.State)"
                }
            }
            
            # 정리
            $Jobs | Remove-Job
            
            # 요약 통계
            $SuccessCount = ($Jobs | Where-Object {$_.State -eq 'Completed'}).Count
            $FailedCount = $Jobs.Count - $SuccessCount
            Write-Output "`n=== Summary ==="
            Write-Output "Total VMs: $($Jobs.Count) | Successful: $SuccessCount | Failed: $FailedCount"
        }
    }
}

Write-Output "`n$Operation operation completed for Resource Group: $ResourceGroupName"



런북 게시 후 원하는 일정을 적용하기 위해 “일정에 연결” 작업을 해줍니다.



일정은ON/OFF 각각 적용해야합니다.

하기 설정은 매주 월요일 오전 08:00에 VM을 켜고 매주 금요일 20:00에 VM을 끄도록 설정합니다.

즉, 월요일 지정한 시간에 VM을 켜면 토요일 지정한 시간까지 VM은 꺼지지 않고 계속해서 동작합니다.

매일 또는 특정일에 끄도록 설정하려면 요일 선택을 통해 조정할 수 있습니다.