Skip to content

Commit 2cd7e37

Browse files
authored
Merge pull request #2 from nossas/feature/terraform
[ Feature ] Terraform + infraestrutura AWS
2 parents a01d7e0 + e17b4c7 commit 2cd7e37

File tree

11 files changed

+14233
-0
lines changed

11 files changed

+14233
-0
lines changed

.github/workflows/terraform-stage.yml

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: 'Stage deploy using Terraform'
2+
3+
# Garante que esse workflow irá executar apenas quando alterados arquivos
4+
# da pasta instances, que é o local onde está concentrado os arquivos de infraestrura
5+
# declarados com Terraform.
6+
on:
7+
push:
8+
branches:
9+
- "feature/*"
10+
- "hotfix/*"
11+
paths:
12+
- "instances/**"
13+
- ".github/workflows/terraform-stage.yml"
14+
15+
jobs:
16+
terraform:
17+
name: 'Terraform'
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
# Confira o repositório para o GitHub Actions runner
22+
- name: Checkout
23+
uses: actions/checkout@v3
24+
# with:
25+
# submodules: true # Clona os submódulos junto com o repositório principal
26+
# fetch-depth: 0 # Garante que o histórico completo seja baixado, necessário para alguns submódulos
27+
# token: ${{ secrets.GITHUB_TOKEN }} # Usa o Github token para acessar submódulos privados
28+
29+
- name: Setup SSH key
30+
env:
31+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
32+
run: |
33+
mkdir -p ~/.ssh
34+
echo "$SSH_PRIVATE_KEY" > ~/.ssh/ailton-krenak.pem
35+
36+
# Instale a versão mais recente do Terraform CLI e defina a configuração do Terraform CLI.
37+
- name: Install Terraform
38+
run: |
39+
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
40+
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
41+
sudo apt update && sudo apt install terraform
42+
43+
# Inicia uma serie de comandos para publicar nossa infraestrura.
44+
# Como estamos publicando uma infraestrutura na AWS é necessário garantir
45+
# a configuração dos secrets AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY no repositório do Github.
46+
- name: Terraform Initialize
47+
working-directory: ./instances
48+
env:
49+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
50+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
51+
TF_VAR_influxdb_token: ${{ secrets.INFLUXDB_TOKEN }}
52+
run: terraform init
53+
54+
- name: Terraform Validate
55+
working-directory: ./instances
56+
run: terraform validate
57+
58+
# Define que iremos trabalhar no ambiente de stage
59+
- name: Terraform Select Workspace
60+
working-directory: ./instances
61+
env:
62+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
63+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
64+
TF_VAR_influxdb_token: ${{ secrets.INFLUXDB_TOKEN }}
65+
run: terraform workspace select stage
66+
67+
- name: Terraform Plan
68+
working-directory: ./instances
69+
env:
70+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
71+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
72+
TF_VAR_influxdb_token: ${{ secrets.INFLUXDB_TOKEN }}
73+
run: terraform plan"
74+
75+
- name: Terraform Apply
76+
working-directory: ./instances
77+
env:
78+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
79+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
80+
TF_VAR_influxdb_token: ${{ secrets.INFLUXDB_TOKEN }}
81+
run: terraform apply -auto-approve"

README.md

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Devops da infraestrutura Nosssas
2+
3+
Este projeto utiliza `awscli` e `terraform` para gerenciar infraestrutura como código. A configuração do estado da infraestrutura é persistida em um bucket S3 e o controle de lock é gerenciado por uma tabela no DynamoDB.
4+
5+
## Dependências
6+
7+
Para executar este projeto, você precisará instalar as seguintes ferramentas:
8+
9+
- `awscli`: Ferramenta de linha de comando da AWS para gerenciar e interagir com serviços da AWS.
10+
- `terraform`: Ferramenta de infraestrutura como código para gerenciar e provisionar recursos em várias plataformas.
11+
12+
### Instalação no MacOS
13+
aws-cli:
14+
```bash
15+
brew install awscli
16+
```
17+
18+
terraform:
19+
```bash
20+
brew tap hashicorp/tap
21+
brew install hashicorp/tap/terraform
22+
brew update
23+
brew upgrade hashicorp/tap/terraform
24+
```
25+
26+
### Instalação no Debian/Ubuntu
27+
aws-cli:
28+
```bash
29+
sudo apt update
30+
sudo apt install awscli -y
31+
```
32+
33+
terraform:
34+
```bash
35+
sudo apt update
36+
sudo apt install -y software-properties-common
37+
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
38+
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
39+
sudo apt update && sudo apt install terraform
40+
```
41+
42+
### Variáveis de ambiente
43+
É necessário inserir duas chaves no seu env para rodar os comandos terraform.
44+
```bash
45+
export AWS_ACCESS_KEY_ID=<inserir chave aqui>
46+
export AWS_SECRET_ACCESS_KEY=<inserir chave aqui>
47+
```
48+
49+
### Chave ssh da AWS
50+
Para fins de criação e manutenção de instâncias na AWS é necessário incluir a chave pública `ailton-krenak.pem` no seguinte path do seu ambiente de desenvolvimento `˜/.ssh/ailton-krenak.pem`.
51+
52+
## Como executar
53+
54+
### Configurando a infraestrutura com Terraform
55+
56+
O estado do terraform está sendo compartilhado no S3 com gerenciamento de lock em uma tabela no DynamoDB.
57+
58+
Se o bucket configurado `bonde-terraform-up-and-running-state` não existir na lista de buckets da sua conta Amazon (região: us-east-1), você deve executar os seguintes comandos na pasta `instances/boostrap`:
59+
60+
```bash
61+
terraform init
62+
terraform plan
63+
terraform init -auto-approve
64+
```
65+
66+
Essa sequência de comandos acima irá criar a infraestrutura não persistente responsável por cuidar do estado da nossa infraestrutura persistente.
67+
68+
### Executando a infraestrutura com esquema de workspaces do terraform
69+
70+
Este projeto utiliza *workspaces* do Terraform para gerenciar múltiplos ambientes (como `dev`, `stage` e `prod`) dentro de uma única configuração de infraestrutura. Cada *workspace* permite isolar o estado e os recursos entre diferentes ambientes.
71+
72+
Dentro da estrutura do nosso código, temos o arquivo `main.tf` onde nós definimos todas as variáveis *default*, como a seguir:
73+
74+
```
75+
locals {
76+
# Tipo de imagem para o servidor legado (APIS e Clientes Bonde)
77+
ami = "ami-0866a3c8686eaeeba"
78+
79+
# Nome da chave SSH
80+
key_name = "custom-host"
81+
82+
# Caminho para a chave privada SSH
83+
private_key_path = "~/.ssh/ailton-krenak.pem"
84+
85+
# Ambiente (dev, staging, production)
86+
env = terraform.workspace
87+
88+
# Tipo de instância para o servidor legado (APIS e Clientes Bonde)
89+
legacy_server_instance_type = terraform.workspace == "stage" ? "t3.small" : "t3.micro"
90+
91+
# Tipo de instância para o servidor de sites (Bonde Público e CMS)
92+
sites_server_instance_type = terraform.workspace == "stage" ? "t3.micro" : "t2.micro"
93+
}
94+
```
95+
96+
1. **Criando ou Selecionando um Workspace**:
97+
- Para criar um novo *workspace*, execute:
98+
```bash
99+
terraform workspace new nome-do-workspace
100+
```
101+
- Para alternar para um *workspace* existente, execute:
102+
```bash
103+
terraform workspace select nome-do-workspace
104+
```
105+
106+
2. **Executando a Configuração no Workspace Selecionado**:
107+
Com o *workspace* adequado selecionado, você pode executar os comandos do Terraform normalmente. O estado será armazenado separadamente para cada *workspace*, mantendo os recursos de cada ambiente isolados.
108+
109+
```bash
110+
terraform init
111+
terraform apply -auto-approve
112+
```
113+
114+
### Configuração do ambiente
115+
116+
Você deve configurar as seguintes váriaveis no seu ambiente de execução do terraform. Lembre-se você deve utilizar os mesmos valores de váriaveis que outros ambientes que também executam o terraform, exemplo dev local e github actions.
117+
118+
```
119+
TF_VAR_influxdb_token=
120+
TF_VAR_ami=
121+
# legacy envs
122+
TF_VAR_legacy_elastic_ip_allocation_id=
123+
TF_VAR_legacy_server_instance_type=
124+
TF_VAR_legacy_portainer_edge_id=
125+
TF_VAR_legacy_portainer_edge_key=
126+
# sites envs
127+
TF_VAR_sites_elastic_ip_allocation_id=
128+
TF_VAR_sites_server_instance_type=
129+
TF_VAR_sites_portainer_edge_id=
130+
TF_VAR_sites_portainer_edge_key=
131+
```
132+
133+
NOTE: As váriaveis com suffix `_elastic_ip_allocation_id` não são obrigatórias, caso você não configure os scripts não vão associar um IP Elástico ao seus servidores.
134+
135+
## Sites
136+
137+
138+
## TODO
139+
140+
- [X] Persistir o estado no S3 e lock com DynamoDB
141+
- [ ] Criar fluxo de trabalho para publicação automatizada no Github
142+
- [X] Resolver caminho da chave privada
143+
- [X] Documentar o uso do workspace
144+
- [X] Documentar o uso da chave privada `custom-host / ailton-krenak`
145+
- [X] Configuração da awscli e terraform e das variaveis de ambiente que precisam ser configuradas para acessar a conta AWS

instances/bootstrap/main.tf

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
provider "aws" {
2+
region = "us-east-1"
3+
}
4+
5+
resource "aws_s3_bucket" "terraform_state" {
6+
bucket = "bonde-terraform-up-and-running-state"
7+
8+
# Prevent accidental deletion of this S3 bucket
9+
lifecycle {
10+
prevent_destroy = true
11+
}
12+
}
13+
14+
resource "aws_s3_bucket_versioning" "enabled" {
15+
bucket = aws_s3_bucket.terraform_state.id
16+
versioning_configuration {
17+
status = "Enabled"
18+
}
19+
}
20+
21+
resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
22+
bucket = aws_s3_bucket.terraform_state.id
23+
24+
rule {
25+
apply_server_side_encryption_by_default {
26+
sse_algorithm = "AES256"
27+
}
28+
}
29+
}
30+
31+
resource "aws_s3_bucket_public_access_block" "public_access" {
32+
bucket = aws_s3_bucket.terraform_state.id
33+
block_public_acls = true
34+
block_public_policy = true
35+
ignore_public_acls = true
36+
restrict_public_buckets = true
37+
}
38+
39+
resource "aws_dynamodb_table" "terraform_locks" {
40+
name = "terraform-up-and-running-locks"
41+
billing_mode = "PAY_PER_REQUEST"
42+
hash_key = "LockID"
43+
44+
attribute {
45+
name = "LockID"
46+
type = "S"
47+
}
48+
}

instances/envs/dev.tfvars

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
legacy_server_instance_type="t2.micro"
2+
sites_server_instance_type="t3.micro"
3+
ami="ami-0866a3c8686eaeeba"
4+
env="dev"
5+
key_name="custom-host"
6+
private_key_path="~/Repositories/nossas/keys/ailton-krenak.pem"

instances/envs/production.tfvars

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
legacy_server_instance_type="t2.micro"
2+
sites_server_instance_type="t3.micro"
3+
ami="ami-0866a3c8686eaeeba"
4+
env="production"
5+
key_name="custom-host"
6+
private_key_path="~/Repositories/nossas/keys/ailton-krenak.pem"

instances/main.tf

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = "~> 4.16"
6+
}
7+
}
8+
9+
required_version = ">= 1.2.0"
10+
11+
backend "s3" {
12+
# Replace this with your bucket name!
13+
bucket = "bonde-terraform-up-and-running-state"
14+
key = "global/s3/terraform.tfstate"
15+
region = "us-east-1"
16+
17+
# Replace this with your DynamoDB table name!
18+
dynamodb_table = "terraform-up-and-running-locks"
19+
encrypt = true
20+
}
21+
}
22+
23+
provider "aws" {
24+
region = "us-east-1"
25+
}
26+
27+
locals {
28+
# Nome da chave SSH
29+
key_name = "custom-host"
30+
31+
# Caminho para a chave privada SSH
32+
private_key_path = "~/.ssh/ailton-krenak.pem"
33+
34+
# Ambiente (dev, staging, production)
35+
env = terraform.workspace
36+
}
37+
38+
# Módulo para o servidor web
39+
module "legacy_server" {
40+
source = "./modules/common"
41+
ami = var.ami
42+
instance_type = var.legacy_server_instance_type
43+
instance_name = "legacy-server-${local.env}"
44+
volume_size = terraform.workspace == "prod" ? 100 : 30
45+
key_name = local.key_name
46+
private_key_path = local.private_key_path
47+
monitoring_files_path = "./monitoring"
48+
influxdb_token = var.influxdb_token
49+
elastic_ip_allocation_id = var.legacy_elastic_ip_allocation_id
50+
portainer_edge_id = var.legacy_portainer_edge_id
51+
portainer_edge_key = var.legacy_portainer_edge_key
52+
}
53+
54+
module "sites_server" {
55+
source = "./modules/common"
56+
ami = var.ami
57+
instance_type = var.sites_server_instance_type
58+
instance_name = "sites-server-${local.env}"
59+
volume_size = terraform.workspace == "prod" ? 100 : 30
60+
key_name = local.key_name
61+
private_key_path = local.private_key_path
62+
monitoring_files_path = "./monitoring"
63+
influxdb_token = var.influxdb_token
64+
elastic_ip_allocation_id = var.sites_elastic_ip_allocation_id
65+
portainer_edge_id = var.sites_portainer_edge_id
66+
portainer_edge_key = var.sites_portainer_edge_key
67+
}

0 commit comments

Comments
 (0)