Terraform első tapasztalatok
Tartalomjegyzék
Ahogy azt pár napja olvashattad, mostanában elég sokat dolgozok GCP-s alertinggel, és elég gyorsan eszkalálódott odáig a helyzet, hogy ezeknek az alerteknek a manuális kezelése elég körülményessé vált. Főleg akkor, amikor belefutottam egy olyan szituba, hogy vannak hasonló-de-kicsit-más alertek, amiket le kéne tudni írni.
Template használat #
Az jött fel, hogy szerettem volna egy fix sablon alapján HTTP latency riasztásokat csinálni, de… endpointonként eltérő riasztási küszöbértékekkel. Amennyire látom, se a GCP-s alerting, se a PromQL nem ad eszközt arra, hogy ezeket valamennyire összefüggően lehessen kezelni. Itt jött a képbe a Terraform, ami képes egy konfig alapján ezeket kötegével kigenerálni és szinkronizálni a GCP-vel. Ezzel lehetővé teszi azt, hogy gyorsan tudjak iterálni az alert beállításokon. Erre szükség is van, mert még egy csomó mindennel csak most kezdek ismerkedni, és azt azért valljuk be, se Prometheusnak, se a GCP-nek nem túl barátságos a tanulási görbéje…
Ez a sablonozás a gyakorlatban kb. úgy néz ki, hogy van egy config fájlom, amiben csak felsorolom hogy mire akarok alerteket és milyen beállításokkal:
locals {
latency_alert_settings = {
percentile = 95
time_window = "5m"
}
latency_alerts = {
normal_endpoint = { endpoint = "/api/v1/normal_endpoint", threshold = 0.5 }
a_bit_slower_endpoint = { endpoint = "/api/v1/a_bit_slower_endpoint", threshold = 0.8 }
kinda_slow_endpoint = { endpoint = "/api/v1/kinda_slow_endpoint", threshold = 3 }
}
}
…aztán a tényleges alertet leíró Terraform fájlom valami ilyesmi:
resource "google_monitoring_alert_policy" "latency" {
for_each = local.latency_alerts
conditions {
# ...
condition_prometheus_query_language {
# ..
query = <<-EOT
histogram_quantile(0.${local.latency_alert_settings.percentile}, sum by (le, job, instance_name) (
rate(http_request_duration_seconds_bucket{
"endpoint"=~"${each.value.endpoint}",
"status"=~"2.."
}[${local.latency_alert_settings.time_window}]))
) > ${each.value.threshold}
EOT
}
}
# ...
}
Persze ezeket a template változókat remekül fel lehet használni az alert meg a condition nevében is, szóval így könnyen lehet konzisztens elnevezéseket fenntartani, ami amúgy egy átnevezéskor eléggé agyzsibbasztó lenne, ha kézzel kéne végigütögetni mindenhol.
A query formátumánál főleg hálás vagyok azért, hogy lehet ilyen indentált heredoc dolgot használni (lásd fenn az EOT rész) . Ez a bonyolultabb PromQL queryknél sokat segít, hogy nem kell mindenféle fura escapeléses körtáncokat járni, maradhatnak szép olvasható formátumban.
Arra a Terraform szintaxisában érdemes figyelni, hogy ha ilyen GCP-s, alertes ügyben van egy olyan rész, amit a GCP-nek kéne templateként értelmeznie - pl. egy ${metric.labels.instance_name} egy alert címében -, azt ki kell escapelni a Terraform elől, szóval $${metric.labels.instance_name} lesz belőle.
Egyébként külön tetszik, hogy mennyire gyorsan alkalmazza a változtatásokat a terraform apply, ha sokat kell valamit állítgatni, ami mélyebben van a GCP-s UI-on, lehet, hogy már csak ezért is megéri használni.
Aktuális élő állapot importálása Terraformba #
Ha valamitől, ettől a résztől külön fáztam, mert nem volt teljesen világos, hogy hogyan fogom tudni kiépíteni az induló konfigot, és féltem, hogy az idők végezetéig kell fura JSON-öket olvasgatnom meg szemmel diffelgetnem… Szerencsére a Terraformot olyanok fejlesztik, akik értik ezt a fájdalmat, és elég jól körbeépítették. Valahogy így néz ki a folyamat a gyakorlatban:
Van valami, amit le akarok írni GCP-ből, mondjuk egy alert. Létrehozok neki egy placeholder fájlt csak annyira, hogy a Terraform tudjon a létezéséről:
resource "google_monitoring_alert_policy" "my_alert" {
}
Ezek után beimportálom a GCP állapotát a Terraformba, összecsatolva az alertet az új fájlban leírtakkal:
terraform import google_monitoring_alert_policy.my_alert projects/<GCP project azonosító>/alertPolicies/<alert azonosító>
Ez a Terraform statejét frissíti, de a konfig fájlodat helyetted nem találja ki - de kapsz segítséget hozzá. Amikor először csináltam ezt, megláttam a .tfstate fájlt, belenéztem, és azt hittem, majd onnan kell kibogarásznom mindent… Nyilván erre van sokkol jobb eszköz is:
terraform state show google_monitoring_alert_policy.my_alert
Ha ezt lefuttatod, kiírja a teljes élő állapotot, amivel nagyjából annyi a dolgod, hogy átdobod a korábbi placeholder fájlodba és kipucolsz belőle ezt-azt. (Pl. ilyenkor látod az alert idjét, de azt a GCP nem szereti, ha megpróbálod diktálni neki, hogy mi legyen az id, úgyhogy az ilyesmit ki kell szedni - de erre figyelmeztet a terraform plan is, ha elmulasztod.)
Ha ez megvan, a terraform plannel megnézheted, hogy mi sülne ki, ha ráalkalmazná az élő rendszerre. Ha minden jól ment, nem fogsz túl sok különbséget látni. Innen el lehet kezdeni variálni, pl. kicserélni olyan dolgokat, amikre jobb lenne, ha változókból jönnének, és a terraform plan + terraform apply kombóval már fel is küldheted élesbe. Elég kényelmes.