CHAPTER 4

image

Virtual Machines Deployment and Management

We think everyone on the planet deserves to have their own virtual data center in the cloud.

—Lew Tucker, CTO, Sun Cloud Group

There is no doubt that virtualization technology plays a major role in cloud computing, whether private or public cloud. In fact, I’d say it’s thanks to virtualization that the cloud runs at all, since it’s the core of the Infrastructure as a Service (IaaS) part of the cloud.

I’m sure I don’t have to tell you about the benefits of using virtualization. Instead, let’s take a couple of minutes and think about it. What if the IaaS ran on top of the physical servers? I think you get my point.

This chapter addresses the virtual machine (VM) service in Azure and its respective PowerShell cmdlets. Mainly, it covers automating different tasks and operations using PowerShell.

Basic Operations: Azure Virtual Machine

The PowerShell fun is about to start, but let’s warm up a little bit to get ready for it.

Since we’re talking about virtual machines, the most basic operations are start, stop, and restart. Although these are basic cmdlets, they are very important, especially when you want to boot-up or shut down a number of VMs.

Again, this is just a stretching exercise. Before you start, make sure that your PowerShell session is authenticated and connected to Azure using either the Import-AzurePublishSettingsFile or the Add-AzureAccount cmdlets. Please refer to Chapter 2 for more details.

To start (turn on) a virtual machine, use the Start-AzureVM cmdlet.

## Start Azure VM (ASM)
Start-AzureVM -ServiceName DevTestFarm -Name WebApp01

## Start Azure VM (ARM)
Start-AzureVM -ResourceGroupName DevTestFarm -Name WebApp01

To restart (reboot) a virtual machine, use the Restart-AzureVM cmdlet.

## Restart Azure VM (ASM)
Restart-AzureVM -ServiceName DevTestFarm -Name WebApp01

## Restart Azure VM (ARM)
Restart-AzureVM -ResourceGroupName DevTestFarm -Name WebApp01

To stop (shut down) a virtual machine, use the Stop-AzureVM cmdlet. The stop cmdlet is a little different. Usually, when you shut down a virtual machine, Azure deallocates its reserved resources to free up hardware and network resources, which also saves you money. For example, the deallocation will free the IP address that was assigned to the virtual machine, so the next time you start the VM, it will acquire a new IP address—unless you assigned a static IP address to it.

Therefore, to make the resource allocated to the VM, use the -StayProvisioned parameter. Just don’t forget that it will keep counting on you.

## Stop Azure VM (ASM)
Stop-AzureVM -ServiceName DevTestFarm -Name WebApp01 –StayProvisioned

## Stop Azure VM (ARM)
Stop-AzureVM -ResourceGroupName DevTestFarm -Name WebApp01 -StayProvisioned

Azure Virtual Machine (VM) Provisioning

Provisioning is the first basic step that everyone has to do to build a virtual machine. The UI looks very neat and attractive, especially with the new colorful Azure portal. It is nice for creating a single or a couple of virtual machines; however, it is not that easy when it comes to the bulk creation of VMs with advanced configurations.

Azure PowerShell provides two different ways to provision a new Azure VM. The first one is the quick provisioning that requires a minimal amount of information to create a VM; this is the PowerShell version of the Azure Portal. Provisioning a VM with the New-AzureQuickVM cmdlet has some limitations. For example, you cannot join a VM to a domain, add new endpoints, set time zones, or disable Windows Updates while creating the virtual machines.

The second way is more advanced; it requires defining each and every detail and configuration item to build a new VM. It is not complicated, but it needs a combination of two or more cmdlets together.

Provisioning a New Azure VM: Quick Configuration

Microsoft Azure allows you to choose from a set of virtual machine templates stored on Azure’s gallery. Those templates are prebuilt images running different operating systems with different server products and software components.

Therefore, you need to know your image name to use it as a parameter within your PowerShell script. You can get the list of available images using the Get-AzureVMImage cmdlet. This cmdlet provides deeply detailed information on the image, which you cannot get from the Azure portal; the recommended VM size is an example.

The following line of code gets the list of available images, and then shows only the VM label, operating system, and recommended VM size.

## Get Azure VM images (ASM)
Get-AzureVMImage | Select Label, OS, RecommendedVmSize, PublishedDate | Sort PublishedDate | ft

You can also use the Get-AzureVMImage cmdlet in the Azure Resource Manager (ARM) module. The great thing about the ARM module is that it provides more capabilities and controls than the same exact cmdlets in the Azure Service Management (ASM) module. For instance, the only available parameter for the Get-AzureVMImage cmdlet in the ASM module is the –ImageName parameter. While in the ARM module, the Get-AzureVMImage cmdlet has the following parameters:

  • -Location: Specifies the location of a VM image, such as Central US or West Europe, and so forth.
  • -Offer: Specifies the type of a VM image offer, such as UbuntuServer or Oracle_Database_11g_R2. You can list the available VM image offers using the Get-AzureVMImageOffer cmdlet.
  • -PublisherName: Specifies the name of the VM image publisher, such as Microsoft or Canonical. You can also use the Get-AzureVMImagePublisher cmdlet.
  • -SKUs: Specifies the VM image SKU, such as JDK. You can also use the Get-AzureVMImageSku cmdlet.
  • -Version: Specifies the VM image version, such as JDK_6 or JDK_7.
## Get Azure VM Images (ARM)

# Get Azure VM Image Publisher
Get-AzureVMImagePublisher -Location "West Europe" |  Group PublisherName | Select Name

# Get Azure VM Image Offer
Get-AzureVMImageOffer -Location "West Europe" -PublisherName Microsoft | Select Offer

# Get Azure VM Image Sku
Get-AzureVMImageSku -Location "West Europe" -PublisherName Microsoft -Offer "JDK" | Select SKUs

# Get Azure VM Image
Get-AzureVMImage -Location "West Europe" -PublisherName Microsoft -Offer JDK -Skus JDK_8

# Get Azure VM Image Details
Get-AzureVMImageDetail -Location "West Europe" -PublisherName Microsoft -Offer JDK -Skus JDK_8 -Version 1.0.0

You have the image name. Now use the New-AzureQuickVM cmdlet to build your first Azure VM using PowerShell. The New-AzureQuickVM cmdlet is used for both Windows and Linux images with a lot of common parameters; however, a few parameters will vary according to the operating system that you are provisioning.

The following code sample shows how to provision a new Azure VM running on the Windows operating system using the New-AzureQuickVM cmdlet. In this example, you use the minimal number of parameters to provision a new VM. These parameters are as follows:

  • -Name: Defines the name of the VM.
  • -ImageName: Specifies which VM image will be used to provision the VM.
  • -ServiceName: Enrolls the VM under an existing cloud service, or creates a new cloud service if the name doesn’t exist.
  • -Windows: Specifies that the VM will run on the Windows operating system.
  • -AdminUsername: Defines the name of the local administrator.
  • -Password: Defines the password for the local administrator with the

    -AdminUsername parameter.

  • -Location: Specifies which region will host the VM.
  • -VNetName: Specifies which virtual network the VM belongs to. (Azure virtual networks are discussed in more detail in Chapter 5.)
  • -AffinityGroup: Chooses which affinity group will host the VM. The AffinityGroup’s properties include location, virtual network, and storage account. Thus, once you specify it, you won’t have to identify parameters like

    -Location or -VNetName. Just remember that Microsoft’s recommendation is to not use affinity groups anymore.

  • -InstanceSize: Defines the size of the VM instance. You can refer to https://msdn.microsoft.com/library/azure/dn197896.aspx for a list of all the available sizes, or you can use the Get-AzureRoleSize cmdlet.
## Provision new Azure VM – Windows – (ASM)

# Windows Server 2012 R2, Datacenter Edition
$ImageName = "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-Datacenter-201412.01-en.us-127GB.vhd"

New-AzureQuickVM -Windows -Name WebSrv01 -ServiceName "myPublicWebsite" -ImageName $ImageName -Password Microsoft@123 -AdminUsername SherifT -Location "West Europe" -InstanceSize Basic_A1

The previous code provisions a new VM from Windows Server 2012 R2 images. The VM named WebSrv01 with size A1 is part of the myPublicWebSite cloud service located in the West Europe datacenter and it has a local administrator called SherifT. Very simple and straightforward, isn’t it?

Now let’s provision another VM, but this time to run on a Linux operating system. You are going to use the same code from the previous example, but you will change two parameters.

Yes, you guessed right—the first parameter to change is -Windows, which is replaced with -Linux. The second parameter to change is -AdminUsername, which is replaced with -LinuxUser. Finally, don’t forget to change the value of -ImageName with a Linux image.

## Provision new Azure VM – Linux – (ASM)

# SUSE Linux Server 12
$ImageName = "b4590d9e3ed742e4a1d46e5424aa335e__suse-sles-12-v20150213"

New-AzureQuickVM -Linux -Name WebSrv01 -ServiceName "myPublicWebsite" -ImageName $ImageName -Password Microsoft@123 -Linuxuser root -Location "West Europe" -InstanceSize Basic_A1

The New-AzureQuickVM cmdlet is an ASM module cmdlet; it has no equivalent in the ARM module.

Provisioning a New Azure VM: Advanced Configuration

The other way to provision a virtual machine is to combine the New-AzureVMConfig, Add-AzureProvisioningConfig, and New-AzureVM cmdlets. Each one of these cmdlets handles a specific part of the provisioning process, and, of course, requires a different set of parameters.

The New-AzureVMConfig cmdlet takes care of creating the virtual machine configuration object, which is simply the configuration required to create the virtual machine itself. An example of the configuration is the VM name, image template, instance size, VM label, and so forth.

The Add-AzureProvisioningConfig cmdlet is always used with the New-AzureVMConfig cmdlet; it’s responsible for adding the provisioning configuration to the virtual machine. The provisioning configuration defines the settings of the operating system running on the virtual machine. For example, you define the operating system—either Windows or Linux, the admin username and password, certificates, the time zone, endpoints, and so forth.

The last cmdlet is the New-AzureVM cmdlet that creates the virtual machine based on the config object and the provisioning config defined earlier using the New-AzureVMConfig and Add-AzureProvisioningConfig cmdlets.

The following code example shows how to combine these cmdlets to provision a Windows virtual machine. In this example, you provision a domain-joined Windows Server VM. You will find that some of the parameters are similar to the parameters of the New-AzureQuickVM cmdlet; however, some of them are new but look familiar, such as the following:

  • -WindowsDomain: Provisions a Windows VM joined to the Active Directory domain.
  • -JoinDomain: Specifies the name of the domain that the computer will join.
  • -DomainUsername: Specifies the domain account that has access to join the machine to the domain. -Domain specifies the domain of the user account. Also, the -DomainPassword parameter specifies the password of the domain account.
  • -MachineObjectOU: Specifies the FQDN of the organizational unit (OU) in which the computer object will be created.

As I said earlier, the combination of cmdlets gives you more config options when it comes to the operating system provisioning configuration, especially on Windows.

## Provision new Azure VM - Windows (Advanced) - (ASM)

# Windows Server 2012 R2, Datacenter Edition
$ImageName = "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-Datacenter-201412.01-en.us-127GB.vhd"

# Create VM Config Object and Provisioning Config
$vm1 = New-AzureVMConfig -Name WebSrv01 -InstanceSize Basic_A1 -ImageName $ImageName

$vm1 | Add-AzureProvisioningConfig -AdminUsername "SherifT" –Password "P@ssw0rd" -WindowsDomain –Domain "Corp" –JoinDomain "Corp.local" –DomainUserName "Administrator" –DomainPassword "P@ssw0rd" -MachineObjectOU "OU=AzureVMs,DC=Corp,DC=local" -DisableAutomaticUpdates -TimeZone "Pacific Standard Time"

# Create Azure VM using the previously created config object
New-AzureVM -ServiceName "myPublicWebsite" -VMs $vm1

On the other hand, to achieve the same task using the ARM module, you’d use the New-AzureVMConfig cmdlet to create the VM config object, and the New-AzureVM cmdlet to provision the virtual machine. You’d replace the Add-AzureProvisioningConfig cmdlet with the following cmdlets:

  • Set-AzureVMSourceImage: Specifies the image that will be used to provision the VM.
  • Set-AzureVMOperatingSystem: Sets the operating system properties and settings for the VM.
  • Add-AzureVMNetworkInterface: Adds a network interface to the VM.
## Provision new Azure VM - Windows (Advanced) - (ARM)
# Create PSCredential Object
$Username = "Sherif"
$Password = "Master@123" | ConvertTo-SecureString -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential($Username,$Password)

# Create VM Config Object
$vm1 = New-AzureVMConfig -VMName WebSrv01 -VMSize Basic_A1

# Configure VM Source Image
Set-AzureVMSourceImage -VM $vm1 -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2012-R2-Datacenter -Version 4.0.20150726

# Configure VM Operating system
Set-AzureVMOperatingSystem -VM $vm1 -Windows -ComputerName "WebSrv01" -ProvisionVMAgent -EnableAutoUpdate -Credential $Cred

# Configure VM Network Interface
Add-AzureVMNetworkInterface -VM $vm1 -Id (Get-AzureNetworkInterface -ResourceGroupName DevTestFarm -Name nic1).Id -Primary

# Provision VM
New-AzureVM -ResourceGroupName DevTestFarm -VM $vm1 -Location "West Europe"

As seen in the preceding example, ARM looks very similar to ASM from a conceptual point of view. However, ARM has more cmdlets with more parameters than ASM, which makes it more straightforward and direct. In this example, you replaced the Add-AzureProvisioningConfig cmdlet that has tons of parameters with the three cmdlets, each having three to five parameters. This is easy to remember and easy to use.

Another interesting cmdlet in the ARM module is the Add-AzureVMAdditionalUnattendContent cmdlet. Yes, it’s what you were thinking! This cmdlet allows you to add extra information to the unattended Windows setup answer file (unattend.xml). Therefore, you are able to configure any operating system’s settings, even if it’s not available as a parameter.

Configuring Virtual Machine Endpoints

Endpoints define how the Internet inbound traffic will be directed to the virtual machine. Each endpoint has a public port, a private port, and a protocol.

The public port is used by Azure load balancers to listen for the incoming traffic from the Internet. The private port is used by the virtual machine to listen for incoming traffic from Azure load balancers. The protocol is either TCP or UDP.

As you can see, endpoints are pretty similar to the idea of networking address translation (NAT) or port forwarding capability in routers and managed switches (gamers and P2P masters can relate).

When you provision a new virtual machine, Azure creates default endpoints: RDP and PowerShell for Windows, and SSH for Linux. You can list all the configured endpoints for a specific virtual machine using the Get-AzureEndpoint cmdlet. The following example lists the endpoints for a VM called WI-DC-01.

## List configured EndPoints for VM (ASM)
# Create a VM object with the targeted VM config
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName CloudFarm

# Retrieve the Endpoints list
$vm | Get-AzureEndpoint | Select Name, Protocol, Port, LocalPort

To add a new endpoint to an Azure VM, you use the Add-AzureEndpoint cmdlet. It is very straightforward: you just define the name, the protocol, and the public and private ports. The following example shows how to add an HTTPs endpoint to an existing Azure virtual machine.

First, you need to create a VM object of the target virtual machine. Then, you add the new endpoint configuration. Finally, you update the virtual machine config using the Update-AzureVM cmdlet.

## Add EndPoint to VM (ASM)
# Create a VM object with the targeted VM config (ASM)
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName  CloudFarm

# Add endPoint and Update the VM
$vm | Add-AzureEndpoint -Name ’HTTPs’ -Protocol TCP -LocalPort 443 -PublicPort 443 | Update-AzureVM

As an extra security, Azure endpoint provides access control list (ACL) capability so that you can permit/deny access to the endpoint based on the source IP address. To define the ACL rule for an endpoint, use the -ACL parameter with the Add-AzureEndpoint cmdlet.

To create a new ACL, you use the New-AzureAclConfig cmdlet. It is just an empty config object for the ACL, so it hasn’t any parameter. Then, you use the Set-AzureAclConfig cmdlet to define the access rules. The Set-AzureAclConfig cmdlet has a different set of parameters, depending on which action you want to apply. You could add a rule, remove a rule, or update an existing rule.

The next example shows how to create a new ACL and add a rule to it.

## Create EndPoint ACL (ASM)
# Create new ACL Config Object
$acl = New-AzureAclConfig

# Set ACL Config - Add Rule
Set-AzureAclConfig -AddRule -ACL $acl -Action Permit -Order 1 -RemoteSubnet "10.10.0.0/8" -Description "On-Premises vLAN"

RuleId       : 0
Order        : 0
Action       : Permit
RemoteSubnet : 10.10.0.0/8
Description  : On-Premises vLAN

In this example, you created the new ACL config object $acl. You then added a new access rule to permit all requests from the 10.10.0.0/8 subnet. Now you can just pass the $acl object to the -ACL parameter with the Add-AzureEndPoint cmdlet.

#Get VM object of VM "WI-DC-01"
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName CloudFarm

#Adding Azure Endpoint to $vm
$vm | Set-AzureEndpoint -Name ’HTTPs’ -Protocol TCP -LocalPort 443 -Port 443 -ACL $acl | Update-AzureVM)

Virtual Machines Load Balancing

Network Load Balancing (NLB) plays a major role in any application serving users, such as web sites. In on-premises scenarios, you usually set NLB hardware in place or set up the NLB role in Windows Server.

In Azure, it’s a little different; the hardware load balancers already exist as part of Azure’s datacenter infrastructure. You just have to configure the NLB settings.

There are two load-balancing options in Azure, depending on the scenario you are looking for. To be more specific, it depends on the source of the incoming traffic—the Internet or an intranet.

For Internet incoming traffic, you use the load-balanced (LB) endpoints. However, for intranet incoming traffic, you use the internal load balancer (ILB) in cases like having back-end database servers that get traffic from front-end Internet-facing web servers.

Configuring NLB Using Endpoints

Using Azure endpoints for load balancing is very similar to adding an endpoint to an Azure VM; the difference is only in the parameter set that differentiates between the stand-alone and the load-balanced endpoints.

I’ll explain by example. You have an Azure cloud service that hosts a web farm consisting of four Azure VM instances. You want to make sure that incoming traffic is distributed among the four VMs.

For the purpose of this task, you will use the Add-AzureEndpoint cmdlet along with the following parameter set:

  • -Name: Specifies a name for the endpoint rule.
  • -Protocol: Specifies the endpoint protocol—either TCP or UDP.
  • -LocalPort: Specifies the endpoint local port.
  • -PublicPort: Specifies the endpoint public port to listen to the incoming Internet requests.
  • -LBSetName: Specifies a name for the load-balanced endpoint that will be used by different VMs.
  • -ProbeProtocol: Specifies the protocol for the load-balanced endpoint to be probed (checked), whether HTTP or TCP.
  • -ProbePort: Specifies the port to be used by the probes; by default, the public port is used if this parameter is not defined.
  • -ProbePath: Specifies the URI to be used by probes; it’s used only with the HTTP probe protocol.
## Configure NLB EndPoints (ASM)
# Get all VMs within Cloud Service
$VMs = Get-AzureVM -ServiceName  CloudFarm

# Adding Load-Balanced Azure Endpoint to $VMs
$VMs | Add-AzureEndpoint -Name "LB-Http" -Protocol tcp -PublicPort 80 -LocalPort 80 -LBSetName "LB-WebFarm" -ProbePort 80 -ProbeProtocol "http" -ProbePath "/" | Update-AzureVM

In this code, the added load-balanced endpoint looks similar to the stand-alone endpoint. However, I am sure that you’ve noticed that few parameters start with the keyword Probe. The probe is what Azure uses to check the health of the endpoint and its resources to make sure that it’s alive and operating. If a resource didn’t respond before the probing timeout, then it gets out of the rotation to avoid sending a request to a resource that is down.

Azure VM endpoints have no cmdlets in the ARM module; the reason is that the service architecture changed entirely and endpoints are no longer part of VM configuration. The endpoints are now known as NAT rules. Network security groups configured as part of Azure networking have their own cmdlets, which will be covered in Chapter 5.

Working with Virtual Machine Data Disks

There are three different types of VM disks in Azure: the operating system disk, the temporary storage disk, and the data disk.

There is one operating system disk per virtual machine. It’s a SATA drive and has a maximum capacity of 127 GB.

The temporary storage disk is non-persistent storage that’s created automatically for applications and processes. Once you restart or shut down the VM, all data is removed.

The data disk is persistent storage that is used to store application data and user files. The data disks are registered as SCSI drives. To attach a data disk to a VM, you use the Add-AzureDataDisk cmdlet, which supports three different parameter sets.

Attaching an Empty Data Disk

In this scenario, you are creating a new empty data disk, which you will attach to an existing Azure VM. For the purpose of this task, you will use the CreateNew parameter set, which uses the following parameters:

  • -CreateNew: Creates a new data disk.
  • -DiskSizeInGB: The size of the data disk in gigabytes.
  • -DiskLabel: Specifies a label for this data disk.
  • -LUN: Specifies the LUN location for the data disk in the VM. You can choose a LUN value from 0 to 15.
  • -VM: Specifies the VM to add the data disk to.
  • -MediaLocation: Specifies the location of the Azure storage account’s blob to store the data disk on. If you didn’t use this parameter, then the default location is the VHDs container under the default storage account.
## Attaching Empty Data Disk to VM (ASM)
# Create a VM object with the targeted VM config
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName  CloudFarm

# Attach new data disk and Update the VM
$vm | Add-AzureDataDisk -CreateNew -DiskSizeInGB 50 –DiskLabel "ISOs" -LUN 0 | Update-AzureVM

In the previous code, you created a 50 GB data disk labeled ISOs and you attached it to the WI-DC-01 VM on LUN 0.

The Add-AzureDataDisk cmdlet could be used in combination with the Add-AzureProvisioningConfig cmdlet to add the data disk while provisioning a new VM.

You can query the data disk information using the Get-AzureDataDisk cmdlet.

# Query Data Disks attached to VM (ASM)
$vm | Get-AzureDataDisk

The equivalent to the Add-AzureDataDisk cmdlet in the ARM module is the Add-AzureVMDataDisk cmdlet along with the following parameters:

  • -Caching: Specifies the caching mode of the disk, either ReadOnly or ReadWrite.
  • -DiskSizeInGB: The size of the data disk in gigabytes.
  • -Name: Specifies a name for the data disk.
  • -LUN: Specifies the LUN location for the data disk in the VM. You can choose a LUN value from 0 to 15.
  • -VM: Specifies the VM to add the data disk to.
  • -VhdUri: Specifies the location of the Azure storage account’s blob to store the data disk on.
  • -CreationOption: Specifies whether the disk will be created as an empty disk or an attached existing disk, or created from an image. The available values are Attach, Empty, and FromImage.
  • -SourceImageUri: Specifies the URI of the disk when the creation option value is Attach.
## Attaching Data Disk to VM (ARM)
# Create a VM object with the targeted VM config
$vm = Get-AzureVM –ResourceGroupName DevTestFarm –Name WebSrv01

#Add Azure Data Disk
$diskLocation = https://mylabstorageaccount.blob.core.windows.net/vhds/datadisk1.vhd

Add-AzureVMDataDisk -VM $VirtualMachine -Name "disk1" -VhdUri $diskLocation -LUN 2 -Caching ReadWrite -DiskSizeinGB 1 -CreateOption Empty

# Update the VM
Update-AzureVM –ResourceGroupName DevTestFarm –Name WebSrv01 –VM $vm1

Attaching an Existing Data Disk

The second scenario is importing an existing data disk to an Azure VM. For example, let’s say that you have a problem with an OS disk in another virtual machine and you want to troubleshoot it. Thus, you can import it as a data disk in a different VM to fix it.

To import an existing data disk, you use the Import parameter set with the following parameters:

  • -Import: Imports an existing data disk.
  • -DiskName: Specifies the name of the disk to import from the default disk library.
  • -LUN: Specifies the LUN location for the data disk in the VM. You can choose a LUN value from 0 to 15.
  • -VM: Specifies the VM to add the data disk to.

Before you start the attachment process, you need to detach the disk from its original VM by using the Remove-AzureDataDisk cmdlet, as shown in the following example.

## Attach an Existing Data Disk to VM (ASM)
# Detach data disk from old VM
Get-AzureVM -Name oldVM -ServiceName CloudFarm | Remove-AzureDataDisk –Lun 2 | Update-AzureVM

# Create a VM object with the targeted VM config
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName CloudFarm

# Import an existing data disk and Update the VM
$vm | Add-AzureDataDisk -Import -DiskName "myISOsVHD" -LUN 1 | Update-AzureVM

Importing a Data Disk from a Different Location

The last parameter set is ImportFrom, which is similar to the Import parameter set, but it is mainly to import a data disk from a specific blob in an Azure storage account. Therefore, you replace the -DiskName parameter with the -MediaLocation parameter, and, of course, change the parameter set from Import to ImportFrom, as shown in the following code sample.

## Importing Data Disk from different Location (ASM)
# Create a VM object with the targeted VM config
$vm = Get-AzureVM -Name WI-DC-01 -ServiceName  CloudFarm

# Import an existing data disk and Update the VM
$DiskLocation = https://mystorage.blob.core.windows.net/Disks/myISOsVHD.vhd

$vm | Add-AzureDataDisk -ImportFrom –MediaLocation –DiskLabel "myISOsVHD" $DiskLocation -LUN 1 | Update-AzureVM

Image Note  If you want to important an Azure data disk that is attached to an Azure VM, you have to detach it from that VM first using the Remove-AzureDataDisk cmdlet.

As you’ve noticed, you have used the blob endpoint URI to specify which data disk to import to the WI-DC-01 VM instance. If the disk is attached to the VM, then you can get the disk location using the Get-AzureDataDisk cmdlet, as shown in the next example, or search the storage account and underlying containers and blobs using the Get-AzureStorageContainer and Get-AzureStorageBlob cmdlets, as discussed in Chapter 3.

## Getting URI of Data Disk Attached to VM (ASM)
$vm = Get-AzureVM -Name WI-SQL-01 -ServiceName  CloudFarm
$diskURI = Get-AzureDataDisk –VM $vm | Select MediaLink
$diskURI.MediaLink.OriginalString

https://mystorage.blob.core.windows.net/Disks/myISOsVHD.vhd

Moving On-Premises VM to Azure

One popular scenario, especially for the cloud-enabled infrastructure, is moving virtual machines between on-premises and cloud sites for migration, disaster recovery, or even testing. So instead of rebuilding the entire VM on Azure, you can simply upload your on-premises VM’s VHD(s) to Azure and build the Azure VM using this uploaded disk. Thus, you have two steps to do here: upload and provision.

To upload a VHD file from on-premise to the Azure blob, you use the Add-AzureVHD cmdlet. To do the reverse, you use the Save-AzureVHD cmdlet to download an Azure disk from the blob to a local file. For a simple VHD upload, you use the -Destination and -LocalFilePath parameters, as shown in the following code.

## Moving On-Premises VM to Azure (ASM)
# Get the Azure Storage Account for the default Azure Subscription
$StorageAccountName = (Get-AzureSubscription).CurrentStorageAccount

# Specify Local VHD file path
$LocalVHD = ’D:Hyper-VVirtual Hard DisksWebSrv01.vhd’

# Specify the URI for the Windows Azure Container
$Destination = ’http://’ + $StorageAccountName + ’.blob.core.windows.net/vhds/ WebSrv01.vhd’

# Move VHD file from local server to Azure Storage account blob
Add-AzureVhd -LocalFilePath $LocalVHD -Destination $Destination

This code uploads a fixed VHD to an Azure blob; however, if you want to upload a different disk, then you need to specify the base image for the disk by using the -BaseImageUriToPatch parameter. You might also use the -overwrite parameter to replace an existing disk. Finally, you can use the -NumberOfUploaderThreads cmdlet while uploading the VHD. The default number of uploader threads is 8.

Well, you have uploaded the VHD file successfully to Azure. Because it is still just a file, you need to register it as a disk using the Add-AzureDisk cmdlet in the Azure disks repository so that you can attach it to the Azure VM. To add it to the disks repository, you use the following parameters:

  • -DiskName: Specifies the name of the disk that will appear in the repository. This is the name that is used with the Import parameter set in the Add-AzureDataDisk cmdlet.
  • -DiskLabel: Specifies a label for the disk.
  • -MediaLocation: Specifies the URI of the blob in the Azure storage account that stores the VHD file.
  • -OS: Specifies that the disk is bootable and has an operating system. You select either Windows or Linux.

Let’s register the disk you uploaded in the previous example.

#Add the VHD file to Azure Disks Repository
Add-AzureDisk -OS Windows -DiskName "WebSrv01" -MediaLocation $Destination

Perfect. Now you have the WebSrv01 disk in the repository. Finally, let’s provision the VM using this disk. To do this task, you use the New-AzureVMConfig cmdlet. Yes, it’s the same cmdlet that you used earlier to provision a VM from an image. The New-AzureVMConfig cmdlet has two parameters sets: ImageName and DiskName.

Both parameter sets are pretty similar; you just need to replace the -ImageName parameter with the -DiskName parameter, as shown in the following example.

#Create VM Config Object with DiskName parameter set
$vm1 = New-AzureVMConfig -Name WebSrv01 -InstanceSize Basic_A1 -DiskName "WebSrv01"

#Create Azure VM using the previously created config object
New-AzureVM -ServiceName "myPublicWebsite" -VMs $vm1

Well done. The virtual machine is being provisioned and it will be ready in a couple of minutes.

Azure VM Images

Although Azure has a huge number of VM images (523 at the moment I’m writing these lines), it is still not enough. Azure VM images are very generic, but your company may require something that is customized. Therefore, Azure allows you to build your own custom images.

There are two ways to build a custom image: the first way is to capture an existing Azure VM and the second way is to use an OS VHD.

Creating a VM Image from an Existing VM

The process is very simple: you build a virtual machine using one of the existing images, and then you customize it to match your business needs and requirements. Lastly, you capture the new state of the VM with customization as a standard VM image.

To capture an existing VM, you use the Save-AzureVMImage cmdlet. This captures and saves the image of a stopped VM, and then deletes the source VM.

Before starting the capturing process, make sure to generalize your operating system by using SysPrep for Windows, or waagent for Linux.

## Create Azure VM Image (ASM)
Save-AzureVMImage -ServiceName CloudWebFarm -Name WebSrv01 -ImageName "WebSrvImage" -ImageLabel "Corp Web Server Image" -OSState Generalized

In this code, you’ve captured the VM WebSrv01 under the CloudWebFarm cloud service, and then saved it to a new VM image called WebSrvImage.

The same cmdlet is available in the ARM module but with different parameters, as usual. After generalizing the operating system, you mark the VM as generalized using the Set-AzureVM cmdlet, as shown in the following example.

## Create Azure VM Image (ARM)
# Mark the VM as generalized
Set-AzureVM –ResourceGroupName CloudWebFarm –Name WebSrv01 –Generalized

# Capture the VM as VM Image
Save-AzureVMImage –ResourceGroupName CloudWebFarm –VMName WebSrv01 –VHDNamePrefix VM01 –DestinationContainerName "VMImages"

Creating a VM Image from a VHD

Unlike the first method, you can build your own VM locally on Hyper-V and generalize the operating system, and then upload the VHD to Azure using the Add-AzureVhd cmdlet. Finally, you add it to the images repository using the Add-AzureVMImage cmdlet.

## Creating VM Image from VHD (ASM)
#Specify Local VHD file path
$LocalVHD = ’D:Hyper-VVirtual Hard DisksWebSrv01.vhd’

#Specify the URI for the Windows Azure Container
$Destination = ’http://’ + $StorageAccountName + ’.blob.core.windows.net/vhds/ WebSrv01.vhd’

#Move VHD file from local server to Azure Storage account blob
Add-AzureVhd -LocalFilePath $LocalVHD -Destination $Destination

#Build VM image using vhd
Add-AzureVMImage -ImageName  WebSrvImage -Label "Corp Web Server Image" -OS Windows -MediaLocation $Destination -PublishedDate (Get-Date)

Once you build the image, you might want to add or modify its properties. Using the Update-AzureVMImage cmdlet, you are able to update the following properties:

  • ImageName
  • Label
  • EULA
  • Description
  • ImageFamily
  • PublishedDate
  • PrivacyUri
  • RecommendedVMSize
  • DiskConfig
  • Language
  • IconUri
  • DontShowInGui

Generating an Azure VM RDP File

Remote Desktop Protocol (RDP) is a very important tool for managing your VM, especially if it is hosted on a remote datacenter like the cloud. Azure configures the RDP endpoint by default for each VM. There is a button on the Azure portal that allows you to save an RDP file (*.rdp), which has required information like the hostname and ports.

Very cool, huh? It’s cool if you want to get the RDP file for one VM, but when it comes to getting the files for a number of VMs under one subscription, trust me, it gets boring very fast. Doing it in PowerShell is cooler. Azure PowerShell has the Get-AzureRemoteDesktopFile cmdlet that gets the RDP file for a selected VM.

In the following example, you use the cmdlet to save the RDP files for all VMs under a specific cloud service.

$VMs = Get-AzureVM -ServiceName CloudFarm

ForEach ($VM in $VMs)
{
    $FileName = $VM.Name + ".rdp"
    Get-AzureRemoteDesktopFile -ServiceName $VM.ServiceName -Name $VM.Name -LocalPath $homeDesktopAzureRDPs$FileName
}

In this code you used the -LocalPath parameter to specify where to save the RDP file. However, you can replace it with the -Launch parameter to initiate a remote connection instead of saving the file.

The same cmdlet is available in the ARM module with almost the same parameters. You just replace the –ServiceName parameter with the –ResourceGroupName parameter.

Exporting and Importing Azure Virtual Machines

How many times you have deleted and rebuilt a virtual machine because you placed it in the wrong cloud service? C’mon, don’t be shy. You are not alone. This happens all the time, but thankfully PowerShell covers us. The problem is not in rebuilding the VM, but in discovering a mistake at a later stage—after finishing all the setup and configuration.

As another scenario, let’s say that you have a virtual machine deployed in the Dev & Test cloud service, and you want to move it to the production cloud service without rebuilding the entire VM from scratch.

The Export-AzureVM cmdlet allows you to export the VM state that includes the configurations and settings of the VM. Then, using the Import-AzureVM cmdlet, you can import again to rebuild this VM, but under a different cloud service.

The following example shows these cmdlets moving VMs between two different cloud services.

First, you need to export the VM state using the Export-AzureVM cmdlet.

#Exporting Azure VMs State
$VMs = Get-AzureVM -ServiceName ’DevTestFarm’

ForEach ($VM in $VMs)
{
    $FileName = $VM.Name + "_VMState.xml"

    Export-AzureVM -ServiceName $VM.ServiceName -Name $VM.Name -Path $homeDesktopVMs$FileName
}

Since you are importing virtual machines that already exist, to avoid conflicts and errors during the import process, you need to remove those VMs before moving to the next step. You use the Remove-AzureVM cmdlet to remove a virtual machine.

You can add it within the ForEach loop just after the Export-AzureVM line. Thus, the new code should looks like the following.

#Exporting Azure VMs State
$VMs = Get-AzureVM -ServiceName ’DevTestFarm’

ForEach ($VM in $VMs)
{
    $FileName = $VM.Name + "_VMState.xml"

    Export-AzureVM -ServiceName $VM.ServiceName -Name $VM.Name -Path $homeDesktopVMs$FileName

    #Removing the VM without Deleting VHD
    Remove-AzureVM -ServiceName $VM.ServiceName -Name $VM.Name
}

Image Note  Removing the virtual machine only removes the VM object without deleting the virtual machine’s disks, unless you use the -DeleteVHD parameter. Keep in mind that Import-AzureVM is just creating a new VM object using the exported virtual machine’s disk.

Finally, import the VM’s state file using the Import-AzureVM cmdlet, and build the virtual machine using the New-AzureVM cmdlet.

#Importing Azure VMs States
$VMs = Get-ChildItem $homeDesktopVMs

ForEach ($VM in $VMs)
{
    Import-AzureVM -Path $VM.Name | New-AzureVM -ServiceName ’ProductionFarm’
}

Azure VM Extensions

Azure VM Extensions are software components (add-ons) that extend the virtual machine’s capabilities and simplify the management of IaaS resources. For example, there is a VMAccess extension that allows you to reset the password of the VM. VMCustomerScriptExtension allows the execution of a PowerShell script. There are so many more on the list, which grows every day. You can list all the available VM Extensions by using the Get-AzureVMAvailableExtension cmdlet.

#List all Available VM Extensions
Get-AzureVMAvailableExtension | Select ExtensionName, Description, Publisher, Version | Out-GridView

How Does the VM Extension Work?

When provisioning a virtual machine, Azure installs a VM Agent that is responsible for handling the extension on the operating system. By default, the VM Agent is installed unless you manually disabled it while configuring the virtual machine.

The following line of code checks the ProvisionGuestAgent VM property to determine if the agent is installed or not.

## Check VM Guest Agent Status (ASM)
(Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’).VM.ProvisionGuestAgent

## Check VM Guest Agent Status (ARM)
(Get-AzureVM -ResourceGroupName ’DevTestFarm’ –Name ’WebSrv01’).OSProfile.WindowsConfiguration.ProvisionVMAgent

Installing and Enabling a VM Agent

If you disabled the VM Agent, for any reason, while building your virtual machine and now you want to enable it again, you need to download and install the VM Agent package on the target virtual machine.

Image Note  The VM Agent MSI Installer is available at http://go.microsoft.com/fwlink/?LinkID=394789&clcid=0x409.

Then change the value of the ProvisionGuestAgent property to $True, as shown in the following code.

#Get the VM object
$VM = Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’

#Update the ProvisionGuestAgent Property
$VM.VM.ProvisionGuestAgent = $True

#Commit the changes on the VM
$VM | Update-AzureVM

Now the VM Agent is installed and the VM Extensions are ready to be enabled.

Working with VM Extensions

As I said, there are a lot of VM Extensions that serve different needs. If you have a virtual machine in which a VM Agent is installed by default, then you will find the BGInfo tool installed. The BGInfo on an Azure virtual machine is actually an Azure VM Extension called VMBGInfo.

You can query the virtual machine’s installed VM Extension by using the Get-AzureVMExtension cmdlet, as follows.

#Listing all enabled VM Extensions
Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’ | Get-AzureVMExtension | Select Name, Publisher, Version

If you want enable an extension for a virtual machine, then use the set-* cmdlet for this extension. For example, use the Set-AzureVMAccessExtension cmdlet to enable the VMAccess extension. You could also use the Set-AzureVMExtension cmdlet along with the ExtensionName, Publisher, and Version parameters.

#Enable VMAccess Extension
$VM = Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’

$VM | Set-AzureVMAccessExtension | Update-AzureVM

This code enables the VMAccess extension of VM WebSrv01.

To use the extension capabilities in this case, reset the local administrator’s password. You will use the Set-AzureVMAccessExtension cmdlet along with the respective parameters, which are -Username and -Password.

#Reset Local Admin Password using VMAccess Extension
$VM = Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’

$VM | Set-AzureVMAccessExtension -Username SherifT -Password ’P@ssw0rd123’ | Update-AzureVM

If you want to disable or uninstall the extension, use the same code and add the -Disable or -Uninstall parameters.

#Disable VMAccess Extension
$VM = Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’

$VM | Set-AzureVMAccessExtension -Disable | Update-AzureVM

#Uninstall VMAccess Extension
$VM = Get-AzureVM -ServiceName ’DevTestFarm’ -Name ’WebSrv01’

$VM | Set-AzureVMAccessExtension -Uninstall | Update-AzureVM

Image Note  Uninstalling a VM Extension will totally remove the extension resource from the virtual machine; however, the Disable option keeps the resource installed by simply changing the state to disabled.

Perfect! Now, you have enabled the extension and you were able to reset the local admin’s password. This concept applies to all VM Extensions.

Summary

In this chapter, you learned about one of the most important components of the Azure IaaS: Azure virtual machines (VM). The chapter covered almost all the PowerShell cmdlets available for Azure VMs. You learned about VM provisioning, VM endpoints, and load balancing, and how to work with VM disks. Then, you moved to more advanced topics, like moving VMs between on-premises and Azure, and building custom Azure VM images. The chapter closed by discussing Azure VM Extensions.

In the next chapter, you jump to another IaaS component: the Azure virtual network. You will learn about its different capabilities. You’ll also learn how to use Azure PowerShell cmdlets to create and configure virtual networks and VPNs, and to manage and maintain virtual networks and other services and components.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.206.69