Spent a bit of time today and and yesterday with Azure. It’s all new stuff to me so here are some notes to my future self.
- You can not move VMs between VNets (Virtual Nets) or Cloud Services. Only option is to delete the VM – keeping the disk – and recreate the VM. That feels so weird to me! Deleting and recreating VMs via the GUI is a PITA. Thankfully PowerShell makes it easier.
123456789101112131415# get the VM detailsPS> Get-AzureVM 'vmname'# note the ServiceName, we need that below# also, be sure to specify the full path below; relative paths silently don't workPS> Export-AzureVM -ServiceName 'svcname' -Name 'vmname' Path '\full\path\to\somefile.xml'# remove the VM (this does not remove the VHD files)PS> Remove-AzureVM -ServiceName 'svcname' -Name 'vmname'# now modify the XML file with your changesPS> notepad '\full\path\to\somefile.xml'# import the VM and create it afreshPS> Import-AzureVM '\full\path\to\somefile.xml' | New-AzureVM -ServiceName "vmname" -VNetName "vmnet"
- To rename a virtual net I’ll have to remove all the VMs assigned to it (as above), then export the VNet config, change it with the new name, import it, and then import the VMs as above. Yeah, not a simple rename as you’d expect …
12345678910# get the current VNet configPS> Get-AzureVNetConfig -ExportToFile \full\path\to\network.xml# make changesPS> notepad \full\path\to\network.xml# remember this file contains your WHOLE configuration; by renaming the entry there to the new one you are actually telling Azure to create a new VNet with that entry and remove the old one (coz it doesn't exist in the file any more)# set it backPS> Set-AzureVNetConfig -ConfigurationPath \full\path\to\network.xml
- Remember, the virtual networks configuration file states the entire configuration of your Virtual Networks. There’s no concept of add/ remove. What you import gets set as the new one.
- The first three IPs in a subnet are reserved. Also see this post.
- You cannot assign static IPs to VMs as you’d normally expect.
- Every VM is assigned an IP automatically from the subnet you define in the virtual network. Sure you’d think you can go into the OS and manually set a static IP – but nope, do that and your VM is unaccessible because then the Azure fabric does not know the VM has this new IP.
- Worse, say you have two VMs with addresses
xxx.6; you shut down the first VM and bring up a third VM, this new VM will get the address of the VM you just shut down (
xxx.5) because when that VM shutdown its address became free! See this post for an elaboration on this behavior.
- Starting from Feb 2014 (I think) you can now set a static IP on your VM and tell Azure about it. Basically, you tell Azure you want a particular IP on your VM and Azure will assign it that during boot up. Later you can go and set it as a static IP in the OS too if certain apps in the OS fuss about it getting a DHCP address (even though it’s actually a reserved DHCP address). Since Azure knows the static IP, things will work when you set the IP statically in the OS.
- The ability to set a static IP is not available via the GUI. Only Azure PowerShell 0.7.3.1 and above (and maybe the other CLI tools, I don’t know). There are cmdlets such as
Set-AzureStaticVNetIP. The first gets the current static IP config, the second removes any such config, and the third sets a static IP.
- There’s also a cmdlet
Test-AzureStaticVNetIPthat lets you test whether a specified static IP is free for use in the specified VNet. If the IP is not free the cmdlet also returns a list of free IPs.
- There’s also a cmdlet
- You can’t set a static IP on a running VM. You can only do it when the VM is being created – so either when creating a VM, or an existing VM but it will involve recreating the VM by restarting it.
- For an existing VM:
1PS> Get-AzureVM -Name 'vmname' -ServiceName 'servicename' | Set-AzureStaticVNetIP -IPAddress 'xxx.xxx.xxx.xxx' | Update-AzureVM
- Maybe when importing from a config file:
1PS> Import-AzureVM '\full\path\to\somefile.xml' | Set-AzureStaticVNetIP -IPAddress "xxx.xxx.xxx.xxx" | New-AzureVM -ServiceName "vmname" -VNetName "vmnet"
- Or just modify the config file beforehand and then import as usual. Here’s where the static IP can be specified in a config file:
12356<SubnetNames><string>RAXNET1-23</string></SubnetNames><PublicIPs /><NetworkInterfaces />
Import as usual:1PS> Import-AzureVM "vmname" | New-AzureVM -ServiceName "vmname"
- See also MSDN article.
- For an existing VM:
- Maybe it’s because I changed my VM IP while it’s running (the first option above), even though the IP address changed it didn’t update on the
BGInfobackground. So I looked into it.
C:\Packages\Plugins\Microsoft.Compute.BGInfo\1.1. The IP address is got via a registry key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Azure\BGInfo\InternalIpwhich seems to be set by
C:\Packages\Plugins\Microsoft.Compute.BGInfo\1.1\BGInfoLauncher.exe(I didn’t investigate further).
- When creating a new VM you must specify the Cloud Service name. Usually it’s the VM name (that’s the default anyways) but it’s possible to have a different name when you have multiple VMs in the same Cloud Service. This blog post has a good explanation of Cloud Services, as does this.
- There’s no console access! Yikes.
While importing VMs above I got the following error from the
New-AzureVm : CurrentStorageAccount is not accessible
- This usually indicates your Storage Account and Cloud Service are in different locations/ affinity groups. So double check that this is not the case.
- Once you are sure of the above, specify a Cloud Service – but no affinity group – so the cmdlet knows which one to use. Else specify a Cloud Service that does not exist so Azure can create a new one. See this blog post for more info.
- In my case it turned out to be a case of Azure PowerShell not knowing which storage account to use. Notice the output below:
123456PS> Get-AzureSubscription<snip>IsDefault : TrueIsCurrent : TrueCurrentStorageAccountName :
There’s no Storage Account associated with my subscription. So all I needed to do was associate one:12345# get a list of available Storage AccountsPS> Get-AzureStorageAccount# associate one with my subscriptionPS> Set-AzureSubscription -SubscriptionName 'SubName' -CurrentStorageAccountName 'fromabove'
That’s all for now!