Automate your deployment with Ansible in Google Cloud Platform

Andrei Ciorba
Andrei Ciorba January 11 2021 #ansible

share this on:

  

So, you need to quickly create, destroy, and then recreate testing infrastructure in the cloud. Sure, you could start copying and pasting long command lines, but why?

What if there was a tool that could not only create the infrastructure, but also configure it exactly the way you need?

Well, there is such a tool. And that is why you are here, isn't it?

Let us see how we can create some cloud instances using Ansible - in a way that is easy to configure, and easily reproducible again and again...

Prerequisites:

  • a machine running Ansible (centos, ubuntu, or pretty much anything else)
  • a GCP account

Create a service account

In order to create a service account, you must access google cloud console http://console.cloud.google.com

ansible-google-cloud-step-1

Make sure that you are within the correct project (or, if you do not have any projects, create one).

Go to IAM & Admin, select Service Accounts

ansible-google-cloud-step-2

Click on Create Service Account button

ansible-google-cloud-step-3.1

Give the service account a name and select the permissions (in our case I’ve selected from compute engine the compute admin role)

ansible-google-cloud-step-3

ansible-google-cloud-step-4

After creating the service account, you should have a green status associated to it.

ansible-google-cloud-step-5

Because we use a service account outside of GCP (in our case Ansible), first we must establish the identity of the service account. Public/private key pairs provide a secure way of accomplishing this goal.

We now need to generate a key that will be used to authenticate the relation between GCP and ansible. We will generate a JSON file, that we will copy it to the ansible host.

ansible-google-cloud-step-6

ansible-google-cloud-step-7

ansible-google-cloud-step-8

When you create a key, your new public/private key pair is generated and downloaded to your machine and is the only copy of the private key. You are responsible for storing the private key securely. Take note of its location and ensure the key is accessible to your application; it needs the key to make authenticated API calls.

ReadDecoding DevOps – How to Use Ansible for Infrastructure Provisioning and Configuration

Create a (preferably encrypted!) file that stores the JSON credentials

So we need to be able to store the credentials from the service account in a secure fashion. One way to do that is by encrypting the file with ansible vault and here is how we can achieve that:

student@ansible:~$ ansible-vault create --vault-id=@prompt credentials.yml
New vault password (default): 
Confirm new vault password (default):

Note: use a password that you will remember, you will use it later

Next a vi window will appear and you need to paste the full contents of the JSON file after gce_json_contents, making sure that each new line is indented by exactly the same amount!

gce_json_contents: >

  {

    "type": "service_account",

    "project_id": "spring-forest-281234",

    "private_key_id": "b87b0a07db3c2d973a0eeabe8c4512cbe7adb483",

    "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCGM1AEjLoGZMOt \n62UjqhvO5Eh8mqzs71CsNAI=\n-----END PRIVATE KEY-----\n",

    "client_email": "deploy-with-ansible@spring-forest-288214.iam.gserviceaccount.com",

    "client_id": "103141607609234533782",

    "auth_uri": "https://accounts.google.com/o/oauth2/auth",

    "token_uri": "https://oauth2.googleapis.com/token",

    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",

    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/deploy-with-ansible%40spring-forest-281234.iam.gserviceaccount.com"

  }

 

Create a variable file describing the compute instances you want to create

The GCP modules require both the requests and the google-auth libraries to be installed on the ansible host machine.

$ pip install requests google-auth

We will create a variable file called cloud-config.yml where we will describe the details for the instances we want to create (name, machine type, source image, zone, in which project it belongs) and also, we will add an SSH public key here, so that we can easily connect to the instances once they have been created.

cloud-config.yml

instances:

- name: instance-01

  gce_machine_type: f1-micro

  gce_source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-l$

  gce_zone: us-central1-a

  gce_project: spring-forest-288214


- name: instance-02

  gce_machine_type: f1-micro

  gce_source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-l$

  gce_zone: us-central1-a

  gce_project: spring-forest-288214


- name: instance-03

  gce_machine_type: f1-micro

  gce_source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-l$

  gce_zone: us-central1-a

  gce_project: spring-forest-288214


admin_username: admin

admin_ssh_key: ssh-rsa +Bz9BUWyVgDF

--------[output omitted]----------------

w+ZyZUk= user@local

 

Read: Terraform vs Ansible

Create a playbook that creates the instances

Now we will create a playbook named playbook.yml that we will use to create the instances defined in cloud-config.yml

playbook.yml

- name: Create cloud instances

  hosts: localhost

  vars_files:

  - cloud-config.yml

  - credentials.yml

  tasks:

  - name: Create instance

    gcp_compute_instance:

      name: "{{item.name}}"

      machine_type: "{{item.gce_machine_type}}"

      disks:

      - auto_delete: true

        boot: true

        initialize_params:

           source_image: "{{item.gce_source_image}}"

      network_interfaces:

      - network:

          selfLink: global/networks/default     

      metadata:

        managed-by: "Ansible"

        ssh-keys: ":\n"

      zone: "{{item.gce_zone}}"

      project: "{{item.gce_project}}"

      auth_kind: serviceaccount

      service_account_contents: "null"

      state: present

      status: RUNNING

    register: gce_instance

    loop: ""

 

Run the playbook

student@ansibl:~$ ansible-playbook --vault-id=@prompt playbook.yml

Vault password (default): 

[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [Create cloud instances] ******************************************************************

TASK [Gathering Facts] ******************************************************************

ok: [localhost]

TASK [Create instance] ******************************************************************

changed: [localhost] => (item={u'gce_machine_type': u'f1-micro', u'gce_zone': u'us-central1-a', u'gce_source_image': u'projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts', u'name': u'instance-01', u'gce_project': u'spring-forest-288214'})

changed: [localhost] => (item={u'gce_machine_type': u'f1-micro', u'gce_zone': u'us-central1-a', u'gce_source_image': u'projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts', u'name': u'instance-02', u'gce_project': u'spring-forest-288214'})

changed: [localhost] => (item={u'gce_machine_type': u'f1-micro', u'gce_zone': u'us-central1-a', u'gce_source_image': u'projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts', u'name': u'instance-03', u'gce_project': u'spring-forest-288214'})

PLAY RECAP ******************************************************************

localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

student@ansible:~$

 

In just a few minutes, your new instances are ready to use!

You open your browser, click in your console cloud google page on VM instance tab and you should see the 3 instances created just like billow: 

ansible-google-cloud-step-9

Well done, with a simple tool you’ve created 3 instances in the cloud!

As we demonstrated, the advantages of this approach are:

  • easy to extend - you can add tasks to the playbook to configure the VMs exactly the way you need them
  • easy to reproduce - just run the playbook again!
  • easy to make changes. Need a bigger instance type? Or maybe instances in different zones? Just edit the variables file!

Take advantage of GCP, the way you want to:

  • Use Ansible to launch instances in any GCP Zone, configure networking setups to accurately simulate real-world scenarios
  • Deploy your code how you want: private disk images, startup scripts pointing to your own package repository and more -- all within your native Ansible Playbooks
  • Tear-down instances when you're done: right after a test or after a review with the team and even keep a snapshot of the disk 

 

ansible advanced course - devops artisan

 

share this on: