An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
Pipeline IaC com Terraform e GitHub Actions
Introduo
Com a difuso da cultura DevOps nos ltimos anos algumas prticas para entrega de novos produtos ou novas funcionalidades no ambiente produtivo mudaram bastante. Nesse artigo vou exemplificar em um pequeno laboratrio um processo de pipeline CD/CD para entrega de uma infraestrutura utilizando Terraform, GitHub Actions e AWS como cloud pblica.
Terraform
Terraform uma ferramenta de infraestrutura como cdigo (IaC) que permite criarmos recursos em clouds pblicas ou privadas utilizando uma linguagem simples e declarativa, podendo assim reutilizar e versionar o cdigo da sua infraestrutura assim como feito com a aplicao. Voc pode ento usar um workflow consistente para provisionar e gerenciar toda a sua infraestrutura ao longo de seu ciclo de vida.
GitHub Actions
GitHub Actions uma plataforma de integrao contnua e entrega contnua (CI/CD) que permite automatizar sua compilao de cdigo, testar e entregar de forma simples e rpida.
Mo na massa!
A ideia do laboratrio provisionar uma instncia EC2 com ip pblico executando um webserver nginx rodando o famoso jogo da cobrinha .
Preparando o GitHub para acessar a AWS com o Terraform
A primeira etapa que precisa ser feita configura as secrets AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY para que o GitHub Actions consiga acessar esses valores durante a execuo do workflow e ter acesso a sua conta da AWS.
Dentro do repositrio v em: Settings -> Secrets -> Actions e adicionei as chaves de acesso da AWS.
Criando os workflows do GitHub Actions
Para termos as actions do GitHub rodando de acordo com cada evento precisar criar o diretrio .github/workflows
na raiz do projeto. Neste caso vamos criar 3 arquivos de workflow, um para o executar o terraform plan
quando for criada um pull request, outro para executar o terraform apply
quando o merge for feito na branch main e o ltimo e no menos importante para executar o terraform destroy
, esse ser executado somente manualmente quando for necessrio destruir a infraestrutura.
Eu utilizei como base para a criao desses workflows a action oficial da HashiCorp - Setup Terraform
Dica: No site HashiCorp Learn temos um tutorial de como criar uma pipeline com GitHub Actions porm utilizando Terraform Cloud.
plan.yml
name: "Plan"on: pull_request:env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}jobs: terraform: name: "Terraform" runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: terraform_version: 0.15.5 - name: Terraform Init id: init run: terraform init - name: Terraform Validate id: validate run: terraform validate -no-color - name: Terraform Plan id: plan run: terraform plan -no-color -input=false continue-on-error: true - uses: actions/github-script@v6 if: github.event_name == 'pull_request' env: PLAN: "terraform
${{ steps.plan.outputs.stdout }}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `#### Terraform Format and Style \`${{ steps.fmt.outcome }}\` #### Terraform Initialization \`${{ steps.init.outcome }}\` #### Terraform Validation \`${{ steps.validate.outcome }}\` #### Terraform Plan \`${{ steps.plan.outcome }}\` <details><summary>Show Plan</summary> \`\`\`
${process.env.PLAN} \`\`\` </details> *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output }) - name: Terraform Plan Status if: steps.plan.outcome == 'failure' run: exit 1 - name: Terraform Apply if: github.ref == 'refs/heads/main' && github.event_name == 'push' run: terraform apply -auto-approve -input=false
apply.yml
name: "Apply"on: push: branches: - mainenv: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}jobs: terraform: name: "Terraform" runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: terraform_version: 0.15.5 - name: Terraform Init id: init run: terraform init - name: Terraform Validate id: validate run: terraform validate -no-color - name: Terraform Plan id: plan run: terraform plan -no-color -input=false continue-on-error: true - uses: actions/github-script@v6 if: github.event_name == 'pull_request' env: PLAN: "terraform
${{ steps.plan.outputs.stdout }}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `#### Terraform Format and Style \`${{ steps.fmt.outcome }}\` #### Terraform Initialization \`${{ steps.init.outcome }}\` #### Terraform Validation \`${{ steps.validate.outcome }}\` #### Terraform Plan \`${{ steps.plan.outcome }}\` <details><summary>Show Plan</summary> \`\`\`
${process.env.PLAN} \`\`\` </details> *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output }) - name: Terraform Plan Status if: steps.plan.outcome == 'failure' run: exit 1 - name: Terraform Apply if: github.ref == 'refs/heads/main' && github.event_name == 'push' run: terraform apply -auto-approve -input=false
destroy.yml
name: "Destroy"on: workflow_dispatch:env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}jobs: destroy: name: "terraform destroy" runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Setup Terraform uses: hashicorp/setup-terraform@v1 with: terraform_version: 0.15.5 - name: Terraform Init id: init run: terraform init - name: Terraform Validate id: validate run: terraform validate -no-color - name: Terraform Destroy run: terraform destroy -auto-approve
Cdigo da infra no Terraform
No vou me aprofundar muito nos detalhes do cdigo do terraform isso pode ficar para outro artigo. Basicamente temos criao de 3 recursos principais dentro da AWS so eles: VPC, Security Group e a Instncia EC2.
Para a criao da VPC j com subnet pblica, AZs e NAT Gateway estou utilizando o mdulo vpc. Abaixo o trecho de cdigo:
module "vpc" { source = "terraform-aws-modules/vpc/aws" name = "snake-vpc" cidr = "10.200.0.0/16" azs = ["us-east-1a", "us-east-1b"] public_subnets = ["10.200.101.0/24", "10.200.102.0/24"] enable_nat_gateway = true tags = { Terraform = "true" Environment = "prod" }}
Para a criao do Security Group estou utilizando o resource aws_security_group, onde configuramos a liberao geral na porta 80, padro HTTP. Abaixo o trecho de cdigo:
resource "aws_security_group" "game_snake_sg" { name = "instances-snake-sg" description = "SG for Instances Snake Security Group" vpc_id = module.vpc.vpc_id ingress { description = "Game Snake port 80" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } tags = { Terraform = "true" Environment = "prod" }}
Para finalizar criamos a instncia EC2 tambm utilizamos o mdulo ec2_instance, onde o servidor com a imagem Amazon Linux 2, tipo t1.micro, anexamos o Security Group criando anteriormente na instncia, anexamos tambm a instncia dentro da Subnet pblica que foi criada junto com a VPC e por fim passamos um arquivo userdata, que basicamente um shell script que ser executando quando a instncia for iniciada.
module "ec2_instance" { source = "terraform-aws-modules/ec2-instance/aws" name = "snake-game" ami = "ami-0cff7528ff583bf9a" instance_type = "t1.micro" vpc_security_group_ids = [aws_security_group.game_snake_sg.id] subnet_id = module.vpc.public_subnets[0] user_data = file("userdata.sh") tags = { Name = "snake-game-ec2" Terraform = "true" Environment = "prod" Team = "gamer-development" Application = "snake-game" Language = "javascript" }}
Desta forma o arquivo do terraform finalizado fica da seguinte maneira:
main.tf
module "vpc" { source = "terraform-aws-modules/vpc/aws" name = "snake-vpc" cidr = "10.200.0.0/16" azs = ["us-east-1a", "us-east-1b"] public_subnets = ["10.200.101.0/24", "10.200.102.0/24"] enable_nat_gateway = true tags = { Terraform = "true" Environment = "prod" }}resource "aws_security_group" "game_snake_sg" { name = "instances-snake-sg" description = "SG for Instances Snake Security Group" vpc_id = module.vpc.vpc_id ingress { description = "Game Snake port 80" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] } tags = { Terraform = "true" Environment = "prod" }}module "ec2_instance" { source = "terraform-aws-modules/ec2-instance/aws" name = "snake-game" ami = "ami-0cff7528ff583bf9a" instance_type = "t1.micro" vpc_security_group_ids = [aws_security_group.game_snake_sg.id] subnet_id = module.vpc.public_subnets[0] user_data = file("userdata.sh") tags = { Name = "snake-game-ec2" Terraform = "true" Environment = "prod" Team = "gamer-development" Application = "snake-game" Language = "javascript" }}
Enviando um Pull Request, fazendo o Merge e executando o deploy da infraestrutura
Vamos criar uma nova branch no projeto chamada deployment
e fazer uma alterao no arquivo README.md
e criar uma Pull Request. Assim que Pull Request for criada a action de plan ser disparada e poderemos verificar o que o terraform ir executar dentro da AWS.
Pull Request
Veja que aps a execuo do workflow de plan que criamos nos comentrios da Pull Request o GitHub Actions informa o resultado na execuo, incrvel n?!
Merge
Agora vamos aprovar o Merge da Pull Request na branch main
. Com essa estratgia possvel revisar o que exatamente o terraform ir aplicar antes ser executado.
Aps a execuo podemos ir no step Terraform Apply
do workflow e verificar se tudo foi executado com sucesso.
Validando a infraestrutura na AWS
Verificando a conta da AWS vemos que toda a infraestrutura foi provisionada com sucesso e a aplicao do jogo da cobrinha est online.
Executando o Destroy
Caso seja necessrio deletar toda a infraestrutura de foi provisionada devemos executar o Workflow Destroy
.
Aps a execuo do Destroy
toda os recursos da AWS foram deletados.
Concluso
Utilizando pipelines CD/CD possvel entregar ambiente completos de forma automtica e rpida. Se voc notou criamos todos os recurso dentro da AWS sem precisar dar ao menos um clique dentro do painel administrativo da cloud. Use a abuse da infraestrutura como cdigo (IaC). Espero que tenha gostado desse hands-on, at a prxima!
Original Link: https://dev.to/santospedroh/pipeline-iac-com-terraform-e-github-actions-k3p
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To