Terraform vs. CloudFormation: Kesin Kılavuz
Yayınlanan: 2022-03-11Benim gibi, kesin bir cevap bulamadan bir sonraki kod olarak altyapı (IaC) aracınız olarak CloudFormation ve Terraform arasında seçim yapmanıza yardımcı olması için interneti araştırdıysanız, acınızı uzun süre paylaştım. Şimdi, her iki araçla da önemli deneyime sahibim ve hangisini kullanacağım konusunda bilinçli bir karar verebilirim.
TL; DR
AWS'deki IaC projeniz için CloudFormation'ı seçin, çünkü:
- CloudFormation, kod (yani şablonlar) ile kodun somutlaştırılması (yani yığınlar) arasında bir ayrım yapar. Terraform'da böyle bir ayrım yoktur. Bir sonraki bölümde bu konuda daha fazlası.
- Terraform, temel bağımlılık yönetimini çok iyi idare etmez. Daha sonraki bir bölümde bununla ilgili daha fazla bilgi.
Kod ve Örneklemeler Arasındaki Fark
CloudFormation ve Terraform arasındaki bir fark, kod ve örneklemelerin her bir hizmet içinde birbiriyle nasıl ilişkili olduğudur.
CloudFormation, bir şablonun somutlaştırılması olan bir yığın kavramına sahiptir. Aynı şablon, belirli bir hesaptaki belirli bir müşteri tarafından, hesaplar arasında veya farklı müşteriler tarafından sonsuza kadar somutlaştırılabilir.
Terraform'un böyle bir konsepti yoktur ve kod ile onun somutlaştırılması arasında bire bir ilişki gerektirir. Çalıştırmak istediğiniz her sunucu için bir web sunucusunun kaynak kodunu çoğaltmaya veya derlenmiş sürümü çalıştırmak yerine bir uygulamayı her çalıştırmanız gerektiğinde kodu çoğaltmaya benzer.
Bu nokta, basit bir kurulum durumunda oldukça önemsizdir, ancak orta ila büyük ölçekli operasyonlar için hızla büyük bir acı noktası haline gelir. Terraform'da, mevcut koddan her yeni bir yığın döndürmeniz gerektiğinde, kodu çoğaltmanız gerekir. Ve komut dosyalarını kopyalamak/yapıştırmak, kendinizi sabote etmenin ve dokunmayı düşünmediğiniz kaynakları bozmanın çok kolay bir yoludur.
Terraform'un aslında CloudFormation gibi bir yığın kavramı yoktur; bu, Terraform'un sıfırdan kod ile yönettiği kaynaklar arasında bire bir eşleşme sağlamak için oluşturulduğunu açıkça gösterir. Bu, daha sonra ortamlar kavramıyla (o zamandan beri "çalışma alanları" olarak yeniden adlandırıldı) kısmen düzeltildi, ancak bunları kullanma yolu, istenmeyen bir ortama dağıtmayı inanılmaz derecede kolaylaştırıyor. Bunun nedeni, konuşlandırmadan önce terraform workspace select
seçimini çalıştırmanız gerektiğidir ve bu adımı unutmak, önceden seçilen çalışma alanına dağıtılacaktır, bu sizin istediğiniz olabilir veya olmayabilir.
Pratikte, bu sorunun Terraform modüllerinin kullanımıyla hafifletildiği doğrudur, ancak en iyi durumda bile, önemli miktarda ortak koda ihtiyacınız olacaktır. Aslında, bu sorun o kadar şiddetliydi ki, insanların bu sorunu çözmek için Terraform çevresinde bir sarmalayıcı araç yaratması gerekiyordu: Terragrunt.
Devlet Yönetimi ve İzinler
CloudFormation ve Terraform arasındaki bir diğer önemli fark, her birinin durumu ve izinleri nasıl yönettiğidir.
CloudFormation, yığın durumlarını sizin için yönetir ve size herhangi bir seçenek sunmaz. Ancak CloudFormation yığın durumları deneyimlerime göre sağlamdı. Ayrıca CloudFormation, daha az ayrıcalıklı kullanıcıların, yığının gerektirdiği tüm gerekli izinlere sahip olmadan yığınları yönetmesine olanak tanır. Bunun nedeni, CloudFormation'ın yığın işlemini çalıştıran kullanıcının izinleri yerine yığına eklenen bir hizmet rolünden izin alabilmesidir.
Terraform, durumları yönetmek için ona bazı arka uçlar sağlamanızı gerektirir. Varsayılan, aşağıdakiler göz önüne alındığında tamamen tatmin edici olmayan yerel bir dosyadır:
- Durum dosyanızın sağlamlığı, tamamen depolandığı makinenin sağlamlığına bağlıdır.
- Bu hemen hemen ekip çalışmasını imkansız kılıyor.
Bu nedenle, AWS'de genellikle durum dosyasını depolamak için bir S3 kovası kullanılarak ve eşzamanlılığı işlemek için bir DynamoDB tablosuyla birlikte elde edilen sağlam ve paylaşılan bir duruma ihtiyacınız vardır.
Bu, somutlaştırmak istediğiniz her yığın için manuel olarak bir S3 kovası ve DynamoDB tablosu oluşturmanız ve ayrıca daha az ayrıcalıklı kullanıcıların erişmemeleri gereken verilere erişimini kısıtlamak için bu iki nesnenin izinlerini manuel olarak yönetmeniz gerektiği anlamına gelir. Yalnızca birkaç yığınınız varsa, bu çok fazla sorun olmaz, ancak yönetilmesi gereken 20 yığınınız varsa, bu çok hantal hale gelir.
Bu arada, Terraform çalışma alanlarını kullanırken, çalışma alanı başına bir DynamoDB tablosu olması mümkün değildir. Bu, dağıtımları gerçekleştirmek için minimum izinlere sahip bir IAM kullanıcısı istiyorsanız, DynamoDB izinleri öğe düzeyinde ayrıntılı olmadığı için bu kullanıcının tüm çalışma alanlarının kilitleriyle uğraşabileceği anlamına gelir.
Bağımlılık Yönetimi
Bu noktada hem CloudFormation hem de Terraform biraz zor olabilir. Bir kaynağın mantıksal kimliğini (yani adını) değiştirirseniz, her ikisi de eski kaynağın yok edilmesi ve yenisinin oluşturulması gerektiğini düşünür. Bu nedenle, özellikle CloudFormation'daki iç içe yığınlar için, her iki araçta da kaynakların mantıksal kimliğini değiştirmek genellikle kötü bir fikirdir.
İlk bölümde bahsedildiği gibi, Terraform temel bağımlılıkları ele almaz. Ne yazık ki, Terraform geliştiricileri, geçici çözümlerin bariz eksikliğine rağmen, uzun süredir devam eden soruna fazla ilgi göstermiyor.
Uygun bağımlılık yönetiminin bir IAC aracı için kesinlikle kritik olduğu göz önüne alındığında, Terraform'daki bu tür sorunlar, bir üretim ortamına dağıtım gibi iş açısından kritik işlemler söz konusu olduğunda uygunluğunun sorgulanmasına neden olur. CloudFormation çok daha profesyonel bir his verir ve AWS, müşterilerine üretim düzeyinde araçlar sunduğundan emin olmak için her zaman çok dikkatlidir. CloudFormation'ı kullandığım tüm yıllar boyunca, bağımlılık yönetimiyle ilgili bir sorunla hiç karşılaşmadım.
CloudFormation, bir yığının, daha sonra diğer yığınlar tarafından yeniden kullanılabilen bazı çıktı değişkenlerini dışa aktarmasına izin verir. Dürüst olmak gerekirse, bölge başına birden fazla yığın başlatamayacağınız için bu işlevsellik sınırlıdır. Bunun nedeni, aynı ada sahip iki değişkeni dışa aktaramamanız ve dışa aktarılan değişkenlerin ad alanlarına sahip olmamasıdır.
Terraform böyle bir imkan sunmuyor, bu yüzden daha az arzu edilen seçeneklerle baş başa kalıyorsunuz. Terraform, başka bir yığının durumunu içe aktarmanıza izin verir, ancak bu, durumda depolanan birçok sır da dahil olmak üzere, o yığındaki tüm bilgilere erişmenizi sağlar. Alternatif olarak, bir yığın bazı değişkenleri bir S3 kovasında depolanan bir JSON dosyası biçiminde dışa aktarabilir, ancak yine bu seçenek daha zahmetlidir: Hangi S3 kovasını kullanacağınıza karar vermeniz ve ona uygun izinleri vermeniz ve tüm bilgileri yazmanız gerekir. sıhhi tesisat hem yazar hem de okuyucu tarafında kendinizi kodlayın.
Terraform'un bir avantajı veri kaynaklarına sahip olmasıdır. Terraform böylece Terraform tarafından yönetilmeyen kaynakları sorgulayabilir. Bununla birlikte, pratikte, genel bir şablon yazmak istediğinizde bunun çok az ilgisi vardır, çünkü daha sonra hedef hesap hakkında hiçbir şey varsaymazsınız. CloudFormation'daki eşdeğeri, daha fazla şablon parametresi eklemektir, bu da tekrarlama ve hata potansiyeli içerir; Ancak, deneyimlerime göre, bu hiçbir zaman bir sorun olmadı.
Terraform'un bağımlılık yönetimi konusuna dönersek, başka bir örnek, bir yük dengeleyici ayarlarını güncellemeye çalıştığınızda bir hata almanız ve aşağıdakileri almanızdır:
Error: Error deleting Target Group: ResourceInUse: Target group 'arn:aws:elasticloadbalancing:us-east-1:723207552760:targetgroup/strategy-api-default-us-east-1/14a4277881e84797' is currently in use by a listener or a rule status code: 400, request id: 833d8475-f702-4e01-aa3a-d6fa0a141905
Beklenen davranış, Terraform'un hedef grubun silinmeyen başka bir kaynağa bağımlı olduğunu algılaması ve sonuç olarak onu silmeye çalışmaması, ancak hata da atmaması gerektiğidir.
Operasyonlar
Terraform bir komut satırı aracı olmasına rağmen, çok etkileşimli olduğu için bir insanın onu çalıştırmasını beklediği çok açık. Toplu modda (yani bir komut dosyasından) çalıştırmak mümkündür, ancak bu, bazı ek komut satırı argümanları gerektirir. Bir IAC aracının amacının otomasyon olduğu göz önüne alındığında, Terraform'un varsayılan olarak insanlar tarafından çalıştırılmak üzere geliştirilmiş olması oldukça şaşırtıcıdır.
Terraform'un hata ayıklaması zordur. Hata mesajları genellikle çok basittir ve neyin yanlış gittiğini anlamanıza izin vermez, bu durumda Terraform'u TF_LOG=debug
ile çalıştırmanız gerekir, bu da trol için büyük miktarda çıktı üretir. Bunu karmaşıklaştıran Terraform, bazen AWS'ye başarısız olan API çağrıları yapar, ancak başarısızlık Terraform ile ilgili bir sorun değildir. Buna karşılık, CloudFormation, sorunun nerede olduğunu anlamanıza izin vermek için yeterli ayrıntıya sahip makul ölçüde net hata mesajları sağlar.
Örnek bir Terraform hata mesajı:
Error: error reading S3 bucket Public Access Block: NoSuchBucket: The specified bucket does not exist status code: 404, request id: 19AAE641F0B4AC7F, host id: rZkgloKqxP2/a2F6BYrrkcJthba/FQM/DaZnj8EQq/5FactUctdREq8L3Xb6DgJmyKcpImipv4s=
Yukarıdaki hata mesajı, aslında altta yatan sorunu yansıtmayan (bu durumda bir izin sorunuydu) net bir hata mesajı gösteriyor.

Bu hata mesajı ayrıca Terraform'un bazen kendisini bir köşeye nasıl boyayabileceğini de gösterir. Örneğin, o kova üzerinde bir S3 kovası ve bir aws_s3_bucket_public_access_block
kaynağı oluşturursanız ve herhangi bir nedenle Terraform kodunda bu kovayı yok eden bazı değişiklikler yaparsanız - örneğin, yukarıda açıklanan "değişiklik, silme ve oluşturma anlamına gelir" yakalamasında— Terraform, aws_s3_bucket_public_access_block
yüklemeye çalışırken takılıyor ancak yukarıdaki hatayla sürekli olarak başarısız oluyor. Terraform'un doğru davranışı, aws_s3_bucket_public_access_block
uygun şekilde değiştirmek veya silmek olacaktır.
Son olarak, Terraform ile CloudFormation yardımcı komut dosyalarını kullanamazsınız. Bu, özellikle CloudFormation'a bir EC2 örneğinin kendini başlatmayı tamamladığını ve istekleri sunmaya hazır olduğunu söyleyen cfn sinyalini kullanmayı umuyorsanız, can sıkıcı olabilir.
Sözdizimi, Topluluk ve Geri Alma
Sözdizimi açısından Terraform, CloudFormation'a kıyasla iyi bir avantaja sahiptir; döngüleri destekler. Ancak kendi deneyimlerime göre bu özellik biraz tehlikeli olabilir. Tipik olarak, bir dizi özdeş kaynak yaratmak için bir döngü kullanılır; ancak, yığını farklı bir sayımla güncellemek istediğinizde, eski ve yeni kaynakları bağlamanız gerekebilir (örneğin, şimdi olması gereken iki diziden değerleri birleştirmek için zipmap()
kullanarak) dizilerden biri eski döngü boyutunun boyutuna sahip olduğundan ve diğeri yeni döngü boyutunun boyutuna sahip olduğundan). Döngüler olmadan böyle bir sorunun olabileceği doğrudur, ancak döngüler olmadan, senaryoyu yazan kişi için sorun çok daha belirgin olacaktır. Böyle bir durumda döngülerin kullanılması sorunu gizler.
Terraform'un sözdiziminin mi yoksa CloudFormation'ın sözdiziminin mi daha iyi olduğu çoğunlukla bir tercih meselesidir. CloudFormation başlangıçta yalnızca JSON'u destekledi, ancak JSON şablonlarını okumak çok zor. Neyse ki CloudFormation, okunması çok daha kolay olan ve yorumlara izin veren YAML'yi de destekler. Yine de CloudFormation'ın sözdizimi oldukça ayrıntılı olma eğilimindedir.
Terraform'un sözdizimi, bir tür JSON türevi olan ve oldukça kendine özgü olan HCL'yi kullanır. Terraform, CloudFormation'dan daha fazla işlev sunar ve genellikle anlamlandırılması daha kolaydır. Dolayısıyla, Terraform'un bu noktada küçük bir avantajı olduğu söylenebilir.
Terraform'un bir başka avantajı da, topluluk tarafından yönetilen modüllerin hazır olarak bulunmasıdır ve bu, şablonları yazmayı basitleştirir. Bir sorun, bu tür modüllerin bir kuruluşun gereksinimlerine uymaya yetecek kadar güvenli olmaması olabilir. Bu nedenle, yüksek düzeyde güvenlik gerektiren kuruluşlar için bu modülleri (geldikleri diğer sürümlerin yanı sıra) gözden geçirmek bir gereklilik olabilir.
Genel olarak konuşursak, Terraform modülleri CloudFormation iç içe yığınlardan çok daha esnektir. Bir CloudFormation iç içe yığın, altındaki her şeyi gizleme eğilimindedir. Yuvalama yığınından bir güncelleme işlemi, yuvalanmış yığının güncelleneceğini gösterir, ancak yuvalanmış yığının içinde ne olacağını ayrıntılı olarak göstermez.
Aslında tartışmalı olabilecek son bir nokta, CloudFormation'ın başarısız dağıtımları geri almaya çalışmasıdır. Bu oldukça ilginç bir özelliktir ancak ne yazık ki çok uzun sürebilir (örneğin, CloudFormation'ın Elastic Container Service dağıtımının başarısız olduğuna karar vermesi üç saat kadar sürebilir). Terraform, başarısızlık durumunda olduğu yerde durur. Geri alma özelliğinin iyi bir şey olup olmadığı tartışılabilir, ancak daha uzun bir beklemenin kabul edilebilir bir takas olduğu durumlarda bir yığının mümkün olduğunca çalışır durumda tutulduğu gerçeğini takdir ettim.
Terraform ve CloudFormation'ın Savunmasında
Terraform, CloudFormation'a göre avantajlara sahiptir. Bana göre en önemlisi, bir güncelleme uygularken Terraform'un kullanmakta olduğu tüm modülleri incelemek de dahil olmak üzere yapmak üzere olduğunuz tüm değişiklikleri size göstermesidir. Buna karşılık, CloudFormation, iç içe yığınları kullanırken, yalnızca yuvalanmış yığının güncellenmesi gerektiğini gösterir, ancak ayrıntılara inmek için bir yol sağlamaz. Bu sinir bozucu olabilir, çünkü bu tür bilgilerin "git" düğmesine basmadan önce bilinmesi oldukça önemlidir.
Hem CloudFormation hem de Terraform uzantıları destekler. CloudFormation'da, kendi oluşturduğunuz bir AWS Lambda işlevini arka uç olarak kullanarak sözde "özel kaynakları" yönetmek mümkündür. Terraform için, uzantıları yazmak ve kodun bir parçasını oluşturmak çok daha kolaydır. Yani bu durumda Terraform için bir avantaj var.
Terraform birçok bulut satıcısını idare edebilir. Bu, Terraform'u belirli bir dağıtımı birden çok bulut platformu arasında birleştirebilecek bir konuma getirir. Örneğin, AWS ile Google Cloud Platform (GCP) arasında tek bir iş yükünüz olduğunu varsayalım. Normalde, iş yükünün AWS kısmı CloudFormation kullanılarak, GCP kısmı ise GCP'nin Bulut Dağıtım Yöneticisi kullanılarak dağıtılır. Terraform ile bunun yerine her iki yığını kendi bulut platformlarında dağıtmak ve yönetmek için tek bir komut dosyası kullanabilirsiniz. Bu şekilde, iki yerine yalnızca bir yığın dağıtmanız gerekir.
Terraform ve CloudFormation için bağımsız değişkenler
İnternette dolaşmaya devam eden birkaç tartışma dışı var. Ortaya atılan en büyük sorun, Terraform çoklu bulut olduğu için, hangi bulut platformunda yapılırsa yapılsın tüm projelerinizi tek bir aracı kullanarak dağıtabilmenizdir. Teknik olarak bu doğrudur, ancak özellikle tipik tek bulut projelerini yönetirken göründüğü kadar büyük bir avantaj değildir. Gerçek şu ki, (örneğin) CloudFormation'da bildirilen kaynaklar ile bir Terraform betiğinde bildirilen aynı kaynaklar arasında neredeyse bire bir yazışma vardır. Her iki durumda da buluta özel kaynakların ayrıntılarını bilmeniz gerektiğinden, fark, dağıtımları yönetmedeki en büyük sorun olan sözdiziminde ortaya çıkar.
Bazıları, Terraform kullanarak satıcının kilitlenmesinden kaçınılabileceğini iddia ediyor. Bu argüman, Terraform kullanarak HashiCorp (Terraform'un yaratıcısı) tarafından kilitlendiğiniz, tıpkı CloudFormation kullandığınızda AWS tarafından kilitlendiğiniz ve diğer bulutlar için böyle devam ettiği gibi geçerli değildir. platformlar.
Terraform modüllerinin kullanımının daha kolay olması benim için daha az önemli. Her şeyden önce, kullanıcı tarafından oluşturulan güvenlik açıkları ve çeşitli uyumluluk programlarının ihlallerine ilişkin algılanan sorumluluk nedeniyle AWS'nin topluluk tabanlı CloudFormation şablonları için tek bir havuz barındırmaktan kasten kaçınmak istediğine inanıyorum.
Daha kişisel bir düzeyde, yazılım geliştirme durumunda kitaplıkları kullanmanın faydalarını tam olarak anlıyorum, çünkü bu kitaplıklar on binlerce kod satırına kolayca girebilir. Ancak IaC durumunda, kodun boyutu genellikle çok daha küçüktür ve bu tür modüller genellikle birkaç düzine satır uzunluğundadır. Kopyala/yapıştır kullanmak aslında o kadar da kötü bir fikir değil, çünkü uyumluluğu koruma ve güvenliğinizi bilinmeyen kişilere devretme ile ilgili sorunları önler.
Kopyala/yapıştır kullanmak birçok geliştirici ve DevOps mühendisi tarafından hoş karşılanmaz ve bunun arkasında iyi nedenler vardır. Ancak benim görüşüme göre, kod parçacıkları için kopyala/yapıştır kullanmak, onu ihtiyaçlarınıza göre kolayca uyarlamanıza izin verir ve bundan bir kitaplık oluşturmaya ve onu genel hale getirmek için çok zaman harcamaya gerek yoktur. Bu kod parçacıklarını korumanın acısı, kodunuz bir düzine veya daha fazla şablonda çoğaltılmadıkça, genellikle çok düşüktür. Böyle bir durumda, kodu uygun hale getirmek ve onu iç içe yığınlar olarak kullanmak mantıklıdır ve kendinizi tekrar etmemenin faydaları, muhtemelen bir güncelleme yaptığınızda iç içe geçmiş yığının içinde neyin güncelleneceğini görememenin sıkıntısından daha büyüktür. operasyon.
CloudFormation ve Terraform Sonuç
AWS, CloudFormation ile müşterilerine her zaman amaçlandığı gibi çalışacak çok sağlam bir araç sağlamak istiyor. Tabii ki Terraform'un ekibi de yapıyor - ancak araçlarının önemli bir yönü olan bağımlılık yönetimi maalesef bir öncelik değil.
Terraform'un projenizde bir yeri olabilir, özellikle bir çoklu bulut mimariniz varsa, bu durumda Terraform komut dosyaları, kullandığınız çeşitli bulut satıcıları arasında kaynakların yönetimini birleştirmenin bir yoludur. Ancak yine de bu durumda Terraform'un olumsuz yanlarını, kendi buluta özel IaC araçları kullanılarak halihazırda uygulanmış yığınları yönetmek için yalnızca Terraform kullanarak önleyebilirsiniz.
Terraform'a karşı CloudFormation'ın genel hissi, CloudFormation'ın kusurlu olmasına rağmen daha profesyonel ve güvenilir olduğudur ve özellikle çoklu bulut olmayan herhangi bir proje için kesinlikle tavsiye ederim.