pitfalls Terraform

pitfalls Terraform
Hayu urang nyorot sababaraha pitfalls, kaasup nu patali jeung loop, lamun pernyataan jeung téhnik deployment, kitu ogé masalah leuwih umum nu mangaruhan Terraform sacara umum:

  • count na for_each parameter boga watesan;
  • ngawatesan enol downtime deployments;
  • malah rencana alus bisa gagal;
  • refactoring tiasa gaduh pitfalls na;
  • kohérénsi ditunda konsisten ... kalawan deferral.

The count jeung for_each parameter boga watesan

Conto dina bab ieu ngagunakeun éksténsif parameter count jeung for_each ekspresi dina loop jeung logika kondisional. Aranjeunna ngalaksanakeun saé, tapi aranjeunna gaduh dua watesan penting anu anjeun kedah perhatosan.

  • Count and for_each teu tiasa ngarujuk kana variabel kaluaran sumber daya.
  • count na for_each teu bisa dipaké dina konfigurasi modul.

count sareng for_each teu tiasa ngarujuk kana variabel kaluaran sumberdaya

Bayangkeun anjeun kedah nyebarkeun sababaraha server EC2 sareng pikeun sababaraha alesan anjeun henteu hoyong nganggo ASG. Kode anjeun tiasa sapertos kieu:

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

Hayu urang tingali aranjeunna hiji-hiji.

Kusabab parameter count disetel ka nilai statik, kode ieu bakal jalan tanpa masalah: mun anjeun ngajalankeun paréntah nerapkeun, bakal nyieun tilu server EC2. Tapi kumaha upami anjeun hoyong nyebarkeun hiji server dina unggal Availability Zone (AZ) dina wilayah AWS anjeun ayeuna? Anjeun tiasa gaduh kode anjeun ngamuat daptar zona tina sumber data aws_availability_zones teras puteran masing-masing sareng ngadamel server EC2 di jerona nganggo parameter count sareng aksés indéks array:

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

Kode ieu ogé tiasa dianggo saé, sabab parameter count tiasa ngarujuk sumber data tanpa aya masalah. Tapi naon anu lumangsung lamun jumlah server anjeun kudu nyieun gumantung kana kaluaran sababaraha sumberdaya? Pikeun nunjukkeun ieu, cara panggampangna nyaéta ngagunakeun sumberdaya random_integer, anu, sakumaha nami nunjukkeun, mulihkeun integer acak:

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

Kode ieu ngahasilkeun angka acak antara 1 jeung 3. Hayu urang tingali naon kajadian lamun urang coba ngagunakeun kaluaran sumberdaya ieu dina parameter count tina sumberdaya aws_instance:

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

Upami anjeun ngajalankeun rencana terraform dina kode ieu, anjeun bakal nampi kasalahan ieu:

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 merlukeun count jeung for_each diitung salila fase perencanaan, saméméh sagala sumberdaya dijieun atawa dirobah. Ieu ngandung harti yén count jeung for_each bisa ngarujuk kana literals, variabel, sumber data, komo daptar sumberdaya (salami panjang maranéhanana bisa ditangtukeun dina waktu scheduling), tapi teu diitung variabel kaluaran sumberdaya.

count na for_each teu bisa dipaké dina konfigurasi modul

Someday Anjeun bisa jadi cocoba pikeun nambahkeun parameter count kana konfigurasi modul anjeun:

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

     count = 3

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

Kode ieu nyobian ngagunakeun cacah dina modul pikeun nyieun tilu salinan sumberdaya webserver-cluster. Atanapi anjeun badé ngajantenkeun ngahubungkeun modul opsional dumasar kana sababaraha kaayaan Boolean ku netepkeun parameter count na ka 0. Ieu sigana sapertos kode anu wajar, tapi anjeun bakal nampi kasalahan ieu nalika ngajalankeun rencana terraform:

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.

Hanjakal, dina Terraform 0.12.6, ngagunakeun count atanapi for_each dina sumberdaya modul teu dirojong. Numutkeun kana catetan pelepasan Terraform 0.12 (http://bit.ly/3257bv4), HashiCorp ngarencanakeun pikeun nambihan kamampuan ieu di hareup, janten gumantung kana nalika anjeun maca buku ieu, éta tiasa sayogi. Pikeun manggihan pasti, baca Terraform changelog dieu.

Watesan Zero Downtime Deployments

Ngagunakeun blok create_before_destroy dina kombinasi kalayan ASG mangrupakeun leyuran gede pikeun nyieun deployments enol-downtime, iwal hiji caveat: aturan autoscaling teu dirojong. Atanapi langkung tepatna, ieu ngareset ukuran ASG deui ka min_size dina unggal panyebaran, anu tiasa janten masalah upami anjeun nganggo aturan autoscaling pikeun ningkatkeun jumlah server anu ngajalankeun.

Contona, modul webserver-cluster ngandung sapasang sumberdaya aws_autoscaling_schedule, nu di 9 am ngaronjatkeun jumlah server dina klaster tina dua nepi ka sapuluh. Upami anjeun nyebarkeun dina, sebutkeun, jam 11, ASG énggal bakal ngamimitian ngan ukur dua server tibatan sapuluh sareng tetep dugi ka jam 9 énjing.

watesan ieu bisa circumvented ku sababaraha cara.

  • Ngarobah parameter ulang dina aws_autoscaling_schedule tina 0 9 * * * ("ngajalankeun di 9 am") kana hal kawas 0-59 9-17 * * * ("ngajalankeun unggal menit ti 9 am ka 5 pm"). Lamun ASG geus boga sapuluh server, ngajalankeun aturan autoscaling ieu deui moal ngarobah nanaon, nu urang hayang. Tapi lamun ASG geus ngan nembe geus deployed, aturan ieu bakal mastikeun yén dina maksimum hiji menit jumlah server na bakal ngahontal sapuluh. Ieu sanes pendekatan sagemblengna elegan, sarta jumps badag ti sapuluh nepi ka dua server na deui ogé bisa ngabalukarkeun masalah pikeun pamaké.
  • Jieun skrip custom anu ngagunakeun API AWS pikeun nangtukeun jumlah server aktip dina ASG, nelepon deui ngagunakeun sumber data éksternal (tingali "Sumber Data éksternal" dina kaca 249), tur nyetel parameter desired_capacity ASG kana nilai balik ku. naskah. Ku cara ieu, unggal instance ASG anyar bakal salawasna ngajalankeun dina kapasitas anu sarua sakumaha kodeu Terraform aya tur ngajadikeun eta leuwih hese pikeun mulasara.

Tangtosna, Terraform idéalna bakal gaduh dukungan anu diwangun pikeun panyebaran enol-downtime, tapi ti Méi 2019, tim HashiCorp henteu ngagaduhan rencana pikeun nambihan fungsionalitas ieu (rinci - dieu).

Rencana anu leres tiasa dilaksanakeun henteu suksés

Kadang-kadang paréntah rencana ngahasilkeun rencana panyebaran anu leres-leres, tapi paréntah panawaran masihan kasalahan. Coba, contona, tambahkeun sumber daya aws_iam_user sareng nami anu sami anu anjeun anggo pikeun pangguna IAM anu anjeun damel sateuacana dina Bab 2:

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

Ayeuna, upami anjeun ngajalankeun paréntah rencana, Terraform bakal ngaluarkeun rencana penyebaran anu lumayan:

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.

Upami anjeun ngajalankeun paréntah panawaran anjeun bakal nampi kasalahan ieu:

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

Masalahna, tangtosna, nyaéta pangguna IAM kalayan nami éta parantos aya. Sareng ieu tiasa kajantenan henteu ngan ukur pikeun pangguna IAM, tapi pikeun ampir sagala sumber. Aya kamungkinan yén aya anu nyiptakeun sumber ieu sacara manual atanapi nganggo garis paréntah, tapi kumaha waé, cocog ID ngabalukarkeun konflik. Aya loba variasi kasalahan ieu nu mindeng nyekel pendatang ka Terraform ku reuwas.

Titik konci éta paréntah rencana terraform ngan nyokot akun eta sumberdaya nu dieusian dina file kaayaan Terraform. Lamun sumberdaya dijieun dina sababaraha cara séjén (Contona, sacara manual ku ngaklik dina konsol AWS), aranjeunna moal mungkas nepi di file kaayaan sahingga Terraform moal nyandak kana rekening nalika ngajalankeun paréntah rencana. Hasilna, rencana anu sigana bener dina glance kahiji bakal tétéla gagal.

Aya dua palajaran pikeun diajar tina ieu.

  • Upami anjeun parantos ngamimitian damel sareng Terraform, ulah nganggo anu sanés. Upami bagian tina infrastruktur anjeun dikokolakeun nganggo Terraform, anjeun moal tiasa ngarobih deui sacara manual. Upami teu kitu, anjeun teu ngan risiko kasalahan Terraform aneh, tapi anjeun ogé negate loba mangpaat IaC saprak kode moal deui ngagambarkeun akurat infrastruktur Anjeun.
  • Upami anjeun parantos ngagaduhan sababaraha infrastruktur, paké paréntah impor. Upami anjeun mimiti nganggo Terraform sareng infrastruktur anu tos aya, anjeun tiasa nambihanana kana file kaayaan nganggo paréntah impor terraform. Ku cara ieu Terraform bakal terang naon infrastruktur anu kedah diurus. Paréntah impor nyandak dua argumen. Anu kahiji nyaéta alamat sumberdaya dina file konfigurasi anjeun. Sintaksis di dieu sami sareng tautan sumber: _. (sapertos aws_iam_user.existing_user). Argumen kadua nyaéta ID sumberdaya pikeun diimpor. Hayu urang nyebutkeun sumberdaya ID aws_iam_user nyaeta ngaran pamaké (Contona, yevgeniy.brikman), sarta sumberdaya ID aws_instance nyaeta ID server EC2 (siga i-190e22e5). Kumaha ngimpor sumber daya biasana dituduhkeun dina dokuméntasi di handapeun halamanna.

    Di handap ieu paréntah impor nu nyingkronkeun sumberdaya aws_iam_user nu ditambahkeun kana konfigurasi Terraform anjeun babarengan jeung pamaké IAM dina Bab 2 (ngaganti ngaran anjeun yevgeniy.brikman, tangtosna):

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Terraform bakal nelepon API AWS pikeun manggihan pamaké IAM anjeun sarta nyieun pakait file kaayaan antara eta jeung sumberdaya aws_iam_user.existing_user dina konfigurasi Terraform Anjeun. Ti ayeuna, nalika anjeun ngajalankeun paréntah rencana, Terraform bakal terang yén pangguna IAM parantos aya sareng moal nyobian nyiptakeunana deui.

    Perlu dicatet yén upami anjeun parantos gaduh seueur sumber anu anjeun hoyong impor kana Terraform, nyerat kodeu sacara manual sareng ngimpor masing-masing sakaligus tiasa janten repot. Janten patut ningali kana alat sapertos Terraforming (http://terraforming.dtan4.net/), anu tiasa otomatis ngimpor kode sareng kaayaan tina akun AWS anjeun.

    Refactoring tiasa gaduh pitfalls na

    Refactoring mangrupakeun prakték umum dina programming dimana anjeun ngarobah struktur internal kode bari ninggalkeun kabiasaan éksternal unchanged. Ieu kanggo ngajantenkeun kodeu langkung jelas, langkung rapih, sareng langkung gampang dijaga. Refactoring mangrupikeun téknik anu penting anu kedah dianggo sacara teratur. Tapi lamun datang ka Terraform atanapi alat IaC anu sanés, anjeun kedah ati-ati pisan ngeunaan naon anu anjeun maksud ku "kalakuan éksternal" sapotong kode, upami henteu masalah anu teu kaduga bakal timbul.

    Salaku conto, jinis refactoring anu umum nyaéta ngagentos nami variabel atanapi fungsi ku anu langkung kaharti. Seueur IDE gaduh dukungan anu diwangun pikeun refactoring sareng tiasa sacara otomatis ngaganti ngaran variabel sareng fungsi sapanjang proyék. Dina basa programming-tujuan umum, ieu prosedur trivial nu bisa jadi teu mikir ngeunaan, tapi di Terraform anjeun kudu ati pisan jeung ieu, disebutkeun Anjeun bisa ngalaman outages.

    Contona, modul webserver-cluster boga input variabel cluster_name:

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

    Bayangkeun yén anjeun mimiti nganggo modul ieu pikeun nyebarkeun microservice anu disebut foo. Engké, anjeun hoyong ngaganti ngaran jasa anjeun kana bar. Parobihan ieu sigana sepele, tapi dina kanyataanana tiasa nyababkeun gangguan jasa.

    Kanyataanna nyaéta modul webserver-cluster ngagunakeun variabel cluster_name dina sababaraha sumber, kalebet parameter nami dua grup kaamanan sareng 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]
    }

    Lamun anjeun ngarobah parameter ngaran dina sumberdaya a, Terraform bakal ngahapus versi heubeul tina sumberdaya éta sarta nyieun nu anyar dina tempatna. Tapi upami sumberdaya éta mangrupikeun ALB, antara ngahapus sareng ngaunduh versi énggal, anjeun moal gaduh mékanisme pikeun alihan lalu lintas ka server wéb anjeun. Kitu ogé, upami grup kaamanan dihapus, pangladén anjeun bakal mimiti nampik lalu lintas jaringan dugi ka grup énggal diciptakeun.

    Jenis refactoring sanés anu anjeun pikahoyong nyaéta ngarobih ID Terraform. Hayu urang nyandak sumberdaya aws_security_group dina modul webserver-cluster salaku conto:

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

    Identifier tina sumberdaya ieu disebut instance. Bayangkeun yén salami refactoring anjeun mutuskeun pikeun ngarobih kana nami cluster_instance anu langkung kaharti (dina pendapat anjeun):

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

    Naon anu bakal kajadian dina tungtungna? Éta leres: gangguan.

    Terraform ngahubungkeun unggal ID sumberdaya sareng ID panyadia awan. Contona, iam_user pakait sareng ID pamaké AWS IAM, sarta aws_instance pakait sareng ID server AWS EC2. Lamun ngarobah ID sumberdaya (sebutkeun ti conto ka cluster_instance, sakumaha dina kasus aws_security_group), mun Terraform bakal némbongan saolah-olah anjeun ngahapus sumberdaya heubeul tur nambahkeun nu anyar. Upami anjeun nerapkeun parobihan ieu, Terraform bakal ngahapus grup kaamanan anu lami sareng nyiptakeun anu énggal, sedengkeun server anjeun mimiti nampik lalulintas jaringan.

    Ieu opat palajaran konci anu anjeun kedah angkat tina diskusi ieu.

    • Salawasna nganggo paréntah rencana. Bisa nembongkeun sagala snags ieu. Tinjau kaluaranna sacara saksama sareng perhatikeun kaayaan dimana Terraform ngarencanakeun ngahapus sumber anu paling dipikaresep henteu kedah dipupus.
    • Jieun sateuacan anjeun ngahapus. Upami anjeun hoyong ngagentos sumber daya, pikirkeun sacara saksama naha anjeun kedah nyiptakeun panggantian sateuacan ngahapus sumber asli. Upami jawabanna leres, create_before_destroy tiasa ngabantosan. Hasil anu sami tiasa dihontal sacara manual ku ngalaksanakeun dua léngkah: mimitina nambihan sumber daya énggal kana konfigurasi sareng ngajalankeun paréntah panawaran, teras cabut sumberdaya lami tina konfigurasi sareng nganggo paréntah panawaran deui.
    • Ngarobah identifiers merlukeun ngarobah kaayaan. Lamun hayang ngarobah ID pakait sareng sumberdaya a (Contona, ngaganti ngaran aws_security_group ti instance ka cluster_instance) tanpa ngahapus sumberdaya jeung nyieun versi anyar eta, anjeun kudu ngamutahirkeun file kaayaan Terraform sasuai. Pernah ngalakukeun ieu sacara manual - nganggo paréntah kaayaan terraform gantina. Nalika ngaganti ngaran identifier, anjeun kedah ngajalankeun paréntah mv state terraform, anu ngagaduhan sintaksis ieu:
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      ORIGINAL_REFERENCE mangrupa ekspresi nu nujul kana sumberdaya dina formulir na ayeuna, sarta NEW_REFERENCE nyaeta dimana anjeun hoyong mindahkeun éta. Contona, nalika ngaganti ngaran grup aws_security_group tina instance ka cluster_instance, anjeun kedah ngajalankeun paréntah di handap ieu:

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      Ieu ngabejaan Terraform yén kaayaan nu saméméhna pakait sareng aws_security_group.instance ayeuna kedah pakait sareng aws_security_group.cluster_instance. Upami saatos ngaganti nami sareng ngajalankeun paréntah ieu rencana terraform henteu nunjukkeun parobihan, maka anjeun ngalakukeun sadayana leres.

    • Sababaraha setélan teu bisa dirobah. Parameter tina seueur sumber daya teu tiasa dirobih. Upami anjeun nyobian ngarobih aranjeunna, Terraform bakal ngahapus sumberdaya anu lami sareng nyiptakeun anu énggal dina tempatna. Unggal halaman sumberdaya biasana bakal nunjukkeun naon anu lumangsung nalika anjeun ngarobih setélan khusus, janten pastikeun pariksa dokuméntasi. Salawasna nganggo paréntah rencana sarta mertimbangkeun ngagunakeun strategi create_before_destroy.

    Konsistensi ditunda konsisten ... kalawan deferral

    Sababaraha API panyadia awan, sapertos AWS, henteu sinkron sareng konsistensi ditunda. Asynchrony hartina panganteur nu bisa langsung balik respon tanpa ngantosan Peta dipénta réngsé. Konsistensi nyangsang hartina parobahan butuh waktu pikeun nyebarkeun sakuliah sistem; bari ieu lumangsung, réspon anjeun bisa jadi inconsistent sarta gumantung kana replika sumber data nu ngarespon kana panggero API Anjeun.

    Bayangkeun, contona, anjeun nelepon API ka AWS naroskeun ngadamel server EC2. API bakal balik respon "suksés" (201 Dijieun) ampir instan, tanpa ngantosan server sorangan dijieun. Upami anjeun nyobian langsung nyambung, éta ampir pasti bakal gagal sabab dina waktos éta AWS masih ngamimitian sumber daya atanapi, alternatipna, server henteu acan boot. Leuwih ti éta, lamun nelepon sejen pikeun meunangkeun informasi ngeunaan server ieu, Anjeun bisa nampa kasalahan (404 Teu Kapanggih). Masalahna nyaéta inpormasi ngeunaan server EC2 ieu masih tiasa disebarkeun ka sakuliah AWS sateuacan sayogi di mana waé, anjeun kedah ngantosan sababaraha detik.

    Iraha waé anjeun nganggo API Asynchronous kalayan konsistensi puguh, anjeun kedah périodik nyobian deui pamundut anjeun dugi tindakanna réngsé sareng nyebarkeun ngaliwatan sistem. Hanjakalna, AWS SDK henteu nyayogikeun alat anu saé pikeun ieu, sareng proyék Terraform biasa ngalaman seueur bug sapertos 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

    Kalayan kecap sanésna, anjeun nyiptakeun sumber daya (sapertos subnet) teras cobian kéngingkeun sababaraha inpormasi ngeunaan éta (sapertos ID subnet anu nembé diciptakeun), sareng Terraform henteu tiasa mendakanana. Seuseueurna bug ieu (kaasup 6813) parantos dibenerkeun, tapi aranjeunna tetep dipotong tina waktos ka waktos, khususna nalika Terraform nambihan dukungan pikeun jinis sumberdaya énggal. Ieu bangor, tapi dina kalolobaan kasus teu ngakibatkeun ngarugikeun nanaon. Nalika anjeun ngajalankeun terraform nerapkeun deui, sadayana kedah dianggo, sabab ku waktos ayeuna inpormasina parantos sumebar ka sakumna sistem.

    excerpt ieu dibere tina buku Evgeniy Brikman "Terraform: infrastruktur dina tingkat kode".

sumber: www.habr.com

Tambahkeun komentar