Ansible - GCP Dynamic inventory bootstrap

Ansible GCP module bootstrap #

The official docs on Ansible GCP module are quite a bit confusing, so I’ve decided to publish some steps to quickly bootstrap a working environment.

Main concept is that Ansible can not only use static files as a source of inventory but also execute a script and use it’s output as an in-memory representation of it. This allows us to make dynamic inventories to load up hosts from your cloud provider, for example. And, conveniently, there’s such a script in the Ansible’s contrib directory named gce.py.

This assumes you already have:

Here are quick bootstrap instructions on how to get it working:

Install libcloud and libcrypto:

λ pip install apache-libcloud pycrypto

Create a working dir:

λ mkdir -p ansible/inventory && cd ansible

Clone ansible repo:

λ git clone https://github.com/ansible/ansible

Copy the gcp.py inventory script and the gcp.ini template from contrib folder:

λ cp ansible/contrib/inventory/gce.* inventory

Populate the .ini file (this is where gce.py will read its’ settings from):

λ cat ~/.ansible/gce.ini

[gce]
gce_service_account_email_address = my-account@my-project.iam.gserviceaccount.com
gce_service_account_pem_file_path = /full/path/to/my_key.json
gce_project_id = my-project

[inventory]
# Use external IP addresses to connect
inventory_ip_type = external

[cache]
cache_path = ~/.ansible/tmp
cache_max_age = 300

You can move it into your home directory and exporting the variable in your .zshrc for future ease-of-use:

λ cat ~/.zshrc | grep gce.ini
  # Export ansible gce.ini
  [[ -s "$HOME/.ansible/gce.ini" ]] && export GCE_INI_PATH="$HOME/.ansible/gce.ini"

Reload your shell and check if it’s working:

λ source ~/.zshrc
λ ./inventory/gce.py --list

If you’ve received a large set of output with your instance data - it’s now set up correctly.

Boom, now you can access your instances by zone:

λ ansible -i inventory australia-southeast1-c -m ping
web-worker-3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web-worker-1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web-worker-2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
master | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

, or tag. For that just prepend the network tag name with tag_, i.e. for web-worker tag:

λ ansible -i inventory tag_web-worker -m ping
web-worker-3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web-worker-1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
web-worker-2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

For more options and further reading, check out the official module docs. Hope it’s helpful!

Materials used:

 
1
Kudos
 
1
Kudos

Now read this

Reading large files in Ruby

I needed to slurp up some very large files into a ruby app recently and noticed some interesting behaviour in IO.foreach method. While it is supposed to read file line by line without loading it up into memory, memory usage is quite... Continue →