Fundamentos do Terraform (part. 1)

26/09/2024

Nos últimos anos, a infraestrutura como código (IaC) tornou-se uma ferramenta essencial para profissionais de TI que buscam agilidade, eficiência e escalabilidade em seus projetos. Nesse cenário, o Terraform se destaca como uma das principais ferramentas para provisionamento e gerenciamento de infraestrutura em nuvem, permitindo que você defina, versione e controle ambientes complexos de forma declarativa.

Este artigo será o primeiro de uma série dedicada ao Terraform e seus componentes. Ao longo dessa jornada, vamos explorar desde os conceitos fundamentais, como providers, recursos e módulos, até práticas avançadas para criação de arquiteturas escaláveis e reutilizáveis. Se você é um profissional que está começando no mundo da infraestrutura como código ou alguém que deseja aprofundar seus conhecimentos em Terraform, esta série foi feita para você.

Nesta primeira parte, vamos abordar o que é o Terraform, suas principais características, a composição da sua arquitetura e os componentes essenciais, como o backend, o statefile e os providers. Vamos entender como cada um desses elementos contribui para a construção e o gerenciamento eficiente da infraestrutura, estabelecendo uma base sólida para avançarmos nas próximas etapas da série.

Terraform, what’s this?

Terraform é uma ferramenta de infraestrutura como código (IaC) criada pela Hashicorp, que permite criar, gerenciar e provisionar recursos de infraestrutura cloud ou on-premises de maneira automatizada e consistente.
Uma ferramenta para programação declarativa que usa uma linguagem de alto nível chamada HCL (Hashicorp Configuration Language) e pode gerenciar tanto componentes de baixo nível (ex:. storage), quanto componentes de alto nível (ex:. SaaS).

Principais características do Terraform

  • Não há necessidade de instalar uma aplicação, além do binário do Terraform
  • Os arquivos do terraform possuem a extensão .tf
  • Os plugins são baixados depois da inicialização do Terraform na pasta .terraform, de acordo com as configurações
  • Armazena todos os estados do provisionamento da infraestrutura e qualquer modificação que seja sinalizada ao aplicar os códigos em Terraform

Composição da arquitetura Terraform

O Terraform Core analisa as configurações e estabelece as dependências entre os recursos.
Os Providers do Terraform servem como intermediários entre o Terraform Core e as APIs correspondentes.

Terraform Components

Backend

O backend é uma configuração do Terraform que indica onde o statefile será armazenado. Existem maneiras de armazenar o state file, e a escolha vai depender das necessidades e requisitos do projeto.

  • Local (padrão): O estado é armazenado localmente no sistema de arquivos do computador em que o Terraform está sendo executado. No entanto, isso não é recomendado para ambientes de produção ou colaborativos, pois pode levar a problemas de sincronização e segurança.
  • Remoto: O estado pode ser armazenado remotamente em um backend, como Amazon S3, Azure Storage, Google Cloud Storage, ou outros. Isso é altamente recomendado para ambientes de produção e equipes colaborativas, pois oferece benefícios como controle de acesso mais granular, capacidade de trabalho colaborativo e maior segurança.

Exemplo de configuração do backend:

backend.tf
terraform {
  backend "s3" {
    bucket         = "s3-bucket-name"
    key            = "path/to/terraform.tfstate"
    region         = "region-aws"
    encrypt        = true
  }
}
HCL

Statefile

O estado do Terraform refere-se a um arquivo que rastreia as informações sobre os recursos provisionados, suas configurações e dependências entre eles. Esse arquivo de estado é fundamental para o Terraform entender o estado atual da infraestrutura e determinar quais alterações são necessárias para atingir o estado desejado.
O statefile é essencial para o Terraform por várias finalidades:

Exemplo de um statefile:

Terraform.tfstate
{
    "version": 1,
    "serial": 7,
    "modules": [
        {
            "path": [
                "root"
            ],
            "outputs": {},
            "resources": {
                "aws_route53_record.site": {
                    "type": "aws_route53_record",
                    "depends_on": [
                        "aws_route53_zone.primary",
                        "aws_s3_bucket.site",
                        "aws_s3_bucket.site"
                    ],
                    "primary": {
                        "id": "Z2OIQETM3FU6D_mikeball.me_A",
                        "attributes": {
                            "alias.#": "1",
                            "alias.701075612.evaluate_target_health": "false",
                            "alias.701075612.name": "s3-website-us-west-2.amazonaws.com",
                            "alias.701075612.zone_id": "Z3BJ6K6RIION7M",
                            "failover": "",
                            "fqdn": "mikeball.me",
                            "health_check_id": "",
                            "id": "Z2OIQETM3FU6D_mikeball.me_A",
                            "name": "mikeball.me",
                            "records.#": "0",
                            "set_identifier": "",
                            "ttl": "0",
                            "type": "A",
                            "weight": "-1",
                            "zone_id": "Z2OIQETM3FU6D"
                        }
                    }
                },
                "aws_route53_zone.primary": {
                    "type": "aws_route53_zone",
                    "primary": {
                        "id": "Z2OIQETM3FU6D",
                        "attributes": {
                            "comment": "Managed by Terraform",
                            "id": "Z2OIQETM3FU6D",
                            "name": "mikeball.me",
                            "name_servers.#": "4",
                            "name_servers.0": "ns-1181.awsdns-19.org",
                            "name_servers.1": "ns-1981.awsdns-55.co.uk",
                            "name_servers.2": "ns-416.awsdns-52.com",
                            "name_servers.3": "ns-969.awsdns-57.net",
                            "tags.#": "0",
                            "zone_id": "Z2OIQETM3FU6D"
                        }
                    }
                },
                "aws_s3_bucket.site": {
                    "type": "aws_s3_bucket",
                    "primary": {
                        "id": "mikeball.me",
                        "attributes": {
                            "acl": "public-read",
                            "arn": "arn:aws:s3:::mikeball.me",
                            "bucket": "mikeball.me",
                            "cors_rule.#": "0",
                            "force_destroy": "false",
                            "hosted_zone_id": "Z3BJ6K6RIION7M",
                            "id": "mikeball.me",
                            "policy": "{\"Statement\":[{\"Action\":\"s3:GetObject\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::mikeball.me/*\",\"Sid\":\"PublicReadForGetBucketObjects\"}],\"Version\":\"2012-10-17\"}",
                            "region": "us-west-2",
                            "tags.#": "0",
                            "website.#": "1",
                            "website.0.error_document": "error.html",
                            "website.0.index_document": "index.html",
                            "website.0.redirect_all_requests_to": "",
                            "website.0.routing_rules": "",
                            "website_domain": "s3-website-us-west-2.amazonaws.com",
                            "website_endpoint": "mikeball.me.s3-website-us-west-2.amazonaws.com"
                        }
                    }
                },
                "aws_s3_bucket.wwwsite": {
                    "type": "aws_s3_bucket",
                    "primary": {
                        "id": "www.mikeball.me",
                        "attributes": {
                            "acl": "public-read",
                            "arn": "arn:aws:s3:::www.mikeball.me",
                            "bucket": "www.mikeball.me",
                            "cors_rule.#": "0",
                            "force_destroy": "false",
                            "hosted_zone_id": "Z3BJ6K6RIION7M",
                            "id": "www.mikeball.me",
                            "policy": "",
                            "region": "us-west-2",
                            "tags.#": "0",
                            "website.#": "1",
                            "website.0.error_document": "",
                            "website.0.index_document": "",
                            "website.0.redirect_all_requests_to": "mikeball.me",
                            "website.0.routing_rules": "",
                            "website_domain": "s3-website-us-west-2.amazonaws.com",
                            "website_endpoint": "www.mikeball.me.s3-website-us-west-2.amazonaws.com"
                        }
                    }
                },
                "aws_s3_bucket_object.css_file": {
                    "type": "aws_s3_bucket_object",
                    "depends_on": [
                        "aws_s3_bucket.site"
                    ],
                    "primary": {
                        "id": "assets/stylesheets/application.css",
                        "attributes": {
                            "bucket": "mikeball.me",
                            "cache_control": "",
                            "content_disposition": "",
                            "content_encoding": "",
                            "content_language": "",
                            "content_type": "text/css",
                            "etag": "cbb4dfe4ff59c374f4d131f6f043e27e",
                            "id": "assets/stylesheets/application.css",
                            "key": "assets/stylesheets/application.css",
                            "kms_key_id": "",
                            "source": "../dist/assets/stylesheets/application.css",
                            "version_id": ""
                        }
                    }
                },
                "aws_s3_bucket_object.error_file": {
                    "type": "aws_s3_bucket_object",
                    "depends_on": [
                        "aws_s3_bucket.site"
                    ],
                    "primary": {
                        "id": "error.html",
                        "attributes": {
                            "bucket": "mikeball.me",
                            "cache_control": "",
                            "content_disposition": "",
                            "content_encoding": "",
                            "content_language": "",
                            "content_type": "text/html",
                            "etag": "eb0465ae8b8f01547a8c3aa3d2911e8f",
                            "id": "error.html",
                            "key": "error.html",
                            "kms_key_id": "",
                            "source": "../dist/error.html",
                            "version_id": ""
                        }
                    }
                },
                "aws_s3_bucket_object.image_file": {
                    "type": "aws_s3_bucket_object",
                    "depends_on": [
                        "aws_s3_bucket.site"
                    ],
                    "primary": {
                        "id": "assets/images/scape_long.png",
                        "attributes": {
                            "bucket": "mikeball.me",
                            "cache_control": "",
                            "content_disposition": "",
                            "content_encoding": "",
                            "content_language": "",
                            "content_type": "image/png",
                            "etag": "7db796890894376b0c20a1265e776ab8",
                            "id": "assets/images/scape_long.png",
                            "key": "assets/images/scape_long.png",
                            "kms_key_id": "",
                            "source": "../dist/assets/images/scape_long.png",
                            "version_id": ""
                        }
                    }
                },
                "aws_s3_bucket_object.index_file": {
                    "type": "aws_s3_bucket_object",
                    "depends_on": [
                        "aws_s3_bucket.site"
                    ],
                    "primary": {
                        "id": "index.html",
                        "attributes": {
                            "bucket": "mikeball.me",
                            "cache_control": "",
                            "content_disposition": "",
                            "content_encoding": "",
                            "content_language": "",
                            "content_type": "text/html",
                            "etag": "c8b17d8fb9bb3663ba4543d3aea43112",
                            "id": "index.html",
                            "key": "index.html",
                            "kms_key_id": "",
                            "source": "../dist/index.html",
                            "version_id": ""
                        }
                    }
                }
            }
        }
    ]
}
HCL

Provider

Terraform Providers são plugins utilizados para interagir e se conectar com um provedor de serviços ou recursos, como provedores de nuvem, provedores de armazenamento, provedores de rede, entre outros. Funcionam como pontes entre o Terraform Core e a API do serviço ou recurso que será provisionado ou gerenciado. Cada provedor é responsável por traduzir as instruções na configuração do Terraform para chamadas apropriadas na API do provedor subjacente.

Alguns Providers necessitam de configurações antes de usá-los. (Ex.: credentials, cloud region, endpoint URL, etc).

Por exemplo, se você estiver usando o Terraform para provisionar recursos na Amazon Web Services (AWS), você precisará do provider AWS. Da mesma forma, se estiver trabalhando com o Microsoft Azure, precisará do provider Azure. Cada provedor possui seus próprios recursos específicos e parâmetros que podem ser configurados no arquivo de configuração do Terraform.

provider.tf
terraform
  provideraws{
  region = “us-east-1
}
HCL

A estrutura modular do Terraform permite que os usuários escolham e incorporem provedores específicos conforme necessário para atender aos requisitos da infraestrutura que estão criando. Essa abordagem permite uma ampla gama de flexibilidade e suporte para diferentes ambientes e serviços de infraestrutura.

IamGrucci

Sou um engenheiro de infraestrutura com mais de 10 anos de experiência, especializado em modernização de sistemas e na criação de soluções IaC (Infrastructure as Code) utilizando ferramentas como Terraform e CloudFormation. Com sólida expertise em automação e orquestração de ambientes cloud. Apaixonado por aprender e ensinar novas tecnologias, dedico-me a ajudar outros profissionais a ingressarem no mundo da TI e a adotar práticas modernas de infraestrutura.