Zim's Notes

Just work related notes.

Installing HTTPD on VMSS Using VMSS Extension

There are two (or three) proper ways of updating Virtual Machine Scale Set instances:

  • use custom images and update instances whenever something changes
  • use VMSS Extension to install additional software on all the VM instances
  • combine both

Possibly there’s a fourth way, but I haven’t investigated that yet. I am thinking of updating VMSS data disks on the fly, but I haven’t tried that yet. Let’s focus on using VMSS Extension. In this article I will show how to use new azure_rm_virtualmachinescalesetextension module. It’s already available in azure_preview_modules and will be released in Ansible 2.8.

Prerequisites

Before trying the playbooks, clone following repository:

1
2
git clone https://github.com/Azure-Samples/ansible-playbooks.git
cd ansible-playbooks/vmss_extension

Step 1: Create VMSS using Ubuntu 16.04 Image

In this step we will just create Azure Virtual Machine Scaleset based using standard Ubuntu 16.04 image and all prerequisites.

Run following playbook:

1
ansible-playbook 01-create-vmss.yml --extra-vars "resource_group=myrg"

After this playbook is executed you will see an IP addres. Copy it to the browser. The page should fail to open as initial Ubuntu 16.04 image doesn’t have web server installed.

You can also go to Azure Portal and check the status of VMSS instances:

VMSS Instances 1

Step 2: Install VMSS extension

In second step we will install a Custom Script VMSS extension that will install httpd.

Run following playbook:

1
ansible-playbook 02-setup-httpd.yml --extra-vars "resource_group=myrg"

In this step we use azure_rm_virtualmachinescalesetextension module:

1
2
3
4
5
6
7
8
9
10
- name: Create VM Extension - HTTPD
  azure_rm_virtualmachinescalesetextension:
    resource_group: ""
    vmss_name: ""
    name: testVMExtension
    publisher: Microsoft.Azure.Extensions
    type: CustomScript
    type_handler_version: 2.0
    auto_upgrade_minor_version: true
    settings: {"commandToExecute": "sudo apt-get -y install apache2"}

Please note that creating extension didn’t update existing instances. You can check how it looks in the portal again - as you see all the instances are not up to date:

VMSS Instances 2

Step 3: Update all the instances

In this step we will actually upgrade all VM instances. Run following script:

1
ansible-playbook 03-update-instances.yml --extra-vars "resource_group=myrg"

First azure_rm_virtualmachinescalesetinstance_facts module is used to get list of instances:

1
2
3
4
5
- name: List all of the instances
  azure_rm_virtualmachinescalesetinstance_facts:
    resource_group: ""
    vmss_name: ""
  register: instances

And then azure_rm_virtualmachinescalesetinstance module to set latest_version to yes:

1
2
3
4
5
6
7
- name: manually upgrade all the instances
  azure_rm_virtualmachinescalesetinstance:
    resource_group: ""
    vmss_name: ""
    instance_id: ""
    latest_model: yes
  with_items: ""

Again, you can see in the portal how instances are being updated one by one:

VMSS Instances 3

When update is completed reload the page, and you should see that this time default Apache index page is displayed:

VMSS Instances 4

Updating Azure Virtual Machine Scale Set Images Using Ansible

This is a new Virtual Machine Scale Set demo I have just released to official Ansible Playbooks for Azure.

I have updated Ansible modules to enable:

  • creating images from existing Azure Virtual Machines
  • updating custom image in Azure Virtual Machine Scale Set

This demo is divided into a few steps. First it demonstrates how to create two custom images (A and B), and we will create VMSS with image A, and finally we will dynamically change image A to image B.

Before trying the playbooks, clone following repository:

1
2
git clone https://github.com/Azure-Samples/ansible-playbooks.git
cd ansible-playbooks/vmss_images

Step One - Create two virtual machines and install HTTPD

Run following playbook:

1
ansible-playbook 01-create-vms.yml --extra-vars "resource_group=myrg"

It will: - create 2 virtual machines - install HTTPD on both of them - change index.html to contain Image A and Image B respectively

Copy and paste IP addresses of both VMs to the browser:

Public IP Address

You should see two different versions of VM:

VM A

and

VM B

Step Two - Capture Images from both Virtual Machines

Run second playbook to capture the images:

1
ansible-playbook 02-capture-images.yml --extra-vars "resource_group=myrg"

Step Three - Create VMSS using Image A

In this step we will create following components: - public IP address - load balancer - VMSS referring image A

Run following playbook:

1
ansible-playbook 03-create-vmss.yml --extra-vars "resource_group=myrg"

Check the IP address printed out at the end:

Public IP Address

check that it works in the browser:

VMSS Image A

Step Four - Update Image Reference in VMSS and Upgrade Instances

Run final playbook to replace image A with image B:

1
ansible-playbook 04-update-vmss-image.yml --extra-vars "resource_group=myrg"

Now press F5 in the browser to reload page and see that image gas changed:

VMSS Image B

Some Notes on Inconsistencies in Examples

Compute, VirtualMachines - “name” parameter in body can’t be different than one in the URL

adminUsername -> “{your-username}” adminPassword -> “{your-password}”

Creating Azure Virtual Machines With Ansible and REST API

Just go to examples folder and run following playbook:

1
ansible-playbook compute_virtualmachines_put.yml

Please note that it will create all the necessary dependencies:

  • resource group
  • network interface
  • public IP address
  • virtual network with subnet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
- import_playbook: network_networkinterfaces_put.yml
- hosts: localhost
  roles:
    - ../modules
  vars:
    subscription_id: ""
    resource_group: myResourceGroup
    virtual_machine_name: myVirtualMachine
    network_interface_name: myNetworkInterface
  tasks:
    - name: Create a vm with password authentication.
      azure_rm_resource:
        idempotency: yes
        api_version: '2018-10-01'
        polling_timeout: 600
        polling_interval: 30
        # url: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}
        resource_group: ''
        provider: Compute
        resource_type: virtualMachines
        resource_name: ""
        body:
          location: eastus
          properties:
            hardwareProfile:
              vmSize: Standard_D3_v2
            storageProfile:
              imageReference:
                sku: 2016-Datacenter
                publisher: MicrosoftWindowsServer
                version: latest
                offer: WindowsServer
              osDisk:
                caching: ReadWrite
                managedDisk:
                  storageAccountType: Standard_LRS
                name: myVMosdisk
                createOption: FromImage
            osProfile:
              adminUsername: adminxyz
              computerName: myVM
              adminPassword: MooMoo123!!!!
            networkProfile:
              networkInterfaces:
                - id: "/subscriptions//resourceGroups//providers/Microsoft.Network/networkInterfaces/"
                  properties:
                    primary: True

Module Azure_rm_virtualmachine - Delta

A

Below is a quick compilation and comparison:

Feature Idempotence Support In Ansible Idempotence in Ansible
identity NO
location YES
plan YES
properties.additionalCapabilities.ultraSSDEnabled deallocated only NO
properties.availabilitySet.id changes not allowed
properties.diagnosticsProfile.bootDiagnostics.enabled NO
properties.diagnosticsProfile.bootDiagnostics.storageUri NO
properties.hardwareProfile.vmSize YES YES (check)
properties.licenseType
properties.networkProfile.networkInterfaces[].id YES YES (check)
properties.osProfile.adminPassword OK
properties.osProfile.adminUsername not allowed
properties.osProfile.allowExtensionOperations OK
properties.osProfile.computerName not allowed YES YES (check)
properties.osProfile.customData not allowed
properties.osProfile.linuxConfiguration…….
properties.osProfile.secrets
properties.osProfile.windowsConfiguration…….
properties.osProfile.
properties.storageProfile.dataDisks[]……… YES - check details
properties.storageProfile.imageReference changes not allowed
properties.storageProfile.osDisk……….. YES - check details
properties.storageProfile.osDisk.caching OK YES YES (check)
properties.storageProfile.osDisk.name not allowed YES YES (check)
properties.storageProfile.osDisk.diskSizeGB deallocated only YES YES (check)
properties.storageProfile.osDisk.writeAcceleratorEnabled managed only
properties.storageProfile.osDisk.osType changes not allowed
properties.storageProfile.osDisk.createOption changes not allowed
tags YES
zones NO

In addition REST API provides several APIs, some of them are supported, but some are not:

Feature Support In Ansible
Capture NO
Convert to Managed Disks
Deallocate YES
Generalize YES (2.8)
Perform Maintenance NO
Power Off YES
Redeploy NO
Reimage NO
Restart YES
Start YES

Just a First Post

Nothing much in here. I have written a lot of notes mostly related to Ansible, but also to Azure REST API, and it’s time to publish it them somewhere and made available to wider public. So, Hello World!