# Terraform Workshop --- ## What is Terraform IaC (Infrastructure as Code) framework which enables programatic definition, deployment and management of infrastructure resources for cloud and on-premises in a declarative manner. It targets all major cloud platforms (GCP, AWS, Azure, DO etc.) --- ## Why do We Need it * Standardization of deployment to ensure a consistent state * Version control * Deploying an additional clone env for testing * Easier auditability to improve quality and security * Modular - reuse & ease of understanding * Resource Graph (dependency graph + parallel execution when possible) * Version control * Enables use of hardened deployment pipelines * Enables immutable infrastructure --- ## Human-Readible Configuration Language HashiCorp Configuration Language (HCL) or JSON ``` provider "aws" { region = "us-west-2" } resource "aws_instance" "example" { ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI ID instance_type = "t2.micro" tags = { Name = "HelloWorldEC2Instance" } } output "instance_public_ip" { value = aws_instance.example.public_ip } ``` --- # Workflow * Write your configuration file * Use `terraform init` to initialize a Terraform workspace * Use the the `terraform plan` action to simulate deployment of resources and assess the outcome * Use `terraform apply` to actually deploy resources --- # Exercise * Set up local credentials for your cloud platform of choice * Write a file that deploys an EC2 instance * Use `terraform plan` and `terraform apply` in order to deploy the resource * Remove the resource by using `terraform destroy` * Take advantage of terraform docs and providers: * https://registry.terraform.io/ * https://developer.hashicorp.com/terraform --- # Solution ``` # Specify the provider provider "aws" { region = "us-west-2" } # Create an EC2 instance resource "aws_instance" "my_ec2" { ami = "ami-03e383d33727f4804" instance_type = "t2.micro" tags = { Name = "TestEC2Instance" } } ``` --- # Extend Configuration * Add a VPC * Define security group that limits ingress and egress to port 22 * Add SSH key(s) which may connect to the instance --- # Solution ``` # Specify the provider provider "aws" { region = "us-west-2" } # Create a security group resource "aws_security_group" "allow_ssh" { name = "allow_ssh" description = "Allow SSH access" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_security_group" "default_egress" { name = "default_egress" description = "Specify egress for instance" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } # Specify the provider provider "aws" { region = "us-west-2" } # Create an EC2 instance resource "aws_instance" "my_ec2" { ami = "ami-03e383d33727f4804" instance_type = "t2.micro" security_groups = [ aws_security_group.allow_ssh.name, aws_security_grou.default_egress.name ] tags = { Name = "TestEC2Instance" } } ``` --- # Additional Notes * Typically the terraform state is stored online in a manner that makes it retrievable by others --- # SOPS for Secrets Management * Download from https://github.com/getsops/sops * Encrypt config file: `sops -e --pgp credentials > credentials.enc` * Decrypt and set: `eval $(sops -d credentials.enc | sed 's/: /=/g')`