I’m starting a fairly heavy Ansible + AWS project and wanted to bounce some approaches around before embarking on a heavy feature implementation.
So far I’ve written an ec2_rds_paramgroup module that allows maintenance of database parameter groups. I’ll be submitting this for core when I get some time to clean it up and after I’ve used it a bit to make sure there aren’t extant use cases I missed.
I was starting on the VPC infrastructure for the site I’m working on and discovered a chicken and egg problem with ec2_vpc: if I want to create a VPC with private and public subnets using a NAT instance for external communication, I have to do the following if I want to use ec2_vpc and not hack in something with the vpc CLI:
Create the VPC with the subnets, leaving off all references in the route tables to the currently non-existing NAT instance.
Create the NAT instance using the ec2 module in a new task
Re-configure the VPC with the subnets, now including references to the NAT instance as the 0.0.0.0 gateway in the route tables of the private subnets that need Internet access. Very not DRY if I use ec2_vpc as I have to respecify everything in step 1.
The reason for this being that it’s not possible to create a NAT instance in a non-existent VPC with non-existent subnets for use in that VPC.
So I’m considering a modification to the ec2_vpc module to allow specifying a NAT instance as part of a subnet, creating the instance in the subnet creation code and referencing it in the route tables later on; this would be similar to the use of the private/public VPC Wizard in the AWS console.
Since I can’t (that I know of) call one module from another, I’ll need to move the ec2 instance creation code to module_utils/ec2.py and call it there.
Any pitfalls/comments/Scott-you-idiot-there’s-a-better-way?
I’m in a similar situation and my approach was to create a ElasticNetworkInterface first and reference it as the 0.0.0.0/0 gateway for the private subnet when creating the VPC and the routing. Then create NAT instance in the private subnet and attach it to the ENI created earlier. Obviously, ec2 and ec2_vpc modules will have to be modified and a new ec2_eni module is needed but it I think the result would be more elegant than configuring VPC twice.
Maybe an action_plugin, that calls the ec2_vpc and ec2 modules. Although it would still probably need to do the 3 steps, create VPC, create VM, update VPC.
Although I do not know whether it’s considered ‘good practise’ to have an action_plugin call multiple modules.
I’m creating a vpc with public route tables, then I’m creating an auto scaling group to bring up my NAT boxes. However I need to add the routes from the private networks to the NAT boxes. I followed Scotts suggestion above, whilst this works the first time you run the playbook and it adds the routes, if you were to add an additional NAT box for redundancy you would need to rerun the ec2_vpc stepo again, at this point your private route from the previous step has been added and you get a dependency violation.
“msg”: “Unable to delete old route table rtb-28b8d64d, error: EC2ResponseError: 400 Bad Request\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\nDependencyViolationThe routeTable ‘rtb-28b8d64d’ has dependencies and cannot be deleted.8b33537f-522c-466b-9c3a-68f95f474c82”
The other option is to update the routes via a launch configuration but to do this you require the routes to exist first - so kind of a catch 22 situation.
How about adding separate NAT instance in the ASG per zone and making it default gw for the private subnets of that zone only? Each NAT instance will be created with instance role that will make it possible to query the ec2 service and find the private subnets in it's own AZ and create the routing table. The private subnets can be also tagged upon creation for easier discovery.
I’m creating a nat instance per asg per zone already. I’ve found a way to update the routes separately from the ec2_vpc, there is a pull request pending for this on github. The task is called ec2_vpc_route_table.py
Hello, there are new vpc related modules in the queue or in the devel branch already. vpc was split into
ec2_vpc_net => creates vpcs, dhcp options, etc
ec2_vpc_route_table => makes route tables
ec2_vpc_igw => igws
ec2_vpc_subnets
It would be super valuable if you guys could see if the problem is solvable with this breakout.
Also, there is a pull request I’ve made for boto3 connection support in module_utils/ec2.py which could help for any future AWS related modules.
I can confirm that by using ec2_vpc_route_table I’m able to update the routes to the private ip of the NAT instance created from my auto scaling group.
However the playbook can only be run once, on subsequent runs it fails with the same error I initially posted ‘Unable to delete the old route table…’ constraint violation etc etc.
If you’d like a copy of the playbook to test with I’m happy to share it with you.