terraform-tofu-labs/2-simple-example/README.md

171 lines
7.1 KiB
Markdown
Raw Normal View History

2024-04-16 17:57:37 +00:00
## Introduction
2024-04-16 15:32:58 +00:00
Welcome to lab 2. You are going to find the code here very similar to lab 1, and thats by design, we'll build upon our experience and learn how to add variables and use environment files, so that you can reuse the code in say a deployment for dev, stage and prod. This is the power of IaC and prevents you having to rebuild everything from scratch.
2024-04-16 17:12:53 +00:00
Now I'll assume you have your AWS account and CloudShell setup already. If not please reffer to the lab 1 [README.md](../1-getting-started/README.md). Remeber i use the command tofu but if you've installed terraform instead you can swap the commands easily enough.
2024-04-16 15:32:58 +00:00
In this example we are going to do the same and deploy a VPC with subnets and an instance with a security group attached. What's different is that this time we'll use the ```user_data``` feature of EC2 to run apache and show you a running web server. In the ```main.tf``` file it differs in the ```aws_resource``` block of code to include the command to start apache.
```terraform
resource "aws_instance" "test_ami" {
ami = "ami-029b91ed285a24a90"
instance_type = "t4g.nano"
associate_public_ip_address = true
subnet_id = module.vpc.public_subnets[0]
vpc_security_group_ids = [aws_security_group.web_server_sg_tf.id]
user_data = <<-EOF
#!/bin/bash
sudo dnf install -y nginx
2024-04-16 16:12:40 +00:00
sudo systemctl enable nginx
sudo systemctl start nginx
2024-04-16 15:32:58 +00:00
EOF
}
```
I've also updated ```outputs.tf``` to show the public IP address of the instance we've deployed by adding this code block:
```terraform
# Public IP of instance
2024-04-16 15:34:31 +00:00
output "instance_public_ip" {
2024-04-16 15:32:58 +00:00
description = "Show the public IP of the instance deployed"
value = aws_instance.test_ami.public_ip
}
```
#### Create a Stack
Once again lets deploy the stack before editing it:
```bash
cd 2-simple-example/code
tofu init
tofu plan
tofu apply
```
Answer yes at the apply prompt and you should end up with a screen like this:
![Tofu apply output](./img/lab-2-tofu-apply.png)
Embedded in there you'll see something liek this ```instance_public_ip``` thats out new output, copy the value and head to ```http://<YOUT_VALUE>/``` and you should get a very similar looking default nginx page.
![Default nginx page](./img/webpage.png)
(I'm of course in dark mode, don't worry if yours is white with black text!)
2024-04-16 16:12:40 +00:00
Right we now have our basic stack to work with. Everything else we do will be to update this stack, so **don't destroy** it just yet
#### Introducing variables
2024-04-16 17:12:53 +00:00
Right this is great and all but what if we want to make it easy to change things, such as the ami_id we are deploying or the size of the instance we are running so we have more CPU and RAM. This is where variables make it easy, and as an added advantage we can create variable files for different environments with different values in them to override the defaults.
2024-04-16 16:12:40 +00:00
2024-04-16 17:12:53 +00:00
> [!Note]
> For this next bit you can use your favourite command line editor to alter the files in CloudShell, vim and nano are installed by deafult, I use vim so if you copy the examples you'll need to press ```i``` after opening the files to go into insert mode and when you want to save and exit the file press ```ESC``` and type ```:wq``` to exit.
2024-04-16 17:12:53 +00:00
Right lets add new variables for both the **ami_id** and **instance_size**, start by opening variables.tf in the code directory from CloudShell:
2024-04-14 16:03:51 +00:00
2024-04-16 17:12:53 +00:00
```bash
vi variables.tf
```
Scroll to the bottom of the file and press ```i``` for insert then add the following:
```terraform
variable "instance_size" {
description = "Size of the instance to run"
type = string
default = "t4g.nano"
}
variable "ami_id" {
description = "Instance Amazon Machine Image to run"
type = string
default = "ami-029b91ed285a24a90"
}
```
Save that file and exit press ```ESC``` and type ```:wq``` to exit (last tiem I'll remind you). Now you've set up terraform/tofu to understand the ```intsance_size``` and ```ami_id``` are variables and we've also given them default values. If you didn't use a dfault in this file when you run apply you'd get prompted to enter the details.
Right now terraform/tofu knows about the variables lets use them. Open up ```main.tf``` ready for editing:
```bash
vi main.tf
```
Scroll down to the code block called **resource "aws_instance" "test_ami"** and edit the following lines:
```terraform
ami = "ami-029b91ed285a24a90"
instance_type = "t4g.nano"
```
you want them to look like this:
```terraform
ami = var.ami_id
instance_type = var.instance_size
```
Now you're ready, it really was that easy. However, if you went and ran ```tofu plan``` right now you'd see that nothing has changed in the stack because our defaults we set on ```variables.tf``` have the same values as before.
![No changes dialog](./img/no-changes.png)
#### Using tfvars
So lets look how to override those settings. In this example we are going to alter both the ```ami_id``` and the ```instance_size``` to something more production ready. Let's use a Redhat AMI rather than Amazon Linux and a larger instance maybe a t4g.small rather than the t4g.nano. Create a new folder called ```env``` and a new file inside it called ```prod.tfvars```
2024-04-14 16:03:51 +00:00
2024-04-16 17:12:53 +00:00
```bash
mkdir env
vi env/prod.tfvars
```
Lets populate it with some new values:
```terraform
ami_id = "ami-01d28a73af0a85125"
instance_size = "t4g.small"
```
Save and quit the file and we are ready to use it! Let's start by running ```tofu plan``` but we are going to add the argument ```--var-file=``` and point it to our file we just created ```env/prod.tfvars```
```bash
tofu plan --var-file=env/prod.tfvars
```
You'll see theres things to be changed now.
![changes to the stack](./img/changes.png)
So let's go ahead and apply that, once again adding our new argument:
```bash
tofu apply --var-file=env/prod.tfvars
```
Remeber to type **yes** at the prompt, you'll see terraform/tofu destroy the old instance and bring up a new one:
![Destroying and instance](./img/destroying.png)
You'll finally land back at the command prompt. At this point I encourage you to go tot he AWS console and open **EC2 > Instances** you should see something liek this happening, which shows a terminated old instance and a new one either fully booted or initializing.
![Instances swapped over in the console](./img/new-instance.png)
There we have it a brand new instance this time running RedHat Linux, it'll also have a new public IP address to view in your web browser. You could go on and update again, adding in aditional arguments to any of the resources we've created. We could use a ```envirnment``` variable for instance to call the VPC a different name and label the instance according to what environment it's running in. You could go ahead and have a plan at this point and create another tfvars file such as ```env/stage.tfvars``` and have different values in there.
#### Clean up
Don't forget to terminate the resources running in this lab. Run the following:
```bash
tofu destroy
```
2024-04-14 16:03:51 +00:00
2024-04-16 17:12:53 +00:00
### Recap
2024-04-14 16:03:51 +00:00
2024-04-16 17:12:53 +00:00
What we've done in this lab is learn how to:
2024-04-14 16:03:51 +00:00
2024-04-16 17:12:53 +00:00
- create variables
- use variables in out HCL code
- create a tfvars file
- specify the tvfars file onthe command line
- update a running stack