Terraform for_each, count ve HCL fonksiyonları: örneklerle kullanım
Terraform HCL'de for_each ve count ile çoklu kaynak oluşturma, each.key ve each.value, toset ve for ifadesi, sık hatalar ve örnekler.
Aynı kaynaktan birden fazla örnek neden gerekir?
Gerçek altyapıda aynı türden kaynak sıkça tekrarlanır: her ortam için bir depolama alanı, her ekip için bir kullanıcı grubu, her alt ağ için bir kural. Bu kaynakları kopyalayarak yazmak hem uzun hem hataya açıktır. Terraform'un count ve for_each meta-argümanları, tek bir kaynak bloğundan birden fazla örnek üretmenizi sağlar.
İkisinin arasındaki seçim HashiCorp belgelerinde açık biçimde tarif edilir: örnekler neredeyse aynıysa count, örnekler birbirinden farklı değerlere ihtiyaç duyuyorsa for_each kullanın. Yani aynı işi N kez yapacaksanız count, her örnek için ayrı bir isim ya da ayar gerekiyorsa for_each doğru araçtır. Pratikte for_each daha çok kullanılır, çünkü örnekler bir sıra numarasıyla değil anlamlı bir anahtarla tanımlanır.
for_each ile kaynak üretmek: map ve set
for_each yalnızca bir map ya da bir string kümesi (set) kabul eder. Bir liste verirseniz Terraform onu örtük olarak dönüştürmez; toset() ile kümeye çevirmeniz gerekir. Küme dönüşümü sırayı korumaz ve yinelenen değerleri siler.
Örnek bir kullanım:
resource "azurerm_resource_group" "ortam" { for_each = toset(["dev", "test", "prod"]) name = format("acme-%s", each.key) location = var.konum }
Burada her ortam adı için ayrı bir kaynak örneği oluşur. each.key o anki küme üyesini ya da map anahtarını, each.value ise map değerini verir; küme kullanıldığında each.value, each.key ile aynıdır. Örnekler ortam["test"] gibi anahtarla adreslenir. Map kullanırsanız her örnek için farklı ayar tanımlayabilirsiniz:
for_each = { web = "buyuk" api = "kucuk" }
Bu durumda each.value ile her örneğe kendi boyut değerini verirsiniz.
count ne zaman yeterlidir?
count, bir sayı alır ve o kadar örnek üretir; sıra numarasına count.index ile ulaşılır. Birbirinden ayrışmayan örnekler (örneğin aynı yapılandırmada birkaç çalışan makine) için basittir. Ayrıca count ile bir kaynağı koşullu açıp kapatmak yaygın bir kalıptır: koşul doğruysa bir, yanlışsa sıfır örnek oluşturulur.
count'un temel zayıflığı sıra numarasına bağlı olmasıdır. Listenin ortasından bir öğe çıkarırsanız sonraki öğelerin numarası kayar ve Terraform bunları değişmiş sayıp yeniden oluşturmak isteyebilir. for_each'te her örnek anahtarla tanımlandığı için bir öğeyi çıkarmak yalnız o örneği etkiler. Bu nedenle sonradan değişebilecek koleksiyonlarda for_each tercih edilmelidir.
Bir kaynak bloğunda count ve for_each birlikte kullanılamaz; ikisinden birini seçmeniz gerekir.
for ifadesi ve sık kullanılan fonksiyonlar
HCL, koleksiyonları dönüştürmek için for ifadesi sunar. Örneğin bir liste içindeki ad değerlerini büyük harfe çevirmek ya da bir map'ten yeni bir map üretmek bu ifadeyle yapılır. for_each ile birlikte kullanımı çok yaygındır: karmaşık bir veriyi for_each'in kabul ettiği map biçimine dönüştürmek için for ifadesi yazılır.
Sık kullanılan yerleşik fonksiyon aileleri şunlardır:
- Koleksiyon fonksiyonları: toset, tomap, tolist (tür dönüşümü), merge (map birleştirme), concat (liste birleştirme), lookup (map'ten güvenli okuma), flatten (iç içe listeyi düzleştirme).
- Metin fonksiyonları: format, join, split, replace, lower, upper.
- Koşullu ifade: koşul ? doğruysa : yanlışsa biçimindeki üçlü operatör.
Her fonksiyonun tam imzası için Terraform belgelerindeki fonksiyon referansına bakmak gerekir. Yeni bir fonksiyon kullanmadan önce küçük bir değerle terraform console içinde denemek hata ayıklamayı hızlandırır.
Örneğin değişken olarak gelen bir ortam listesinden etiketli bir map üretmek isterseniz for ifadesiyle her ortam adını anahtar, büyük harfli halini değer yapabilirsiniz; ardından bu map'i for_each'e verirsiniz. Bu yaklaşım, veriyi önce şekillendirip sonra kaynak üretmek anlamına gelir ve kaynak bloğunu sade tutar.
Dinamik bloklar: iç içe tekrarlayan yapılar
Bazı kaynaklar içinde tekrarlanan alt bloklar barındırır; örneğin bir güvenlik grubunun birden çok giriş kuralı. Bunları el ile yazmak yerine dynamic bloğu kullanılır. Dinamik blok, bir koleksiyonu dolaşarak her öğe için bir alt blok üretir ve for_each'e benzer bir yapı taşır.
Örnek:
dynamic "ingress" { for_each = var.kurallar content { from_port = ingress.value.port protocol = ingress.value.protokol } }
Burada kurallar değişkeni bir koleksiyon olmalıdır; her öğe için ingress alt bloğu oluşturulur. Dinamik blokları gereğinden fazla kullanmak okunabilirliği düşürür. Alt blok sayısı sabit ve azsa doğrudan yazmak daha anlaşılırdır.
Sık yapılan hatalar ve çözümleri
- Liste ile for_each kullanmak: Terraform listeyi kabul etmez. toset ile kümeye ya da bir for ifadesiyle map'e çevirin.
- Bilinmeyen değerle anahtar üretmek: HashiCorp belgelerine göre map anahtarları ve küme değerleri uygulamadan önce bilinebilir olmalıdır. Başka bir kaynağın apply sonrası oluşan özniteliğini anahtar yaparsanız hata alırsınız. Anahtarı sabit adlardan, değeri ise sonradan bilinen özniteliklerden türetin.
- Saf olmayan fonksiyonları anahtarda kullanmak: uuid, bcrypt ve timestamp gibi her çalıştırmada farklı değer üreten fonksiyonlar anahtar için kullanılamaz.
- Hassas değerlerle for_each: Hassas işaretli değişken ya da çıktılar for_each'te kullanılamaz; çözüm için hassas olmayan anahtarları bir for ifadesiyle ayıklamak gerekir.
- Duplikat anahtarı sessizce yutmak: toset yinelenen değeri siler; beklenmedik şekilde az kaynak oluştuğunda listenizde tekrar olup olmadığına bakın.
- count'tan for_each'e geçerken adresleri unutmak: moved bloğu ya da state komutlarıyla adres taşımadan geçerseniz kaynaklar yeniden oluşturulur.
Mindset programlarında nerede çalışılır?
for_each, count ve fonksiyonlar, Terraform kodunu tekrar eden bloklardan kurtarıp yönetilebilir hale getiren orta düzey bir beceri grubudur. Mindset'in Terraform ile Altyapı Otomasyonu programı Terraform temelleri ve HCL dili, modüler Terraform mimarisi ve gelişmiş HCL ile fonksiyonlar modüllerini içerir. Altyapı kodunu tek tek kaynaklar halinde yazan ekipler, bu programla ortak kod kalıpları oluşturabilir ve inceleme süreçlerini bu kalıplar üzerinden yürütebilir.
İlgili Mindset programı
Terraform ile Altyapı Otomasyonu
Sık sorulan sorular
for_each ve count aynı kaynakta birlikte kullanılabilir mi?
Hayır. Bir kaynak bloğunda yalnız birini kullanabilirsiniz. Neredeyse aynı örnekler için count, her örneğe farklı değer gereken durumlar için for_each tercih edilir. Aynı kaynakta ikisine de ihtiyaç duyuyorsanız tasarımı gözden geçirmek gerekir.
for_each'e liste verirsem ne olur?
Terraform hata verir; çünkü for_each yalnızca map ya da string kümesi kabul eder. Listeyi toset() ile kümeye çevirebilir ya da bir for ifadesiyle map üretebilirsiniz. Küme dönüşümünde sıra kaybolur ve yinelenen öğeler silinir.
each.key ile each.value farkı nedir?
each.key map'in anahtarını ya da küme üyesini verir. each.value ise map değerini verir. Küme kullandığınızda ikisi aynı değeri taşır. Örnek adreslemesi de anahtara göre yapıldığından, kaynak örneklerine anahtarla ulaşırsınız. Map kullanımında ikisi farklı bilgi taşıdığı için çoğu zaman map tercih edilir.
for_each için bilinmeyen değer hatası nasıl çözülür?
Anahtarlar apply öncesinde bilinebilir olmalıdır. Başka bir kaynağın sonradan oluşan özniteliğini anahtar yapmayın; sabit adlar ya da değişkenlerden anahtar üretin. Sonradan bilinen değerleri map değerine yerleştirmek sorun çıkarmaz. Gerekirse kaynağı iki aşamada oluşturarak bağımlılığı çözebilirsiniz.
Dinamik blok ne zaman kullanılmalı?
Alt blok sayısı koleksiyona bağlı olarak değişiyorsa kullanın. Sayı sabit ve azsa doğrudan yazmak daha okunaklıdır. Dinamik blokları iç içe kullanmak kodun anlaşılmasını zorlaştırır; gerektiğinde veri yapısını sadeleştirmek daha iyi bir çözümdür.