Skip to content

Latest commit

 

History

History
243 lines (197 loc) · 10.7 KB

File metadata and controls

243 lines (197 loc) · 10.7 KB

Lesson 04 - Building an Ansible sandbox

We will use Terraform to stand up an environment to use Ansible from and on. The Ansible control node, which is where Ansible runs from, needs to be a Linux system with Python installed. We will create 3 target systems that we will configure using Ansible. Those systems will have the web server ports exposed to the public internet, but will otherwise only be accessible from the control node and other targets.

Using the Terraform code

The variables that need to be populated are listed in the documentation at the bottom of this file. This documentation is generated from the Terraform code itself using terraform-docs.

$ terraform-docs markdown table --output-file README.md --output-mode inject .
README.md updated successfully

Create the environment

Create terraform.tfvars:

aws_region       = "us-east-2"
owner_email      = "[email protected]"
key_name         = "gene-test-us-east-2"
private_key_file = "/home/ggotimer/.ssh/gene-test-us-east-2.pem"

Then we can use Terraform to create the environment. The remote_exec provisioner will make it take longer that we've seen.

$ terraform init
...

$ terraform apply
...
Outputs:

target_instance_ids = [
  "i-063e6e1b8ac71119d",
  "i-035125762cbce935d",
  "i-00fbe57ff4efea08a",
]
target_private_ips = [
  "10.8.0.10",
  "10.8.0.41",
  "10.8.0.178",
]
target_public_ips = [
  "18.117.70.148",
  "18.188.98.141",
  "18.116.43.247",
]
workstation_instance_id = "i-02890a16937a7af84"
workstation_private_ip = "10.8.0.26"
workstation_public_ip = "3.142.171.59"

Retrieving output values

We'll need to use these output values in this and later lessons. If the values scroll off the screen, we can use terraform output to extract them from the state file again. That means we have to run the commands in this directory so Terraform finds the right state, or we'll have to use the -state=path option to point to the correct terraform.tfstate file.

$ terraform output
target_instance_ids = [
  "i-063e6e1b8ac71119d",
  "i-035125762cbce935d",
  "i-00fbe57ff4efea08a",
]
target_private_ips = [
  "10.8.0.10",
  "10.8.0.41",
  "10.8.0.178",
]
target_public_ips = [
  "18.117.70.148",
  "18.188.98.141",
  "18.116.43.247",
]
workstation_instance_id = "i-02890a16937a7af84"
workstation_private_ip = "10.8.0.26"
workstation_public_ip = "3.142.171.59"

$ terraform output target_private_ips
[
  "10.8.0.10",
  "10.8.0.41",
  "10.8.0.178",
]

$ cd ..

$ terraform output -state=lesson-04/terraform.tfstate workstation_public_ip
"3.142.171.59"

Connect to the workstation

SSH into the Ansible workstation using the workstation_public_ip and the key file we specified. The username is ubuntu.

$ ssh -i /home/ggotimer/.ssh/gene-test-us-east-2.pem [email protected]
The authenticity of host '3.142.171.59 (3.142.171.59)' can't be established.
ED25519 key fingerprint is SHA256:s14sJUQRjUGCD5/9SE9SeVcfsV0f3qDocxrwrSPSMbM.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '3.142.171.59' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.19.0-1026-aws x86_64)
...
ubuntu@ip-10-8-0-26:~$

Verify Ansible is installed

On the Ansible workstation, we'll run our first Ansible command to verify it is installed correctly.

ubuntu@ip-10-8-0-26:~$ ansible localhost -m ping
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

If we get a pong back from our ping, then Ansible was able to log onto the target (localhost in this case) and run a command.

Leave the environment running

We'll leave the environment running for now since we'll be using it for the upcoming lessons. We can destroy it later (and recreate it again if we need to).

Why not local Ansible

It might be easier in a lot of ways if we used our laptop as our Ansible control node instead of creating a workstation in AWS and working remotely. But there are reasons we aren't doing that. Some of them are:

  1. Installing the correct version of Python is generally easy, but only if another version of Python isn't already installed.
  2. Set up and configuration on different OSes and platforms sometimes has subtle or non-subtle differences.
  3. Use of the command line (e.g., escaping special characters) differs between shells.
  4. It is safer to work in a sandbox as closed off from the public internet as possible, especially while we are learning.
  5. Using a system near the target network as a bastion host or workstation is not an uncommon pattern.
  6. SSH tunneling can be non-trivial to set up and troubleshoot, especially on multiple platforms and SSH clients.
  7. We aren't using this environment for an extended period.

So in the interest of simplifying the workshop, I chose to use a remote control node. It just makes for a smoother, more homogeneous workshop experience.

That said, we could do the rest of the exercises with some changes to the security groups on the targets, eliminating the workstation, and making sure Ansible is installed and configured correctly on our laptop. If you choose to go that route, caveat lector. The necessary changes are left as an exercise for the reader.

End of Lesson 04

In the next lesson, we'll start looking at some Ansible basics.

Terraform documentation

Requirements

Name Version
terraform >= 1.8.3
aws ~> 5.49.0

Providers

Name Version
aws 5.49.0

Modules

No modules.

Resources

Name Type
aws_default_security_group.default resource
aws_instance.target resource
aws_instance.workstation resource
aws_internet_gateway.sandbox_gateway resource
aws_route_table.rtb_public resource
aws_route_table_association.rta_subnet_public resource
aws_security_group.target_sg resource
aws_security_group.workstation_sg resource
aws_security_group_rule.target_sg_allow_all_outgoing resource
aws_security_group_rule.target_sg_allow_internal_mongodb resource
aws_security_group_rule.target_sg_allow_public_http resource
aws_security_group_rule.target_sg_allow_public_https resource
aws_security_group_rule.target_sg_allow_workstation_mongodb resource
aws_security_group_rule.target_sg_allow_workstation_ssh resource
aws_subnet.public_subnet resource
aws_vpc.sandbox_vpc resource
aws_ami.ubuntu_focal data source
aws_ami.ubuntu_jammy data source

Inputs

Name Description Type Default Required
aws_profile Local AWS profile to use for AWS credentials string "default" no
aws_region AWS region to build in string n/a yes
key_name Name of an already-installed AWS keypair string n/a yes
owner_email Email address to tag resources with string n/a yes
private_key_file Path to the private key of the already-installed AWS keypair string n/a yes
project_tag Project name to tag resources with for grouping string "IntroToTerraformAndAnsible" no

Outputs

Name Description
target_instance_ids IDs of the Ansible target instances
target_private_ips Private IP addresses of the Ansible targets
target_public_ips Public IP addresses of the Ansible targets
workstation_instance_id ID of the Ansible workstation instance
workstation_private_ip Private IP address of the Ansible workstation
workstation_public_ip Public IP address of the Ansible workstation