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!