2014-03-14 20:01:07 +01:00
Google Cloud Platform Guide
===========================
2014-03-05 16:53:38 +01:00
2014-03-14 20:01:07 +01:00
.. gce_intro:
2014-03-05 16:53:38 +01:00
Introduction
2018-07-06 16:09:13 +02:00
--------------------------
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
Ansible + Google have been working together on a set of auto-generated
Ansible modules designed to consistently and comprehensively cover the entirety
2019-07-01 17:37:13 +02:00
of the Google Cloud Platform (GCP).
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
Ansible contains modules for managing Google Cloud Platform resources,
including creating instances, controlling network access, working with
persistent disks, managing load balancers, and a lot more.
2014-03-14 20:01:07 +01:00
2018-07-06 16:09:13 +02:00
These new modules can be found under a new consistent name scheme "gcp_*"
(Note: gcp_target_proxy and gcp_url_map are legacy modules, despite the "gcp_*"
name. Please use gcp_compute_target_proxy and gcp_compute_url_map instead).
2019-07-01 17:37:13 +02:00
Additionally, the gcp_compute inventory plugin can discover all
Google Compute Engine (GCE) instances
2018-07-06 16:09:13 +02:00
and make them automatically available in your Ansible inventory.
You may see a collection of other GCP modules that do not conform to this
naming convention. These are the original modules primarily developed by the
Ansible community. You will find some overlapping functionality such as with
2018-08-22 21:53:30 +02:00
the "gce" module and the new "gcp_compute_instance" module. Either can be
2018-07-06 16:09:13 +02:00
used, but you may experience issues trying to use them together.
While the community GCP modules are not going away, Google is investing effort
into the new "gcp_*" modules. Google is committed to ensuring the Ansible
2019-05-08 20:51:18 +02:00
community has a great experience with GCP and therefore recommends adopting
2018-11-02 22:05:23 +01:00
these new modules if possible.
2018-07-06 16:09:13 +02:00
2018-11-02 22:05:23 +01:00
Requisites
2018-07-06 16:09:13 +02:00
---------------
2019-07-01 17:37:13 +02:00
The GCP modules require both the `` requests `` and the
2018-07-06 16:09:13 +02:00
`` google-auth `` libraries to be installed.
2014-03-05 16:53:38 +01:00
.. code-block :: bash
2018-07-06 16:09:13 +02:00
$ pip install requests google-auth
2014-03-05 16:53:38 +01:00
2019-05-08 20:51:18 +02:00
Alternatively for RHEL / CentOS, the `` python-requests `` package is also
2018-11-02 22:05:23 +01:00
available to satisfy `` requests `` libraries.
.. code-block :: bash
$ yum install python-requests
2014-03-05 16:53:38 +01:00
Credentials
-----------
2018-07-06 16:09:13 +02:00
It's easy to create a GCP account with credentials for Ansible. You have multiple options to
get your credentials - here are two of the most common options:
* Service Accounts (Recommended): Use JSON service accounts with specific permissions.
* Machine Accounts: Use the permissions associated with the GCP Instance you're using Ansible on.
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
For the following examples, we'll be using service account credentials.
To work with the GCP modules, you'll first need to get some credentials in the
2016-05-12 17:57:26 +02:00
JSON format:
2014-03-05 16:53:38 +01:00
2016-05-12 17:57:26 +02:00
1. `Create a Service Account <https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount> `_
2. `Download JSON credentials <https://support.google.com/cloud/answer/6158849?hl=en&ref_topic=6262490#serviceaccounts> `_
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
Once you have your credentials, there are two different ways to provide them to Ansible:
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
* by specifying them directly as module parameters
2016-05-12 17:57:26 +02:00
* by setting environment variables
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
Providing Credentials as Module Parameters
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
2014-03-05 16:53:38 +01:00
2014-03-14 20:01:07 +01:00
For the GCE modules you can specify the credentials as arguments:
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
* `` auth_kind `` : type of authentication being used (choices: machineaccount, serviceaccount, application)
2014-03-05 16:53:38 +01:00
* `` service_account_email `` : email associated with the project
2018-07-06 16:09:13 +02:00
* `` service_account_file `` : path to the JSON credentials file
* `` project `` : id of the project
* `` scopes `` : The specific scopes that you want the actions to use.
2014-03-05 16:53:38 +01:00
2019-04-15 23:30:36 +02:00
For example, to create a new IP address using the `` gcp_compute_address `` module,
2018-07-06 16:09:13 +02:00
you can use the following configuration:
2014-03-05 16:53:38 +01:00
.. code-block :: yaml
2014-03-14 20:01:07 +01:00
2018-07-06 16:09:13 +02:00
- name: Create IP address
2014-03-05 16:53:38 +01:00
hosts: localhost
gather_facts: no
2014-03-14 20:01:07 +01:00
2014-03-05 16:53:38 +01:00
vars:
2018-07-06 16:09:13 +02:00
service_account_file: /home/my_account.json
project: my-project
auth_kind: serviceaccount
scopes:
2019-05-13 19:11:49 +02:00
- https://www.googleapis.com/auth/compute
2014-03-14 20:01:07 +01:00
2014-03-05 16:53:38 +01:00
tasks:
2014-03-14 20:01:07 +01:00
2018-07-06 16:09:13 +02:00
- name: Allocate an IP Address
gcp_compute_address:
state: present
name: 'test-address1'
region: 'us-west1'
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
scopes: "{{ scopes }}"
Providing Credentials as Environment Variables
2016-05-12 17:57:26 +02:00
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
Set the following environment variables before running Ansible in order to configure your credentials:
.. code-block :: bash
2018-07-06 16:09:13 +02:00
GCP_AUTH_KIND
GCP_SERVICE_ACCOUNT_EMAIL
GCP_SERVICE_ACCOUNT_FILE
GCP_SCOPES
2016-05-12 17:57:26 +02:00
2014-03-14 20:01:07 +01:00
GCE Dynamic Inventory
---------------------
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
The best way to interact with your hosts is to use the gcp_compute inventory plugin, which dynamically queries GCE and tells Ansible what nodes can be managed.
2014-03-14 20:01:07 +01:00
2019-01-03 16:02:46 +01:00
To be able to use this GCE dynamic inventory plugin, you need to enable it first by specifying the following in the `` ansible.cfg `` file:
.. code-block :: ini
[inventory]
enable_plugins = gcp_compute
Then, create a file that ends in `` .gcp.yml `` in your root directory.
The gcp_compute inventory script takes in the same authentication information as any module.
2014-03-14 20:01:07 +01:00
2018-07-06 16:09:13 +02:00
Here's an example of a valid inventory file:
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
.. code-block :: yaml
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
plugin: gcp_compute
projects:
2019-01-03 16:02:46 +01:00
- graphite-playground
2018-07-06 16:09:13 +02:00
auth_kind: serviceaccount
service_account_file: /home/alexstephen/my_account.json
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
Executing `` ansible-inventory --list -i <filename>.gcp.yml `` will create a list of GCP instances that are ready to be configured using Ansible.
2014-03-05 16:53:38 +01:00
Create an instance
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
2018-07-06 16:09:13 +02:00
The full range of GCP modules provide the ability to create a wide variety of
GCP resources with the full support of the entire GCP API.
2014-03-05 16:53:38 +01:00
2018-07-06 16:09:13 +02:00
The following playbook creates a GCE Instance. This instance relies on a GCP
network and a Disk. By creating the Disk and Network separately, we can give as
much detail as necessary about how we want the disk and network formatted. By
registering a Disk/Network to a variable, we can simply insert the variable
into the instance task. The gcp_compute_instance module will figure out the
rest.
2014-03-05 16:53:38 +01:00
.. code-block :: yaml
2018-07-06 16:09:13 +02:00
- name: Create an instance
2014-03-05 16:53:38 +01:00
hosts: localhost
gather_facts: no
vars:
2019-04-26 17:15:51 +02:00
gcp_project: my-project
gcp_cred_kind: serviceaccount
gcp_cred_file: /home/my_account.json
2018-07-06 16:09:13 +02:00
zone: "us-central1-a"
region: "us-central1"
2014-03-14 20:01:07 +01:00
2014-03-05 16:53:38 +01:00
tasks:
2018-07-06 16:09:13 +02:00
- name: create a disk
gcp_compute_disk:
name: 'disk-instance'
size_gb: 50
source_image: 'projects/ubuntu-os-cloud/global/images/family/ubuntu-1604-lts'
zone: "{{ zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: present
register: disk
- name: create a network
gcp_compute_network:
name: 'network-instance'
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: present
register: network
- name: create a address
gcp_compute_address:
name: 'address-instance'
region: "{{ region }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
state: present
register: address
- name: create a instance
gcp_compute_instance:
state: present
name: test-vm
machine_type: n1-standard-1
disks:
- auto_delete: true
boot: true
source: "{{ disk }}"
network_interfaces:
- network: "{{ network }}"
access_configs:
- name: 'External NAT'
nat_ip: "{{ address }}"
type: 'ONE_TO_ONE_NAT'
zone: "{{ zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
register: instance
2014-03-14 20:01:07 +01:00
- name: Wait for SSH to come up
2019-05-08 20:51:18 +02:00
wait_for: host={{ address.address }} port=22 delay=10 timeout=60
2014-03-14 20:01:07 +01:00
2014-09-29 05:18:39 +02:00
- name: Add host to groupname
2019-05-08 20:51:18 +02:00
add_host: hostname={{ address.address }} groupname=new_instances
2018-07-06 16:09:13 +02:00
2014-03-14 20:01:07 +01:00
- name: Manage new instances
hosts: new_instances
connection: ssh
2014-09-29 05:18:39 +02:00
sudo: True
2014-03-14 20:01:07 +01:00
roles:
- base_configuration
- production_server
2014-09-29 05:18:39 +02:00
2014-03-14 20:01:07 +01:00
Note that use of the "add_host" module above creates a temporary, in-memory group. This means that a play in the same playbook can then manage machines
in the 'new_instances' group, if so desired. Any sort of arbitrary configuration is possible at this point.
2018-07-30 23:12:36 +02:00
For more information about Google Cloud, please visit the `Google Cloud website <https://cloud.google.com> `_ .
2019-04-15 23:30:36 +02:00
Migration Guides
----------------
gce.py -> gcp_compute_instance.py
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
As of Ansible 2.8, we're encouraging everyone to move from the `` gce `` module to the
`` gcp_compute_instance `` module. The `` gcp_compute_instance `` module has better
support for all of GCP's features, fewer dependencies, more flexibility, and
better supports GCP's authentication systems.
The `` gcp_compute_instance `` module supports all of the features of the `` gce ``
module (and more!). Below is a mapping of `` gce `` fields over to
`` gcp_compute_instance `` fields.
============================ ========================================== ======================
2019-05-08 20:51:18 +02:00
gce.py gcp_compute_instance.py Notes
2019-04-15 23:30:36 +02:00
============================ ========================================== ======================
state state/status State on gce has multiple values: "present", "absent", "stopped", "started", "terminated". State on gcp_compute_instance is used to describe if the instance exists (present) or does not (absent). Status is used to describe if the instance is "started", "stopped" or "terminated".
image disks[].initialize_params.source_image You'll need to create a single disk using the disks[] parameter and set it to be the boot disk (disks[].boot = true)
image_family disks[].initialize_params.source_image See above.
external_projects disks[].initialize_params.source_image The name of the source_image will include the name of the project.
instance_names Use a loop or multiple tasks. Using loops is a more Ansible-centric way of creating multiple instances and gives you the most flexibility.
service_account_email service_accounts[].email This is the service_account email address that you want the instance to be associated with. It is not the service_account email address that is used for the credentials necessary to create the instance.
service_account_permissions service_accounts[].scopes These are the permissions you want to grant to the instance.
pem_file Not supported. We recommend using JSON service account credentials instead of PEM files.
credentials_file service_account_file
project_id project
name name This field does not accept an array of names. Use a loop to create multiple instances.
num_instances Use a loop For maximum flexibility, we're encouraging users to use Ansible features to create multiple instances, rather than letting the module do it for you.
network network_interfaces[].network
subnetwork network_interfaces[].subnetwork
persistent_boot_disk disks[].type = 'PERSISTENT'
disks disks[]
ip_forward can_ip_forward
external_ip network_interfaces[].access_configs.nat_ip This field takes multiple types of values. You can create an IP address with `` gcp_compute_address `` and place the name/output of the address here. You can also place the string value of the IP address's GCP name or the actual IP address.
disks_auto_delete disks[].auto_delete
preemptible scheduling.preemptible
disk_size disks[].initialize_params.disk_size_gb
============================ ========================================== ======================
An example playbook is below:
.. code :: yaml
gcp_compute_instance:
name: "{{ item }}"
machine_type: n1-standard-1
... # any other settings
zone: us-central1-a
project: "my-project"
auth_kind: "service_account_file"
service_account_file: "~/my_account.json"
state: present
with_items:
- instance-1
- instance-2