Ansible to a private VPC

Almost a year of changes and hectic! My last company didn't do well as a startup so I got a chaos time to find a new job within 60 days. Anyway, I'm seating here and writing this short update means I have overcome my challenger.

So, what do we have today after a long break, a short tip on how to use Ansible to a private VPC (Virtual Private Cloud). A side note, as I am working for a Cloud provider so most of my updates from now will involve to Cloud solution. I also mentioned before that I'm creating a GitHub repository for the sourcecode sample so this will be in a project of moving this site into Medium where most of the technical blogs allocated.

What is the main talk today? When you want to create an environment in AWS, obviously, almost the whole environment will be in a private subnet within a VPC, so how you will run the configuration without using OpsWork or from your local machine? You have to be in that VPC route by:

  • Create a bastion in public subnet of that VPC.
  • Option 1: run your Ansible control on that bastion.
  • Option 2: use that bastion as Proxy forwarder from your local machine.
So I will discuss in detail on option 2 because option 1 is like building an open gate with on-premise machine.


Let's get your hands dirty!

Pre-requisite:
  • Create a VPC with private subnet for the back-end environment and public subnet for the front-end and bastion host. For example, your VPC cidr is: 10.70.0.0/16
  • Create a system Keypair to access into your compute, for example: admin_infrastructure (download 'admin_infrastructure.pem' to your local machine)
  • Allow traffic flows by, create a Security Group (for the bastion) to allow ingress from the whole VPC, 10.70.0.0/16 (make sure the bastion can communicate to all computes within the VPC, you can fine grain the traffic bases on your need) and allow ingress from your local IP via internet (use 'what is my ip address' in google search, make sure turn off any VPN to get the IP to avoid split tunneling on your VPN that blocks the traffic to your VPC)
  • Create an EC2 in your public subnet as a bastion host (nothing special, just an EC2) and copy the private key into this machine (/Users/ubuntu/.ssh) to let it connect to other computes and use the Security Group above. Make sure you have a proper IAM role/instance profile if you need your bastion to communicate to any other AWS services. Your bastion must have a public IP, for example: 12.34.56.78.
  • Assuming that you have couple machines within your private subnet with private IPs such as 10.70.0.1, 10.70.0.2 ...
You can create those resources by CloudFormation or Terraform, as we won't use AWS tools so Terraform should be the case.

Note: my habit of using Ubuntu so I will use Ubuntu LTS 18.04 instead of Amazon Linux 2, the system user will be 'ubuntu' instead of 'ec2-user'.

So now, let connect to a private machine 10.70.0.1 via your bastion 12.34.56.78 via this command (make sure you can connect to your bastion via public IP first to confirm the SG ingress rule is fine)

ssh -i admin_infrastruture.pem  ubuntu@10.70.0.1 -o "proxycommand ssh -W %h:%p -i admin_infrastruture.pem ubuntu@12.34.56.78"

Then, let's generalize the ssh config to point into any of your machines/hosts in your VPC (10.70.*.*), open ~/.ssh/config add the host definitions

Host bastion
    Hostname 12.34.56.78
    User ubuntu
    IdentityFile ~/.ssh/admin_infrastructure.pem
    ControlMaster auto
    ControlPath ~/.ssh/ansible-%r@%h:%p
    ControlPersist 5m

Host 10.70.*.*
    IdentityFile ~/.ssh/admin_infrastructure.pem
    User ubuntu
    ProxyCommand ssh -W %h:%p ubuntu@bastion

Voila, now your local machine can ssh directly into any of your private hosts via the private IPs. The last 3 lines of the bastion config are for the Ansible, so now, you should add the ssh configuration for your Ansible, open ansible.cfg in your installation or add new file (ansible.cfg) into your Ansible workspace with the content below

[ssh_connection]
ssh_args = -F /Users/<your_user>/.ssh/config -o ControlMaster=auto -o ControlPersist=30m
control_path = ~/.ssh/ansible-%%r@%%h:%%p

Alright, you can test from here as I can make it run quite smooth.

Another tip that you can also use ssh port forwarding via the bastion (I haven't tried to shorten it with the defined bastion host), for example: the private machine 10.70.0.1 has host a web application at port 8888 then you can port forwarding to your local machine at port 8888 via ssh with this command

ssh -i admin_infrastructure.pem -N -L 8888:10.70.0.1:8888 ubuntu@12.34.56.78

Then from your local machine, you can open browser and browse for the application on your private machine with localhost.

OK! That's for now, hope you still find my blog is useful! See you next time!

Comments