cover

Terraform Pull Request Automation

Pre-requisitos:

  • TRS: Terraform Remote State es necesario, el backend local no está soportado, debido a que Atlantis no posee storage propio (y ya que estamos: es una muy mala práctica ejecutar nuestros tf files desde nuestra laptop)
  • Permisos en GCP: necesitas conocimiento básico para setear una SA (service Account) con los permisos necesarios para leer y escribir ese tfstate remoto (para este post vamos a usar Google Cloud Storage) y por supuesto también debes tener permisos sobre los objetos que estás a punto de crear con Terraform (containers, vm, functions, databases etc), los datos de dicha SA lo vamos a pasar a nuestra configuración de Atlantis vía helmchart más adelante.
  • Github PAT: necesitas un personal access token o PAT de GitHub, para pasarle esta información a nuestro Atlantis server.
  • Weebhook Secret: una pass cualquiera para pasarla al weebhook, la pueden generar por ejemplo con ruby de la siguiente manera:

      $ ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'
    
  • Acceso a un cluster de kubernetes, donde va a vivir nuestra instalación de Atlantis (se recomienda tener un cluster dedicado a herramientas satélite de infraestructura, no uses prod para Atlantis por favor)
  • Conocimiento básico de k8s deployments y Helm

Instalación de Atlantis server vía HelmChart

Primero lo primero, vamos a crear el namespace donde va a vivir nuestro Atlantis server:

$ kubectl create ns atlantis

luego nos traemos los values por default del chart para personalizarlos, con el siguiente comando:

helm show values runatlantis/atlantis > values.yaml

ahora cambiamos los datos en la siguientes secciones:

# If using GitHub, specify like the following:
github: 
  user: TU-USUARIO
  token: TU-GH-PAT
  secret: TU-WEBHOOK-SECRET
GitHub Enterprise only:
   hostname: GH-ORG

Ahora en la sección de permisos contra el cloud, podemos hacerlo de dos maneras según el helmchart de Atlantis, la primera es encodear en base64 el valor JSON de nuestra SA y pasarla como string, o también como un archivo (no hagan esto):

## To be used for mounting credential files (when using google provider).
serviceAccountSecrets: 
  credentials: 'SA-IN-BASE64-STRING'
  # credentials-staging: path/key.json

La otra opción es pasar simplemente el nombre del secreto en la siguiente sección:

googleServiceAccountSecrets:
  - name: gcpsa
    secretName: gcpsa

El secret puede ser creado previamente utilizando alguna integración con cualquier servicio Secret Manager de cualquier main cloud, algunas opciones recomendadas para esto son:

  • ExternalSecret
  • CSI-Provider

trabajé con ambas opciones en prod, e incluso en las 3 main cloud (AWS, Azure, GCP) y ambos productos funcionan muy bien:

ahora con los valores listos, instalamos Atlantis con el siguiente comando:

helm install atlantis runatlantis/atlantis -f values.yaml -n atlantis

si necesita modificar algún valor de la instalación, pueden hacerlo en cualquier momento, y actualizar el server con el subcomando upgrade:

helm upgrade atlantis runatlantis/atlantis -f values.yaml --atomic -n atlantis

deberían tener un output con esta facha:

Release "atlantis" has been upgraded. Happy Helming!
NAME: atlantis
LAST DEPLOYED: Fri Aug 25 10:03:29 2023
NAMESPACE: atlantis
STATUS: deployed
REVISION: 2

Felicitaciones, tenes Atlantis server selfhosted corriendo en tu cluster.

Github Enterprise Conf

Ahora vamos a la sección de settings en GitHub y nos vamos a Webhooks para agregar la siguiente info:

  • Payload URL : YOUR-ATLANTIS-SRV-IP-OR-URL/events
  • Content type: application/json
  • Which events would you like to trigger this webhook?
    • Let me select individual events * Issue comments * Pull request reviews * Pull requests * Pushes

DEMO TIME

Vamos a probar Atlantis con un pequeño bloque de código para levantar GKE con autopilot, nada complejo, solo un par de lineas, junto la configuración del provider de GCP y por supuesto el backend correctamente configurado hacia GCS (pueden hacer esta prueba con cualquier código Terraform válido, no hace falta que usen este ejemplo).

# gke.tf file
provider "google" {
  project = var.project_id
  region  = var.region
}

# GKE cluster
resource "google_container_cluster" "primary" {
  name     = "${var.project_id}-gke-atlantis"
  location = var.region
 
  network    = var.network
  subnetwork = var.subnet
 
# Enabling Autopilot for this cluster
  enable_autopilot = true
}

# backend.tf file 
terraform {
  backend "gcs" {
    bucket  = "infra-trs"
    prefix  = "trs-gke-demo"
  }
}

creamos una feature branch y luego la pusheamos para hacer nuestra PR:

pr

ni bien levantemos la PR vamos a ver que auto-mágicamente Atlantis comienza a trabajar, en la misma PR, como vemos en la imagen, comenzó a ejecutar el Tf Plan en forma de checks:

prcomm

al finalizar va a escribir en forma de comentarios de la PR el output completo además de los next steps del workflow, si queremos aplicar el tf plan lo podemos hacer escribiendo como comentario la instrucción “atlantis apply” (en lugar de terraform apply):

prcomm2

podemos expandir el output del plan y revisarlo en detalle antes de hacer el apply, lo mas lindo de esto, es que tendremos todo el detalle en la PR, es decir, todos los miembros de nuestro equipo pueden ver y analizar el tf plan, además de aprobar o no esos cambios, se puede jugar bastante con Atlantis en conjunto con las branches policies, merge strategies y demas

prcomm3

Además de esto, Atlantis cuenta con un portal web en donde podemos visualizar todas las ejecuciones que está manejando en tiempo real, así como también un histórico de todas las ejecuciones pasadas, como para tener centralizado el monitoreo de todas las ejecuciones de los proyectos tf de la compañía

prcomm4

Fuente

Material Extra: Curso “Devops en 5 Pasos” Disponible en Udemy

Temas:

  • Docker
  • Kubernetes
  • MultiCloud (AWS - Azure - GCP)
  • IaC (Terraform, Cloud Formation, ARM Templates, Cloud Resource Manager)
  • CI/CD Pipelines (GitlabCI, Azure Devops, CircleCI)

Descripción completa: Detalle y enlaces del curso

Invitame un CaféInvitame un Café