terraform-101

Terraform 101

logo

Documentação

cursos

Generate apresentation

rm -rf presentation.html; \
docker run -v $PWD:/src afonsoaugusto/markdown-to-slides README.md -d -o presentation.html; \
sudo chown :$USER presentation.html

Agenda

Fundamentos de IaC

Infrastructure as Code

Infraestrutura como código (em inglês: infrastructure as code, ou IaC) é o processo de gerenciamento e provisionamento de centros de processamentos dados usando arquivos de configuração ao invés de configurações físicas de hardware ou ferramentas de configuração interativas.

IaC

IaC

Dry - Don’t repeat yourself

Quando dizemos “como código”, queremos dizer que todas as boas práticas que aprendemos no mundo do software devem ser aplicadas à infraestrutura.

Uso do controle de versão, adesão ao princípio DRY, modularização, manutenção e uso de testes e implantação automatizados são práticas fundamentais.

Casos de Uso

Terraform

Intro

Terraform é uma ferramenta open source de provisionamento de infraestrutura, criada pela HashiCorp, que permite que definamos nossa infraestrutura como código(IaC), usando uma linguagem simples e declarativa.

O terraform é desenvolvido em GO e é openSource

Terraform-flow

Terraform

Arquivos

Terraform Basics

Variables

Variaveis são parametros para um modulo de Terraform, permitem que aspectos da implementação seja customizado sem que seu codigo seja alterado.

Temos 3 tipos de uso de variaveis:

Declarando uma variavel de input

variable "image_id" {
  type = string
}
variable "availability_zone_names" {
  type    = list(string)
  default = ["us-west-1a"]
}
variable "docker_ports" {
  type = list(object({
    internal = number
    external = number
    protocol = string
  }))
  default = [
    {
      internal = 8300
      external = 8300
      protocol = "tcp"
    }
  ]
}
variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."
}
variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."

  validation {
    condition     = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
  }
}

Precedencia de carregamento

Locals

Um Local é um valor que recebe um nome a partir de uma expressão ou valor.

locals {
  # Ids for multiple sets of EC2 instances, merged together
  instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)
}

locals {
  # Common tags to be assigned to all resources
  common_tags = {
    Service = local.service_name
    Owner   = local.owner
  }
}

Output

Output é uma forma de expor o valor, seja como retorno de um modulo ou imprimindo como retorno do root.

output "instance_ip_addr" {
  value = aws_instance.server.private_ip
}
output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."
}
output "db_password" {
  value       = aws_db_instance.db.password
  description = "The password for logging in to the database."
  sensitive   = true
}
output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."

  depends_on = [
    # Security group rule must be created before this IP address could
    # actually be used, otherwise the services will be unreachable.
    aws_security_group_rule.local_access,
  ]
}

Type Constraints

São os tipos que as variaveis podem receber como argumentos na declaração.

Simples

Complexos

Functions

Principais funções

Format

format(spec, values...)

> format("Hello, %s!", "Ander")
Hello, Ander!
> format("There are %d lights", 4)
There are 4 lights
> format("Hello, %s!", var.name)
Hello, Valentina!
> "Hello, ${var.name}!"
Hello, Valentina!
Join

join(separator, list)

> join(", ", ["foo", "bar", "baz"])
foo, bar, baz
> join(", ", ["foo"])
foo
Split

split(separator, string)

> split(",", "foo,bar,baz")
[
  "foo",
  "bar",
  "baz",
]
> split(",", "foo")
[
  "foo",
]
> split(",", "")
[
  "",
]
Upper, lower, title
> upper("hello")
HELLO
> upper("алло!")
АЛЛО!
> lower("HELLO")
hello
> lower("АЛЛО!")
алло!
> title("hello world")
Hello World
Element Index

element(list, index)

> element(["a", "b", "c"], 1)
b

index(list, value)

> index(["a", "b", "c"], "b")
1
Map
> map("a", "b", "c", "d")
{
  "a" = "b"
  "c" = "d"
}
> {"a" = "b", "c" = "d"}
{
  "a" = "b"
  "c" = "d"
}
File

file(path)

> file("${path.module}/hello.txt")
Hello World

Providers

É a estrutura resposavel por comunicar com a API da estrutura desejada.

# The default provider configuration; resources that begin with `aws_` will use
# it as the default, and it can be referenced as `aws`.
provider "aws" {
  region = "us-east-1"
}

# Additional provider configuration for west coast region; resources can
# reference this as `aws.west`.
provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

Principais que nós utilizamos

Resources

Item mais importante do Terraform, ele informa o recurso que será criado/gerenciado.

resource "aws_instance" "web" {
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
}

Dynamic Blocks

resource "aws_elastic_beanstalk_environment" "tfenvtest" {
  name = "tf-test-name" # can use expressions here

  setting {
    # but the "setting" block is always a literal block
  }
}
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
  name                = "tf-test-name"
  application         = "${aws_elastic_beanstalk_application.tftest.name}"
  solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"

  dynamic "setting" {
    for_each = var.settings
    content {
      namespace = setting.value["namespace"]
      name = setting.value["name"]
      value = setting.value["value"]
    }
  }
}

Best Practices for dynamic Blocks

Overuse of dynamic blocks can make configuration hard to read and maintain, so we recommend using them only when you need to hide details in order to build a clean user interface for a re-usable module. Always write nested blocks out literally where possible.

Data Sources

Data recupera informações de recursos já criados no ambiente sem precisar de gerenciar o mesmo. Ou seja, sem precisar de importar o recurso e gerenciar ele.

data "aws_ami" "example" {
  most_recent = true

  owners = ["self"]
  tags = {
    Name   = "app-server"
    Tested = "true"
  }
}

Modulos

É como uma abstração de um conjunto de recursos para reaproveitamento do mesmo.

module "servers" {
  source = "./app-cluster"

  servers = 5
}

Workspaces

workspaces

Backend - TFSTATE

Terraform Best Pratices

Modulos para analise

Perguntas