There is no cloud. It's just someone else's computer.
Use Terraform to automatically launch and configure Amazon EC2 resources. Each box
includes its own:
- EC2 instance to run programs
- keypair to allow remote SSH login
- security group to control network access
- CloudWatch log group to store and read log messages
- IAM role, policy, and profile to authorize use of other AWS resources
- cloud-init template to configure logs, install software, and run a script
The test module launches example free-tier Ubuntu boxes:
| box name | script language | what it does |
|---|---|---|
| dorothy | ruby | print timestamped messages |
| leeroy | bash | print a message, then crash |
- Create a new repo from this template.
- Open a terminal and
cdto this folder.
Terraform needs access to AWS security credentials. These can be hard-coded in .tf files, but storing secrets in code can be dangerous. It is safer to use environment variables:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEYor credentials files in the user's home folder:
~/.aws/config
~/.aws/credentials- Run
bin/keygento generate a keypair.
The private and public keys will be saved here:
etc/ec2box_rsa
etc/ec2box_rsa.pubWhen a new box is created, or the public key changes, Terraform will upload a copy of the public key to AWS. Anyone with both keys (public and private) can then login remotely to each box with SSH.
Caution: The private key in the ec2box_rsa file must be kept secret. This repo gitignores it.
- Edit terraform.tfvars to choose an AWS profile and AWS region.
- Run
bin/up testto launch all example boxes.
Terraform will save state files when the test module is initialized:
terraform.tfstate
terraform.tfstate.backupCaution: State files (including remote state) can contain secrets! This repo gitignores them.
- Run
bin/loginto login to a box remotely with SSH.
Usually, remote login is unnecessary because boxes can be monitored by reading log messages. Each box creates its own CloudWatch log group and streams logs to it. The pipeline works like this:
- cloud-init downloads, installs, configures, and starts an AWS CloudWatch agent.
- The agent creates a log stream and begins streaming from
/var/log/syslog. - The launch script prints errors to STDERR and all other messages to STDOUT.
- The shell redirects STDERR and STDOUT to the Ubuntu logger.
- The logger saves logs to
/var/log/syslog.
Cloud-init, system, and launch script logs will then be visible in the AWS CloudWatch console.
- Run
bin/down testto destroy all example resources.
Configuration files for the Terraform root module:
- main.tf declares AWS resources to acquire.
- outputs.tf declares outputs to return to other modules.
- variables.tf declares required inputs and their default values.
- terraform.tfvars file sets root module variables.
Short scripts to run Terraform commands:
bin/clean [FOLDER]autoformats and validates Terraform code.bin/down [FOLDER]destroys all resources declared in a folder.bin/keygengenerates and saves an RSA keypair to theetcfolder.bin/login [BOXNAME]uses SSH to login to an EC2 instance remotely.bin/up [FOLDER]creates or updates all resources declared in a folder.
Default configuration files for each newly-created box:
ec2box_rsais an RSA private key.ec2box_rsa.pubis an RSA public key.installis a script which installs software.launchruns in the background when a box is ready to use.policy.jsonis an IAM policy which grants AWS permissions to a box.templateis a template file for a cloud-init script.
Example resources for testing ec2box:
main.tfdeclares boxes to be created byterraform apply test.outputs.tfdeclares outputs to be shown byterraform output.variables.tfdeclares inputs to be read from terraform.tfvars.
Configuration files for a test box named dorothy which prints timestamped messages every 1 second.
- AWS credentials
- Terraform >= 0.12
- OpenSSH to run
bin/keygenandbin/login - jq to run
bin/login
Create or update all test boxes. (Terraform will prompt for confirmation.)
> bin/up
Initialize and update test resources
Initializing modules...
...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
...Remote login to dorothy via SSH. (You might need to confirm the host public key.)
> bin/login dorothy
SSH into dorothy at [email protected]
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-1051-aws x86_64)
...
ubuntu@ip-123-45-67-89:~$
Use SSH to run the launch script on the leeroy box again:
> bin/login leeroy '~/launch'
SSH into leeroy at [email protected]
LEEROOOOOOOOOOOOOOOOOOOOOOOY JENKINSDestroy all test boxes. (Terraform will prompt for confirmation.)
Destroy all Terraform-managed resources in test
...
Destroy complete! Resources: 14 destroyed.
Edit the test folder. Rename it if you want to.
Do I need to use remote state?
No, but it's usually safer than keeping local state files on one person's laptop.
See the dorothy box in test/main.tf for an example.
Here are some common methods:
- Upload code to a private S3 bucket and aws s3 sync it to a box.
- Use deploy keys to pull from a private GitHub repository.
- Use AWS CodeDeploy for everything.
To deploy code automatically when a box is created, edit its install script.
- Terraform docs
- Terraform AWS provider docs
- Terraform AWS example modules
