Use Ansible to Automate Google Cloud Platform: Creating & Removing Instances

In this exercise we’ll use Ansible and automate some common tasks with Google Cloud Platform. What if you want to save some bucks and automatically start & stop all

a year ago

Latest Post kubectl: most useful commands (a growing list) by Matthew Davis

In this exercise we’ll use Ansible and automate some common tasks with Google Cloud Platform.

What if you want to save some bucks and automatically start & stop all of your GCP instances when you’re working? The answer is simple: Ansible!

Getting Started

First thing is first, let’s use a virtualenv and install ansible:

$ python3 -m venv .
$ source bin/activate
$ pip install apache-libcloud pycrypto ansible

Second, you’ll need to create a Service Account Key and download it locally. (See: Creating and Managing Service Account Keys)

Create our first Playbook

A “Playbook” is simply a logical grouping of instructions (or “plays”).

gce-instances-create.yaml
- name: Create instances ("{{ instances }}")
  hosts: localhost
  connection: local
  gather_facts: no

  vars:
    service_account_email: your@serviceaccount.iam.gserviceaccount.com
    credentials_file: /some/path/yourkey.json
    project_id: your-project-id
    machine_type: n1-standard-1
    image: centos-7

  tasks:
    - name: Launch instances ("{{ instances }}")
      gce:
          instance_names: "{{ instances }}"
          machine_type: "{{ machine_type }}"
          image: "{{ image }}"
          service_account_email: "{{ service_account_email }}"
          credentials_file: "{{ credentials_file }}"
          project_id: "{{ project_id }}"
          disk_auto_delete: true
          preemptible: true
          tags: ansible
      register: gce

    - name: Wait for SSH to come up ("{{ instances }}")
      wait_for: host={{ item.public_ip }} port=22 delay=10 timeout=60
      with_items: "{{ gce.instance_data }}"

    - name: Add host to groupname ("{{ instances }}")
      add_host: hostname={{ item.public_ip }} groupname=new_instances
      with_items: "{{ gce.instance_data }}"
    
    - name: Save host data ("{{ instances }}")
      add_host:
        hostname: "{{ item.public_ip }}"
        groupname: gce_instances
      with_items: "{{ gce.instance_data }}"

Running the Playbook

To run our playbook we’ll use the ansible-playbook command:

$ ansible-playbook -e instances="test-1 test-2" gce-instances-create.yml

Notice that we’re passing the names of the instances to create as an environment variable with the -e instances=”..” switch.

Here is the output:

PLAY [Create instances ("test-1")] ********************************************************************************************************************************************************************************

TASK [Launch instances ("test-1")] ********************************************************************************************************************************************************************************
changed: [localhost]

TASK [Wait for SSH to come up ("test-1")] *************************************************************************************************************************************************************************
ok: [localhost] => (item={'image': 'centos-7-v20181210', 'disks': ['test-1'], 'machine_type': 'n1-standard-1', 'metadata': {}, 'name': 'test-1', 'network': 'default', 'subnetwork': 'default', 'private_ip': '10.128.0.2', 'public_ip': '23.251.150.222', 'status': 'RUNNING', 'tags': ['ansible'], 'zone': 'us-central1-a'})

TASK [Add host to groupname ("test-1")] ***************************************************************************************************************************************************************************
changed: [localhost] => (item={'image': 'centos-7-v20181210', 'disks': ['test-1'], 'machine_type': 'n1-standard-1', 'metadata': {}, 'name': 'test-1', 'network': 'default', 'subnetwork': 'default', 'private_ip': '10.128.0.2', 'public_ip': '23.251.150.222', 'status': 'RUNNING', 'tags': ['ansible'], 'zone': 'us-central1-a'})

TASK [Save host data ("test-1")] **********************************************************************************************************************************************************************************
changed: [localhost] => (item={'image': 'centos-7-v20181210', 'disks': ['test-1'], 'machine_type': 'n1-standard-1', 'metadata': {}, 'name': 'test-1', 'network': 'default', 'subnetwork': 'default', 'private_ip': '10.128.0.2', 'public_ip': '23.251.150.222', 'status': 'RUNNING', 'tags': ['ansible'], 'zone': 'us-central1-a'})

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=3    unreachable=0    failed=0

Removing the new instances

We’ll use the following playbook.. notice the state: absent instruction at the end. This will tell the gce ansible module to delete these instances:

- name: Delete instance(s)
  hosts: localhost
  connection: local
  gather_facts: no

  vars:
    service_account_email: your@serviceaccount.iam.gserviceaccount.com
    credentials_file: /some/path/yourkey.json
    project_id: your-project-id 
    zone: us-central1-a

  tasks:

    - name: Destroy instances

      gce:
        instance_names: "{{ instances }}"
        zone: "{{ zone }}"
        project_id: "{{ project_id }}"
        credentials_file: "{{ credentials_file }}"
        service_account_email: "{{ service_account_email }}"
        state: absent

Run the playbook with:

$ ansible-playbook -e instances="test-1 test-2" gce-instances-delete.yml

So with these two commands you can easily enough spin up your infrastructure and clean up when you’re done saving you money and time!

See Also

Matthew Davis

Published a year ago

Comments?

Leave us your opinion.