Toome mĂ”ned kibedused, sealhulgas need, mis on seotud tsĂŒklite, if-lausete ja deployâimise meetoditega, samuti ĂŒldiste probleemidega, mis puudutavad Terraformi laiemalt:
- parameetrites count ja for_each on piirangud;
- nullaegade vahedega seotud deploymise piirangud;
- isegi hea plaan vÔib osutuda ebaÔnnestunud;
- refaktoreerimisel vĂ”ivad olla oma ĂŒllatused;
- viivitatud kooskÔla on seotud⊠viivitamisega.
Parameetrid count ja for_each on piirangud
Selle peatĂŒki nĂ€idetes kasutatakse parameetrit count ja vĂ€ljendit for_each aktiivselt tsĂŒklites ja tingimuslikus loogikas. Need toimivad hĂ€sti, kuid neil on kaks olulist piirangut, millest tuleb teada.
- count ja for_each ei saa viidata ĂŒhele olemasoleva ressursi vĂ€ljundmuutujale.
- count ja for_each ei saa kasutada mooduli konfiguratsioonis.
count ja for_each ei saa viidata ĂŒhele olemasoleva ressursi vĂ€ljundmuutujale
Kujutage ette, et peate kÀivitama mitu EC2-serverit, kuid mingil pÔhjusel ei soovi te kasutada ASG-d. Teie kood vÔiks olla selline:
resource "aws_instance" "example_1" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Vaadakem neid ĂŒkshaaval.
Kuna parameetrile count on mÀÀratud staatiline vÀÀrtus, töötab see kood probleemideta: kui kĂ€itate apply kĂ€sku, loob see kolm EC2-serverit. Aga kui soovite kĂ€ivitada ĂŒhe serveri igas kĂ€ttesaadavusala (Availability Zone vĂ”i AZ) praeguses AWS-i regioonis? Te saate teha nii, et teie kood laadib nimekirja tsoonidest aws_availability_zones andmeallikast ja seejĂ€rel lĂ€bib need âtsĂŒkliliseltâ ning loob igas neist EC2-serveri, kasutades parameetrit count ja juurdepÀÀsu massiivi kaudu indeksi jĂ€rgi:
resource "aws_instance" "example_2" {
count = length(data.aws_availability_zones.all.names)
availability_zone = data.aws_availability_zones.all.names[count.index]
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
data "aws_availability_zones" "all" {}See kood töötab samuti suurepÀraselt, kuna parameeter count vÔib probleemideta viidata andmeallikatele. Aga mis juhtub, kui serverite arv, mille peate looma, sÔltub mÔne ressursi vÀljundist? Selle demonstreerimiseks on lihtsam vÔtta ressursi random_integer, mis, nagu nimi vihjab, tagastab juhusliku tÀisarvu:
resource "random_integer" "num_instances" {
min = 1
max = 3
}See on kood, mis genereerib juhusliku numbri vahemikus 1 kuni 3. Vaatame, mis juhtub, kui proovime kasutada selle ressursi vÀljundit result parameetrina aws_instance ressursis:
resource "aws_instance" "example_3" {
count = random_integer.num_instances.result
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}Kui kÀitada selle koodi terraform plan, tekib jÀrgmine viga:
Error: Invalid count argument
on main.tf line 30, in resource "aws_instance" "example_3":
30: count = random_integer.num_instances.result
"count" vÀÀrtus sÔltub ressursside atribuutidest, mida ei saa mÀÀrata enne rakendamist, seetÔttu ei saa Terraform ennustada, kui palju instantsi luuakse. Selle lahendamiseks kasutage -target argumenti, et esmalt rakendada ainult ressursse, millele count toetub.Terraform nÔuab, et count ja for_each arvutatakse planeerimise etapis, enne kui mÔnda ressurssi luuakse vÔi muudetakse. See tÀhendab, et count ja for_each vÔivad viidata konstanditele, muutujatele, andmeallikatele ja isegi ressursside loenditele (kui nende pikkus on planeerimise ajal mÀÀratav), kuid mitte arvutatavatele vÀljundmuutujatele.
count ja for_each ei saa olla modulite konfiguratsioonis kasutuses
Varem vÔi hiljem vÔib teil tekkida kiusatus lisada count parameeter mooduli konfiguratsioonidesse:
module "count_example" {
source = "..\/..\/..\/..\/modules\/services\/webserver-cluster"
count = 3
cluster_name = "terraform-up-and-running-example"
server_port = 8080
instance_type = "t2.micro"
}See kood proovib kasutada count'i mooduli sees, et luua kolm koopiat webserver-cluster ressursist. VĂ”i vĂ”ib-olla soovite mooduli ĂŒhenduse teha valikuliseks mingi boolesekondit toetava vÀÀrtuse pĂ”hjal, mÀÀrates count vÀÀrtuseks 0. Selline kood nĂ€ib tĂ€iesti mĂ”istlik, kuid terraform plan'i kĂ€itamisel tekib teil selline viga:
Error: Reserved argument name in module block
on main.tf line 13, in module "count_example":
13: count = 3
Nimi "count" on reserveeritud kasutamiseks tulevikus Terraform'i versioonis.Kahjuks ei toeta Terraform 0.12.6 seisuga count vÔi for_each kasutamine module ressurssides. Vastavalt Terraform 0.12 vÀljaannete mÀrkmetele (http:\/\/bit.ly\/3257bv4) plaanib HashiCorp tulevikus sellise vÔimaluse lisada, seetÔttu, sÔltuvalt sellest, millal te seda raamatut loete, vÔib see juba saadaval olla. Et seda kindlasti teada saada, .
Nulli aegadega juurutamise piirangud
Create_before_destroy ploki kasutamine ASG-ga on suurepĂ€rane lahendus nullist seisakutega turutarnete korraldamiseks, vĂ€lja arvatud ĂŒks nĂŒanss: automaatse skaleerimise reeglid ei ole selle puhul toetatud. VĂ”i kui olla tĂ€psem, nullib see ASG suuruse tagasi min_size-ks igal tarnel, mis vĂ”ib muutuda probleemiks, kui olete kasutanud automaatse skaleerimise reegleid serverite arvu suurendamiseks.
NĂ€iteks sisaldab webserver-cluster moodul paari aws_autoscaling_schedule ressursi, mis hommikul kell 9 suurendab klastris serverite arvu kahest kĂŒmneni. Kui teete tarnet nĂ€iteks kell 11, siis uus ASG rĂŒhm ei kĂ€ivitu kĂŒmne, vaid vaid kahe serveriga ja jÀÀb sellesse olekusse kuni jĂ€rgmise pĂ€eva hommikuni kell 9.
Seda piirangut on vĂ”imalik ĂŒmber mĂ€ngida mitmel viisil.
- Muuda aws_autoscaling_schedule parameetrit recurrence 0 9 * * * (âkĂ€ivita kell 9 hommikulâ) nĂ€iteks millegiks selliseks nagu 0-59 9-17 * * * (âkĂ€ivita igal minutil kell 9 hommikul kuni 5 Ă”htulâ). Kui ASG-s on juba kĂŒmme serverit, ei muuda selle automaatse skaleerimise reegli uuesti kĂ€ivitamine midagi, mis ongi vajalik. Kuid kui ASG rĂŒhm on hiljuti kĂ€ivitatud, tagab see reegel, et maksimaalselt minuti jooksul jĂ”uab serverite arv kĂŒmnele. See pole just elegantne lĂ€henemine ja suured hĂŒpped kĂŒmne serveri ja kahe vahel vĂ”ivad samuti kasutajatele probleeme tekitada.
- Loo kohandatud skript, mis kasutab AWS API-d aktiivsete serverite arvu mÀÀramiseks ASG-s, kutsu see ĂŒles vĂ€lise andmeallika abil (vt jaotist âVĂ€line andmeallikasâ lk 249) ja mÀÀra ASG rĂŒhma desired_capacity parameetriks selle skripti tagastatud vÀÀrtus. SeelĂ€bi kĂ€ivitatakse iga uus ASG instants alati sama mahuga nagu meie Terraformi kood ja keerulisem on selle hooldamine.
Muidugi peaks ideaaljuhul Terraform toetama nullist seisakutega tarnete kÀivitamist, kuid seisuga mai 2019 ei kavatse HashiCorpi meeskond seda funktsionaalsust lisada ().
Korralik plaan vÔib osutuda ebaÔnnestunuks
MĂ”nikord, kui kĂ€ivitate plaani kĂ€su, saadakse tĂ€iesti Ă”ige juurutusplaan, kuid apply kĂ€sk tagastab vea. Proovige nĂ€iteks lisada aws_iam_user ressursi sama nimega, mida kasutasite IAM kasutaja jaoks, mille lĂ”ite varasemalt peatĂŒkis 2:
resource "aws_iam_user" "existing_user" {
# Sisestage siia juba olemasoleva IAM kasutaja nimi,
# et harjutada terraform import kÀsu kasutamist
name = "yevgeniy.brikman"
}NĂŒĂŒd, kui kĂ€ivitate plaani kĂ€su, vĂ€ljendab Terraform esmapilgul tĂ€iesti mĂ”istlikku juurutusplaani:
Terraform will perform the following actions:
# aws_iam_user.existing_user will be created
+ resource "aws_iam_user" "existing_user" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "yevgeniy.brikman"
+ path = "\/"
+ unique_id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.Kui kÀivitate apply kÀsu, tekib jÀrgmine viga:
Error: Error creating IAM User yevgeniy.brikman: EntityAlreadyExists:
User with name yevgeniy.brikman already exists.
on main.tf line 10, in resource "aws_iam_user" "existing_user":
10: resource "aws_iam_user" "existing_user" {Probleem on loomulikult see, et IAM kasutaja sama nimega juba eksisteerib. Ja see vĂ”ib juhtuda mitte ainult IAM kasutajatega, vaid ka peaaegu iga ressursiga. VĂ”ib-olla on keegi loonud selle ressursi kĂ€sitsi vĂ”i kĂ€sureal, kuid igal juhul toovad ID-de kokkulangemised kaasa konflikte. Sellel veal on mitu varianti, mis sageli ĂŒllatavad Terraformi algajaid.
Oluline punkt on see, et terraform plan kÀsk arvestab ainult neid ressursse, mis on Àra toodud Terraformi oleku failis. Kui ressursid on loodud mÔne muude meetoditega (nÀiteks kÀsitsi, klikkides AWS konsoolil), ei jÔua need oleku faili ja seega ei arvestata Terraformi poolt plaani kÀsu tÀitmisel. LÔppkokkuvÔttes osutub nÀiliselt korrektne plaan ebaÔnnestunuks.
Sellest vÔib tuletada kaks Ôpetust.
- Kui olete juba Terraformiga töötamise alustanud, Àrge kasutage midagi muud. Kui osa teie infrastruktuurist juhitakse Terraformi abil, ei tohi seda kÀsitsi muuta. Vastasel juhul mitte ainult ei riski te kummaliste Terraformi vigade saamisega, vaid ka kaotate paljusid IaC eeliseid, kuna kood ei kajasta enam tÀpselt teie infrastruktuuri.
- Kui teil on juba olemas mingi infrastruktuur, kasutage kĂ€sku import. Kui hakkate Terraformi kasutama juba olemasoleva infrastruktuuriga, saab selle lisada olekufaili kĂ€suga terraform import. Nii oskab Terraform teads, millise infrastruktuuriga tuleb hallata. KĂ€sk import vĂ”tab vastu kaks argumenti. Esimene on ressursi aadress teie konfiguratsioonifailides. Siin kehtib sama sĂŒntaks, mis ressursside linkide puhul: _. (nagu aws_iam_user.existing_user). Teine argument on identifikaator ressursile, mille soovite importida. NĂ€iteks on ressursi aws_iam_user ID kasutajanimi (nt yevgeniy.brikman) ja ressursi aws_instance ID EC2 serveri identifikaator (nt i-190e22e5). Kuidas ressurssi importida, on tavaliselt toodud hĂ”ive dokumentatsioonis lehe allosas.
Allpool on toodud kĂ€sk import, mis vĂ”imaldab sĂŒnkroonida ressursi aws_iam_user, mille olete lisanud oma Terraformi konfiguratsiooni koos IAM kasutajaga peatĂŒkis 2 (loomulikult tuleks yevgeniy.brikman asemele kirjutada teie nimi):
$ terraform import aws_iam_user.existing_user yevgeniy.brikmanTerraform pöördub AWS API poole, et leida teie IAM kasutaja ja luua olekufailis link ressursi aws_iam_user.existing_user ja teie Terraformi konfiguratsiooni vahel. Sellest hetkest alates, kui kĂ€ivitate kĂ€su plan, teab Terraform, et IAM kasutaja juba eksisteerib, ja ei pĂŒĂŒa seda veel kord luua.
Tasub mĂ€rkida, et kui teil on juba palju ressursse, mida soovite Terraformi importida, vĂ”ib igaĂŒhe kĂ€sitsi kodeerimine ja jĂ€rjestikune importimine osutuda vaevarikkaks. SeetĂ”ttu tasub tĂ€helepanu pöörata sellisele tööriistale nagu Terraforming (http://terraforming.dtan4.net/), mis suudab automaatselt importida AWS kontolt koodi ja oleku.
Refaktooringul vÔivad olla oma lÔksud
Refaktooring on laialdaselt levinud praktika programmeerimises, kus muudetakse koodi sisemist struktuuri, jĂ€ttes vĂ€lise kĂ€itumise muutumatuks. See on vajalik, et muuta kood arusaadavamaks, puhtamaks ja lihtsamaks hooldada. Refaktooring on ĂŒlioluline meetod, mida tuleks regulaarselt rakendada. Kuid kui jutt on Terraformist vĂ”i mĂ”nest muust IaC vahendist, tuleb olla ÀÀrmiselt ettevaatlik selles, mida mĂ”istetakse "vĂ€lise kĂ€itumise" all, muidu tekivad ettearvamatud probleemid.
NĂ€iteks on levinud refaktoreerimise tĂŒĂŒp muutmine muutuja vĂ”i funktsiooni nimedele selgemateks. Paljud IDE-d pakuvad sisseehitatud refaktoreerimise tuge ja vĂ”ivad automaatselt ĂŒmber nimetada muutujaid ja funktsioone kogu projekti ulatuses. Ăldiseks otstarbeks programmeerimiskeeltes on see triviaalne protseduur, millest ei pea eriti mĂ”tlema, kuid Terraformis tuleb olla ÀÀrmiselt ettevaatlik, vastasel juhul vĂ”ib tekkida hĂ€ireid töös.
NĂ€iteks on webserver-cluster modulil sisenemisvariable cluster_name:
variable "cluster_name" { description = "Nimi, mida kasutada kÔigi klastrite ressursside jaoks" type = string }Kujutage ette, et hakkasite kasutama seda moodulit mikroteenuse juurutamiseks nimega foo. Hiljem soovisite oma teenuse nime muuta bar-iks. See muudatus vÔib tunduda triviaalne, kuid tegelikult vÔivad selle tÔttu tekkida hÀired.
Asi on selles, et webserver-cluster moodul kasutab muutuja cluster_name mitmesugustes ressurssides, sealhulgas kahes turvagruppide ja ALB nimede parameetris:
resource "aws_lb" "example" { name = var.cluster_name load_balancer_type = "application" subnets = data.aws_subnet_ids.default.ids security_groups = [aws_security_group.alb.id] }Kui muudad mĂ”nes ressursis parameetrit name, siis Terraform kustutab selle ressursi vana versiooni ja loob uue. Kuid kui selliseks ressursiks on ALB, siis ajavahemikul, mil see kustutatakse ja uus versioon laaditakse, ei ole sul mehhanismi, et suunata liiklust oma veebiserverisse. Samamoodi, kui kustutatakse turvagrupp, hakkavad sinu serverid igasugust vĂ”rgu liiklust tagasi lĂŒkkama, kuni kuvatakse uus grupp.
Teine refaktoreerimise tĂŒĂŒp, mis vĂ”iks sind huvitada, on Terraformi identifikaatori muutmine. VĂ”tame nĂ€iteks aws_security_group ressursi webserver-cluster moodulis:
resource "aws_security_group" "instance" { # (...) }Selle ressursi identifikaator on instance. Kujutage ette, et otsustate refaktoreerimise kÀigus selle muuta mÔistetavamaks (sinu arvates) nimeks cluster_instance:
resource "aws_security_group" "cluster_instance" { # (...) }Mis lĂ”puks juhtuma hakkab? Ăige: hĂ€ired töös.
Terraform seobade iga iga ressurssi ID pilti pilti pilbiga. NĂ€iteks on iam_user seotud IAM-kasutaja ID-ga AWS-is ja aws_instance on seotud AWS EC2 serveri ID-ga. Kui muudad ressurssi ID-d (ĂŒtleme, et instance'ilt cluster_instance'ile, nagu aws_security_group puhul), nĂ€eb Terraform seda nagu vana ressursi eemaldamist ja uue lisamist. Kui need muudatused rakendada, eemaldab Terraform vana turbarĂŒhma ja loob teise, samas kui teie serverid hakkavad blokeerima igasugust vĂ”rguliiklust.
Siin on neli peamist Ôppetundi, mille peaksite sellest arutelust vÀlja tÔmbama.
- Kasutage alati kÀsku plan. Sellega saab tuvastada kÔik need probleemid. Vaadake hoolikalt selle vÀljundit ja pöörake tÀhelepanu olukordadele, kus Terraform plaanib eemaldada ressursse, mida tÔenÀoliselt ei tasu eemaldada.
- Looge enne kustutamist. Kui soovite ressurssi asendada, mÔelge pÔhjalikult, kas uue loomine tuleks teha enne originaali kustutamist. Kui vastus on jaatav, aitab teid create_before_destroy. Sama tulemuse saavutamiseks saate manuaalselt jÀrgida kahte sammu: esmalt lisage konfiguratsiooni uus ressurss ja kÀivitage kÀsk apply, seejÀrel eemaldage konfiguratsioonist vana ressurss ja kasutage kÀsku apply veel kord.
- ID-de muutmine nĂ”uab oleku muutmist. Kui soovite muuta ressursiga seotud ID-d (nĂ€iteks ĂŒmber nimetada aws_security_group instance'ilt cluster_instance'ile), vĂ€ltides samas ressursi eemaldamist ja uue versiooni loomist, tuleb vastavalt uuendada Terraformi olekufaili. Ărge tehke seda kunagi kĂ€sitsi â kasutage selle asemel kĂ€sku terraform state. ID-de ĂŒmbernimetamisel tuleb kasutada kĂ€sku terraform state mv, millel on jĂ€rgmine sĂŒntaks:
terraform state mvORIGINAL_REFERENCE on vĂ€ljund, mis viitab ressurssile selle praeguses vormis, ja NEW_REFERENCE on koht, kuhu soovite selle liigutada. NĂ€iteks aws_security_group grupi ĂŒmbernimetamiseks instance'ilt cluster_instance'ile tuleb kĂ€ivitada jĂ€rgmine kĂ€sk:
$ terraform state mv aws_security_group.instance aws_security_group.cluster_instanceNii teavitada Terraform'i, et olek, mis varem kuulus aws_security_group.instance'ile, peab nĂŒĂŒd olema seotud aws_security_group.cluster_instance'iga. Kui pĂ€rast ĂŒmbernimetamist ja selle kĂ€su `terraform plan` kĂ€ivitamist ei nĂ€ita mingeid muudatusi, siis olete kĂ”ik Ă”igesti teinud.
- MÔningaid parameetreid ei saa muuta. Paljude ressursside parameetrid on muutumatud. Kui proovite neid muuta, kustutab Terraform vana ressursi ja loob selle asemel uue. Iga ressursi lehelt on tavaliselt kirjas, mis juhtub, kui muudate mÔnda parameetrit, seega Àrge unustage dokumentatsiooniga tutvuda. Kasutage alati kÀsku `plan` ja kaalutage `create_before_destroy` strateegia rakendamise otstarbekust.
Viivitatud kooskÔla kooskÔlastub... viivitamisega
MĂ”nede pilveteenuste pakkujate, nagu AWS, API-d on asĂŒnkroonsed ja neil on viivitatud kooskĂ”la. AsĂŒnkroonsus tĂ€hendab, et liidest saab kohe vastuse, ootamata nĂ”utud tegevuse lĂ”puleviimist. Viivitatud kooskĂ”la tĂ€hendab, et muudatuste levimiseks kogu sĂŒsteemis vĂ”ib kuluda aega; kuni see toimub, vĂ”ivad teie vastused olla kooskĂ”lastamata ja sĂ”ltuda sellest, milline andmeallika koopia vastab teie API-pĂ€ringutele.
Kujutage ette, et teete nĂ€iteks API-pĂ€ringu AWS-ile, paludes luua EC2 server. API tagastab "eduka" vastuse (201 Created) peaaegu kohe, ootamata serveri loomist. Kui proovite sellele kohe juurdepÀÀsu saada, ei Ă”nnestu see tĂ”enĂ€oliselt, kuna AWS on endiselt ressursse initsialiseerimas vĂ”i server ei ole veel kĂ€ivitatud. Veelgi enam, kui teete veel ĂŒhe pĂ€ringu, et saada teavet selle serveri kohta, vĂ”ib tulla viga (404 Not Found). Asi on selles, et teave selle EC2 serveri kohta vĂ”ib endiselt AWS-is levida ning selle kĂ€ttesaadavaks tegemiseks vĂ”ib kuluda mitu sekundit.
Iga kord, kui kasutate asĂŒnkroonset API-d viivitatud kooskĂ”laga, peate perioodiliselt oma pĂ€ringut kordama, kuni tegevus on lĂ”pule viidud ja levinud kogu sĂŒsteemis. Kahjuks ei paku AWS SDK selleks mingeid hĂ€id tööriistu ning Terraformi projekt on varem kannatanud palju selliste vigade all nagu 6813 (https://github.com/hashicorp/terraform/issues/6813):
$ terraform apply aws_subnet.private-persistence.2: InvalidSubnetID.NotFound: The subnet ID 'subnet-xxxxxxx' does not existTeisisĂ”nu loote ressursi (nt alamvĂ”rgu) ja proovite seejĂ€rel saada teavet sellest (nt just loodud alamvĂ”rgu ID), kuid Terraform ei suuda neid leida. Enamik selliseid vigu (sealhulgas 6813) on juba parandatud, kuid need vĂ”ivad aeg-ajalt ikka ilmneda, eriti siis, kui Terraform lisab toele uue ressursitĂŒĂŒbi. See on tĂŒ annoying, kuid enamasti ei too see kaasa mingeid tĂ”siseid tagajĂ€rgi. Uue terraform apply kĂ€itamisel peaks kĂ”ik toimima, kuna sel hetkel on teave juba sĂŒsteemis hajutatud.
See lÔik on pÀrit Jevgeni Brikmani raamatust .
Allikas: habr.com
