Vaatame ĂŒle mĂ”ned peidetud probleemid, sealhulgas need, mis on seotud tsĂŒklite, if avalduste ja juurutamismeetoditega, samuti probleemid, mis puudutavad Terraformi laiemalt:
- count ja for_each parameetrites on piirangud;
- nullaegsetele juurutustele on piirangud;
- isegi hea plaan vÔib osutuda ebaÔnnestunuks;
- refaktoreerimisel vÔivad olla omad varjatud probleemid;
- viivitav kooskÔla kooskÔlastub... viivitusega.
count ja for_each parameetrites on piirangud
Selle peatĂŒki nĂ€idetes kasutatakse count parameetrit ja for_each avaldust aktiivselt tsĂŒklites ja tingimuslikus loogikas. Need toimivad hĂ€sti, kuid neil on kaks olulist piirangut, millest tuleb teadlik olla.
- count ja for_each ei saa osutada ĂŒkski ressursi vĂ€ljundmuutuja.
- count ja for_each ei saa kasutada mooduli konfiguratsioonis.
count ja for_each ei saa osutada ĂŒkski ressursi vĂ€ljundmuutuja
Kujutage ette, et peate juurutama mitu EC2 serverit ja mingil pÔhjusel ei soovi kasutada ASG-d. Teie kood vÔib vÀlja nÀha nii:
resource "aws_instance" "example_1" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Vaadakem neid jÀrjestikku.
Kuna parameetrile count on mÀÀratud staatiline vÀÀrtus, töötab see kood probleemideta: kui teete kĂ€su apply, luuakse kolm EC2-serverit. Kuid kui soovite kĂ€ivitada ĂŒhe serveri igas piirkonna kĂ€ttesaadavuse tsoonis (Availability Zone vĂ”i AZ) AWS praeguse regiooni raames? Saate seadistada oma koodi, et laadida tsoonide nimekiri andmeallikast aws_availability_zones ja seejĂ€rel "tsĂŒkliliselt" lĂ€bida igaĂŒht neist ja luua seal EC2-server, kasutades parameetrit count ja juurdepÀÀsu massiivi indeksi kaudu:
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 saab probleemideta viidata andmeallikatele. Kuid mis juhtub, kui serverite arv, mida peate looma, sÔltub mÔne ressursi vÀljundist? Seda demonstreerida, on kÔige lihtsam vÔtta ressursiks random_integer, mis, nagu nimest vÔib aru saada, tagastab juhusliku tÀisarvu:
resource "random_integer" "num_instances" {
min = 1
max = 3
}See kood genereerib juhusliku arvu vahemikus 1 kuni 3. Vaadakem, mis juhtub, kui proovime kasutada selle ressursi vÀljundit result aws_instance parameetris count:
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, saame jÀrgmise vea:
Error: Invalid count argument
on main.tf line 30, in resource "aws_instance" "example_3":
30: count = random_integer.num_instances.result
The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.Terraform nÔuab, et count ja for_each arvutatakse planeerimise etapis, enne kui mingit ressursi luuakse vÔi muudetakse. See tÀhendab, et count ja for_each vÔivad viidata literaalidele, muutujatele, andmeallikatele ja isegi ressursiloenditele (tingimusel, et nende pikkus on planeerimise ajal mÀÀratletav), kuid mitte arvutatud vÀljundmuutujatele.
count ja for_each ei tohi kasutada mooduli konfiguratsioonis.
Kunagi vÔite tunda ahvatlust lisada count parameeter mooduli konfiguratsioonidesse:
moodul "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 ĂŒritab kasutada count'i mooduli sees, et luua kolm koopia ressursist webserver-cluster. VĂ”ib-olla soovite teha mooduli ĂŒhendamise valikuliseks, andes count'i parameetrile vÀÀrtuse 0. Selline kood nĂ€eks vĂ€lja ĂŒsna mĂ”istlik, kuid terraform plan'i kĂ€ivitamisel saate sellise vea:
Viga: Reserveeritud argumendi nimi mooduli plokis
faili main.tf rida 13, moodulis "count_example":
13: count = 3
Nimi "count" on reserveeritud tulevaste versioonide jaoks Terraformis.Kahjuks ei toetata Terraform 0.12.6 vÀljalaskmise ajal count'i vÔi for_each'i kasutamist mooduli ressursis. Vastavalt Terraform 0.12 vÀljalasketeatele (http://bit.ly/3257bv4) plaanib HashiCorp tulevikus selle vÔimaluse lisada, seega, sÔltuvalt sellest, millal te seda raamatut loete, vÔib see juba saadaval olla. Kuidas olla kindel, .
Nulli seisakuga juurutamise piirangud
create_before_destroy ploki kasutamine ASG-ga on suurepĂ€rane lahendus nullkauguse seisakute korraldamiseks, vĂ€lja arvatud ĂŒks nĂŒanss: automaatsed skaaleerimise reeglid ei ole sel juhul toetatud. TĂ€psemalt öeldes seadistab see ASG suuruse iga juurutamise jĂ€rel tagasi min_size'ile, mis vĂ”ib olla probleem, kui olete kasutanud automaatsete skaaleerimise reegleid kĂ€ivitatud serverite arvu suurendamiseks.
NĂ€iteks webserver-cluster moodul sisaldab paari aws_autoscaling_schedule ressurssi, mis kell 9 suurendavad klastris serverite arvu kahest kĂŒmneni. Kui juurutamine toimub nĂ€iteks kell 11, laadib uus ASG rĂŒhm ĂŒles mitte kĂŒmne, vaid vaid kahe serveriga ja jÀÀb sellesse olekusse kuni jĂ€rgmise pĂ€eva kell 9.
Seda piiri on vĂ”imalik ĂŒletada mitmete viiside kaudu.
- Muutke aws_autoscaling_schedule'i recurrence parameeter vÀÀrtusele 0 9 * * * ("kĂ€ivita kell 9 hommikul") millegi nagu 0-59 9-17 * * * ("kĂ€ivita iga minut kell 9 hommikul kuni 5 Ă”htul"). Kui ASG-s on juba kĂŒmme serverit, ei muuda selle automaatse skaleerimise reegli rakendamine midagi, ja seda me vajamegi. Kuid kui ASG grupp on just hiljuti juurutatud, tagab see reegel, et maksimaalselt minuti jooksul saavutab selle serverite arv kĂŒmme. See pole just elegantne lĂ€henemine ning suured kĂ”ikumised kĂŒmne ja kahe serveri vahel vĂ”ivad samuti kasutajatele probleeme tekitada.
- Looge kohandatud skript, mis kasutab AWS API-d aktiveeritud serverite arvu mÀÀramiseks ASG-s, kutsuge seda vĂ€lja vĂ€lise andmeallika kaudu (vt punkit âVĂ€line andmeallikasâ lk 249) ning mÀÀrake ASG grupi desired_capacity parameetrile vÀÀrtus, mille see skript tagastab. Nii alustab iga uus ASG eksemplar alati sama mahutavusega, nagu oli meil Terraformi koodis, mis muudab selle haldamise keerulisemaks.
Kindlasti, ideaalis peaks Terraform toetama nullis kÀivitamisi, kuid 2019. aasta mais ei kavatsenud HashiCorpi meeskond seda funktsionaalsust lisada ().
Korrektselt koostatud plaan vÔib osutuda ebaÔnnestunuks
MĂ”nikord, kui kĂ€ivitate kĂ€su plan, saadakse tĂ€iesti korrektne juurutamisplaan, kuid kĂ€sk apply tagastab vea. Proovige nĂ€iteks lisada aws_iam_user ressursi sama nimega, mida kasutasite IAM kasutaja loomiseks, mille lĂ”ite varem 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 kĂ€su plan, loob Terraform esmapilgul tĂ€iesti mĂ”istliku juurutamisplaani:
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.KÀsk apply kÀivitamisel ilmneb jÀrgmine tÔrketeade:
Error: IAM kasutaja yevgeniy.brikman loomisel ilmnes viga: EntityAlreadyExists:
Kasutaja nimega yevgeniy.brikman juba eksisteerib.
failis main.tf rida 10, ressurss "aws_iam_user" "existing_user":
10: ressurss "aws_iam_user" "existing_user" {Probleem on selles, et selle nimega IAM kasutaja on juba olemas. Ja see ei kehti ainult IAM kasutajate, vaid ka praktiliselt iga ressursi kohta. VĂ”ib olla, et keegi on selle ressursi loonud kĂ€sitsi vĂ”i kĂ€surealt, kuid igal juhul pĂ”hjustavad identifikaatorite ristumised konflikte. Sellel veal on palju varieeruvaid vorme, mis sageli ĂŒllatavad uusi kasutajaid Terraformi kasutamisel.
Oluline punkt on see, et terraform plan kÀsk arvestab ainult neid ressursse, mis on mÀÀratud Terraformi olekufailis. Kui ressursid on loodud muul viisil (nÀiteks kÀsitsi AWSi konsoolil nuppu klÔpsates), siis need ei kuulu olekufaili ja seetÔttu ei arvestata neid Terraformi poolt plaani kÀivitamisel. Tulemuseks on esialgu Ôige plaan, mis osutub nurjunuks.
Sellest saab vÀlja tuua kaks Ôppetundi.
- Kui olete juba Terraformiga töötama hakanud, Àrge kasutage midagi muud. Kui osa teie infrastruktuurist hallatakse Terraformi abil, ei saa te seda enam kÀsitsi muuta. Vastasel juhul mitte ainult ei riski te kummaliste Terraformi vigade saamisega, vaid ka kaotate paljusid IaC eeliseid, kuna kood ei ole enam teie infrastruktuuri tÀpne esitus.
- Kui teil on juba olemas olemasolev infrastruktuur, kasutage import kĂ€sku. Kui alustate Terraformi kasutamist juba olemasoleva infrastruktuuriga, saate selle lisada olekufaili abil kĂ€sku terraform import. Nii juhib Terraform selle infrastruktuuri haldamist. Import kĂ€sk vĂ”tab vastu kaks argumenti. Esimene on ressursi aadress teie konfiguratsioonifailides. Siin kehtib sama sĂŒntaks kui ressursside linkide puhul: _. (nĂ€iteks aws_iam_user.existing_user). Teine argument on ressursi identifikaator, mida tuleb importida. NĂ€iteks aws_iam_user identifikaatorina on kasutajanimi (nt yevgeniy.brikman), samas kui aws_instance identifikaator on EC2 serveri identifikaator (nt i-190e22e5). Kuidas ressursi importimine toimub, on tavaliselt nĂ€idatud selle lehe dokumentatsioonis.
Allpool on nĂ€idatud import kĂ€sk, mis vĂ”imaldab sĂŒnkroonida aws_iam_user ressurssi, mille olete lisanud oma Terraform konfiguratsiooni koos IAM kasutajaga peatĂŒkis 2 (loomulikult tuleb yevgeniy.brikman asendada teie nimega):
$ terraform import aws_iam_user.existing_user yevgeniy.brikmanTerraform pöördub AWS API poole, et leida teie IAM kasutaja ja luua seisundi failis seos selle ja teie Terraformi konfiguratsioonis oleva aws_iam_user.existing_user ressursi vahel. Sellest hetkest alates teab Terraform plaanimise kĂ€ivitamisel, et IAM kasutaja olemas on, ning ei pĂŒĂŒa seda uuesti luua.
Oluline on mĂ€rkida, et kui teil on juba palju ressursse, mida soovite Terraformi importida, vĂ”ib igaĂŒhe kĂ€sitsi kodeerimine ja importimine osutuda tĂŒlikaks. SeetĂ”ttu tasub kaaluda sellist tööriista nagu Terraforming (http://terraforming.dtan4.net/), mis suudab automaatselt importida teie AWS kontolt koodi ja seisundi.
Refactoring vÔib sisaldada oma komistuskive
Refactoring â levinud praktika programmeerimises, kus muudate koodi sisemist struktuuri, jĂ€ttes samas vĂ€lise kĂ€itumise muutumatuks. See on vajalik, et muuta kood arusaadavamaks, puhtamaks ja hooldatavamaks. Refaktoreerimine on asendamatu meetod, mida tuleks regulaarselt rakendada. Kuid kui rÀÀkida Terraformist vĂ”i mistahes muust IaC vahendist, tuleb olla ÀÀrmiselt ettevaatlik, mida mĂ”istetakse «vĂ€lise kĂ€itumise» all, vastasel juhul vĂ”ivad tekkida ettenĂ€gematud probleemid.
NĂ€iteks on levinud refaktoreerimise tĂŒĂŒp muutuja vĂ”i funktsiooni nimede asendamine arusaadavamatega. Paljud IDE-d toetavad refaktoreerimist ja suudavad automaatselt muuta muutujaid ja funktsioone kogu projekti ulatuses. Ăldotstarbelistes programmeerimiskeeltes on see triviaalne protseduur, millele ei pea mĂ”tlema, kuid Terraformi puhul tuleb olla ÀÀrmiselt ettevaatlik, muidu vĂ”ib tekkida töökatkestusi.
NĂ€iteks on moodulil webserver-cluster sisendmuutuja cluster_name:
variable "cluster_name" { description = "Nimi, mida kasutada kĂ”igi klastrite ressursside jaoks" type = string }Kujutage ette, et hakkasite seda moodulit kasutama mikroteenusena nimega foo. Hiljem soovisite oma teenust nimetada ĂŒmber bariks. See muudatus vĂ”ib tunduda triviaalne, kuid tegelikult vĂ”ib see pĂ”hjustada katkestusi.
Asi on selles, et moodul webserver-cluster kasutab muutujaid cluster_name paljude ressursside, sealhulgas kahe turvagruppi ja ALB parameetrites name:
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 muudate mÔne ressursi parameetrit name, siis Terraform kustutab selle ressursi vana versiooni ja loob selle asemel uue. Kuid kui see ressurss on ALB, siis ajavahemikus, mil see kustutatakse ja uus versioon laaditakse, ei ole teil mehhanismi liikluse suunamiseks oma veebiserverisse. Samamoodi, kui kustutatakse turvagrupp, hakkavad teie serverid keelama igasuguse vÔrgu liikluse, kuni uus grupp on loodud.
Teine refaktooringu tĂŒĂŒp, mis vĂ”iks sind huvitada, on Terraformi identifikaatori muutmine. Vaatame nĂ€iteks aws_security_group ressurssi webserver-cluster moodulis:
resource "aws_security_group" "instance" { # (...) }Selle ressursi identifikaator on nimetatud instance. Kujutage ette, et refaktooringu kÀigus otsustasite selle asendada arusaadavamate (teie arvates) nimedega, nÀiteks cluster_instance:
resource "aws_security_group" "cluster_instance" { # (...) }Mida see siis kaasa toob? Ăige: katkemise.
Terraform sidub iga ressursi ID pilveteenuse pakkuja identifikaatoriga. NĂ€iteks iam_user seotakse AWS-i IAM kasutaja identifikaatoriga ja aws_instance â AWS EC2 serveri ID-ga. Kui muudate ressursi identifikaatorit (nt instance'ist cluster_instance'iks nagu aws_security_group puhul), tundub Terraformile, et olete vana ressursi kustutanud ja uue lisanud. Kui need muutused rakendada, eemaldab Terraform vana turvagrupi ja loob uue, samal ajal kui teie serverid hakkavad kĂ”iki vĂ”rgu liiklust tagasi lĂŒkkama.
Siin on neli pÔhijÀreldust, mida peaksite sellest arutelust Ôppima.
- Kasutage alati kÀsku plan. Selle abil saate tuvastada kÔik need probleemid. Uurige hoolikalt selle vÀljundit ja pöörake tÀhelepanu olukordadele, kus Terraform kavandab ressursside kustutamist, mida ilmselt ei peaks eemaldama.
- Looge enne kustutamist. Kui soovite ressursi asendada, kaaluge hoolikalt, kas on vajalik asenduse loomine enne originaali kustutamist. Kui vastus on jaatav, vÔib aidata create_before_destroy. Sama tulemuse saab saavutada ka kÀsitsi, tehes kaks sammu: esmalt lisage konfiguratsiooni uus ressurss ja kÀivitage kÀsk apply, seejÀrel kustutage konfiguratsioonist vana ressurss ja kasutage uuesti kÀsku apply.
- Identifikaatorite muutmine nĂ”uab oleku muutmist. Kui soovite muuta ressurssiga seotud identifikaatorit (nĂ€iteks ĂŒmber nimetada aws_security_group instance'ilt cluster_instance'iks), vĂ€ltides samas ressursi kustutamist ja uue versiooni loomist, peate vastavalt uuendama Terraformi olekufaili. Ărge tehke seda kunagi kĂ€sitsi â kasutage selle asemel kĂ€sku terraform state. Identifikaatorite ĂŒmber nimetamisel tuleks kasutada kĂ€sku terraform state mv, millel on jĂ€rgmine sĂŒntaks:
terraform state mvORIGINAL_REFERENCE on vĂ€ljend, mis viitab ressursile selle praeguses vormis, ja NEW_REFERENCE on koht, kuhu soovite selle teisaldada. NĂ€iteks, kui soovite nimetada aws_security_group rĂŒhm oma nime instance'ilt cluster_instance'iks, peate kĂ€ivitama jĂ€rgmise kĂ€su:
$ terraform state mv aws_security_group.instance aws_security_group.cluster_instanceNii teavitate Terraformi, et olek, mis varem kuulus aws_security_group.instance'le, peaks nĂŒĂŒd olema seotud aws_security_group.cluster_instance'iga. Kui pĂ€rast ĂŒmbernimetamist ja selle kĂ€su kĂ€ivitamist terraform plan ei nĂ€ita mingeid muudatusi, on see mĂ€rk, et 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 lehel on tavaliselt mainitud, mis juhtub konkreetse parameetri muutmisel, seetÔttu Àrge unustage dokumentatsiooniga tutvuda. Alati kasutage kÀsku plan ja hindake create_before_destroy strateegia rakendamise mÔistlikkust.
Viivitusega kooskÔlastamine kooskÔlastub... viivitusega.
MĂ”nede pilveteenuste pakkujate API-d, nagu AWS, on asĂŒnkroonsed ja neil on viivitusega kooskĂ”lastamine. AsĂŒnkroonsus tĂ€hendab, et liides vĂ”ib kohe vastuse anda, ootamata taotletud toimingu lĂ”petamist. Viivitusega kooskĂ”lastamine tĂ€hendab, et muudatuste levimiseks kogu sĂŒsteemis vĂ”ib kuluda aega; seni, kuni see toimub, vĂ”ivad teie vastused olla jĂ€rgitavad ja sĂ”ltuda sellest, milline andmeallika koopia teie API-kĂ”nedele vastab.
Kujutage ette, et teete API-kĂ”ne AWS-ile, paludes luua EC2-server. API tagastab peaaegu koheselt "eduka" vastuse (201 Created), ootamata serveri loomist. Kui proovite sellele kohe juurde pÀÀseda, ei Ă”nnestu tĂ”enĂ€oliselt midagi, kuna AWS initsialiseerib veel ressursse vĂ”i alternatiivselt on server veel kĂ€ivitumisel. Veelgi enam, kui teete veel ĂŒhe kĂ”ne, 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 levida AWS-is, et see oleks kĂ”ikjal kĂ€ttesaadav, nagu oleks vaja oodata paar sekundit.
Iga kord, kui kasutate asĂŒnkroonset API-d, millel on viivitatud kooskĂ”la, peate oma pĂ€ringut perioodiliselt kordama, kuni toiming on lĂ”pule viidud ja levinud sĂŒsteemis. Kahjuks ei paku AWS SDK selleks mingeid hĂ€id tööriistu, ja Terraformi projekt on varem kannatanud mitme vea, nagu 6813 (https://github.com/hashicorp/terraform/issues/6813) tĂ”ttu:
$ terraform apply aws_subnet.private-persistence.2: InvalidSubnetID.NotFound: AlamvĂ”rgu ID 'subnet-xxxxxxx' puudubTeisisĂ”nu loote ressursi (nĂ€iteks alamvĂ”rgu) ja ĂŒritate seejĂ€rel saada teavet selle kohta (nt just loodud alamvĂ”rgu ID), kuid Terraform ei suuda neid leida. Enamik selliseid vigu (sealhulgas 6813) on juba parandatud, kuid aeg-ajalt esinevad need ikka, eriti kui Terraform lisab toetuse uuele ressursitĂŒĂŒbile. See on tĂŒĂŒtav, kuid enamikul juhtudel ei pĂ”hjusta mingit kahju. Kui kĂ€itate uuesti terraform apply, peaks kĂ”ik toimima, kuna selleks ajaks on teave juba sĂŒsteemi laiali levinud.
See lÔik on vÀlja toodud Jevgeni Brikmani raamatust .
Allikas: habr.com
