In this chapter you will learn about using the Microsoft Azure PowerShell cmdlets to create a virtual machine with Microsoft Azure platform images. As part of learning this process, you will learn how to specify the initial configuration settings such as the local administrator account name and password, the virtual machine size (CPUs and memory), network endpoints, and underlying storage. From there you will learn how to use those same concepts to modify the configuration of existing virtual machines, whether they are running or not.
To get started creating your first virtual machine using PowerShell, you will need some environment information from Microsoft Azure. This is the same information that you use in the portal, such as the region name and the storage account that will be used as the location where your virtual machine disks are created.
For the first part of this chapter, I would recommend creating a new PowerShell file and saving it with a name such as chapter3create.ps1. Some portions of this chapter will be saved to the script and edited in the Script pane (top portion of the ISE) to make it easier to follow, and some portions should be executed in the Console pane (bottom portion of the ISE) for immediate results.
The first call related to Microsoft Azure of your new script should always be to Select-AzureSubscription
to ensure that you are executing commands against the correct Microsoft Azure subscription.
Add the code shown in Example 3-1 to create a variable to store your subscription name and then select that subscription for use. Ensure that you replace the placeholder values with real ones.
$subscription
=
"[subscription name]"
Select-AzureSubscription
$subscription
Remember, you can find the name of your subscriptions by calling Get-AzureSubscription | Select SubscriptionName
in the Console pane. Use that value instead of the placeholder value in the example. The subscription name is case sensitive!
Executing the script
When the call to Select-AzureSubscription
is in place, press F5, or highlight the script and press F8, to select your current subscription. This will validate that you have the correct subscription name in place and will also set any future commands run from the Console pane to that subscription.
All resources in Microsoft Azure are created in a specific region. This is the same region that you see in the management portal when you create a virtual machine.
To retrieve a list of available regions, you can run the Get-AzureLocation
cmdlet (see Example 3-2). Since the goal is to have an immediate list of available names and not run these each time you execute this script, I would suggest you run this command in the Console pane of the PowerShell ISE (see Example 3-2).
A few properties of the output shown in Figure 3-1 are very important for provisioning virtual machines:
AvailableServices
Name
You can create a virtual machine only in locations where the AvailableServices
list contains PersistentVMRole
. The AvailableServices
list can also contain a HighMemory
value. This denotes locations where the A5, A6, A7, A8, A9, and future high-memory virtual machine configurations are available to be provisioned. The Name
property is the value you will use to specify the location during the creation of resources.
After you have determined the region in which to create virtual machines, you can store the name of the region in a variable for later reference. Add the code in Example 3-3 to your script to store the region name.
The next step is to specify the storage account where the virtual machines will be created. The storage account must be in the same region as the virtual machine. This is enforced at the API level so you do not accidentally end up in a situation where your virtual machine is running on the West Coast of the United States but the underlying disks are in Europe!
The first option is to enumerate your existing storage accounts for a suitable storage account. The command in Example 3-4 will enumerate all of the storage accounts in your subscription but return only the StorageAccountName
and Location
properties (see Figure 3-2).
Get-AzureStorageAccount
|
select
StorageAccountName
,
Location
If you do not have a storage account available, or you just want to create a new one, use the New-AzureStorageAccount
cmdlet.
To ensure the availability of the Microsoft Azure storage account name, you should use the Test-AzureName
cmdlet first (see Example 3-5). Test-AzureName
verifies whether the name is available for your use in Microsoft Azure. Make sure you replace the [storage account name]
placeholder in the script before executing!
Test-AzureName
-Storage
-Name
"[storage account name]"
If the call returns True
, the storage account name already exists and is not available to you. Run the command with a new name until the call returns False
, which means that the storage account name is available. Create the new storage account as shown in Example 3-6.
The name of your storage account must be unique within Azure. Storage account names must be between 3 and 24 characters in length and use numbers and lowercase letters only.
New-AzureStorageAccount
-StorageAccountName
"[storage account name]"
`
-Location
$location
When you determine the name of the storage account to use, save it in a variable for later reference. Add the code in Example 3-7 to your script to store the storage account name.
$storageAccount
=
"[storage account name]"
The next step is to associate the storage account with the subscription you are using by specifying the name with the -CurrentStorageAccountName
parameter in the Set-AzureSubscription
cmdlet. Once set, any PowerShell cmdlets that create virtual machines or deploy cloud-service packages will use this storage account as the default.
Add the code in Example 3-8 to associate the subscription with the storage account.
When creating a virtual machine, you can start from an existing disk or from one of the platform images in Microsoft Azure. In Chapter 5 I will cover provisioning virtual machines directly from disk. For now, this chapter will focus on using an image. To view the available images for your subscription run the command Get-AzureVMImage
, as shown in Example 3-9.
The amount of information that Get-AzureVMImage
returns can be quite overwhelming (see Figure 3-3).
Table 3-1 lists some important properties to note.
EULA | This is a link to an end-user license agreement for the particular image. |
LogicalDiskSizeInGB | Shows how large the OS disk will be if you use this image (maximum 127 GB). |
RecommendedVMSize | The recommended size to run this image. |
IsPremium | If True, you are paying above standard compute rates for the operating system. SQL Server is a good example, as you are paying a premium for the SQL Server licensing cost. |
Description | Description of what the image contains. |
ImageFamily | A name to group the same type of images. There are multiple images of the same family due to creating new patched images and sometimes configuration differences. |
ImageName | When provisioning from PowerShell, this is the value you will use when specifying the image. |
Thankfully, PowerShell provides the ability to quickly filter out information.
The first step is to identify the image family by using the Get-AzureVMImage
cmdlet and returning only the ImageFamily
property (see Example 3-10).
Get-AzureVMImage
|
select
ImageFamily
When you have identified the image family that you want to use, assign the image family name to a variable. You can use that variable with PowerShell’s native comparison and filter capabilities to always return the latest image for that family and store that image name in a variable for later use.
The code in Example 3-11 returns a list of available images, and then passes that output to the where
command, which filters only images with the image family name that matches $imageFamily
. That output is then sorted by PublishedDate
(Descending
) so the newest image is the first one returned. Finally, that output is then passed to the select
command with the -First
parameter, which indicates to return only the first item.
Add the code in Example 3-11 to your script to return and store the name of the virtual machine image to use.
The Get-AzureRoleSize
cmdlet can be used to enumerate the available virtual machine sizes (see Example 3-12). This will tell you the maximum memory, the maximum size on the resource disk, and the number of data disks supported per role (see Figure 3-4).
Ensure that the size you select has SupportedByVirtualMachines
set to True
. Since this is PowerShell, you can filter output on that property (see Example 3-13).
Get-AzureRoleSize
|
where
{
$_
.
SupportedByVirtualMachines
-eq
$true
}
When you have identified which role size to use to create your virtual machines, simply store the InstanceSize
name in a variable.
Add the code in Example 3-14 to store the virtual machine size.
are always created in a container called a cloud service. A cloud service provides a networking and security boundary for your virtual machines. Virtual machines that are created in the same cloud service are on the same private network and can directly communicate with each other without going through the public load balancer or a virtual network to communicate.
Also, if virtual machines need to be load-balanced together or require high availability, they must be created in the same cloud service as load-balanced endpoints (internal and external), and availability sets cannot span multiple cloud services. Microsoft Azure also provides built-in name resolution to virtual machines in the same cloud service.
During virtual machine creation, you are required either to specify the cloud service name for an existing cloud service that is available in your subscription or to supply a new name that is not in use and is globally available. In this chapter you will use PowerShell to create a new cloud service.
Just like the name of a Microsoft Azure storage account, a cloud service name must be globally unique in Microsoft Azure. To ensure the availability of the cloud service name, use the Test-AzureName
cmdlet first (see Example 3-15).
Ensure that you replace the [cloud service name]
placeholder with the name of the cloud service you wish to create.
Test-AzureName
-Service
-Name
"[cloud service name]"
If the call returns True
, the service name exists and cannot be created again (this does not indicate whether the service is in your subscription). In this example, we specifically want to create a new cloud service, so you should run the command with a new name until the call returns False
. When you have identified a unique name, store it in a variable for later reference.
Add the code in Example 3-16 to your script to store the cloud service name.
The New-AzureQuickVM
cmdlet is very similar to using the Quick Create button in the Microsoft Azure management portal. The available customizations are limited, but it is a relatively easy way of provisioning a virtual machine.
To use this technique, you will need to define three more variables: the administrator username, the password, and the computer name. When choosing the name and password for the local administrator account, ensure that the values you choose are not overly obvious, like “administrator” or “password”, because the Microsoft Azure API will reject them. Add the code in Example 3-17 to your script and replace the placeholder values with values of your own.
# Specify the admin credentials
$adminUser
=
"[admin username]"
$password
=
"[admin password]"
# Specify the virtual machine name
$vmName
=
"ps-vm1"
As a general rule, it is a bad security practice and a bad maintenance practice to store credentials directly in a script. It is shown here to keep the scripts simple and focus on the task at hand. Practical alternatives include passing credentials in as parameters to a script or prompting for credentials by using the Get-Credential
cmdlet.
The computer name must be unique to all of the virtual machines in the same cloud service.
Now that all of the necessary information is stored in variables, you can create a virtual machine (VM).
The New-AzureQuickVM
cmdlet supports parameter sets for creating Windows- or Linux-based virtual machines from an image. In this example, passing -Windows
tells the cmdlets that the image you are passing is a Windows-based OS.
Add the code in Example 3-18 to your script.
New-AzureQuickVM
-Windows
`
-ServiceName
$serviceName
`
-Name
$vmName
`
-ImageName
$imageName
`
-Location
$location
`
-InstanceSize
$vmSize
`
-AdminUsername
$adminUser
`
-Password
$password
This technique is quick and simple but it does have its drawbacks. The limitations to using New-AzureQuickVM
are as follows:
Several other provisioning features supported by New-AzureQuickVM
are discussed in Chapter 7.
The second technique for creating a virtual machine requires the use of two (or more) cmdlets together to compose a virtual machine by creating a configuration object, modifying it, and then creating a virtual machine with the customized configuration object. This pattern is similar to how the cmdlets are used for updating existing virtual machines.
As the name New-AzureVMConfig
implies, this cmdlet does not create a virtual machine but instead creates a virtual machine configuration object. Once it is created, you modify the configuration object with other cmdlets to have all of the characteristics that you want the virtual machine to have at provisioning time. This technique can save you several API calls, such as individually adding data disks or network endpoints. If you are automating the creation of several virtual machines, this can save you a lot of time spent in provisioning and, in the long run, a lot of code you do not have to write.
Add the code in Example 3-19 to your script. Note that the $vmName
variable has also been modified because this code will create a second virtual machine named ps-vm2 in the same cloud service as ps-vm1.
$vmName
=
"ps-vm2"
$vmConfig
=
New-AzureVMConfig
-Name
$vmName
`
-InstanceSize
$vmSize
`
-ImageName
$imageName
When the virtual machine configuration is created, you then modify it using the PowerShell pipeline and several other Microsoft Azure cmdlets that know how to modify this object.
Creating a virtual machine configuration from an image, as shown in the previous example, requires you to specify the initial provisioning configuration. Use the Add-AzureProvisioningConfig
cmdlet to specify these settings (see Example 3-20). This cmdlet accepts the passed-in object $vmConfig
and modifies it by creating and setting the properties that will hold the local administrator username, password, and various other properties that can be set at provisioning time.
Creating virtual machines by composing the configuration allows you to specify additional information such as adding data disks at provisoning time. The amount of storage you can specify per virtual machine depends on the instance size you are creating. Each disk can be up to 1023 GB in size. Each virtual machine size allows a different number of data disks to be attached. The output from the Get-AzureRoleSize
cmdlet used earlier will show the maximum number of data disks supported.
In Example 3-21 Add-AzureDataDisk
with the -CreateNew
parameter is used to modify the passed-in configuration $vmConfig
to create blank, unformatted VHDs attached to the virtual machine on boot.
Add the code in Example 3-21 to your script to attach a new 500 GB data disk on LUN 0 of the virtual machine that will be created.
$vmConfig
|
Add-AzureDataDisk
-CreateNew
`
-DiskSizeInGB
500
`
-DiskLabel
"data 1"
`
-LUN
0
The Add-AzureDataDisk
cmdlet supports three parameter sets. As shown in Example 3-21, the -CreateNew
parameter is used to create blank VHDs. The -Import
parameter allows you to specify a disk by referencing the name of the disk registered in Microsoft Azure. The -ImportFrom
parameter allows you to specify the URL to the VHD in a Microsoft Azure storage account (in the same subscription and same region) and a disk label.
I will cover managing disks, images, and storage in greater detail in Chapter 5.
Similar to adding storage, you can also add network endpoints at provisioning time by modifying the virtual machine configuration before passing it to Microsoft Azure for creation.
Example 3-22 modifies the virtual machine configuration $vmConfig
by adding a new load-balanced endpoint named HTTP to the configuration.
This endpoint is using TCP as the protocol accepting traffic on public port 80 and forwarding it to local port 80. The -LBSetName
parameter specifies that this endpoint is part of a load-balanced set. If I wanted to create additional virtual machines to handle additional traffic on port 80, I would just need to reference the same load-balanced set name as specified in the following example.
The -DefaultProbe
parameter tells Microsoft Azure to set up a TCP health probe on the local port. This means that the load balancer will occasionally attempt to connect on the port specified with -LocalPort
. If it can connect, the endpoint is considered healthy, but if it cannot connect after a configurable number of tries, then it will no longer be considered healthy and the load balancer will not forward traffic to the endpoint.
Add the code in Example 3-22 to modify your $vmConfig
to add the load-balanced endpoint.
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTP"
`
-Protocol
tcp
`
-LocalPort
80
`
-PublicPort
80
`
-LBSetName
"LBHTTP"
`
-DefaultProbe
As with data disks, I can add more endpoints if needed just by adding another call to Add-AzureEndpoint
. In Example 3-22 I have added an endpoint for port 80 for HTTP traffic. I could also open up port 443 for HTTPS traffic simply by adding an endpoint to the configuration (see Example 3-23).
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTPS"
`
-Protocol
tcp
`
-LocalPort
443
`
-PublicPort
443
`
-LBSetName
"LBHTTPS"
`
-DefaultProbe
I will cover managing endpoints in greater detail in Chapter 4.
The cmdlet that does the heavy lifting of actually creating virtual machines from one or more configuration objects is New-AzureVM
. The New-AzureVM
cmdlet supports passing a single configuration object or an array of configuration objects to the -VMs
parameter (see Example 3-24). If passed an array, the cmdlet will automatically create each virtual machine in the same cloud service for you.
New-AzureVM
-ServiceName
$serviceName
-VMs
$vmConfig
Now that the last line of code is added, let me add a complete example (see Example 3-25) using placeholder values (ensure that you replace them with real values), and then I will review what the script does.
# Replace with your own subscription name
$subscription
=
"[subscription name]"
Select-AzureSubscription
$subscription
# Replace with the region you wish to deploy in
$location
=
"[region name]"
$vmSize
=
"Small"
# Replace with your own storage account name
$storageAccount
=
"[storage account name]"
Set-AzureSubscription
-SubscriptionName
$subscription
`
-CurrentStorageAccountName
$storageAccount
$imageFamily
=
"Windows Server 2012 R2 Datacenter"
$imageName
=
Get-AzureVMImage
|
where
{
$_
.
ImageFamily
-eq
$imageFamily
}
|
sort
PublishedDate
-Descending
|
select
-ExpandProperty
ImageName
-First
1
# Replace with a unique cloud service name
$serviceName
=
"[cloud service name]"
# Specify the admin credentials
$adminUser
=
"[admin user name]"
$password
=
"[admin password]"
# Specify the computer name
$vmName
=
"ps-vm1"
New-AzureQuickVM
-Windows
`
-ServiceName
$serviceName
`
-Name
$vmName
`
-ImageName
$imageName
`
-Location
$location
`
-InstanceSize
$vmSize
`
-AdminUsername
$adminUser
`
-Password
$password
$vmName
=
"ps-vm2"
$vmConfig
=
New-AzureVMConfig
-Name
$vmName
`
-InstanceSize
$vmSize
`
-ImageName
$imageName
$vmConfig
|
Add-AzureProvisioningConfig
-Windows
`
-AdminUsername
$adminUser
`
-Password
$password
$vmConfig
|
Add-AzureDataDisk
-CreateNew
`
-DiskSizeInGB
500
`
-DiskLabel
"data 1"
`
-LUN
0
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTP"
`
-Protocol
tcp
`
-LocalPort
80
`
-PublicPort
80
`
-LBSetName
"LBHTTP"
`
-DefaultProbe
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTPS"
`
-Protocol
tcp
`
-LocalPort
443
`
-PublicPort
443
`
-LBSetName
"LBHTTPS"
`
-DefaultProbe
New-AzureVM
-ServiceName
$serviceName
-VMs
$vmConfig
This script performs the following operations:
CurrentStorageAccountName
property, which is really just a shortcut so you do not have to specify the storage account to use with each call.
New-AzureQuickVM
cmdlet. This cmdlet also creates the cloud service container for the virtual machine.
New-AzureVM
cmdlet actually creates the ps-vm2 virtual machine and, by omitting the -Location
parameter, creates the virtual machine in the same cloud service as ps-vm1.
Now that you understand what the script is intended to do, simply press F5, or highlight the script and press F8 to execute.
The New-AzureVM
cmdlet accepts a cloud service name, an array of configuration objects, a location or affinity group, and optionally a virtual network name. Provisioning virtual machines inside a virtual network will be discussed later.
Under the covers, New-AzureVM
performs several activities against the Microsoft Azure Service Management API on your behalf. If you specify the -Location
or -AffinityGroup
parameter, the cmdlet will first create the cloud service container in the location or affinity group you specify. The cmdlet will then loop through the array of virtual machine configuration objects passed to it and create the virtual machines in the cloud service. The New-AzureVM
cmdlet performs the serialization required to create multiple virtual machines if passed more than one configuration object. Serialization is required because virtual machines created in the same cloud service or the same virtual network must be created one by one due to locks put in place at the API level.
The New-AzureVM
behavior regarding creating a new cloud service or using an existing cloud service depends on the -Location
or -AffinityGroup
parameters passed to it. If you want the cmdlet to create a new cloud service, simply specify one of the location parameters (-Location
or -AffinityGroup
). Passing either of these parameters tells the cmdlet that you want to create a new cloud service in the specified location or affinity group.
To create a virtual machine in an existing cloud service, simply omit the parameters (-Location
or -AffinityGroup
), and New-AzureVM
will assume that the cloud service exists in your subscription and will attempt to create the virtual machine in that cloud service. In the previous code example, -Location
was omitted because the cloud service was created with the previous call to New-AzureQuickVM
.
When you run New-AzureVM
, you might see: “WARNING: The specified DNS name is already taken.” This means that the -ServiceName
you have specified already exists. If the cloud service is part of your subscription and in the same region of the virtual machine you are going to create, you can ignore the warning or simply omit -Location
or -AffinityGroup
to avoid it altogether. If the cloud service name is owned by another Microsoft Azure subscription, the warning will be followed by an error: “New-AzureVM: ResourceNotFound: The hosted service does not exist.” This is beyond your control, and it is time to pick a new name for your cloud service!
The Get-AzureVM
cmdlet is very useful for managing virtual machines. It has three distinct behaviors that allow you to perform some fairly advanced operations.
Run Get-AzureVM
without passing any parameters, and the cmdlet will enumerate all of the virtual machines in your subscription (see Example 3-26 and Figure 3-5). Depending on how many virtual machines you have, this can be a lengthy operation. The architecture of the Microsoft Azure API requires that the cmdlet query the available virtual machines per cloud service. So if you have 100 cloud services, each with 1 virtual machine, the cmdlet will have to make 100 round-trips to the Microsoft Azure Service Management API.
The Get-AzureVM
cmdlet can also return the detailed configuration of one or more virtual machines.
To return detailed configuration, you must specify the cloud service name and optionally the name of the virtual machine (see Example 3-27 and Figure 3-6). If the name of the virtual machine is specified with the -Name
parameter, the Get-AzureVM
cmdlet will return the configuration for only that virtual machine. If a virtual machine name is not specified, Get-AzureVM
returns the configuration for all of the virtual machines in the cloud service.
Get-AzureVM
-ServiceName
$serviceName
The detailed configuration can be inspected using standard PowerShell operators or by using helper cmdlets that are part of the Microsoft Azure PowerShell cmdlets (see Examples 3-28 through 3-30, and Figures 3-7 through 3-9).
Get-AzureVM
-ServiceName
$serviceName
|
Get-AzureEndpoint
Get-AzureVM
-ServiceName
$serviceName
|
Get-AzureDataDisk
Updating a Microsoft Azure virtual machine is very similar to creating a new one. The difference is that instead of creating a new virtual machine configuration object, you are retrieving an existing configuration from the virtual machine that you want to update.
To retrieve an existing virtual machine configuration, use the Get-AzureVM
cmdlet, passing the name of the cloud service and optionally the name of the virtual machine. Once the configuration is retrieved, you then modify it with the changes you want, using the same cmdlets used during creation. To make the final changes, call the Update-AzureVM
cmdlet instead of New-AzureVM
. Update-AzureVM
accepts the cloud service name and the virtual machine name and passes the configuration back to the Microsoft Azure Management API to perform the update.
Using the pattern of Get-Modify-Update, Example 3-31 retrieves the configuration of the specified virtual machine, indicating the cloud service name and the virtual machine name. The configuration is stored in the $vmConfig
variable. To modify the configuration, the $vmConfig
variable is piped to the Remove-AzureEndpoint
cmdlet, which looks in the configuration for an endpoint named RemoteDesktop and removes it if it exists. When the Remove-AzureEndpoint
cmdlet has removed the endpoint from the virtual machine configuration, it is then piped to Update-AzureVM
, which makes the API call to update the virtual machine.
$serviceName
=
"[cloud service name]"
$vmName
=
"ps-vm1"
$vmConfig
=
Get-AzureVM
-ServiceName
$serviceName
-Name
$vmName
$vmConfig
|
Remove-AzureEndpoint
-Name
"RemoteDesktop"
$vmConfig
|
Update-AzureVM
If you try the previous example against the ps-vm2 virtual machine, the code will not work. Virtual machines created with the New-AzureQuickVM
cmdlet name the endpoint RemoteDesktop, and virtual machines created using New-AzureVM
use RDP as the endpoint name. In Chapter 4 I will show how to identify endpoints by using the local port instead of the name.
The previous example removes the remote desktop endpoint from the specified virtual machine. Since the endpoint is removed, you can no longer use remote desktop to connect to the virtual machine. You can try this on your own by executing the Get-AzureRemoteDesktopFile
cmdlet to attempt a connection (see Example 3-32.
Get-AzureRemoteDesktopFile
-ServiceName
$serviceName
-Name
$vmName
-Launch
This can be very useful from a security perspective, as it gives you the ability to open up remote desktop only when needed and remove it when it is not. Later, I will show how to configure an access control list (ACL) to make this even more secure.
Now we will create another simple script that takes the ps-vm1 virtual machine and updates it to have the same network endpoints and data disk configuration that ps-vm2 was provisioned with, since it was created with New-AzureVMConfig
. We will also add the RemoteDesktop endpoint back and validate that connectivity works.
Create a new PowerShell script with the name chapter3update.ps1 and add the code in Example 3-33. Ensure that you replace the placeholder values with the actual values for your subscription.
Select-AzureSubscription
"[subscription name]"
$serviceName
=
"[cloud service name]"
$vmName
=
"ps-vm1"
$vmConfig
=
Get-AzureVM
-ServiceName
$serviceName
-Name
$vmName
$vmConfig
|
Add-AzureEndpoint
-Name
"RemoteDesktop"
`
-LocalPort
3389
`
-Protocol
TCP
$vmConfig
|
Add-AzureDataDisk
-CreateNew
`
-DiskSizeInGB
500
`
-DiskLabel
"data 1"
`
-LUN
0
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTP"
`
-Protocol
tcp
`
-LocalPort
80
`
-PublicPort
80
`
-LBSetName
"LBHTTP"
`
-DefaultProbe
$vmConfig
|
Add-AzureEndpoint
-Name
"HTTPS"
`
-Protocol
tcp
`
-LocalPort
443
`
-PublicPort
443
`
-LBSetName
"LBHTTPS"
`
-DefaultProbe
$vmConfig
|
Update-AzureVM
Press F5 to execute the script, or highlight the script and press F8.
When the script has finished executing, run the Get-AzureRemoteDesktopFile
cmdlet again from the console to verify that you can now connect to the virtual machine (see Example 3-34).
The final topic of this chapter is a very important one for your pocketbook: stopping and starting virtual machines.
When you stop a virtual machine in Microsoft Azure using PowerShell or the portal (not from within the virtual machine), you are no longer billed for the compute time used (just for the storage cost for the underlying disks). As part of this book, I will point back to virtual machines created in previous topics and chapters so we don’t have to re-create them with each example. With this in mind, it is likely a good idea to learn how to not be charged for virtual machines when not in use.
Example 3-35 will shut down all of the virtual machines in the cloud service. One of the limitations of Microsoft Azure is that if you shut down the last virtual machine in a cloud service without assigning a reserved IP address to the virtual machine, you will lose the public IP address (VIP) of the cloud service. This is why running the following code will prompt you to ensure that you are aware of this fact.
Get-AzureVM
-ServiceName
$serviceName
|
Stop-AzureVM
There are three things you can do to avoid the prompt shown in Figure 3-10:
-Force
parameter. This tells the cmdlet to not prompt you.
-StayProvisioned
parameter. This tells the cmdlet to not deprovision the virtual machine and to just shut it down. However, you will still be charged for compute time when you use this switch, so it is not a good solution for saving money.
In addition to Stop-AzureVM
, there are also Start-AzureVM
and Restart-AzureVM
. All three cmdlets accept the same -ServiceName
and -Name
parameters that correspond to the cloud service container name and the virtual machine name. They all accept pipeline output, as shown in the previous example, so you can run them against multiple virtual machines, if needed.
In this chapter we explored the basics of using the Microsoft Azure PowerShell cmdlets to create and configure a virtual machine. We learned how to use the Get-AzureLocation
cmdlet to identify the Microsoft Azure regions that are available for virtual machines, and also to create them using the high-memory configurations.
This chapter also introduced the idea of using the virtual machine configuration object not only to create a virtual machine, but also to update an existing one by modifying the configuration and posting it back to the Microsoft Azure API by using the cmdlets. You will see this Get-Modify-Update pattern used throughout this book, as it is the underlying convention of the Microsoft Azure API and the command-line tools that use it.
In the next chapter we will dig deeper into virtual machine configuration by investigating the network stack in thorough detail from PowerShell.