Հողային որոգայթներ

Հողային որոգայթներ
Եկեք ընդգծենք մի քանի որոգայթներ, այդ թվում՝ կապված օղակների, եթե հայտարարությունների և տեղակայման տեխնիկայի հետ, ինչպես նաև ավելի ընդհանուր խնդիրներ, որոնք ազդում են Terraform-ի վրա ընդհանրապես.

  • count և for_each պարամետրերը սահմանափակումներ ունեն.
  • սահմանափակել զրոյական պարապուրդի տեղակայումները;
  • նույնիսկ լավ պլանը կարող է ձախողվել.
  • վերամշակումը կարող է ունենալ իր որոգայթները.
  • հետաձգված համահունչությունը համահունչ է... հետաձգմանը.

count և for_each պարամետրերը սահմանափակումներ ունեն

Այս գլխի օրինակները լայնորեն օգտագործում են count պարամետրը և for_each արտահայտությունը հանգույցներում և պայմանական տրամաբանության մեջ: Նրանք լավ են գործում, բայց նրանք ունեն երկու կարևոր սահմանափակում, որոնց մասին դուք պետք է իմանաք:

  • Count-ը և for_each-ը չեն կարող հղում կատարել ռեսուրսի ելքային որևէ փոփոխականի:
  • count-ը և for_each-ը չեն կարող օգտագործվել մոդուլի կազմաձևման մեջ:

count-ը և for_each-ը չեն կարող հղում կատարել ռեսուրսի ելքային որևէ փոփոխականի

Պատկերացրեք, որ դուք պետք է տեղակայեք մի քանի EC2 սերվերներ և ինչ-ինչ պատճառներով չեք ցանկանում օգտագործել ASG: Ձեր կոդը կարող է լինել այսպիսին.

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

Եկեք նայենք նրանց մեկ առ մեկ:

Քանի որ count պարամետրը դրված է ստատիկ արժեքի վրա, այս կոդը կաշխատի առանց խնդիրների. երբ գործարկեք «apple» հրամանը, այն կստեղծի երեք EC2 սերվեր: Բայց ի՞նչ, եթե ցանկանում եք մեկ սերվեր տեղակայել յուրաքանչյուր Հասանելիության գոտում (AZ) ձեր ընթացիկ AWS տարածաշրջանում: Դուք կարող եք թույլ տալ, որ ձեր կոդը բեռնի գոտիների ցանկը aws_availability_zones տվյալների աղբյուրից, այնուհետև անցեք յուրաքանչյուրի միջով և դրանում ստեղծեք EC2 սերվեր՝ օգտագործելով count պարամետրը և զանգվածի ինդեքսը հասանելիությունը:

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

Այս կոդը նույնպես լավ կաշխատի, քանի որ count պարամետրը կարող է առանց որևէ խնդիրների հղում կատարել տվյալների աղբյուրներին: Բայց ի՞նչ կլինի, եթե սերվերների քանակը, որոնք դուք պետք է ստեղծեք, կախված է ինչ-որ ռեսուրսի արդյունքից: Դա ցույց տալու համար ամենահեշտ ճանապարհն է օգտագործել random_integer ռեսուրսը, որը, ինչպես հուշում է անունը, վերադարձնում է պատահական ամբողջ թիվ.

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

Այս կոդը ստեղծում է պատահական թիվ 1-ի և 3-ի միջև: Եկեք տեսնենք, թե ինչ տեղի կունենա, եթե փորձենք օգտագործել այս ռեսուրսի արդյունքը aws_instance ռեսուրսի count պարամետրում.

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

Եթե ​​այս կոդի վրա գործարկեք terraform plan, դուք կստանաք հետևյալ սխալը.

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-ը պահանջում է, որ count-ը և for_each-ը հաշվարկվեն պլանավորման փուլում՝ նախքան որևէ ռեսուրս ստեղծելը կամ փոփոխելը: Սա նշանակում է, որ count և for_each-ը կարող է վերաբերել բառացիներին, փոփոխականներին, տվյալների աղբյուրներին և նույնիսկ ռեսուրսների ցուցակներին (քանի դեռ դրանց երկարությունը կարող է որոշվել պլանավորման ժամանակ), բայց ոչ հաշվարկված ռեսուրսի ելքային փոփոխականներին:

count-ը և for_each-ը չեն կարող օգտագործվել մոդուլի կազմաձևման մեջ

Մի օր դուք կարող եք գայթակղվել ձեր մոդուլի կազմաձևում ավելացնել հաշվարկի պարամետր.

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

     count = 3

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

Այս կոդը փորձում է օգտագործել count-ը մոդուլի ներսում՝ ստեղծելու վեբսերվեր-կլաստերի ռեսուրսի երեք օրինակ: Կամ գուցե ցանկանաք մոդուլի միացումը պարտադիր դարձնել որոշ բուլյան պայմանի հիման վրա՝ դրա հաշվառման պարամետրը դնելով 0-ի: Սա կարող է թվալ ողջամիտ կոդ, բայց դուք կստանաք այս սխալը, երբ գործարկում եք terraform plan-ը.

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.

Ցավոք, Terraform 0.12.6-ի դրությամբ մոդուլի ռեսուրսում count կամ for_each-ի օգտագործումը չի աջակցվում: Համաձայն Terraform 0.12 թողարկման նշումների (http://bit.ly/3257bv4), HashiCorp-ը նախատեսում է ապագայում ավելացնել այս հնարավորությունը, ուստի կախված նրանից, թե երբ եք կարդում այս գիրքը, այն կարող է արդեն հասանելի լինել: Հաստատ պարզելու համար, կարդացեք Terraform փոփոխության լոգն այստեղ.

Զրոյական պարապուրդի տեղակայման սահմանափակումները

Create_before_destroy բլոկի օգտագործումը ASG-ի հետ համատեղ հիանալի լուծում է զրոյական դադարի տեղակայումներ ստեղծելու համար, բացառությամբ մեկ նախազգուշացման. ավտոմատ մասշտաբավորման կանոնները չեն ապահովվում: Կամ ավելի ճշգրիտ լինելու համար, սա վերականգնում է ASG-ի չափը փոքր չափի յուրաքանչյուր տեղակայման դեպքում, ինչը կարող է խնդիր լինել, եթե դուք օգտագործում եք ավտոմատ մասշտաբավորման կանոններ՝ աշխատող սերվերների թիվը մեծացնելու համար:

Օրինակ, webserver-cluster մոդուլը պարունակում է մի զույգ aws_autoscaling_schedule ռեսուրսներ, որոնք առավոտյան ժամը 9-ին կլաստերի սերվերների թիվը երկուսից ավելացնում են տասի: Եթե ​​դուք տեղակայեք, ասենք, առավոտյան ժամը 11-ին, նոր ASG-ը կգործարկվի ընդամենը երկու սերվերով, քան տասը և այդպես կմնա մինչև հաջորդ օրը առավոտյան ժամը 9-ը:

Այս սահմանափակումը կարելի է շրջանցել մի քանի եղանակներով.

  • Փոխեք aws_autoscaling_schedule-ի կրկնության պարամետրը 0 9 * * * («վազել առավոտյան 9-ին») մինչև 0-59 9-17 * * * («վազել ամեն րոպե առավոտյան 9-ից մինչև երեկոյան 5-ը»): Եթե ​​ASG-ն արդեն ունի տասը սերվեր, ապա այս autoscaling կանոնը նորից գործարկելը ոչինչ չի փոխի, ինչը մենք ուզում ենք: Բայց եթե ASG-ը միայն վերջերս է գործարկվել, այս կանոնը կապահովի, որ առավելագույնը մեկ րոպեում նրա սերվերների թիվը կհասնի տասի։ Սա ամբողջովին էլեգանտ մոտեցում չէ, և մեծ թռիչքները տասը սերվերից երկու սերվերից և ետ կարող են նաև խնդիրներ առաջացնել օգտվողների համար:
  • Ստեղծեք հատուկ սկրիպտ, որն օգտագործում է AWS API-ը՝ ASG-ում ակտիվ սերվերների քանակը որոշելու համար, կանչեք այն՝ օգտագործելով արտաքին տվյալների աղբյուրը (տես «Տվյալների արտաքին աղբյուր» էջ 249) և սահմանեք ASG-ի wish_capacity պարամետրը վերադարձված արժեքին: սցենարը։ Այսպիսով, ASG-ի յուրաքանչյուր նոր օրինակ միշտ կաշխատի նույն հզորությամբ, ինչ գործող Terraform կոդը և ավելի դժվարացնում է դրա պահպանումը:

Իհարկե, Terraform-ը իդեալականորեն կունենա ներկառուցված աջակցություն զրոյական ժամանակի տեղակայման համար, սակայն 2019 թվականի մայիսի դրությամբ HashiCorp-ի թիմը մտադիր չէր ավելացնել այս գործառույթը (մանրամասները՝ այստեղ).

Ճիշտ պլանը կարող է անհաջող կյանքի կոչվել

Երբեմն պլանի հրամանը ստեղծում է միանգամայն ճիշտ տեղակայման պլան, սակայն կիրառել հրամանը վերադարձնում է սխալ: Փորձեք, օրինակ, ավելացնել aws_iam_user ռեսուրսը նույն անունով, որն օգտագործել եք IAM օգտվողի համար, որը նախկինում ստեղծել եք Գլուխ 2-ում:

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

Այժմ, եթե գործարկեք պլանի հրամանը, Terraform-ը կթողարկի թվացյալ ողջամիտ տեղակայման պլան.

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.

Եթե ​​գործարկեք դիմում հրամանը, կստանաք հետևյալ սխալը.

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

Խնդիրն, իհարկե, այն է, որ այդ անունով IAM-ի օգտատեր արդեն գոյություն ունի: Եվ դա կարող է պատահել ոչ միայն IAM-ի օգտատերերի, այլ գրեթե ցանկացած ռեսուրսի հետ: Հնարավոր է, որ ինչ-որ մեկը ստեղծեց այս ռեսուրսը ձեռքով կամ օգտագործելով հրամանի տողը, բայց ցանկացած դեպքում, ID-ների համապատասխանությունը հանգեցնում է կոնֆլիկտների: Այս սխալի բազմաթիվ տարբերակներ կան, որոնք հաճախ անակնկալի են բերում Terraform-ի նորեկներին:

Հիմնական կետն այն է, որ terraform plan հրամանը հաշվի է առնում միայն այն ռեսուրսները, որոնք նշված են Terraform պետական ​​ֆայլում: Եթե ​​ռեսուրսները ստեղծվեն որևէ այլ ձևով (օրինակ՝ ձեռքով սեղմելով AWS վահանակի վրա), դրանք չեն հայտնվի պետական ​​ֆայլում և, հետևաբար, Terraform-ը դրանք հաշվի չի առնի պլանի հրամանը կատարելիս: Արդյունքում առաջին հայացքից ճիշտ թվացող ծրագիրն անհաջող կստացվի։

Այստեղից կարելի է երկու դաս քաղել:

  • Եթե ​​արդեն սկսել եք աշխատել Terraform-ի հետ, մի օգտագործեք այլ բան: Եթե ​​ձեր ենթակառուցվածքի մի մասը կառավարվում է Terraform-ի միջոցով, դուք այլևս չեք կարող այն ձեռքով փոփոխել: Հակառակ դեպքում, դուք ոչ միայն վտանգում եք Terraform-ի տարօրինակ սխալները, այլև ժխտում եք IaC-ի առավելություններից շատերը, քանի որ կոդը այլևս չի լինի ձեր ենթակառուցվածքի ճշգրիտ ներկայացումը:
  • Եթե ​​դուք արդեն ունեք որոշակի ենթակառուցվածք, օգտագործեք ներմուծման հրամանը: Եթե ​​դուք սկսում եք օգտագործել Terraform-ը գոյություն ունեցող ենթակառուցվածքով, կարող եք այն ավելացնել պետական ​​ֆայլում՝ օգտագործելով terraform import հրամանը: Այս կերպ Terraform-ը կիմանա, թե ինչ ենթակառուցվածք է պետք կառավարել: Ներմուծման հրամանը վերցնում է երկու արգումենտ: Առաջինը ռեսուրսի հասցեն է ձեր կազմաձևման ֆայլերում: Այստեղ շարահյուսությունը նույնն է, ինչ ռեսուրսների հղումների դեպքում՝ _. (ինչպես aws_iam_user.existing_user): Երկրորդ փաստարկը ներմուծվող ռեսուրսի ID-ն է: Ենթադրենք, aws_iam_user ռեսուրսի ID-ն օգտվողի անունն է (օրինակ, yevgeniy.brikman), իսկ ռեսուրսի ID-ն aws_instance-ը EC2 սերվերի ID-ն է (ինչպես i-190e22e5): Ինչպես ներմուծել ռեսուրս, սովորաբար նշվում է իր էջի ներքևում գտնվող փաստաթղթերում:

    Ստորև բերված է ներմուծման հրամանը, որը համաժամացնում է aws_iam_user ռեսուրսը, որը դուք ավելացրել եք ձեր Terraform կոնֆիգուրացիային Գլուխ 2-ում IAM օգտագործողի հետ միասին (իհարկե, փոխարինելով ձեր անունը yevgeniy.brikman-ով):

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Terraform-ը կկանչի AWS API՝ գտնելու ձեր IAM օգտատիրոջը և ստեղծի պետական ​​ֆայլային կապ նրա և aws_iam_user.existing_user ռեսուրսի միջև՝ ձեր Terraform կազմաձևում: Այսուհետ, երբ գործարկեք plan հրամանը, Terraform-ը կիմանա, որ IAM-ի օգտատերն արդեն գոյություն ունի և չի փորձի այն նորից ստեղծել:

    Հարկ է նշել, որ եթե դուք արդեն ունեք շատ ռեսուրսներ, որոնք ցանկանում եք ներմուծել Terraform, ծածկագիրը ձեռքով գրելը և յուրաքանչյուրը մեկ-մեկ ներմուծելը կարող է դժվարություն առաջացնել: Այսպիսով, արժե փնտրել այնպիսի գործիք, ինչպիսին է Terraforming-ը (http://terraforming.dtan4.net/), որը կարող է ավտոմատ կերպով ներմուծել կոդը և վիճակագրությունը ձեր AWS հաշվից:

    Refactoring-ը կարող է ունենալ իր որոգայթները

    Refactoring սովորական պրակտիկա է ծրագրավորման մեջ, որտեղ դուք փոխում եք կոդի ներքին կառուցվածքը՝ արտաքին վարքագիծը թողնելով անփոփոխ: Սա կոդն ավելի պարզ, կոկիկ և պահպանումն ավելի հեշտ դարձնելու համար է: Refactoring-ը անփոխարինելի տեխնիկա է, որը պետք է պարբերաբար օգտագործվի: Բայց երբ խոսքը վերաբերում է Terraform-ին կամ IaC-ի ցանկացած այլ գործիքին, դուք պետք է չափազանց զգույշ լինեք, թե ինչ նկատի ունեք կոդի «արտաքին վարքագիծ» ասելով, հակառակ դեպքում կառաջանան անսպասելի խնդիրներ:

    Օրինակ, վերաֆակտորինգի սովորական տեսակն է փոփոխականների կամ ֆունկցիաների անունները ավելի հասկանալիներով փոխարինելը: Շատ IDE-ներ ունեն ներկառուցված աջակցություն վերամշակման համար և կարող են ավտոմատ կերպով վերանվանել փոփոխականներն ու գործառույթները ողջ նախագծի ընթացքում: Ընդհանուր նշանակության ծրագրավորման լեզուներում սա աննշան պրոցեդուրա է, որի մասին գուցե չմտածեք, բայց Terraform-ում դուք պետք է չափազանց զգույշ լինեք դրա հետ, հակառակ դեպքում կարող եք ընդհատումներ ունենալ:

    Օրինակ, webserver-cluster մոդուլն ունի մուտքագրման փոփոխական cluster_name:

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

    Պատկերացրեք, որ դուք սկսել եք օգտագործել այս մոդուլը՝ foo կոչվող միկրոսերվիսը տեղակայելու համար: Ավելի ուշ դուք ցանկանում եք վերանվանել ձեր ծառայությունը բարի: Այս փոփոխությունը կարող է չնչին թվալ, բայց իրականում այն ​​կարող է ծառայության խափանումներ առաջացնել:

    Փաստն այն է, որ վեբսերվեր-կլաստերի մոդուլը օգտագործում է cluster_name փոփոխականը մի շարք ռեսուրսներում, ներառյալ անվտանգության երկու խմբերի անվան պարամետրը և 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]
    }

    Եթե ​​դուք փոխեք անվանման պարամետրը ռեսուրսի վրա, Terraform-ը կջնջի այդ ռեսուրսի հին տարբերակը և դրա փոխարեն կստեղծի նորը: Բայց եթե այդ ռեսուրսը ALB է, այն ջնջելու և նոր տարբերակ ներբեռնելու միջև, դուք չեք ունենա երթևեկությունը ձեր վեբ սերվերին վերահղելու մեխանիզմ: Նմանապես, եթե անվտանգության խումբը ջնջվի, ձեր սերվերները կսկսեն մերժել ցանցի ցանկացած տրաֆիկ մինչև նոր խումբ ստեղծվի:

    Վերագործարկման մեկ այլ տեսակ, որը ձեզ կարող է հետաքրքրել, Terraform ID-ի փոփոխությունն է: Եկեք որպես օրինակ վերցնենք aws_security_group ռեսուրսը webserver-cluster մոդուլում.

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

    Այս ռեսուրսի նույնացուցիչը կոչվում է օրինակ: Պատկերացրեք, որ վերամշակման ժամանակ որոշեցիք փոխել այն ավելի հասկանալի (ձեր կարծիքով) անվանման cluster_instance:

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

    Ի՞նչ է լինելու վերջում։ Ճիշտ է. խանգարում:

    Terraform-ը կապում է յուրաքանչյուր ռեսուրսի ID-ի ամպային մատակարարի ID-ի հետ: Օրինակ, iam_user-ը կապված է AWS IAM օգտվողի ID-ի հետ, իսկ aws_instance-ը կապված է AWS EC2 սերվերի ID-ի հետ: Եթե ​​փոխեք ռեսուրսի ID-ն (ասենք օրինակից cluster_instance, ինչպես դա տեղի է ունենում aws_security_group-ի դեպքում), Terraform-ի կհայտնվի, կարծես ջնջել եք հին ռեսուրսը և ավելացրել եք նորը: Եթե ​​դուք կիրառեք այս փոփոխությունները, Terraform-ը կջնջի անվտանգության հին խումբը և կստեղծի նորը, մինչդեռ ձեր սերվերները կսկսեն մերժել ցանցի ցանկացած տրաֆիկ:

    Ահա չորս հիմնական դասեր, որոնք դուք պետք է վերցնեք այս քննարկումից:

    • Միշտ օգտագործեք պլանի հրամանը: Այն կարող է բացահայտել այս բոլոր խոչընդոտները: Զգուշորեն վերանայեք դրա արդյունքը և ուշադրություն դարձրեք այն իրավիճակներին, երբ Terraform-ը նախատեսում է ջնջել ռեսուրսները, որոնք, ամենայն հավանականությամբ, չպետք է ջնջվեն:
    • Ստեղծեք նախքան ջնջելը: Եթե ​​ցանկանում եք փոխարինել ռեսուրսը, նախքան բնօրինակը ջնջելը, ուշադիր մտածեք, թե արդյոք անհրաժեշտ է ստեղծել փոխարինում: Եթե ​​պատասխանը այո է, ապա create_before_destroy-ը կարող է օգնել: Նույն արդյունքին կարելի է ձեռքով հասնել՝ կատարելով երկու քայլ՝ սկզբում ավելացրեք նոր ռեսուրս կոնֆիգուրացիայի մեջ և գործարկեք հավելվածի հրամանը, այնուհետև հեռացրեք հին ռեսուրսը կազմաձևից և նորից օգտագործեք կիրառել հրամանը։
    • Նույնացուցիչները փոխելը պահանջում է փոխել վիճակը: Եթե ​​ցանկանում եք փոխել ռեսուրսի հետ կապված ID-ն (օրինակ՝ վերանվանել aws_security_group-ը օրինակից դեպի cluster_instance) առանց ռեսուրսը ջնջելու և դրա նոր տարբերակ ստեղծելու, դուք պետք է համապատասխանաբար թարմացնեք Terraform պետական ​​ֆայլը։ Երբեք դա մի արեք ձեռքով, փոխարենը օգտագործեք terraform state հրամանը: Նույնացուցիչները վերանվանելիս դուք պետք է գործարկեք terraform state mv հրամանը, որն ունի հետևյալ շարահյուսությունը.
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      ORIGINAL_REFERENCE արտահայտությունն է, որը վերաբերում է ռեսուրսին իր ներկայիս տեսքով, և NEW_REFERENCE-ն այն տեղն է, որտեղ դուք ցանկանում եք տեղափոխել այն: Օրինակ, aws_security_group խումբը օրինակից cluster_instance վերանվանելիս պետք է գործարկել հետևյալ հրամանը.

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      Սա ասում է Terraform-ին, որ այն վիճակը, որը նախկինում կապված էր aws_security_group.instance-ի հետ, այժմ պետք է կապված լինի aws_security_group.cluster_instance-ի հետ: Եթե ​​այս հրամանը վերանվանելուց և գործարկելուց հետո terraform plan-ը որևէ փոփոխություն չի ցուցադրում, ապա դուք ամեն ինչ ճիշտ եք արել:

    • Որոշ կարգավորումներ հնարավոր չէ փոխել: Շատ ռեսուրսների պարամետրերն անփոփոխ են։ Եթե ​​փորձեք դրանք փոխել, Terraform-ը կջնջի հին ռեսուրսը և դրա փոխարեն կստեղծի նորը: Յուրաքանչյուր ռեսուրսի էջ սովորաբար ցույց է տալիս, թե ինչ է տեղի ունենում, երբ դուք փոխում եք որոշակի կարգավորում, այնպես որ համոզվեք, որ ստուգեք փաստաթղթերը: Միշտ օգտագործեք պլանի հրամանը և մտածեք «create_before_destroy» ռազմավարության մասին:

    Հետաձգված հետևողականությունը համահունչ է... հետաձգմանը

    Որոշ ամպային մատակարարների API-ներ, ինչպիսիք են AWS-ը, ասինխրոն են և ունեն հետաձգված հետևողականություն: Ասինխրոնությունը նշանակում է, որ ինտերֆեյսը կարող է անմիջապես պատասխան տալ՝ չսպասելով պահանջվող գործողության ավարտին: Հետաձգված հետևողականությունը նշանակում է, որ փոփոխությունները կարող են ժամանակ պահանջել համակարգում տարածվելու համար. մինչ դա տեղի է ունենում, ձեր պատասխանները կարող են լինել անհամապատասխան և կախված այն բանից, թե որ տվյալների աղբյուրի կրկնօրինակն է արձագանքում ձեր API զանգերին:

    Պատկերացրեք, օրինակ, որ դուք API զանգ եք անում AWS-ին՝ խնդրելով ստեղծել EC2 սերվեր: API-ն գրեթե ակնթարթորեն կվերադարձնի «հաջող» պատասխանը (ստեղծվել է 201), առանց սպասելու սերվերի ստեղծմանը: Եթե ​​փորձեք անմիջապես միանալ դրան, այն գրեթե անկասկած կձախողվի, քանի որ այդ պահին AWS-ը դեռ սկզբնավորում է ռեսուրսները, կամ, որպես այլընտրանք, սերվերը դեռ չի բեռնվել: Ավելին, եթե այս սերվերի մասին տեղեկություններ ստանալու համար մեկ այլ զանգ կատարեք, կարող եք սխալ ստանալ (404 Not Found): Բանն այն է, որ այս EC2 սերվերի մասին տեղեկատվությունը դեռևս կարող է տարածվել AWS-ում, մինչև այն հասանելի դառնա ամենուր, դուք պետք է սպասեք մի քանի վայրկյան:

    Ամեն անգամ, երբ դուք օգտագործում եք ասինխրոն API՝ ծույլ հետևողականությամբ, դուք պետք է պարբերաբար կրկնեք ձեր հարցումը, մինչև գործողությունն ավարտվի և տարածվի համակարգի միջոցով: Ցավոք, AWS SDK-ն դրա համար ոչ մի լավ գործիք չի տրամադրում, և Terraform նախագիծը նախկինում տառապում էր 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

    Այսինքն՝ դու ստեղծում ես ռեսուրս (ինչպես ենթացանցը), հետո փորձում ես դրա մասին ինչ-որ տեղեկություն ստանալ (ինչպես նորաստեղծ ենթացանցի ID-ն), իսկ Terraform-ը չի կարողանում գտնել այն։ Այս վրիպակների մեծ մասը (ներառյալ 6813-ը) շտկվել են, բայց դրանք դեռ ժամանակ առ ժամանակ հայտնվում են, հատկապես, երբ Terraform-ն աջակցություն է ավելացնում ռեսուրսի նոր տեսակի համար: Սա նյարդայնացնում է, բայց շատ դեպքերում ոչ մի վնաս չի պատճառում: Երբ նորից գործարկեք terraform application-ը, ամեն ինչ պետք է աշխատի, քանի որ այս պահին տեղեկատվությունը արդեն տարածված կլինի համակարգով մեկ:

    Այս հատվածը ներկայացված է Եվգենի Բրիկմանի գրքից «Terraform. ենթակառուցվածք կոդի մակարդակով».

Source: www.habr.com

Добавить комментарий