Slide 1

Slide 1 text

DRY deployments with Terragrunt Vítor Brandão PHPSW, June 2022

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Not really about PHP ! [ angry elephant noises ]

Slide 4

Slide 4 text

Code is up in the sky

Slide 5

Slide 5 text

Infrastructure as Code · Terraform is an open source "Infrastructure as Code" tool, created by HashiCorp. · The Terraform language (HCL) is declarative, describing an intended goal rather than the steps to reach that goal. · Terraform providers are plugins that implement resource types typically in a public cloud provider. · The infrastructure provisioned is considered immutable (avoids configuration dri ).

Slide 6

Slide 6 text

Scenario: WordPress on Amazon ECS

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Terraform modules Terraform modules are small, reusable Terraform configurations for multiple infrastructure resources that are used together. ❯ modules/ !"" networking !"" website-db #"" website-ecs ❯ modules/website-ecs/ !"" ecs.tf !"" load-balancer.tf !"" locals.tf !"" outputs.tf #"" variables.tf

Slide 9

Slide 9 text

modules/website-ecs/ecs.tf resource "aws_ecs_task_definition" "my_website" { family = local.project_name network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] memory = 1024 container_definitions = jsonencode([ { name = "my-wordpress-website" image = "123456789.dkr.ecr.eu-west-2.amazonaws.com/my-wordpress-website-fpm:latest" environment = [ { name = "WORDPRESS_DB_HOST", value = var.db_endpoint }, { name = "WORDPRESS_DB_NAME", value = var.db_name }, ... }

Slide 10

Slide 10 text

Terraform "components" Think of a module as a PHP class declaration and a component as instantiating that class. ❯ live/prod !"" networking #"" website ❯ live/prod/website !"" backend.tf !"" datasource.tf !"" main.tf !"" outputs.tf !"" providers.tf #"" variables.tf

Slide 11

Slide 11 text

live/production/website/main.tf module "database" { source = "./modules/website-db" vpc_id = data.terraform_remote_state.networking.outputs.vpc_id subnets_id = data.terraform_remote_state.networking.outputs.subnet_id db_name = "wordpress" db_username = "wordpress" } module "ecs" { source = "./modules/website-ecs" vpc_id = data.terraform_remote_state.networking.outputs.vpc_id subnets_id = data.terraform_remote_state.networking.outputs.subnet_id db_endpoint = module.database.db_endpoint db_name = module.database.db_name db_username = module.database.db_username }

Slide 12

Slide 12 text

Required Terraform configuration live/production/website/ backend.tf terraform { backend "s3" { bucket = "my-project-tfstate" region = "eu-west-2" key = "website.tfstate" encrypt = "true" dynamodb_table = "prod-tflock" acl = "bucket-owner-full-control" } } live/production/website/ providers.tf terraform { required_version = "= 1.2.2" required_providers { aws = { version = "~> 4.17" source = "hashicorp/aws" } external = { version = "~> 2.2" source = "hashicorp/external" } } } provider "aws" { region = "eu-west-2" }

Slide 13

Slide 13 text

Environments, the more the merrier messier ❯ live/ !"" dev # !"" networking # $"" website !"" prod # !"" networking # $"" website $"" qa !"" networking $"" website ❯ live/ !"" dev # !"" networking/... # $"" website # !"" backend.tf # !"" datasource.tf # !"" main.tf # !"" outputs.tf # !"" providers.tf # $"" variables.tf !"" prod # !"" networking/... # $"" website # !"" backend.tf # !"" datasource.tf # !"" main.tf # !"" outputs.tf # !"" providers.tf # $"" variables.tf $"" qa !"" networking/... $"" website !"" backend.tf !"" datsource.tf !"" main.tf !"" outputs.tf !"" providers.tf $"" variables.tf

Slide 14

Slide 14 text

Keeping it DRY with Terragrunt · Define Terraform code once, no matter how many environments you have · Gets rid of duplicated backend code · Defines how to manage the Terraform state once in a root directory and inherits it in all child modules.

Slide 15

Slide 15 text

With Terragrunt ❯ live/ !"" dev # !"" networking/... # !"" website-db/... # $"" website-ecs # $"" terragrunt.hcl !"" prod # !"" networking/... # !"" website-db/... # $"" website-ecs # $"" terragrunt.hcl !"" qa # !"" networking/... # !"" website-db/... # $"" website-ecs # $"" terragrunt.hcl $"" terragrunt.hcl

Slide 16

Slide 16 text

website-ecs/terragrunt.hcl terraform { source = "../../../modules//website-ecs" } include { path = find_in_parent_folders("terragrunt.hcl") } dependency "networking" { config_path = "../networking" } dependency "website_db" { config_path = "../website-db" } inputs = { subnet_ids = dependency.networking.outputs.private_subnet_ids vpc_id = dependency.networking.outputs.vpc_id db_name = dependency.website_db.outputs.db_database_name db_endpoint = dependency.website_db.outputs.db_instance_endpoint db_username = dependency.website_db.outputs.db_instance_username }

Slide 17

Slide 17 text

Benefits of using Terragrunt · Gets rid of repeated Terraform config (backend, providers, etc.) · Environment variables support (variables can be populated programmatically) · Automatic resource tagging (applies metadata universally) · Able to execute custom code before or a er running Terraform (before & a er hooks) · Explicit dependencies ("dependency injection") · Makes testing easier (see Terratest)

Slide 18

Slide 18 text

Resources · https://www.terraform.io/ · https://github.com/terraform-aws-modules · https://terragrunt.gruntwork.io/ · https://transcend.io/blog/why-we-use-terragrunt/ · https://github.com/gruntwork-io/terragrunt-infrastructure- live-example · https://terratest.gruntwork.io/

Slide 19

Slide 19 text

DRY deployments with Terragrunt Thank you! Talk feedback: https://joind.in/talk/2b840/