Build Your Own Default Amazon VPC (Virtual Private Cloud) Using Ansible
Just like when we have an on premise model for our infrastructure, we also need a network for our cloud infrastructure either public or private. Yes, we can build secure and isolated private network. If you have a plan to use AWS resources, let's say you want to host your servers using EC2 instances. Then, you can create your own network for them or on AWS it's called as Virtual Private Cloud (VPC) instead of using the default one.
More about VPC, click here!
In this section, we'll create a VPC to connect our EC2 instances placed in different AZs and give them internet connection. From this scenario, we'll need:
- VPC in a region (me: ap-southeast-3 or Indonesia);
- Subnet on each AZ (3 in total);
- Internet gateway;
- Route table;
- Security group.
Then, I won't go through the console but I'll use ansible instead. Why? If you've ever seen my previous posts, you should know why :)
Alright, just like my previous posts. We'll use localhost as the target host, because here we don't touch EC2 instances yet. Make sure you've installed:
- AWS CLI and setup at least one credential;
- Ansible;
- Ansible collection for AWS by running
ansible-galaxy collection install community.aws
.
Note*: All details below, you can replace with your own value if you already prepared.
Inventory: host.yml
---
localhost:
hosts:
127.0.0.1:
Playbook: vpc.yml
- name: vpc
hosts: localhost
connection: local
gather_facts: no
tasks:
1. Create a VPC
- name: create vpc
amazon.aws.ec2_vpc_net:
name: custom_vpc
cidr_block: 10.0.0.0/16
region: ap-southeast-3
register: vpc
2. Create Subnets
(make sure all subnets are included in the same VPC network range but in different network between subnets).
- Availability Zone A
- name: create subnet for first az
amazon.aws.ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
state: present
az: ap-southeast-3a
cidr: 10.0.1.0/28
register: az1_apse3
- Availability Zone B
- name: create subnet for second az
amazon.aws.ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
state: present
az: ap-southeast-3b
cidr: 10.0.2.0/28
register: az2_apse3
- Availability Zone C
- name: create subnet for third az
amazon.aws.ec2_vpc_subnet:
vpc_id: "{{ vpc.vpc.id }}"
state: present
az: ap-southeast-3c
cidr: 10.0.3.0/28
register: az3_apse3
Note*: The "vpc" variable is only available or defined when we register it on the VPC creation (Step 1) above.
3. Create Internet Gateway
- name: create internet gateway
amazon.aws.ec2_vpc_igw:
vpc_id: "{{ vpc.vpc.id }}"
state: present
register: igw
4. Create Route Table
When we create a VPC, a (main) route table will be created along with it but it only create a local route. Then, to have an internet connection we should add a route with destination (anywhere) through Internet Gateway.
Note*: You can choose which subnets will be given internet connection. In this case, we'll make them all as public subnet.
- name: create custom route table
amazon.aws.ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc.id }}"
region: ap-southeast-3
subnets:
- "{{ az1_apse3.subnet.id }}"
- "{{ az2_apse3.subnet.id }}"
- "{{ az3_apse3.subnet.id }}"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ igw.gateway_id }}"
5. Create Security Group
If you've already decided which ports to be allowed for our EC2 instance, let's make it too under our VPC. Cause the default one is under default VPC. For instance, I'll host web servers using EC2 instances. So, I'll allow port 22 for remote and 80 to access the web servers.
- name: create security group
amazon.aws.ec2_group:
name: ssh-web
description: allow ssh and http
vpc_id: "{{ vpc.vpc.id }}"
region: ap-southeast-3
rules:
- proto: tcp
ports: 22
cidr_ip: 0.0.0.0/0
- proto: tcp
ports: 80
cidr_ip: 0.0.0.0/0
Run the playbook!
$ ansible-playbook -i host.yml vpc.yml
PLAY [vpc] **************************************************************************************************************************************************************
TASK [create vpc] *******************************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create subnet for first az] ***************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create subnet for second az] **************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create subnet for third az] ***************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create internet gateway] ******************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create custom route table] ****************************************************************************************************************************************
changed: [127.0.0.1]
TASK [create security group] ********************************************************************************************************************************************
changed: [127.0.0.1]
PLAY RECAP **************************************************************************************************************************************************************
127.0.0.1 : ok=7 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Let's check!
$ aws ec2 describe-vpcs --query 'Vpcs[?Tags[?Value==`custom_vpc`]].{VPC:VpcId, CIDR:CidrBlock}'
[
{
"VPC": "vpc-0a6bbb5ca26b09679",
"CIDR": "10.0.0.0/16"
}
]
$ aws ec2 describe-subnets --query 'Subnets[?VpcId==`vpc-0a6bbb5ca26b09679`].{AZ:AvailabilityZone, CIDR:CidrBlock, SubnetID:SubnetId}'
[
{
"AZ": "ap-southeast-3c",
"CIDR": "10.0.3.0/28",
"SubnetID": "subnet-00b4e72d63a2125de"
},
{
"AZ": "ap-southeast-3a",
"CIDR": "10.0.1.0/28",
"SubnetID": "subnet-0276d466994fa3087"
},
{
"AZ": "ap-southeast-3b",
"CIDR": "10.0.2.0/28",
"SubnetID": "subnet-07bb6501337e4f87b"
}
]
Note*: Since VPC is not used yet and it doesn't cause availability risks or bandwidth constraints on our network traffic, we'll not billed for what we've created above. Don't worry! If you want to delete them all, we'll do it at the end cause we still need it for our EC2 instances next.
That's it for the VPC! We'll use this VPC to launch EC2 instances. Let's move to the next post!
References:
https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_vpc_net_module.html
https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_vpc_subnet_module.html
https://docs.ansible.com/ansible/devel/collections/amazon/aws/ec2_vpc_route_table_module.html
https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_vpc_igw_module.html
https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_group_module.html