Terraform gildrur

Terraform gildrur
Við skulum varpa ljósi á nokkrar gildrur, þar á meðal þá sem tengjast lykkjum, ef yfirlýsingum og dreifingartækni, sem og almennari atriði sem hafa áhrif á Terraform almennt:

  • fjöldi og fyrir_hverja færibreytur hafa takmarkanir;
  • takmarka núll dreifingu niður í miðbæ;
  • jafnvel góð áætlun getur mistekist;
  • endurnýjun getur haft sínar gildrur;
  • frestað samræmi er í samræmi við frestun.

Fjöldi og fyrir_hverja færibreytur hafa takmarkanir

Dæmin í þessum kafla nota talsbreytuna og for_each tjáninguna í lykkjum og skilyrtri rökfræði. Þeir standa sig vel, en þeir hafa tvær mikilvægar takmarkanir sem þú þarft að vera meðvitaður um.

  • Count og for_each geta ekki vísað til neinar auðlindaúttaksbreytur.
  • count og for_each er ekki hægt að nota í einingauppsetningu.

count og for_each geta ekki vísað til neinar auðlindaúttaksbreytur

Ímyndaðu þér að þú þurfir að setja upp nokkra EC2 netþjóna og af einhverjum ástæðum viltu ekki nota ASG. Kóðinn þinn gæti verið svona:

resource "aws_instance" "example_1" {
   count             = 3
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

Við skulum líta á þá einn af öðrum.

Þar sem talningarbreytan er stillt á kyrrstætt gildi mun þessi kóði virka án vandræða: þegar þú keyrir apply skipunina mun hann búa til þrjá EC2 netþjóna. En hvað ef þú vildir setja upp einn netþjón á hverju Availability Zone (AZ) innan núverandi AWS svæðis þíns? Þú getur látið kóðann þinn hlaða inn lista yfir svæði úr aws_availability_zones gagnagjafanum og fara síðan í gegnum hvert og eitt og búa til EC2 netþjón í honum með því að nota talfæribreytuna og fylkisvísitöluaðgang:

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" {}

Þessi kóði mun líka virka vel, þar sem talningarbreytan getur vísað til gagnagjafa án vandræða. En hvað gerist ef fjöldi netþjóna sem þú þarft að búa til fer eftir framleiðslu einhverrar auðlindar? Til að sýna fram á þetta er auðveldasta leiðin að nota random_integer auðlindina, sem, eins og nafnið gefur til kynna, skilar tilviljunarkenndri heiltölu:

resource "random_integer" "num_instances" {
  min = 1
  max = 3
}

Þessi kóði býr til handahófskennda tölu á milli 1 og 3. Við skulum sjá hvað gerist ef við reynum að nota úttak þessarar auðlindar í talfæribreytu aws_instance auðlindarinnar:

resource "aws_instance" "example_3" {
   count             = random_integer.num_instances.result
   ami                = "ami-0c55b159cbfafe1f0"
   instance_type = "t2.micro"
}

Ef þú keyrir terraform plan á þessum kóða færðu eftirfarandi villu:

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 krefst þess að talning og fyrir_hver sé reiknuð út á áætlunarstigi, áður en tilföng eru búin til eða breytt. Þetta þýðir að count og for_each getur átt við bókstafi, breytur, gagnagjafa og jafnvel auðlindalista (svo lengi sem hægt er að ákvarða lengd þeirra á tímaáætlunartíma), en ekki til reiknaðra auðlindaúttaksbreyta.

count og for_each er ekki hægt að nota í einingauppsetningu

Einhvern tíma gætirðu freistast til að bæta talningarfæribreytu við einingastillinguna þína:

module "count_example" {
     source = "../../../../modules/services/webserver-cluster"

     count = 3

     cluster_name = "terraform-up-and-running-example"
     server_port = 8080
     instance_type = "t2.micro"
}

Þessi kóði reynir að nota talningu inni í einingu til að búa til þrjú eintök af vefþjónklasanum. Eða þú gætir viljað gera tengingu einingarinnar valfrjáls eftir einhverju Boolean ástandi með því að stilla talningarbreytu hennar á 0. Þetta gæti litið út eins og sanngjarn kóði, en þú munt fá þessa villu þegar þú keyrir terraform áætlun:

Error: Reserved argument name in module block

   on main.tf line 13, in module "count_example":
   13: count = 3

The name "count" is reserved for use in a future version of Terraform.

Því miður, frá og með Terraform 0.12.6, er það ekki stutt að nota count eða for_each í einingatilföngum. Samkvæmt Terraform 0.12 útgáfuskýringunum (http://bit.ly/3257bv4), ætlar HashiCorp að bæta við þessari getu í framtíðinni, þannig að það fer eftir því hvenær þú lest þessa bók, hún gæti nú þegar verið fáanleg. Til að komast að því með vissu, lestu Terraform breytingaskrána hér.

Takmarkanir á engum niðurtímauppfærslum

Að nota create_before_destroy blokkina ásamt ASG er frábær lausn fyrir dreifingu á núll niður í miðbæ, fyrir utan einn fyrirvara: reglur um sjálfstýringu eru ekki studdar. Eða til að vera nákvæmari, þetta endurstillir ASG stærðina aftur í min_size á hverri dreifingu, sem gæti verið vandamál ef þú varst að nota sjálfvirka stærðarreglur til að auka fjölda netþjóna í gangi.

Til dæmis inniheldur vefþjónaþyrpingareiningin par af aws_autoscaling_schedule tilföngum, sem klukkan 9 að morgni eykur fjölda netþjóna í þyrpingunni úr tveimur í tíu. Ef þú sendir til dæmis klukkan 11 að morgni, mun nýja ASG ræsa sig með aðeins tveimur netþjónum frekar en tíu og haldast þannig til klukkan 9 að morgni næsta dag.

Hægt er að sniðganga þessa takmörkun á nokkra vegu.

  • Breyttu endurtekningarbreytu í aws_autoscaling_schedule úr 0 9 * * * ("hlaupið kl. 9") í eitthvað eins og 0-59 9-17 * * * ("hlaupið á hverri mínútu frá 9:5 til XNUMX:XNUMX"). Ef ASG er nú þegar með tíu netþjóna mun það ekki breyta neinu að keyra þessa sjálfvirka skalunarreglu aftur, sem er það sem við viljum. En ef ASG hefur aðeins nýlega verið sett á vettvang mun þessi regla tryggja að eftir eina mínútu verði fjöldi netþjóna þess orðinn tíu. Þetta er ekki alveg glæsileg nálgun og stór stökk úr tíu í tvo netþjóna og til baka geta einnig valdið vandamálum fyrir notendur.
  • Búðu til sérsniðna skriftu sem notar AWS API til að ákvarða fjölda virkra netþjóna í ASG, hringdu í það með því að nota utanaðkomandi gagnagjafa (sjá "Ytri gagnaheimild" á síðu 249) og stilltu færibreytu ASG's wanted_capacity á gildið sem skilað er af handritið. Þannig mun hvert nýtt ASG tilvik alltaf keyra á sömu getu og núverandi Terraform kóða og gerir það erfiðara að viðhalda.

Auðvitað myndi Terraform helst hafa innbyggðan stuðning fyrir dreifing á núllniðurtíma, en frá og með maí 2019 hafði HashiCorp teymið engin áform um að bæta við þessari virkni (smáatriði - hér).

Rétt áætlun gæti verið misheppnuð

Stundum framleiðir áætlunarskipunin fullkomlega rétta dreifingaráætlun, en beita skipunin skilar villu. Prófaðu til dæmis að bæta við aws_iam_user auðlindinni með sama nafni og þú notaðir fyrir IAM notandann sem þú bjóst til fyrr í kafla 2:

resource "aws_iam_user" "existing_user" {
   # Подставьте сюда имя уже существующего пользователя IAM,
   # чтобы попрактиковаться в использовании команды terraform import
   name = "yevgeniy.brikman"
}

Nú, ef þú keyrir áætlunarskipunina, mun Terraform gefa út að því er virðist sanngjarna dreifingaráætlun:

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.

Ef þú keyrir apply skipunina færðu eftirfarandi villu:

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" {

Vandamálið er auðvitað að IAM notandi með það nafn er þegar til. Og þetta getur ekki aðeins gerst fyrir IAM notendur, heldur næstum hvaða auðlind sem er. Það er mögulegt að einhver hafi búið til þessa tilföng handvirkt eða með skipanalínunni, en hvort sem er, þá leiðir samsvarandi auðkenni til árekstra. Það eru mörg afbrigði af þessari villu sem kemur nýliðum á Terraform oft á óvart.

Lykilatriðið er að skipunin terraform plan tekur aðeins tillit til þeirra auðlinda sem tilgreind eru í Terraform ástandsskránni. Ef auðlindir eru búnar til á einhvern annan hátt (til dæmis handvirkt með því að smella á AWS stjórnborðið), munu þau ekki lenda í ástandsskránni og því mun Terraform ekki taka tillit til þeirra þegar áætlunarskipunin er framkvæmd. Fyrir vikið mun áætlun sem virðist rétt við fyrstu sýn reynast misheppnuð.

Af þessu má draga tvo lærdóma.

  • Ef þú hefur þegar byrjað að vinna með Terraform skaltu ekki nota neitt annað. Ef hluti af innviði þínu er stjórnað með Terraform geturðu ekki lengur breytt því handvirkt. Annars er ekki aðeins hætta á undarlegum Terraform villum, heldur afneitar þú líka mörgum af kostum IaC þar sem kóðinn mun ekki lengur vera nákvæm framsetning á innviðum þínum.
  • Ef þú ert nú þegar með einhvern innviði skaltu nota innflutningsskipunina. Ef þú ert að byrja að nota Terraform með núverandi innviðum geturðu bætt því við ástandsskrána með því að nota terraform import skipunina. Þannig mun Terraform vita hvaða innviði þarf að stjórna. Innflutningsskipunin tekur tvö rök. Það fyrsta er vistfang tilfangsins í stillingarskránum þínum. Setningafræðin hér er sú sama og fyrir tilföngstengla: _. (eins og aws_iam_user.existing_user). Önnur röksemdin er auðkenni auðlindarinnar sem á að flytja inn. Segjum að auðkenni auðlinda aws_iam_user sé notandanafnið (til dæmis yevgeniy.brikman) og auðkenni auðlindar aws_instance sé EC2 netþjónakenni (eins og i-190e22e5). Hvernig á að flytja inn auðlind er venjulega tilgreint í skjölunum neðst á síðunni.

    Hér að neðan er innflutningsskipun sem samstillir aws_iam_user auðlindina sem þú bættir við Terraform stillingarnar þínar ásamt IAM notandanum í kafla 2 (sem kemur að sjálfsögðu í stað nafns þíns fyrir yevgeniy.brikman):

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Terraform mun hringja í AWS API til að finna IAM notandann þinn og búa til stöðuskráartengingu milli þess og aws_iam_user.existing_user tilföngsins í Terraform stillingunum þínum. Héðan í frá, þegar þú keyrir áætlunarskipunina, mun Terraform vita að IAM notandinn er þegar til og mun ekki reyna að búa hann til aftur.

    Það er athyglisvert að ef þú ert nú þegar með mikið af auðlindum sem þú vilt flytja inn í Terraform, getur það verið vandræðalegt að skrifa kóðann handvirkt og flytja inn hvern og einn í einu. Svo það er þess virði að skoða tól eins og Terraforming (http://terraforming.dtan4.net/), sem getur sjálfkrafa flutt inn kóða og ástand af AWS reikningnum þínum.

    Endurnýjun getur haft sínar gildrur

    Endurnýjun er algeng aðferð í forritun þar sem þú breytir innri uppbyggingu kóðans á meðan ytri hegðun er óbreytt. Þetta er til að gera kóðann skýrari, snyrtilegri og auðveldari í viðhaldi. Refactoring er ómissandi tækni sem ætti að nota reglulega. En þegar kemur að Terraform eða einhverju öðru IaC tóli, verður þú að vera mjög varkár um hvað þú átt við með „ytri hegðun“ kóðastykkis, annars munu óvænt vandamál koma upp.

    Til dæmis er algeng tegund endurstillingar að skipta út nöfnum breyta eða aðgerða fyrir skiljanlegri. Margir IDE hafa innbyggðan stuðning fyrir endurstillingu og geta sjálfkrafa endurnefna breytur og aðgerðir í gegnum verkefnið. Í almennum forritunarmálum er þetta léttvæg aðferð sem þú gætir ekki hugsað um, en í Terraform þarftu að vera mjög varkár með þetta, annars gætirðu lent í truflunum.

    Til dæmis, vefþjón-þyrpingareiningin hefur inntaksbreytu cluster_name:

    variable "cluster_name" {
       description = "The name to use for all the cluster resources"
       type          = string
    }

    Ímyndaðu þér að þú hafir byrjað að nota þessa einingu til að dreifa örþjónustu sem kallast foo. Seinna vilt þú endurnefna þjónustuna þína í bar. Þessi breyting kann að virðast léttvæg, en í raun getur hún valdið þjónustutruflunum.

    Staðreyndin er sú að vefþjón-þyrpingareiningin notar þyrpinga_nafn breytuna í fjölda auðlinda, þar á meðal nafnbreytu tveggja öryggishópa og ALB:

    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]
    }

    Ef þú breytir nafnbreytu á tilfangi mun Terraform eyða gömlu útgáfunni af því tilfangi og búa til nýja í staðinn. En ef þessi auðlind er ALB, á milli þess að eyða því og hlaða niður nýrri útgáfu, muntu ekki hafa kerfi til að beina umferð á vefþjóninn þinn. Sömuleiðis, ef öryggishópi er eytt, munu netþjónar þínir byrja að hafna allri netumferð þar til nýr hópur er stofnaður.

    Önnur tegund endurstillingar sem þú gætir haft áhuga á er að breyta Terraform ID. Tökum aws_security_group auðlindina í vefþjónklasaeiningunni sem dæmi:

    resource "aws_security_group" "instance" {
      # (...)
    }

    Auðkenni þessarar auðlindar er kallað tilvik. Ímyndaðu þér að við endurstillingu ákvaðstu að breyta því í skiljanlegra (að þínu mati) nafni cluster_instance:

    resource "aws_security_group" "cluster_instance" {
       # (...)
    }

    Hvað mun gerast á endanum? Það er rétt: truflun.

    Terraform tengir hvert auðkenni auðlindar við auðkenni skýjaveitunnar. Til dæmis er iam_user tengt AWS IAM notandaauðkenninu og aws_instance er tengt AWS EC2 miðlaraauðkenninu. Ef þú breytir auðkenni auðlindar (td úr tilviki í cluster_instance, eins og er tilfellið með aws_security_group), í Terraform mun það birtast eins og þú hafir eytt gömlu auðlindinni og bætt við nýrri. Ef þú beitir þessum breytingum mun Terraform eyða gamla öryggishópnum og búa til nýjan, á meðan netþjónarnir þínir byrja að hafna allri netumferð.

    Hér eru fjórir lykillexíur sem þú ættir að draga af þessari umræðu.

    • Notaðu alltaf skipunina áætlun. Það getur leitt í ljós alla þessa hnökra. Skoðaðu framleiðsluna vandlega og gefðu gaum að aðstæðum þar sem Terraform ætlar að eyða tilföngum sem líklega ætti ekki að eyða.
    • Búðu til áður en þú eyðir. Ef þú vilt skipta um tilföng skaltu íhuga vandlega hvort þú þurfir að búa til staðgengill áður en þú eyðir frumritinu. Ef svarið er já getur create_before_destroy hjálpað. Sömu niðurstöðu er hægt að ná handvirkt með því að framkvæma tvö skref: Bættu fyrst nýju tilfangi við uppsetninguna og keyrðu appið skipunina og fjarlægðu síðan gamla tilfangið úr uppsetningunni og notaðu appið skipunina aftur.
    • Til að breyta auðkennum þarf að breyta ástandi. Ef þú vilt breyta auðkenninu sem tengist auðlind (til dæmis, endurnefna aws_security_group úr tilviki í cluster_instance) án þess að eyða auðlindinni og búa til nýja útgáfu af henni, verður þú að uppfæra Terraform ástandsskrána í samræmi við það. Gerðu þetta aldrei handvirkt - notaðu terraform state skipunina í staðinn. Þegar þú endurnefnir auðkenni ættir þú að keyra terraform state mv skipunina, sem hefur eftirfarandi setningafræði:
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      ORIGINAL_REFERENCE er tjáning sem vísar til auðlindarinnar í núverandi mynd og NEW_REFERENCE er þar sem þú vilt færa hana. Til dæmis, þegar þú endurnefnir aws_security_group hópinn úr tilviki í cluster_instance, þarftu að keyra eftirfarandi skipun:

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      Þetta segir Terraform að ástandið sem áður var tengt aws_security_group.instance ætti nú að vera tengt aws_security_group.cluster_instance. Ef eftir að hafa endurnefna og keyrt þessa skipun sýnir terraform plan engar breytingar, þá gerðir þú allt rétt.

    • Sumum stillingum er ekki hægt að breyta. Færibreytur margra auðlinda eru óbreytanlegar. Ef þú reynir að breyta þeim mun Terraform eyða gömlu auðlindinni og búa til nýja í staðinn. Hver auðlindasíða mun venjulega gefa til kynna hvað gerist þegar þú breytir tiltekinni stillingu, svo vertu viss um að skoða skjölin. Notaðu alltaf áætlunarskipunina og íhugaðu að nota create_before_destroy stefnuna.

    Frestað samræmi er í samræmi við frestun

    Forritaskil sumra skýjaveitna, eins og AWS, eru ósamstilltur og hafa seinkað samræmi. Ósamstilling þýðir að viðmótið getur strax skilað svari án þess að bíða eftir að umbeðinni aðgerð ljúki. Seinkað samræmi þýðir að breytingar geta tekið tíma að breiðast út um allt kerfið; á meðan þetta er að gerast gætu svör þín verið ósamræmi og háð því hvaða eftirmynd gagnagjafa er að svara API símtölum þínum.

    Ímyndaðu þér til dæmis að þú hringir API til AWS og biður það um að búa til EC2 netþjón. API mun skila „vel heppnuðu“ svari (201 Búið til) næstum samstundis, án þess að bíða eftir að þjónninn sjálfur verði búinn til. Ef þú reynir að tengjast honum strax mun það næstum örugglega mistakast vegna þess að á þeim tímapunkti er AWS enn að frumstilla auðlindir eða að öðrum kosti hefur þjónninn ekki enn ræst. Þar að auki, ef þú hringir annað til að fá upplýsingar um þennan netþjón, gætirðu fengið villu (404 fannst ekki). Málið er að upplýsingarnar um þennan EC2 netþjón gætu enn verið dreift um AWS áður en þær verða aðgengilegar alls staðar, þú verður að bíða í nokkrar sekúndur.

    Alltaf þegar þú notar ósamstillt API með lata samkvæmni, verður þú reglulega að reyna beiðni þína aftur þar til aðgerðinni lýkur og breiðist út í gegnum kerfið. Því miður býður AWS SDK ekki upp á nein góð verkfæri fyrir þetta og Terraform verkefnið þjáðist áður af mörgum villum eins og 6813 (https://github.com/hashicorp/terraform/issues/6813):

    $ terraform apply
    aws_subnet.private-persistence.2: InvalidSubnetID.NotFound:
    The subnet ID 'subnet-xxxxxxx' does not exist

    Með öðrum orðum, þú býrð til auðlind (eins og undirnet) og reynir síðan að fá einhverjar upplýsingar um það (eins og auðkenni nýstofnaðs undirnets), og Terraform finnur það ekki. Flestar þessar villur (þar á meðal 6813) hafa verið lagfærðar, en þær birtast samt af og til, sérstaklega þegar Terraform bætir við stuðningi við nýja auðlindategund. Þetta er pirrandi en veldur í flestum tilfellum ekki skaða. Þegar þú keyrir terraform app aftur ætti allt að virka, þar sem á þessum tíma munu upplýsingarnar hafa þegar dreift sér um kerfið.

    Þessi útdráttur er kynntur úr bók eftir Evgeniy Brikman "Terraform: innviðir á kóðastigi".

Heimild: www.habr.com

Bæta við athugasemd