VM Backup with Powershell

โดยปกติการ Backup VM บน VMware ก็สามารถทำได้หลายท่า แต่ส่วนใหญ่ที่นิยมทำกันก็คือการ Clone VM ด้วย PowerCLI Script แล้วตั้ง Schedule เอาไว้ หรือใช้ Software ซึ่งก็มีหลายเจ้าให้เลือกใช้ แต่ต้องเสียตังค์ เราจะมาพูดถึงการ Backup VM ด้วย Powershell Script บน Windows กัน


Backup Policy

ก่อนอื่นให้เรากำหนด Backup Policy กันก่อน โดยแบ่งความถี่ในการสำรองข้อมูล Backup Frequency เช่น รายวัน Daily, รายสัปดาห์ Weekly, รายเดือน Monthly จากนั้นก็กำหนด Data Retention ระยะเวลาของการเก็บไฟล์ เช่น Daily 7 วัน, Weekly 1 เดือน, Monthly 4 เดือน จะมีประโยชน์ตรงที่เวลาเราต้องการข้อมูลย้อนหลัง

Directory Structure

ต่อมาก็กำหนดโครงสร้างของ File และ Folder โดยจะประกอบไปด้วยโครงสร้างดังนี้

C:\powershell-script
├───Credential/
│   └───vcsa.lab.local.clixml
├───VM-List/
│   ├───Daily.txt
│   ├───Monthly.txt
│   └───Weekly.txt
├───VM-Log/
│   ├───Daily/
│   ├───Monthly/
│   └───Weekly/
└───VM-Script/
    ├───Backup-Daily.ps1
    ├───Backup-Monthly.ps1
    ├───Backup-Weekly.ps1
    ├───Configuration.ps1
    ├───Create-Credential.ps1
    └───Delete.ps1

Clone VM vs Clone Template

การสำรองข้อมูลด้วยการ Clone VM เวลานำไปใช้งานเราสามารถ Rename VM แล้วสั่ง PowerOn ได้เลย แต่มันจะทำให้ Data Retention เราหายไป ซึ่งวิธีแก้คือการ Clone เป็น Template แทน แต่การ Clone เป็น Template จะติดปัญหาที่ไม่สามารถ Clone ไปเก็บข้าม Datacenter ได้ จึงต้องใช้วิธี Clone เป็น VM ก่อนแล้วค่อย Convert เป็น Template ทีหลัง ซึ่งก็มีข้อดีข้อเสียต่างกัน ใน Script ผมก็เขียนไว้ หากใครไม่ใช้ก็ Remark เอานะครับ แล้วไปแก้ไฟล์ Delete.ps1 ด้วย

Get Started

  • ทำการสร้างไฟล์ Configuration.ps1
Import-Module VMware.VimAutomation.Core
# VMware Parameter
$Global:root = "C:\powershell-script\"
$Global:date = Get-Date -Format yyyyMMdd
$Global:server = 'vcsa.lab.local'
$Global:vmhost = '10.10.10.20'
$Global:datacenter = 'Datacenter'
$Global:cluster = 'Cluster'
$Global:resourcepool = 'Resourcepool'
$Global:datastore = 'Datastore'
$Global:folder_daily = 'Daily'
$Global:folder_weekly = 'Weekly'
$Global:folder_monthly = 'Monthly'

# Credential
$Global:logon = 'LAB\administrator'
$Global:credential = Import-clixml ($root + 'Credential\vcsa.lab.local.clixml')
$Global:path_credential = $root + 'Credential\vcsa.lab.local.clixml'

# VM-List
$Global:vm_daily = Get-Content ($root + 'VM-List\Daily.txt')
$Global:vm_weekly = Get-Content ($root + 'VM-List\Weekly.txt')
$Global:vm_monthly = Get-Content ($root + 'VM-List\Monthly.txt')

# VM-Log
$Global:path_log_daily = $root + 'VM-Log\Daily\Backup-Daily-' + $date + '.log'
$Global:path_log_weekly = $root + 'VM-Log\Weekly\Backup-Weekly-' + $date + '.log'
$Global:path_log_monthly = $root + 'VM-Log\Monthly\Backup-Monthly-' + $date + '.log'

# Data Retention
$Global:lastdate_daily = (Get-Date (Get-Date).AddDays(-7) -Format yyyyMMdd)
$Global:lastdate_weekly = (Get-Date (Get-Date).AddDays(-28) -Format yyyyMMdd)
$Global:lastdate_monthly = (Get-Date (Get-Date).AddMonths(-3) -Format yyyyMMdd)
  • ทำการสร้างไฟล์ Create-Credential.ps1
. "$PSScriptRoot\Configuration.ps1"
Get-Credential –Credential $logon | Export-Clixml $path_credential
  • ทำการสร้างไฟล์ Backup-Daily.ps1
. "$PSScriptRoot\Configuration.ps1"
Connect-VIServer -Server $server -Credential $credential

$vm = $vm_daily
$path = $path_log_daily
$folder = $folder_daily
$datastore = $datastore

foreach ($line in $vm) {

	$name = 'Backup-Daily-' + $date + '-' + $line
	$dsdc = Get-Datastore $datastore -Datacenter $datacenter

	try {

		$backup = New-VM -Name $name -VM $line -VMHost $vmhost -Datastore $dsdc -ResourcePool $resourcepool -Location $folder -ErrorAction Stop
		$backup | Out-File $path -Append

		Get-VM -Name $name | Set-VM -ToTemplate -Confirm:$false

		$query = Get-VM -Name $line | select Name, VMHost, GuestId, NumCpu, MemoryMB -ErrorAction Stop
		$query | Out-File $path -Append

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}

}

Disconnect-VIServer -Server $server -Confirm:$false
  • ทำการสร้างไฟล์ Backup-Monthly.ps1
. "$PSScriptRoot\Configuration.ps1"
Connect-VIServer -Server $server -Credential $credential

$vm = $vm_monthly
$path = $path_log_monthly
$folder = $folder_monthly
$datastore = $datastore

foreach ($line in $vm) {

	$name = 'Backup-Monthly-' + $date + '-' + $line
	$dsdc = Get-Datastore $datastore -Datacenter $datacenter

	try {

		$backup = New-VM -Name $name -VM $line -VMHost $vmhost -Datastore $dsdc -ResourcePool $resourcepool -Location $folder -ErrorAction Stop
		$backup | Out-File $path -Append

		Get-VM -Name $name | Set-VM -ToTemplate -Confirm:$false

		$query = Get-VM -Name $line | select Name, VMHost, GuestId, NumCpu, MemoryMB -ErrorAction Stop
		$query | Out-File $path -Append

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}	

}

Disconnect-VIServer -Server $server -Confirm:$false
  • ทำการสร้างไฟล์ Backup-Weekly.ps1
. "$PSScriptRoot\Configuration.ps1"
Connect-VIServer -Server $server -Credential $credential

$vm = $vm_weekly
$path = $path_log_weekly
$folder = $folder_weekly
$datastore = $datastore

foreach ($line in $vm) {

	$name = 'Backup-Weekly-' + $date + '-' + $line
	$dsdc = Get-Datastore $datastore -Datacenter $datacenter

	try {

		$backup = New-VM -Name $name -VM $line -VMHost $vmhost -Datastore $dsdc -ResourcePool $resourcepool -Location $folder -ErrorAction Stop
		$backup | Out-File $path -Append

		Get-VM -Name $name | Set-VM -ToTemplate -Confirm:$false

		$query = Get-VM -Name $line | select Name, VMHost, GuestId, NumCpu, MemoryMB -ErrorAction Stop
		$query | Out-File $path -Append

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}

}

Disconnect-VIServer -Server $server -Confirm:$false
  • ทำการสร้างไฟล์ Delete.ps1
. "$PSScriptRoot\Configuration.ps1"
Connect-VIServer -Server $server -Credential $credential

foreach ($line_d in $vm_daily) {

	try {
	
		$lastvm = 'Backup-Daily-' + $lastdate_daily + '-' + $line_d
		#Remove-VM $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop
		Remove-Template -Template $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}

}

foreach ($line_w in $vm_weekly) {

	try {

		$lastvm = 'Backup-Weekly-' + $lastdate_weekly + '-' + $line_w
		#Remove-VM $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop
		Remove-Template -Template $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}

}

foreach ($line_m in $vm_monthly) {

	try {

		$lastvm = 'Backup-Monthly-' + $lastdate_monthly + '-' + $line_m
		#Remove-VM $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop
		Remove-Template -Template $lastvm -DeleteFromDisk -Confirm:$false -ErrorAction Stop

	} catch {

		# $ErrorMessage = $_.Exception.Message
    		# $FailedItem = $_.Exception.ItemName
		# $error += $line + "`r`n"

	}

}

Disconnect-VIServer -Server $server -Confirm:$false

อ่านเพิ่มเติม : https://bit.ly/2TC5Isg

One response to “VM Backup with Powershell”

  1. Korawit Deaw Chaiyen Avatar
    Korawit Deaw Chaiyen

    ไฟล์โหลดไม่ได้แล้วครับ

Leave a Reply

Your email address will not be published. Required fields are marked *