AAP 2.6 Cloud Automation: AWS, Azure, and GCP with Ansible
By Luca Berton · Published 2024-01-01 · Category: linux-administration
Automate multi-cloud infrastructure with AAP 2.6. Provision and manage AWS EC2, Azure VMs, GCP instances, Kubernetes clusters, and cloud-native services.
Multi-Cloud Automation with AAP 2.6
AAP 2.6 provides native integrations with all major cloud providers through certified collections. Manage cloud infrastructure alongside on-premises systems from a single platform.
See also: Ansible for Cloud Automation: AWS, Azure, and GCP Complete Guide
Cloud Collections
| Collection | Provider | Key Modules |
|-----------|----------|-------------|
| amazon.aws | AWS | ec2_instance, s3_bucket, rds_instance, lambda, vpc |
| amazon.cloud | AWS (CloudControl) | Cloud-native resource management |
| azure.azcollection | Azure | azure_rm_virtualmachine, azure_rm_webapp, azure_rm_aks |
| google.cloud | GCP | gcp_compute_instance, gcp_sql_database, gcp_container_cluster |
| kubernetes.core | Kubernetes | k8s, helm, k8s_info |
Cloud Execution Environment
---
version: 3
images:
base_image:
name: registry.redhat.io/ansible-automation-platform-26/ee-minimal-rhel9:latest
dependencies:
galaxy:
collections:
- name: amazon.aws
version: ">=9.0.0"
- name: azure.azcollection
version: ">=3.0.0"
- name: google.cloud
version: ">=1.4.0"
- name: kubernetes.core
version: ">=5.0.0"
python:
- boto3>=1.34
- botocore>=1.34
- azure-mgmt-compute>=32.0
- azure-mgmt-network>=26.0
- azure-mgmt-resource>=23.0
- azure-identity>=1.16
- google-auth>=2.0
- google-cloud-compute>=1.0
- kubernetes>=29.0
- jmespath>=1.0
AWS Automation
Credential Setup
- name: Create AWS credential
ansible.platform.credential:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "AWS Production"
organization: "Cloud Team"
credential_type: "Amazon Web Services"
inputs:
username: "{{ aws_access_key }}"
password: "{{ aws_secret_key }}"
state: present
Provision EC2 Instances
- name: Provision AWS infrastructure
hosts: localhost
gather_facts: false
collections:
- amazon.aws
tasks:
- name: Create VPC
amazon.aws.ec2_vpc_net:
name: "production-vpc"
cidr_block: "10.0.0.0/16"
region: us-east-1
tags:
Environment: production
ManagedBy: ansible
register: vpc
- name: Create subnet
amazon.aws.ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
cidr: "10.0.1.0/24"
az: us-east-1a
tags:
Name: "prod-subnet-1a"
register: subnet
- name: Create security group
amazon.aws.ec2_security_group:
name: "web-servers"
description: "Web server security group"
vpc_id: "{{ vpc.vpc.id }}"
region: us-east-1
rules:
- proto: tcp
ports: [80, 443]
cidr_ip: 0.0.0.0/0
rule_desc: "HTTP/HTTPS"
- proto: tcp
ports: [22]
cidr_ip: 10.0.0.0/8
rule_desc: "SSH from internal"
register: sg
- name: Launch EC2 instances
amazon.aws.ec2_instance:
name: "web-{{ item }}"
instance_type: t3.medium
image_id: ami-0abcdef1234567890
vpc_subnet_id: "{{ subnet.subnet.id }}"
security_groups:
- "{{ sg.group_id }}"
key_name: "ansible-key"
count: 1
tags:
Environment: production
Role: webserver
ManagedBy: ansible
wait: true
loop: ["01", "02", "03"]
register: ec2_instances
- name: Create RDS instance
amazon.aws.rds_instance:
db_instance_identifier: "prod-database"
engine: postgres
engine_version: "15"
db_instance_class: db.t3.medium
allocated_storage: 100
master_username: admin
master_user_password: "{{ vault_db_password }}"
vpc_security_group_ids:
- "{{ sg.group_id }}"
multi_az: true
tags:
Environment: production
AWS Dynamic Inventory
- name: Configure AWS dynamic inventory
ansible.platform.inventory_source:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "AWS Production"
inventory: "Cloud Servers"
source: "amazon.aws.aws_ec2"
credential: "AWS Production"
source_vars:
regions:
- us-east-1
- us-west-2
filters:
tag:ManagedBy: ansible
instance-state-name: running
keyed_groups:
- key: tags.Role
prefix: role
- key: tags.Environment
prefix: env
- key: placement.region
prefix: region
compose:
ansible_host: private_ip_address
update_on_launch: true
state: present
See also: Ansible Dynamic Inventory: Complete Guide to AWS, Azure, GCP, and Custom Plugins
Azure Automation
Credential Setup
- name: Create Azure credential
ansible.platform.credential:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "Azure Production"
organization: "Cloud Team"
credential_type: "Microsoft Azure Resource Manager"
inputs:
subscription: "{{ azure_subscription_id }}"
client: "{{ azure_client_id }}"
secret: "{{ azure_client_secret }}"
tenant: "{{ azure_tenant_id }}"
state: present
Provision Azure Resources
- name: Provision Azure infrastructure
hosts: localhost
gather_facts: false
collections:
- azure.azcollection
tasks:
- name: Create resource group
azure.azcollection.azure_rm_resourcegroup:
name: "production-rg"
location: eastus
tags:
Environment: production
ManagedBy: ansible
- name: Create virtual network
azure.azcollection.azure_rm_virtualnetwork:
resource_group: "production-rg"
name: "prod-vnet"
address_prefixes: "10.0.0.0/16"
- name: Create subnet
azure.azcollection.azure_rm_subnet:
resource_group: "production-rg"
virtual_network: "prod-vnet"
name: "web-subnet"
address_prefix: "10.0.1.0/24"
- name: Create VMs
azure.azcollection.azure_rm_virtualmachine:
resource_group: "production-rg"
name: "web-{{ item }}"
vm_size: Standard_B2s
admin_username: ansible
ssh_password_enabled: false
ssh_public_keys:
- path: /home/ansible/.ssh/authorized_keys
key_data: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
image:
offer: RHEL
publisher: RedHat
sku: "9_4"
version: latest
tags:
Role: webserver
ManagedBy: ansible
loop: ["01", "02"]
- name: Create AKS cluster
azure.azcollection.azure_rm_aks:
name: "prod-aks"
resource_group: "production-rg"
location: eastus
kubernetes_version: "1.29"
dns_prefix: "prod-aks"
agent_pool_profiles:
- name: default
count: 3
vm_size: Standard_D2s_v3
mode: System
tags:
Environment: production
GCP Automation
Provision GCP Resources
- name: Provision GCP infrastructure
hosts: localhost
gather_facts: false
collections:
- google.cloud
tasks:
- name: Create VPC network
google.cloud.gcp_compute_network:
name: "production-network"
auto_create_subnetworks: false
project: "{{ gcp_project }}"
auth_kind: serviceaccount
service_account_file: "{{ gcp_cred_file }}"
state: present
register: network
- name: Create subnet
google.cloud.gcp_compute_subnetwork:
name: "prod-subnet-us-east1"
region: us-east1
network: "{{ network }}"
ip_cidr_range: "10.0.1.0/24"
project: "{{ gcp_project }}"
auth_kind: serviceaccount
service_account_file: "{{ gcp_cred_file }}"
- name: Create instances
google.cloud.gcp_compute_instance:
name: "web-{{ item }}"
machine_type: e2-medium
zone: us-east1-b
network_interfaces:
- network: "{{ network }}"
subnetwork: "{{ subnet }}"
disks:
- auto_delete: true
boot: true
initialize_params:
source_image: projects/rhel-cloud/global/images/family/rhel-9
disk_size_gb: 50
labels:
role: webserver
managed_by: ansible
project: "{{ gcp_project }}"
auth_kind: serviceaccount
service_account_file: "{{ gcp_cred_file }}"
loop: ["01", "02"]
See also: Automating Azure DevTest Labs Course by Luca Berton | Pluralsight
Multi-Cloud Patterns
Unified Provisioning Workflow
[Survey: Select Cloud + Size] → [Provision VMs]
│
┌─────────────────┼─────────────────┐
│ │ │
[AWS Provision] [Azure Provision] [GCP Provision]
│ │ │
└─────────────────┼─────────────────┘
│
[Configure All Hosts]
│
[Deploy Application]
│
[Verify and Report]
Cross-Cloud Cost Tagging
- name: Enforce cost tags across clouds
hosts: localhost
tasks:
- name: Tag AWS resources
amazon.aws.ec2_tag:
resource: "{{ item }}"
tags:
CostCenter: "{{ cost_center }}"
Project: "{{ project_name }}"
Owner: "{{ team_name }}"
loop: "{{ aws_resources }}"
- name: Tag Azure resources
azure.azcollection.azure_rm_resource_tag:
resource_group: "{{ resource_group }}"
tags:
CostCenter: "{{ cost_center }}"
Project: "{{ project_name }}"
Owner: "{{ team_name }}"
- name: Label GCP resources
google.cloud.gcp_compute_instance:
name: "{{ item }}"
labels:
cost_center: "{{ cost_center | lower | replace(' ', '_') }}"
project: "{{ project_name | lower | replace(' ', '_') }}"
project: "{{ gcp_project }}"
Kubernetes Automation
- name: Deploy to Kubernetes
hosts: localhost
collections:
- kubernetes.core
tasks:
- name: Create namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: "{{ app_namespace }}"
labels:
managed-by: ansible
- name: Deploy application
kubernetes.core.k8s:
state: present
src: "manifests/{{ item }}"
namespace: "{{ app_namespace }}"
loop:
- deployment.yml
- service.yml
- ingress.yml
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ release_name }}"
chart_ref: "{{ chart_repo }}/{{ chart_name }}"
chart_version: "{{ chart_version }}"
release_namespace: "{{ app_namespace }}"
values:
replicaCount: 3
image:
repository: "{{ image_repo }}"
tag: "{{ image_tag }}"
FAQ
Should I use Ansible or Terraform for cloud provisioning?
Use both for their strengths. Terraform excels at declarative infrastructure state management with plan/apply workflow. Ansible excels at configuration management, application deployment, and orchestration. Many teams use Terraform for infrastructure and Ansible for everything that runs on that infrastructure. AAP can call Terraform via the cloud.terraform collection.
How do I handle cloud credentials securely?
Use AAP's external secret backends — HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. For AWS, consider IAM roles for execution nodes running in AWS. Never store cloud credentials in playbooks or Git.
Can I manage resources across multiple AWS accounts?
Yes. Use STS AssumeRole with different credentials per account. Create separate AAP credentials for each AWS account and use inventory or job template variables to select the target account.
How do I prevent cloud cost overruns?
Implement tag enforcement playbooks, scheduled cleanup of unused resources, and budget alerting. AAP workflows can run nightly jobs to identify and terminate untagged or idle resources.
Can AAP manage serverless resources?
Yes. The amazon.aws collection includes modules for Lambda, API Gateway, SQS, SNS, and other serverless services. Azure Functions and GCP Cloud Functions can be managed through their respective collections.
Conclusion
AAP 2.6 provides a unified automation platform for multi-cloud infrastructure management. Whether provisioning AWS EC2 instances, Azure VMs, GCP compute instances, or Kubernetes workloads, the same platform handles it all — with enterprise RBAC, credential management, and audit logging. Combine cloud provisioning with AAP's workflow engine for end-to-end infrastructure-as-code pipelines.
Related Articles
• AAP 2.6 Architecture and Components: Complete Guide • AAP 2.6 Credential Management: Vaults, External Secrets, and Machine Credentials • AAP 2.6 Execution Environments: Build, Manage, and Deploy Custom EEs • AAP 2.6 Job Templates and Inventories: Complete Configuration Guide • Ansible GitOps Infrastructure as Code with Git Workflows and AAPSee also
• Ansible on Oracle Cloud Infrastructure: VM Provisioning Complete GuideCategory: linux-administration