Terraform pitfalls

Terraform pitfalls
Ayo nyorot sawetara pitfalls, kalebu sing ana gandhengane karo puteran, yen statement lan teknik penyebaran, uga masalah umum sing mengaruhi Terraform ing umum:

  • count lan for_each paramèter duwe watesan;
  • matesi panyebaran downtime nul;
  • malah rencana apik bisa gagal;
  • refactoring bisa duwe pitfalls sawijining;
  • koherensi tundha konsisten ... karo penundaan.

Parameter count lan for_each duwe watesan

Conto ing bab iki nggunakake ekstensif parameter count lan for_each expression ing puteran lan logika kondisional. Dheweke nindakake kanthi apik, nanging duwe rong watesan penting sing kudu dingerteni.

  • Count lan for_each ora bisa ngrujuk marang variabel output sumber daya.
  • count lan for_each ora bisa digunakake ing konfigurasi modul.

count lan for_each ora bisa ngrujuk marang variabel output sumber daya

Mbayangno sampeyan kudu masang sawetara server EC2 lan sakperangan alesan sampeyan ora pengin nggunakake ASG. Kode sampeyan bisa kaya iki:

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

Ayo padha ndeleng siji-siji.

Wiwit parameter count disetel menyang nilai statis, kode iki bakal bisa tanpa masalah: nalika sampeyan mbukak printah aplikasi, bakal nggawe telung server EC2. Nanging kepiye yen sampeyan pengin nyebarake siji server ing saben Availability Zone (AZ) ing wilayah AWS sampeyan saiki? Sampeyan bisa njaluk kode mbukak dhaptar zona saka sumber data aws_availability_zones banjur puter maneh saben siji lan nggawe server EC2 ing nggunakake parameter count lan akses indeks 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 iki uga bisa digunakake kanthi becik, amarga parameter count bisa ngrujuk sumber data tanpa masalah. Nanging apa sing kedadeyan yen jumlah server sing kudu digawe gumantung saka output sawetara sumber? Kanggo nduduhake iki, cara paling gampang yaiku nggunakake sumber random_integer, sing, kaya jeneng kasebut, ngasilake integer acak:

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

Kode iki ngasilake nomer acak antarane 1 lan 3. Ayo ndeleng apa sing kedadeyan yen kita nyoba nggunakake output saka sumber iki ing parameter count saka sumber aws_instance:

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

Yen sampeyan mbukak rencana terraform ing kode iki, sampeyan bakal entuk kesalahan ing ngisor iki:

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 mbutuhake count lan for_each diwilang sajrone tahap perencanaan, sadurunge sumber daya digawe utawa diowahi. Iki tegese count lan for_each bisa ngrujuk menyang literal, variabel, sumber data, lan malah dhaptar sumber daya (anggere dawa bisa ditemtokake ing wektu jadwal), nanging ora kanggo ngitung variabel output sumber.

count lan for_each ora bisa digunakake ing konfigurasi modul

Ing sawijining dina sampeyan bisa uga digodha kanggo nambah parameter count menyang konfigurasi modul:

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 iki nyoba nggunakake count ing modul kanggo nggawe telung salinan sumber webserver-cluster. Utawa sampeyan bisa uga pengin nggawe sambungan modul opsional gumantung sawetara kondisi Boolean kanthi nyetel parameter count kanggo 0. Iki bisa uga katon kaya kode cukup, nanging sampeyan bakal njaluk kesalahan iki nalika nglakokaké 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.

Sayange, ing Terraform 0.12.6, nggunakake count utawa for_each ing sumber modul ora didhukung. Miturut cathetan rilis Terraform 0.12 (http://bit.ly/3257bv4), HashiCorp ngrancang nambah kemampuan iki ing mangsa ngarep, dadi gumantung nalika maca buku iki, bisa uga wis kasedhiya. Kanggo ngerteni manawa, maca Terraform changelog kene.

Watesan Zero Downtime Deployments

Nggunakake pamblokiran create_before_destroy ing kombinasi karo ASG minangka solusi sing apik kanggo nggawe panyebaran nul-downtime, kajaba siji caveat: aturan autoscaling ora didhukung. Utawa luwih tepat, iki ngreset ukuran ASG bali menyang min_size ing saben penyebaran, sing bisa dadi masalah yen sampeyan nggunakake aturan autoscaling kanggo nambah jumlah server sing mlaku.

Contone, modul webserver-cluster ngemot pasangan sumber aws_autoscaling_schedule, sing jam 9 nambah jumlah server ing kluster saka loro dadi sepuluh. Yen sampeyan nyebarke ing, ngomong, 11 a.m., ASG anyar bakal boot munggah karo mung loro server tinimbang sepuluh lan tetep ing cara sing nganti 9 esuk.

Watesan iki bisa diatasi kanthi sawetara cara.

  • Ngganti parameter ambalan ing aws_autoscaling_schedule saka 0 9 * * * ("mlaku ing 9 am") kanggo kaya 0-59 9-17 * * * ("mlaku saben menit saka 9 am kanggo 5 pm"). Yen ASG wis sepuluh server, mlaku aturan autoscaling iki maneh ora bakal ngganti apa-apa, kang kita arep. Nanging yen ASG mung bubar wis disebarake, aturan iki bakal mesthekake yen ing maksimum menit nomer server sawijining bakal tekan sepuluh. Iki dudu pendekatan sing elegan, lan lompatan gedhe saka sepuluh nganti rong server lan mburi uga bisa nyebabake masalah kanggo pangguna.
  • Nggawe skrip khusus sing nggunakake API AWS kanggo nemtokake jumlah server aktif ing ASG, nelpon nggunakake sumber data eksternal (ndeleng "Sumber Data Eksternal" ing kaca 249), lan nyetel parameter ASG sing dipengini kanggo nilai bali dening naskah. Kanthi cara iki, saben instance ASG anyar bakal tansah mlaku ing kapasitas sing padha karo kode Terraform sing wis ana lan nggawe luwih angel kanggo njaga.

Mesthine, Terraform bakal duwe dhukungan sing dibangun kanggo panyebaran wektu nol, nanging wiwit Mei 2019, tim HashiCorp ora duwe rencana kanggo nambah fungsi iki (rincian - kene).

Rencana sing bener bisa uga ora bisa ditindakake

Kadhangkala printah rencana ngasilake rencana penyebaran sing bener, nanging printah aplikasi ngasilake kesalahan. Coba, contone, nambahake sumber daya aws_iam_user kanthi jeneng sing padha digunakake kanggo pangguna IAM sing digawe sadurunge ing Bab 2:

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

Saiki, yen sampeyan mbukak printah rencana, Terraform bakal ngasilake rencana penyebaran sing katon cukup:

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.

Yen sampeyan mbukak perintah aplikasi sampeyan bakal entuk kesalahan ing ngisor iki:

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

Masalahe, mesthi, pangguna IAM kanthi jeneng kasebut wis ana. Lan iki bisa kedadeyan ora mung kanggo pangguna IAM, nanging meh kabeh sumber daya. Bisa uga ana sing nggawe sumber daya iki kanthi manual utawa nggunakake baris perintah, nanging kanthi cara apa wae, ID sing cocog nyebabake konflik. Ana akeh variasi saka kesalahan iki sing asring nyekel wong anyar ing Terraform kanthi kaget.

Intine yaiku perintah rencana terraform mung njupuk sumber daya sing ditemtokake ing file negara Terraform. Yen sumber daya digawe ing sawetara cara liyane (Contone, kanthi manual kanthi ngeklik ing console AWS), padha ora bakal mungkasi munggah ing file negara lan mulane Terraform ora bakal njupuk menyang akun nalika nglakokaké printah rencana. Akibaté, rencana sing katon bener ing sepisanan bakal dadi ora kasil.

Ana rong piwulang sing bisa disinaoni saka iki.

  • Yen sampeyan wis miwiti nggarap Terraform, aja nganggo liya. Yen bagean saka infrastruktur sampeyan dikelola nggunakake Terraform, sampeyan ora bisa ngowahi kanthi manual maneh. Yen ora, sampeyan ora mung menehi risiko kesalahan Terraform sing aneh, nanging uga negate akeh keuntungan saka IaC amarga kode kasebut ora bakal dadi perwakilan akurat saka infrastruktur sampeyan.
  • Yen sampeyan wis duwe sawetara infrastruktur, gunakake printah impor. Yen sampeyan miwiti nggunakake Terraform karo infrastruktur sing wis ana, sampeyan bisa nambah menyang file negara nggunakake printah impor terraform. Kanthi cara iki, Terraform bakal ngerti apa infrastruktur sing kudu dikelola. Printah impor njupuk rong argumen. Kapisan yaiku alamat sumber daya ing file konfigurasi sampeyan. Sintaks ing kene padha karo pranala sumber: _. (kaya aws_iam_user.existing_user). Argumentasi kapindho yaiku ID sumber daya sing bakal diimpor. Ayo dadi ngomong ID sumber aws_iam_user iku jeneng pangguna (contone, yevgeniy.brikman), lan ID sumber aws_instance ID server EC2 (kaya i-190e22e5). Cara ngimpor sumber daya biasane dituduhake ing dokumentasi ing sisih ngisor kaca.

    Ing ngisor iki ana printah impor sing nyinkronake sumber aws_iam_user sing ditambahake menyang konfigurasi Terraform bebarengan karo pangguna IAM ing Bab 2 (tentu wae ngganti jeneng sampeyan yevgeniy.brikman):

    $ terraform import aws_iam_user.existing_user yevgeniy.brikman

    Terraform bakal nelpon API AWS kanggo nemokake pangguna IAM lan nggawe asosiasi file negara ing antarane lan sumber daya aws_iam_user.existing_user ing konfigurasi Terraform sampeyan. Wiwit saiki, nalika sampeyan mbukak printah rencana, Terraform bakal ngerti manawa pangguna IAM wis ana lan ora bakal nyoba nggawe maneh.

    Wigati dicathet yen sampeyan wis duwe akeh sumber daya sing pengin diimpor menyang Terraform, nulis kode kanthi manual lan ngimpor saben siji bisa dadi repot. Dadi, sampeyan kudu nggoleki alat kaya Terraforming (http://terraforming.dtan4.net/), sing bisa ngimpor kode lan negara kanthi otomatis saka akun AWS sampeyan.

    Refactoring bisa duwe pitfalls

    Refactoring iku laku umum ing program ngendi sampeyan ngganti struktur internal kode nalika ninggalake prilaku external panggah. Iki kanggo nggawe kode luwih cetha, luwih rapi, lan luwih gampang dijaga. Refactoring minangka teknik sing penting sing kudu digunakake kanthi rutin. Nanging nalika nerangake Terraform utawa alat IaC liyane, sampeyan kudu ati-ati banget babagan "prilaku eksternal" saka potongan kode, yen ora ana masalah sing ora dikarepake.

    Contone, jinis refactoring sing umum yaiku ngganti jeneng variabel utawa fungsi kanthi jeneng sing luwih bisa dingerteni. Akeh IDE duwe dhukungan kanggo refactoring lan bisa ngganti jeneng variabel lan fungsi kanthi otomatis sajrone proyek kasebut. Ing basa pamrograman umum, iki minangka prosedur sepele sing bisa uga ora sampeyan pikirake, nanging ing Terraform sampeyan kudu ati-ati banget, yen ora, sampeyan bisa ngalami gangguan.

    Contone, modul webserver-cluster duwe variabel input cluster_name:

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

    Mbayangno yen sampeyan miwiti nggunakake modul iki kanggo masang microservice disebut foo. Mengko, sampeyan pengin ngganti jeneng layanan dadi bar. Owah-owahan iki katon ora pati penting, nanging nyatane bisa nyebabake gangguan layanan.

    Kasunyatane yaiku modul kluster webserver nggunakake variabel cluster_name ing sawetara sumber, kalebu parameter jeneng rong klompok keamanan lan 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]
    }

    Yen sampeyan ngganti parameter jeneng ing sumber daya, Terraform bakal mbusak versi lawas saka sumber kasebut lan nggawe sing anyar ing panggonane. Nanging yen sumber daya iku ALB, antarane mbusak lan ngundhuh versi anyar, sampeyan ora bakal duwe mekanisme kanggo pangalihan lalu lintas menyang server web. Kajaba iku, yen grup keamanan dibusak, server sampeyan bakal wiwit nolak lalu lintas jaringan nganti grup anyar digawe.

    Jinis refactoring liyane sing bisa uga sampeyan kasengsem yaiku ngganti ID Terraform. Ayo njupuk sumber aws_security_group ing modul webserver-cluster minangka conto:

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

    Pengenal sumber daya iki diarani conto. Mbayangno yen sajrone refactoring sampeyan mutusake kanggo ngganti jeneng cluster_instance sing luwih dingerteni (miturut pendapat sampeyan):

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

    Apa sing bakal kelakon ing pungkasan? Sing bener: gangguan.

    Terraform nggandhengake saben ID sumber karo ID panyedhiya awan. Contone, iam_user digandhengake karo ID pangguna AWS IAM, lan aws_instance digandhengake karo ID server AWS EC2. Yen sampeyan ngganti ID sumber (kasebut saka conto kanggo cluster_instance, kaya kasus karo aws_security_group), Terraform bakal katon kaya sampeyan mbusak sumber lawas lan nambah sing anyar. Yen sampeyan ngetrapake owah-owahan kasebut, Terraform bakal mbusak grup keamanan lawas lan nggawe grup anyar, nalika server sampeyan wiwit nolak lalu lintas jaringan.

    Ing ngisor iki ana papat piwulang utama sing kudu dijupuk saka diskusi iki.

    • Tansah nggunakake printah rencana. Bisa mbukak kabeh snags iki. Deleng output kasebut kanthi teliti lan mbayar manungsa waé kanggo kahanan ngendi Terraform plans kanggo mbusak sumber sing paling ora kudu dibusak.
    • Nggawe sadurunge mbusak. Yen sampeyan pengin ngganti sumber daya, pikirake kanthi teliti apa sampeyan kudu nggawe panggantos sadurunge mbusak sing asli. Yen jawabane ya, create_before_destroy bisa mbantu. Asil sing padha bisa digayuh kanthi manual kanthi nindakake rong langkah: pisanan nambah sumber daya anyar kanggo konfigurasi lan mbukak printah aplikasi, banjur mbusak sumber lawas saka konfigurasi lan nggunakake printah aplikasi maneh.
    • Ngganti pengenal mbutuhake ganti status. Yen sampeyan pengin ngganti ID sing digandhengake karo sumber daya (Contone, ngganti jeneng aws_security_group saka Kayata kanggo cluster_instance) tanpa mbusak sumber lan nggawe versi anyar saka iku, sampeyan kudu nganyari file negara Terraform patut. Aja nindakake iki kanthi manual - gunakake perintah negara terraform. Nalika ngganti jeneng pengenal, sampeyan kudu mbukak perintah mv negara terraform, sing nduweni sintaks ing ngisor iki:
      terraform state mv <ORIGINAL_REFERENCE> <NEW_REFERENCE>

      ORIGINAL_REFERENCE minangka ekspresi sing nuduhake sumber daya ing wangun saiki, lan NEW_REFERENCE ing ngendi sampeyan pengin mindhah. Contone, nalika ngganti jeneng grup aws_security_group saka instance menyang cluster_instance, sampeyan kudu mbukak printah ing ngisor iki:

      $ terraform state mv 
         aws_security_group.instance 
         aws_security_group.cluster_instance

      Iki ngandhani Terraform yen negara sing sadurunge digandhengake karo aws_security_group.instance saiki kudu digandhengake karo aws_security_group.cluster_instance. Yen sawise ngganti jeneng lan nglakokake rencana terraform printah iki ora nuduhake owah-owahan, sampeyan nindakake kabeh kanthi bener.

    • Sawetara setelan ora bisa diganti. Parameter saka akeh sumber daya ora bisa diganti. Yen sampeyan nyoba ngganti, Terraform bakal mbusak sumber lawas lan nggawe sing anyar ing panggonane. Saben kaca sumber biasane bakal nuduhake apa sing kedadeyan nalika sampeyan ngganti setelan tartamtu, mula priksa dokumentasi kasebut. Tansah nggunakake printah rencana lan nimbang nggunakake strategi create_before_destroy.

    Konsistensi sing ditundha konsisten ... karo penundaan

    Sawetara API panyedhiya awan, kayata AWS, ora sinkron lan konsistensi telat. Asynchrony tegese antarmuka bisa langsung ngasilake respon tanpa ngenteni tumindak sing dijaluk rampung. Konsistensi telat tegese owah-owahan mbutuhake wektu kanggo nyebar ing saindhenging sistem; nalika iki kedadeyan, respon sampeyan bisa uga ora konsisten lan gumantung marang replika sumber data sing nanggapi telpon API sampeyan.

    Mbayangno, contone, sampeyan nelpon API kanggo AWS takon kanggo nggawe server EC2. API bakal ngasilake respon "sukses" (201 Digawe) meh langsung, tanpa ngenteni server dhewe digawe. Yen sampeyan nyoba nyambungake langsung, mesthine bakal gagal amarga ing wektu kasebut AWS isih miwiti sumber daya utawa, minangka alternatif, server durung boot. Menapa malih, yen sampeyan nelpon liyane kanggo njaluk informasi bab server iki, sampeyan bisa nampa kesalahan (404 Ora Ditemokake). Masalahe yaiku informasi babagan server EC2 iki isih bisa disebar ing saindenging AWS sadurunge kasedhiya ing endi wae, sampeyan kudu ngenteni sawetara detik.

    Yen sampeyan nggunakake API asinkron kanthi konsistensi kesed, sampeyan kudu nyoba maneh panjalukan kanthi periodik nganti tumindak rampung lan nyebar liwat sistem. Sayange, AWS SDK ora nyedhiyakake alat sing apik kanggo iki, lan proyek Terraform biasane nandhang akeh kewan omo kaya 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

    Ing tembung liyane, sampeyan nggawe sumber daya (kaya subnet) lan banjur nyoba kanggo njaluk sawetara informasi bab iku (kaya ID saka subnet mentas digawe), lan Terraform ora bisa nemokake. Umume kewan omo iki (kalebu 6813) wis didandani, nanging isih katon saka wektu kanggo wektu, utamane nalika Terraform nambah dhukungan kanggo jinis sumber daya anyar. Iki ngganggu, nanging ing sawetara kasus ora nyebabake gawe piala. Nalika sampeyan mbukak terraform aplikasi maneh, kabeh kudu bisa, amarga ing wektu iki informasi wis nyebar ing saindhenging sistem.

    Kutipan iki diwenehi saka buku Evgeniy Brikman "Terraform: infrastruktur ing tingkat kode".

Source: www.habr.com

Add a comment