Ansible provides extensive support for managing Google Cloud Platform (GCP) resources through the google.cloud collection. This guide covers common GCP operations and provides practical examples for automating your cloud infrastructure.
Install the GCP collection:
ansible-galaxy collection install google.cloud
Ansible can authenticate with GCP using several methods:
gcloud auth application-default login
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
vars:
auth_kind: serviceaccount
service_account_file: "/path/to/service-account.json"
project: "my-project-id"
Ensure your service account has the following roles:
roles/compute.admin)roles/storage.admin)roles/cloudsql.admin)roles/iam.serviceAccountUser)- name: Create GCP Compute Engine instance
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
zone: us-central1-a
tasks:
- name: Create instance
google.cloud.gcp_compute_instance:
name: web-server-01
machine_type: e2-medium
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
disks:
- boot: true
auto_delete: true
initialize_params:
source_image: projects/debian-cloud/global/images/family/debian-11
disk_size_gb: 50
network_interfaces:
- network:
name: global/networks/default
access_configs:
- name: External NAT
type: ONE_TO_ONE_NAT
tags:
items:
- http-server
- https-server
labels:
environment: production
application: webserver
register: gce_instance
- name: Display instance information
ansible.builtin.debug:
var: gce_instance.networkInterfaces[0].accessConfigs[0].natIP
- name: Create multiple GCP instances
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
zone: us-central1-a
instance_count: 3
tasks:
- name: Create instances
google.cloud.gcp_compute_instance:
name: "app-server-{{ item }}"
machine_type: e2-standard-2
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
disks:
- boot: true
auto_delete: true
initialize_params:
source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts
disk_size_gb: 100
network_interfaces:
- network:
name: global/networks/default
access_configs:
- name: External NAT
type: ONE_TO_ONE_NAT
labels:
environment: development
application: appserver
loop: "{{ range(1, instance_count + 1) | list }}"
register: gce_instances
- name: Manage VM instance state
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
zone: us-central1-a
tasks:
- name: Stop instance
google.cloud.gcp_compute_instance:
name: web-server-01
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
status: TERMINATED
- name: Start instance
google.cloud.gcp_compute_instance:
name: web-server-01
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
status: RUNNING
- name: Delete VM instance
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
zone: us-central1-a
tasks:
- name: Delete instance
google.cloud.gcp_compute_instance:
name: web-server-01
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
state: absent
- name: Create Cloud Storage bucket
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Create bucket
google.cloud.gcp_storage_bucket:
name: my-unique-bucket-name-12345
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
location: US
storage_class: STANDARD
versioning:
enabled: true
lifecycle_rules:
- action:
type: Delete
condition:
age: 365
labels:
environment: production
project: datalake
- name: Upload files to Cloud Storage
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Upload single file
google.cloud.gcp_storage_object:
bucket: my-bucket-name
key: backups/database-{{ ansible_date_time.date }}.sql
src: /path/to/backup.sql
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
- name: Upload with metadata
google.cloud.gcp_storage_object:
bucket: my-secure-bucket
key: configs/app-config.json
src: /path/to/config.json
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
metadata:
environment: production
encrypted: "true"
- name: Download files from Cloud Storage
hosts: all
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Download configuration file
google.cloud.gcp_storage_object:
bucket: my-bucket-name
key: configs/app-config.json
dest: /etc/myapp/config.json
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
- name: Create Cloud SQL instance
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
tasks:
- name: Create PostgreSQL instance
google.cloud.gcp_sql_database_instance:
name: my-postgres-instance
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
region: "{{ region }}"
settings:
tier: db-custom-2-4096
backup_configuration:
enabled: true
binary_log_enabled: true
start_time: "02:00"
ip_configuration:
ipv4_enabled: true
authorized_networks:
- name: app-server-network
value: 10.0.0.0/8
user_labels:
environment: production
database: postgresql
database_version: POSTGRES_15
root_password: "{{ vault_db_password }}"
- name: Create Cloud SQL database
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Create database
google.cloud.gcp_sql_database:
name: myapp_db
instance: my-postgres-instance
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
charset: UTF8
- name: Create Cloud SQL user
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Create database user
google.cloud.gcp_sql_user:
name: app_user
instance: my-postgres-instance
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
password: "{{ vault_db_user_password }}"
host: "%"
- name: Create VPC network
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Create custom VPC
google.cloud.gcp_compute_network:
name: production-vpc
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
auto_create_subnetworks: false
routing_config:
routing_mode: REGIONAL
- name: Create subnets
google.cloud.gcp_compute_subnetwork:
name: "{{ item.name }}"
region: "{{ item.region }}"
network:
name: production-vpc
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
ip_cidr_range: "{{ item.cidr }}"
private_ip_google_access: true
loop:
- { name: "subnet-us-central1", region: "us-central1", cidr: "10.0.1.0/24" }
- { name: "subnet-us-east1", region: "us-east1", cidr: "10.0.2.0/24" }
- name: Create firewall rules
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Allow HTTP/HTTPS
google.cloud.gcp_compute_firewall:
name: allow-http-https
network:
name: production-vpc
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
direction: INGRESS
allowed:
- IP_protocol: tcp
ports:
- "80"
- "443"
source_ranges:
- 0.0.0.0/0
target_tags:
- http-server
- https-server
- name: Allow SSH from internal
google.cloud.gcp_compute_firewall:
name: allow-ssh-internal
network:
name: production-vpc
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
direction: INGRESS
allowed:
- IP_protocol: tcp
ports:
- "22"
source_ranges:
- 10.0.0.0/8
target_tags:
- ssh-server
- name: Create HTTP Load Balancer
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
tasks:
- name: Create health check
google.cloud.gcp_compute_health_check:
name: web-health-check
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
type: HTTP
http_health_check:
port: 80
request_path: /health
- name: Create backend service
google.cloud.gcp_compute_backend_service:
name: web-backend
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
health_checks:
- name: web-health-check
backends:
- group: projects/{{ project }}/regions/{{ region }}/instanceGroups/web-instance-group
balancing_mode: UTILIZATION
capacity_scaler: 1.0
max_utilization: 0.8
protocol: HTTP
port_name: http
timeout_sec: 30
- name: Create URL map
google.cloud.gcp_compute_url_map:
name: web-url-map
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
default_service:
name: web-backend
- name: Create target HTTP proxy
google.cloud.gcp_compute_target_http_proxy:
name: web-http-proxy
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
url_map:
name: web-url-map
- name: Create global forwarding rule
google.cloud.gcp_compute_global_forwarding_rule:
name: web-forwarding-rule
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
IP_protocol: TCP
port_range: 80-80
target:
name: web-http-proxy
- name: Create service account
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Create service account
google.cloud.gcp_iam_service_account:
name: projects/{{ project }}/serviceAccounts/deploy@{{ project }}.iam.gserviceaccount.com
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
display_name: Deploy Service Account
description: Service account for deployment automation
- name: Grant IAM roles
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
tasks:
- name: Grant Compute Admin role
google.cloud.gcp_resourcemanager_project_iam_policy:
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
bindings:
- role: roles/compute.admin
members:
- serviceAccount:deploy@{{ project }}.iam.gserviceaccount.com
- role: roles/storage.admin
members:
- serviceAccount:deploy@{{ project }}.iam.gserviceaccount.com
- name: Create GKE cluster
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
tasks:
- name: Create GKE cluster
google.cloud.gcp_container_cluster:
name: production-cluster
location: "{{ region }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
initial_node_count: 3
node_config:
machine_type: e2-standard-4
disk_size_gb: 100
oauth_scopes:
- https://www.googleapis.com/auth/cloud-platform
min_master_version: "1.28"
release_channel:
channel: REGULAR
network:
name: production-vpc
subnetwork:
name: subnet-us-central1
ip_allocation_policy:
create_subnetwork: false
addons_config:
http_load_balancing:
disabled: false
horizontal_pod_autoscaling:
disabled: false
network_policy_config:
disabled: false
- name: Create GKE node pool
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
tasks:
- name: Create node pool
google.cloud.gcp_container_node_pool:
name: high-memory-pool
location: "{{ region }}"
cluster_name: production-cluster
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
initial_node_count: 2
config:
machine_type: e2-highmem-4
disk_size_gb: 200
oauth_scopes:
- https://www.googleapis.com/auth/cloud-platform
autoscaling:
enabled: true
min_node_count: 2
max_node_count: 10
management:
auto_repair: true
auto_upgrade: true
This example provisions a complete web application infrastructure on GCP:
- name: Deploy complete GCP infrastructure
hosts: localhost
gather_facts: false
vars:
auth_kind: serviceaccount
service_account_file: "{{ lookup('env', 'GOOGLE_APPLICATION_CREDENTIALS') }}"
project: "my-project-id"
region: us-central1
zone: us-central1-a
environment: production
app_name: mywebapp
tasks:
# VPC Network
- name: Create VPC
google.cloud.gcp_compute_network:
name: "{{ app_name }}-vpc"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
auto_create_subnetworks: false
# Subnet
- name: Create subnet
google.cloud.gcp_compute_subnetwork:
name: "{{ app_name }}-subnet"
region: "{{ region }}"
network:
name: "{{ app_name }}-vpc"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
ip_cidr_range: 10.0.1.0/24
# Firewall Rules
- name: Create firewall rules
google.cloud.gcp_compute_firewall:
name: "{{ app_name }}-firewall"
network:
name: "{{ app_name }}-vpc"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
direction: INGRESS
allowed:
- IP_protocol: tcp
ports:
- "80"
- "443"
- "22"
source_ranges:
- 0.0.0.0/0
# Compute Instances
- name: Create compute instances
google.cloud.gcp_compute_instance:
name: "{{ app_name }}-web-{{ item }}"
machine_type: e2-medium
zone: "{{ zone }}"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
disks:
- boot: true
auto_delete: true
initialize_params:
source_image: projects/debian-cloud/global/images/family/debian-11
disk_size_gb: 50
network_interfaces:
- network:
name: "{{ app_name }}-vpc"
access_configs:
- name: External NAT
type: ONE_TO_ONE_NAT
tags:
items:
- http-server
- https-server
labels:
environment: "{{ environment }}"
application: "{{ app_name }}"
loop: "{{ range(1, 3) | list }}"
register: instances
# Health Check
- name: Create health check
google.cloud.gcp_compute_health_check:
name: "{{ app_name }}-health-check"
project: "{{ project }}"
auth_kind: "{{ auth_kind }}"
service_account_file: "{{ service_account_file }}"
type: HTTP
http_health_check:
port: 80
request_path: /health
# Output
- name: Display instance IPs
ansible.builtin.debug:
msg: "Instance {{ item.name }}: {{ item.networkInterfaces[0].accessConfigs[0].natIP }}"
loop: "{{ instances.results }}"
labels:
environment: "{{ environment }}"
application: "{{ app_name }}"
managed_by: ansible
cost_center: "12345"
All GCP modules support idempotent operations:
- name: Ensure bucket exists
google.cloud.gcp_storage_bucket:
name: my-bucket
state: present
- name: Ensure old bucket is removed
google.cloud.gcp_storage_bucket:
name: old-bucket
state: absent
For high availability, use regional resources:
- name: Create regional instance group
google.cloud.gcp_compute_region_instance_group_manager:
name: web-instance-group
region: "{{ region }}"
base_instance_name: web
target_size: 3
- name: Create uptime check
google.cloud.gcp_monitoring_uptime_check_config:
display_name: web-uptime-check
project: "{{ project }}"
http_check:
path: /health
port: 80
request_method: GET
monitored_resource:
type: uptime_url
labels:
project_id: "{{ project }}"
host: "{{ instance_ip }}"
Any questions?
Feel free to contact us. Find all contact information on our contact page.