AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

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

CollectionProviderKey Modules
amazon.awsAWSec2_instance, s3_bucket, rds_instance, lambda, vpc
amazon.cloudAWS (CloudControl)Cloud-native resource management
azure.azcollectionAzureazure_rm_virtualmachine, azure_rm_webapp, azure_rm_aks
google.cloudGCPgcp_compute_instance, gcp_sql_database, gcp_container_cluster
kubernetes.coreKubernetesk8s, 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.

See also

Category: linux-administration

Browse all Ansible tutorials · AnsiblePilot Home