Ekiplerin çoğu Terraform'a aynı şekilde başlar. Biri dizüstü bilgisayarında bir main.tf yazar, terraform apply çalıştırır ve Azure'da bir App Service, bir veritabanı ve bir depolama hesabı belirir. Çalışır ve birkaç hafta kimse bunu tekrar düşünmez.
Sonra ikinci bir ortam gerekir. Bir ekip arkadaşı bir ayarı değiştirmek ister. Altyapıyı bir kişi yerine CI hattının kurması istenir. İşte o noktada baştaki kestirmeler bedel ödetmeye başlar: tek bir bilgisayarda duran bir state dosyası, test ve canlı ortamda birbirini tutmayan isimler, bir hat değişkenine yapıştırılmış bir client secret.
Azure'da bir müşteri portalı çalıştıran üç kişilik bir ekip düşünün: bir web uygulaması, bir PostgreSQL veritabanı, yüklenen dosyalar için bir depolama hesabı ve bir Key Vault. Hiçbiri tam zamanlı altyapıyla uğraşmıyor. Aşağıdaki sekiz karar, böyle bir ekip için, tercihen ikinci ortam kurulmadan önce netleştireceğimiz konulardır.
1. State'i ilk günden Azure Storage'a koyun
Terraform'un state dosyası, neyi oluşturduğunun kaydıdır. Tek bir bilgisayardaysa başka kimse Terraform'u güvenle çalıştıramaz; o bilgisayar kaybolursa Terraform neyi yönettiğini artık bilmez.
State'i azurerm backend'iyle bir Azure Storage hesabında tutun. Backend, biri plan ya da apply çalıştırırken state'i bir blob lease ile kilitler; böylece iki kişi aynı ortamı aynı anda değiştiremez. O depolama hesabında blob sürümlemeyi ve geçici silmeyi (soft delete) açın ki bozulan bir state geri alınabilsin.
Bu depolama hesabını bir kez, elle ya da küçük ayrı bir yapılandırmayla oluşturun ve tarif ettiği altyapının dışında tutun. Her ortama kendi state dosyasını verin.
2. Ortam başına bir klasör, altında ortak modüller
Test ve canlı ortamı ayırmanın birkaç yolu var. Küçük bir ekip için okunması en kolay olanı, aynı modülleri farklı değerlerle çağıran ortam başına bir klasördür.
infra/
modules/
web-app/
database/
envs/
staging/
main.tf
terraform.tfvars
production/
main.tf
terraform.tfvars
Sadeleştirilmiş taslak.
Her ortam klasörünün kendi backend ayarı ve kendi state'i olur. Bir modüldeki değişiklik iki ortama da ulaşır, ama önce test ortamına uygular, canlı ortamın planını ayrıca görürsünüz. Workspace'ler de aynı işi görebilir; klasörler ise hangi ortamda durduğunuzu açıkça gösterir.
3. Bir isimlendirme kuralında anlaşın ve onu tek yerde tutun
Azure'da isimler zahmetlidir. Depolama hesabı adları 3 ile 24 karakter arasında olmalı, yalnızca küçük harf ve rakam içermeli ve tüm Azure'da benzersiz olmalıdır. Başka kaynaklar tire ve daha uzun isimlere izin verir. Herkes isimleri o an uydurursa portal test2, portal-db-new ve stgportalprod01 gibi adlarla dolar.
Kuralı bir kez yazın, örneğin proje, ortam, kaynak türü ve bölge, ve isimleri her modülün kullandığı tek bir locals bloğunda üretin. Böylece bir kaynağın adı, hiçbir şey açmadan onun ne olduğunu ve nereye ait olduğunu söyler.
4. Terraform ve provider sürümlerini sabitleyin
azurerm provider'ı sık değişir ve ana sürümler argümanları yeniden adlandırır ya da kaldırır. Bir kişi hattan daha yeni bir provider çalıştırıyorsa aynı kod farklı bir plan üretebilir.
Terraform için required_version, her provider için bir sürüm kısıtı tanımlayın ve .terraform.lock.hcl dosyasını depoya ekleyin. Yükseltmeyi bilerek, bir dalda yapın ve birleştirmeden önce planı okuyun.
5. Hat Azure'a kayıtlı bir secret olmadan girsin
Terraform'u çalıştıran hattın Azure'u değiştirme yetkisi olmalı. Alışılmış kestirme, client secret'ı bir hat değişkeni olarak kaydedilmiş bir service principal'dır. O secret'ın süresi dolar, kopyalanır ve izini sürmek zordur.
GitHub Actions ve Azure DevOps bunun yerine Azure'a OpenID Connect ile girebilir: Azure belirli bir depo ve dal için üretilen token'lara güvenir ve hiçbir yerde uzun ömürlü bir secret saklanmaz. Bu kimliğe tüm abonelikte Owner değil, yalnızca yönettiği kaynak gruplarında ihtiyaç duyduğu rolleri verin.
6. Secret'ları Key Vault'ta tutun, state'i hassas kabul edin
Veritabanı şifreleri ve API anahtarları terraform.tfvars dosyasına ya da depoya ait değildir. Onları üretin ya da Key Vault'ta saklayın ve uygulamanın oradan okumasını sağlayın.
Terraform'un yönettiği kaynakların değerlerini, şifreler dahil, state'e düz metin olarak yazdığını unutmayın. Bu da state'in durduğu depolama hesabını hassas yapar: okuyabilecek kişileri sınırlayın, state dosyalarını sohbet mesajlarına ya da kayıtlara kopyalamayın.
7. Planı pull request'te görün, birleştirmeden sonra uygulayın
En güvenli düzen aynı zamanda en sade olanıdır: infra/ altındaki her değişiklik bir pull request'ten geçer, hat terraform plan çalıştırıp sonucu paylaşır, ikinci bir kişi okur ve hat birleştirmeden sonra apply çalıştırır. Kimse kendi bilgisayarından uygulamaz.
Er ya da geç biri bir kesinti sırasında Azure portalında bir ayarı değiştirecektir. Bu, değişiklik koda geri döndüğü sürece sorun değildir. Her gece çalışan ve farkı bildiren zamanlanmış bir terraform plan, bu sapmayı bir sonraki uygulayan kişiyi şaşırtmadan önce gösterir.
8. Kaybetmesi pahalı olanları koruyun
Kod öyle diyorsa Terraform bir kaynağı siler; adı değişen bir kaynak da planda "sil ve yeniden oluştur" gibi görünebilir. Veritabanı, müşteri dosyalarının durduğu depolama hesabı ve Key Vault için lifecycle { prevent_destroy = true } ekleyin ki Terraform onları kaldırmayı reddetsin. Canlı ortamın kaynak grubunda bir Azure CanNotDelete kilidi, Terraform dışında yapılan değişiklikleri de kapsayan ikinci bir koruma ekler.
Bu iki ayar birkaç dakika sürer ve en kötü hatayı yapmayı çok daha zor hale getirir.
Kısaca
Küçük bir ekibin Terraform'u tek ortamın ötesine geçmeden önce sekiz şeyi netleştirin: kilitleme ve sürümlemeyle Azure Storage'da uzak state, ortak modüller üzerinde ortam başına bir klasör, tek yerde duran yazılı bir isimlendirme kuralı, kilit dosyası depoda olacak şekilde sabit sürümler, hat için OIDC ile giriş, Key Vault'ta secret'lar ve hassas kabul edilen state, incelemede plan ve birleştirmeden sonra apply, kaybetmeyi göze alamayacağınız kaynaklar için koruma. Bunların hiçbiri ilk gün zor değildir; hepsi ikinci ortamdan sonra eklemesi daha zor olan şeylerdir.
Bulut ve DevOps çalışmalarımızda sunucuları, ağı ve veritabanlarını Terraform ile tanımlıyoruz; böylece her ortam sıfırdan yeniden kurulabiliyor ve her değişiklik kayıt altında ve incelenebilir oluyor.
Böyle bir proje mi planlıyorsun?
10 adımda planla