Hoje gostaria de mostrar como podemos usar Github Actions ao lado de GCP, Packer e Ansible, para construir e rastrear imagens de máquinas.
Configuração do Hashicorp Cloud
Antes de prosseguirmos para a explicação do pipeline, precisamos configurar algumas credenciais. Começando pelo Hashicorp Cloud.
- Faça login no Hashicorp Cloud
- Vá para a seção IAM
- Crie um Principal de Serviço e salve o ID e o SECRET fornecidos.
Exemplo de Principal de Serviço
- Em seguida, vá para a seção Packer e crie o repositório.
Configuração do Google Cloud
No Google Cloud, precisamos apenas criar uma Conta de Serviço com três funções: Admin de Instância de Computação v1, Usuário de Conta de Serviço e Usuário de Túnel Seguro IAP.
- Faça login no Google Cloud.
- Vá para a página IAM -> Conta de Serviço
- Crie uma Conta de Serviço
Exemplo de Conta de Serviço
- Adicione as permissões:
Adicione os Papéis
- Pronto. (você pode pular o passo 3)
- Crie uma Chave para a Conta de Serviço e Salve.
Crie uma Chave JSON na Seção de Chaves
Código
Agora, vamos programar. Neste exemplo, vamos criar uma imagem do Prometheus. A imagem abaixo mostra uma ideia de como estruturar o repositório.
- Uma subpasta por imagem
- Cada subpasta contendo pelo menos dois arquivos: build.pkr.hcl e variables.pkr.hcl.
Estrutura de Pastas
Aviso Eu sei que hoje existem muitos Serviços Gerenciados de Prometheus disponíveis para uso, eu apenas decidi criar uma máquina do Prometheus apenas para fins de exemplo.
O código abaixo é um exemplo da configuração mínima a seguir. Mas antes, algumas considerações importantes:
- Para rastrear os metadados da imagem no Hashicorp Cloud, precisamos adicionar o bloco hcp_packer_registry, fornecendo valores adequados.
- Para o GCP, é importante desativar use_proxy no bloco Ansible, caso contrário, você pode enfrentar alguns problemas quando o Ansible tentar estabelecer uma conexão com a máquina.
- O Packer Cloud armazenará apenas os metadados das imagens. build.pkr.hcl
locals {
timestamp = regex_replace(timestamp(), "[- TZ:]", "")
}
source "googlecompute" "prometheus-image" {
project_id = var.project_id
zone = var.zone
source_image_family = "centos-7"
image_name = "packer-prometheus-${local.timestamp}"
image_description = "Prometheus Web Server"
ssh_username = "packer"
tags = ["packer"]
}
build {
sources = ["sources.googlecompute.prometheus-image"]
hcp_packer_registry {
bucket_name = "packer-prometheus-images"
description = "Bucket used to store Prometheus images metadata"
}
provisioner "ansible" {
playbook_file = "./playbook.yml"
use_proxy = false
}
}
variable project_id {}
variable zone {}
E então, crie o arquivo de playbook (veja no Github).
Pipeline
Sobre o pipeline, podemos criar um baseado em recursos. Para isso, temos algumas considerações importantes também:
- A imagem oficial do contêiner do Hashicorp Packer não tem Ansible instalado, e falta ferramentas binárias para nos ajudar a personalizar a imagem. Então, devemos criar uma personalizada. Aqui está um exemplo de como podemos fazer isso:
FROM --platform=amd64 python:3.9.16
RUN wget -q https://releases.hashicorp.com/packer/1.8.5/packer_1.8.5_linux_amd64.zip && \
unzip packer_1.8.5_linux_amd64.zip && \
mv packer /usr/local/bin && \
python3 -m pip -q install ansible
ENTRYPOINT [ "/bin/bash" ]
Em seguida, marque e publique em seu repositório.
- Temos que definir três variáveis em nossos Segredos do GitHub: o ID do Cliente e o Segredo do Principal de Serviço do Hashicorp configurado anteriormente, e nossa chave JSON da Conta de Serviço. Então, basta usá-las no pipeline como no exemplo abaixo.
- O Packer usará uma VM no GCP para executar os comandos do Ansible e criar a imagem, no final ou se ocorrer algum erro, essa VM será destruída. Então, tenha cuidado em seu pipeline se você estiver usando uma matriz como eu para executar a construção em paralelo para não habilitar o fail-fast. O Packer possui um bom tratamento de erros, mas se alguns trabalhos paralelos falharem quando o fail-fase estiver habilitado, todos os outros receberão um encerramento forçado, fazendo com que o tratamento de erros não funcione, e então as instâncias criadas pelo Packer não serão destruídas, e claro, não queremos surpresas na fatura.
Agora, vamos definir nosso código:
name: Build and Publish VM Image
on:
push:
branches:
- main
env:
HCP_CLIENT_ID: ${{ secrets.HCP_CLIENT_ID }}
HCP_CLIENT_SECRET: ${{ secrets.HCP_CLIENT_SECRET }}
jobs:
build:
runs-on: ubuntu-20.04
container:
image: andersondarioo/packer-ansible:1.0.0
strategy:
matrix:
subfolder: [ prometheus ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
- name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/[email protected]'
with:
credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}'
- name: Build image
run: |
cd ${{ matrix.subfolder }}
packer build -var "project_id=aa-devops" -var "zone=us-central1-a"
Fluxo de Trabalho Principal
name: Validate Pull Request
on:
pull_request:
branches:
- main
env:
HCP_CLIENT_ID: ${{ secrets.HCP_CLIENT_ID }}
HCP_CLIENT_SECRET: ${{ secrets.HCP_CLIENT_SECRET }}
jobs:
validate:
runs-on: ubuntu-20.04
container:
image: andersondarioo/packer-ansible:1.0.0
strategy:
matrix:
subfolder: [ prometheus ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Validate image
run: |
cd ${{ matrix.subfolder }}
packer validate -var "project_id=aa-devops" -var "zone=us-central1-a" .
packer fmt -check .
Fluxo de Trabalho de PR
Validação
Agora, se olharmos dentro do Hashicorp Packer Cloud, podemos ver os metadados do nosso balde de imagens criados:
Metadados da Imagem Publicados
E também podemos ver nossa imagem criada no GCP:
Imagem GCP
Agora você pode usar a imagem.
Se você gostaria de saber como configurar o Terraform Cloud e o GCP para implantar as imagens do Packer criadas aqui, por favor, dê uma olhada no meu próximo
Suporte
Se você achar meus posts úteis e gostaria de me apoiar, por favor, me compre um café: Anderson Dario é blog pessoal e blog de tecnologia
Isso é tudo. Obrigado.