Ansible for AWS

Setup

ansible-galaxy collection install amazon.aws community.aws
pip install boto3 botocore

Configure credentials:

# Option 1: Environment variables
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=secret...
export AWS_DEFAULT_REGION=us-east-1

# Option 2: ~/.aws/credentials
aws configure

EC2 Instances

- name: Launch EC2 instance
  amazon.aws.ec2_instance:
    name: web-server
    instance_type: t3.micro
    image_id: ami-0c55b159cbfafe1f0
    key_name: deploy-key
    security_groups:
      - web-sg
    subnet_id: subnet-abc123
    network:
      assign_public_ip: true
    volumes:
      - device_name: /dev/sda1
        ebs:
          volume_size: 30
          volume_type: gp3
    tags:
      Environment: production
      Project: webapp
    state: running
  register: ec2

- name: Show instance IP
  ansible.builtin.debug:
    msg: "Instance IP: {{ ec2.instances[0].public_ip_address }}"

Security Groups

- name: Create security group
  amazon.aws.ec2_security_group:
    name: web-sg
    description: Web server security group
    vpc_id: vpc-abc123
    rules:
      - proto: tcp
        from_port: 80
        to_port: 80
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        from_port: 443
        to_port: 443
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: 10.0.0.0/8
    rules_egress:
      - proto: all
        cidr_ip: 0.0.0.0/0

S3

- name: Create S3 bucket
  amazon.aws.s3_bucket:
    name: myapp-assets-{{ aws_account_id }}
    state: present
    versioning: true
    encryption: AES256
    public_access:
      block_public_acls: true
      block_public_policy: true

- name: Upload files to S3
  amazon.aws.s3_object:
    bucket: myapp-assets
    object: "app/{{ item }}"
    src: "dist/{{ item }}"
    mode: put
  loop:
    - index.html
    - app.js
    - style.css

RDS

- name: Create RDS PostgreSQL
  amazon.aws.rds_instance:
    db_instance_identifier: myapp-db
    engine: postgres
    engine_version: "16.1"
    db_instance_class: db.t3.micro
    allocated_storage: 20
    master_username: admin
    master_user_password: "{{ vault_rds_password }}"
    vpc_security_group_ids:
      - sg-db123
    db_subnet_group_name: default
    multi_az: false
    backup_retention_period: 7
    tags:
      Environment: production

VPC

- name: Create VPC
  amazon.aws.ec2_vpc_net:
    name: myapp-vpc
    cidr_block: 10.0.0.0/16
    region: us-east-1
    tags:
      Project: myapp
  register: vpc

- name: Create subnets
  amazon.aws.ec2_vpc_subnet:
    vpc_id: "{{ vpc.vpc.id }}"
    cidr: "{{ item.cidr }}"
    az: "{{ item.az }}"
    tags:
      Name: "{{ item.name }}"
  loop:
    - { cidr: '10.0.1.0/24', az: 'us-east-1a', name: 'public-1' }
    - { cidr: '10.0.2.0/24', az: 'us-east-1b', name: 'public-2' }
    - { cidr: '10.0.3.0/24', az: 'us-east-1a', name: 'private-1' }

IAM

- name: Create IAM role
  amazon.aws.iam_role:
    name: app-role
    assume_role_policy_document:
      Version: "2012-10-17"
      Statement:
        - Effect: Allow
          Principal:
            Service: ec2.amazonaws.com
          Action: sts:AssumeRole
    managed_policies:
      - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

- name: Create IAM user
  amazon.aws.iam_user:
    name: deploy-user
    state: present
    managed_policies:
      - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess

Dynamic Inventory

# aws_ec2.yml - place in inventory directory
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type
filters:
  tag:Project: myapp
  instance-state-name: running
hostnames:
  - private-ip-address
compose:
  ansible_host: public_ip_address
ansible-inventory -i aws_ec2.yml --graph

Conclusion

Ansible's AWS modules cover the full AWS service catalog. Use amazon.aws for core services and community.aws for extended coverage. Combine with dynamic inventory for fully automated cloud management.