GitOps: Erkennen von Abweichungen in Ihrer Terraform / Terragrunt-Infrastruktur

Hallo, alle miteinander.





Haftungsausschluss : Ich sage Ihnen, dass ich unterwegs einen Artikel schreibe, der darin enthaltene "Code" funktioniert, aber keine Best Practices vorgibt. Finden Sie also keinen Fehler :) Der Zweck des Artikels: to Wenn Sie dem interessierten russischsprachigen Teil der Bevölkerung allgemeine Grundsätze vermitteln, ist es möglich, das Interesse zu wecken, es selbst zu klären und etwas viel Besseres und Interessanteres zu tun. So lass uns gehen!





Angenommen, Sie arbeiten mit Terraform / Terragrunt (letzteres ist hier nicht grundlegend, aber Sie sollten besser studieren, wenn Sie es nicht bereits verwenden) und die Infrastruktur beispielsweise in AWS (aber nicht unbedingt in AWS) automatisieren. Die Infrastruktur befindet sich im Code des Repositorys, sie wird von dort bereitgestellt, es scheint, dass dies GitOps Glück ist :)





Alles läuft gut, bis ein Benutzer etwas mit den Händen über die Konsole / Benutzeroberfläche ändert und natürlich vergessen hat, jemandem davon zu erzählen. Und dann hat er absichtlich etwas Schlechtes getan. Und hier ist es Ihr Drift: Code und Infrastruktur stimmen nicht mehr überein! :(





Um dies zumindest rechtzeitig zu erfahren, muss die Automatisierung leicht verfeinert werden.





Wie üblich gibt es viele verschiedene Möglichkeiten, um das zu bekommen, was Sie wollen. Zum Beispiel ist kürzlich am Horizont ein sich gut entwickelndes Dienstprogramm am Horizont https://github.com/cloudskiff/driftctl erschienen , das vielleicht sogar mehr ist, als ich Ihnen weiter unten anbieten werde, aber zum Zeitpunkt dieses Schreibens driftctl unterstützt zumindest nicht die Arbeit mit aws provider v2 und weiß auch nicht, wie man mehrere Regionen bearbeitet, was seine Verwendung in den meisten ernsthaften Projekten unmöglich macht. Aber die Jungs versprechen, es in ein oder zwei Monaten zu beenden.





In der Zwischenzeit werde ich eine kleine Menge Code für das folgende sehr einfache Schema beschreiben und ein Beispiel geben:





  1. Wir erstellen eine Pipeline, die entweder nach einem Zeitplan (in Gitlab können Sie Pipeline-Zeitpläne verwenden) oder in einem Kreis einen Terraform-Plan erstellt





  2. (diff ) pipeline , , Slack.





, , issue , api , apply, . - state, .





live , .. , :





account_1/
├── eu-central-1
│   ├── dev
│   │   ├── eks
│   │   │   ├── terragrunt.hcl
│   │   │   └── values.yaml
│   │   └── s3-bucket
│   │       ├── terragrunt.hcl
│   │       └── values.yaml
│   ├── prod
│   │   ├── eks
│   │   │   ├── terragrunt.hcl
│   │   │   └── values.yaml
│   │   └── s3-bucket
│   │       ├── terragrunt.hcl
│   │       └── values.yaml
│   └── staging
│       ├── eks
│       │   ├── terragrunt.hcl
│       │   └── values.yaml
│       └── s3-bucket
│           ├── terragrunt.hcl
│           └── values.yaml
├── us-east-1
│   ├── dev
│   │   ├── eks
│   │   │   ├── terragrunt.hcl
│   │   │   └── values.yaml
│   │   └── s3-bucket
│   │       ├── terragrunt.hcl
│   │       └── values.yaml
│   ├── prod
│   │   ├── eks
│   │   │   ├── terragrunt.hcl
│   │   │   └── values.yaml
│   │   └── s3-bucket
│   │       ├── terragrunt.hcl
│   │       └── values.yaml
│   └── staging
│       ├── eks
│       │   ├── terragrunt.hcl
│       │   └── values.yaml
│       └── s3-bucket
│           ├── terragrunt.hcl
│           └── values.yaml
└── terragrunt.hcl
      
      



account_1



2 : us-east-1



eu-central-1



, AWS. Terragrunt /, , "${basename(get_terragrunt_dir())}"







, 2: eks



s3-bucket







,





<account_name>/<region>/<environment>/<component>/*







.. " " */*/*/<component>/*







, , s3-bucket ( , ).





Incoming WebHooks Slack Webhook URL. : https://api.slack.com/messaging/webhooks





pipeline Slack diff' :





#!/bin/bash

ROOT_DIR=$(pwd)

plan () {
  echo -e "$(date +'%H-%M-%S %d-%m-%Y') $F"

  CURRENT_DIR=$(pwd)
  PLAN=$CURRENT_DIR/plan.tfplan

  terragrunt run-all plan --terragrunt-non-interactive -lock=false -detailed-exitcode -out=$PLAN 2>/dev/null || ec=$?
  
  case $ec in
    0) echo "No Changes Found"; exit 0;;
    1) printf '%s\n' "Command exited with non-zero"; exit 1;;
    2) echo "Changes Found! Reporting!"; 
  
       MESSAGE=$(terragrunt show -no-color ${PLAN} | sed "s/\"/'/g");    # let's replace the double quotes from the diff with single as double quotes "break" the payload
       curl -X POST --data-urlencode "payload={\"channel\": \"#your-slack-channel-here\", \"username\": \"webhookbot\", \"text\": \"DRIFT DETECTED!!!\n ${MESSAGE}\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/YOUR/WEBHOOK/URL_HERE;;
  esac
}

N="$(($(grep -c ^processor /proc/cpuinfo)*4))"    # any number suitable for your situation goes here

for F in */*/*/s3-bucket/*; do
  ((i=i%N)); ((i++==0)) && wait    # let's run only N jobs in parallel to speed up the process
  cd $ROOT_DIR
  cd $F
  plan &    # send the job to background to start the new one
done
      
      



- , pipeline :)





!





, /, - , , , , , , @vainkop







PS: IMHO scheint mir das Projekt https://github.com/cloudskiff/driftctl persönlich sehr nützlich zu sein und das richtige Problem zu lösen, und es hat keine guten Analoga. Deshalb bitte ich Sie, die Jungs zu unterstützen und wenn möglich Ihren Beitrag zu leisten für Open Source.





Gute Laune euch allen!








All Articles