Create Azure VM with Ansible
With a little googling this task isn’t very complex, however, for those wanting to consume this information easily – this post is for you.
There’s a lot of cloud provisioning tools out there; if you’re like me and prefer to leverage your existing knowledge wherever possible you might come to the conclusion that using the same tool to provision your VMs as you do to manage them makes sense. I already know Ansible, why not leverage it to create my infrastructure as well as manage it post-creation.
First, in your Azure account you will want to create a service principal. This is basically an authentication token that Ansible will use to access the Azure API. Using the Azure Active Directory component for identity management, Microsoft has a good how-to article guiding you through creating this service principal. In Azure the terminology gets a little confusing as this technically gets created as an “application”, but really what we’re doing here is creating a service account identity to use with the Azure API via Ansible modules.
Once you’ve got this service principal created, I prefer to create a ~/.azure/credentials file to store the identity information. This keeps the private auth details out of any public Ansible git repositories I may create and share with others. Microsoft publishes another good article on how to install Ansible and how-to create the Ansible credentials file.
I like to use python virtual environments to keep any installed python libraries from overwriting the ones that come with my linux distro (Fedora 29). So here I create a python virtual environment where I can install the Ansible Azure packages:
$ python3 -m virtualenv azure Using base prefix '/usr' New python executable in /home/aludwar/code/azure/bin/python3 Also creating executable in /home/aludwar/code/azure/bin/python Installing setuptools, pip, wheel...done. $ source azure/bin/activate (azure) $ which python /home/aludwar/code/azure/bin/python (azure) $ pip install 'ansible[azure]' Collecting ansible[azure] Downloading https://files.pythonhosted.org/packages/56/fb/b661ae256c5e4a5c42859860f59f9a1a0b82fbc481306b30e3c5159d519d/ansible-2.7.5.tar.gz (11.8MB) 100% |████████████████████████████████| 11.8MB 2.6MB/s Collecting jinja2 (from ansible[azure]) Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB) 100% |████████████████████████████████| 133kB 14.3MB/s ... <snip> ... Stored in directory: /home/aludwar/.cache/pip/wheels/f2/9a/90/de94f8556265ddc9d9c8b271b0f63e57b26fb1d67a45564511 Successfully built ansible PyYAML tabulate pycparser Installing collected packages: MarkupSafe, jinja2, PyYAML, pyasn1, pycparser, cffi, idna, asn1crypto, six, cryptography, pynacl, bcrypt, paramiko, pyparsing, packaging, chardet, certifi, urllib3, pyOpenSSL, requests, applicationinsights, azure-nspkg, azure-cli-nspkg, pygments, argcomplete, humanfriendly, colorama, entrypoints, jeepney, secretstorage, keyring, isodate, oauthlib, requests-oauthlib, msrest, python-dateutil, PyJWT, adal, msrestazure, jmespath, wheel, tabulate, knack, azure-cli-core, azure-common, azure-mgmt-nspkg, azure-mgmt-batch, azure-mgmt-compute, azure-mgmt-containerinstance, azure-mgmt-containerregistry, azure-mgmt-containerservice, azure-mgmt-dns, azure-mgmt-keyvault, azure-mgmt-marketplaceordering, azure-mgmt-monitor, azure-mgmt-network, azure-mgmt-rdbms, azure-mgmt-resource, azure-mgmt-sql, azure-mgmt-storage, azure-mgmt-trafficmanager, azure-mgmt-web, azure-storage, azure-keyvault, azure-graphrbac, ansible Found existing installation: wheel 0.32.3 Uninstalling wheel-0.32.3: Successfully uninstalled wheel-0.32.3 Successfully installed MarkupSafe-1.1.0 PyJWT-1.7.1 PyYAML-3.13 adal-1.2.0 ansible-2.7.5 applicationinsights-0.11.7 argcomplete-1.9.4 asn1crypto-0.24.0 azure-cli-core-2.0.35 azure-cli-nspkg-3.0.2 azure-common-1.1.11 azure-graphrbac-0.40.0 azure-keyvault-1.0.0a1 azure-mgmt-batch-4.1.0 azure-mgmt-compute-2.1.0 azure-mgmt-containerinstance-0.4.0 azure-mgmt-containerregistry-2.0.0 azure-mgmt-containerservice-3.0.1 azure-mgmt-dns-1.2.0 azure-mgmt-keyvault-0.40.0 azure-mgmt-marketplaceordering-0.1.0 azure-mgmt-monitor-0.5.2 azure-mgmt-network-1.7.1 azure-mgmt-nspkg-2.0.0 azure-mgmt-rdbms-1.2.0 azure-mgmt-resource-1.2.2 azure-mgmt-sql-0.7.1 azure-mgmt-storage-1.5.0 azure-mgmt-trafficmanager-0.50.0 azure-mgmt-web-0.32.0 azure-nspkg-2.0.0 azure-storage-0.35.1 bcrypt-3.1.5 certifi-2018.11.29 cffi-1.11.5 chardet-3.0.4 colorama-0.4.1 cryptography-2.4.2 entrypoints-0.2.3 humanfriendly-4.17 idna-2.8 isodate-0.6.0 jeepney-0.4 jinja2-2.10 jmespath-0.9.3 keyring-17.1.1 knack-0.3.3 msrest-0.4.29 msrestazure-0.4.31 oauthlib-2.1.0 packaging-18.0 paramiko-2.4.2 pyOpenSSL-18.0.0 pyasn1-0.4.5 pycparser-2.19 pygments-2.3.1 pynacl-1.3.0 pyparsing-2.3.0 python-dateutil-2.7.5 requests-2.21.0 requests-oauthlib-1.0.0 secretstorage-3.1.0 six-1.12.0 tabulate-0.8.2 urllib3-1.24.1 wheel-0.30.0
Now with the Azure dependencies for Ansible installed, and my ~/.azure/credentials file created, I can start writing a playbook to create a new virtual machine. I’ve previously created some virtual networks, security groups, and public IP addresses, etc. so I’m going to reference those in my playbook. If you don’t have these, you can create them in the playbook as well. The Ansible docs guide for Azure gives a good example playbook to do this.
Here’s my playbook:
(azure) $ cat create-vm-azure.yml --- - name: Create Azure VM hosts: localhost connection: local tasks: - name: Create VM azure_rm_virtualmachine: profile: default resource_group: rgDefault name: tower vm_size: Standard_B1s admin_username: aludwar ssh_password_enabled: false ssh_public_keys: - path: /home/aludwar/.ssh/authorized_keys key_data: <public SSH key> network_interfaces: nicTest image: offer: CentOS publisher: OpenLogic sku: '7.5' version: latest
So with that created, let’s run it:
(azure) $ ansible-playbook create-vm-azure.yml [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [Create Azure VM] ******************************************************************************************************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************************************************************************************************************** ok: [localhost] TASK [Create VM] ************************************************************************************************************************************************************************************************** changed: [localhost] PLAY RECAP ******************************************************************************************************************************************************************************************************** localhost : ok=2 changed=1 unreachable=0 failed=0 (azure) $
Alright, that looks to have been successful. Let’s check the Azure Portal:
Nice. It’s showing my VM as created and now running. Let’s test a login:
(azure) $ ssh 13.88.235.189 Warning: Permanently added '13.88.235.189' (ECDSA) to the list of known hosts. [aludwar@tower ~]$ hostname tower [aludwar@tower ~]$ exit logout Connection to 13.88.235.189 closed.
There we have it! Note, you’ll of course need to make sure your security group allows inbound SSH.