Hakan Ungan
SabancıDx
Published in
7 min readJul 2, 2019

--

Terraform ile IaC kullanımı

Bu yazımda Infrastructure as Code (IaC) araçlarından Terraform’a giriş yapacağım. Terraform nedir, nasıl çalışır açıklamadan önce IaC kavramını açıklamakta fayda var.

Özellikle bulut teknolojilerinin yaygınlaşması ile birlikte bir uygulamada çok sayıda sunucu veya servis bir arada kullanılabilmektedir. Geleneksel monolith uygulamalardan mikroservis teknolojierine doğru geçiş yapıldığında iş lojiklerine göre gruplanmış ve ölçeklenebilen çok sayıda sunucu veya konteyner üzerinde çalışan dağınık mimarilere doğru yönelim zorunluluğu oluşmuştur. Bu ortamları manuel tek tek kurmak ciddi efor gerektirmektedir. Böyle olunca da bu altyapıları yönetebilecek, otomasyonla kurulumlarını gerçekleştirebilecek teknolojik gereksinimlerin bir sonucu olarak Infrastructure as Code (IaC) araçları kullanılmaya başlandı. IaC ile altyapı için gerekli her türlü bileşen kod olarak tanımlanıp tüm altyapı bu kodlar üzerinden ayağa kaldırılabilmektedir.

IaC DevOps kültürünün en önemli yapıtaşlarından biridir. IaC ile uygulama için gerekli olan test ortamları otomatik olarak ayağa kaldırılıp uygulama kodları deploy edilip uygulama start edilp testlerin yapılması mümkün olabilmektedir.

Bulut ortamlarında AWS üzerinde CloudFormation, Azure üzerinde RM Template’ler IaC için kullanılan servislere örnek olarak gösterilebilir.

IaC araçlarında kodlar prosedurel veya declarative olmak üzere iki farklı tipte kullanılmaktadır. Prosedürel yaklaşımda tıpkı geleneksel programla dillerinde olduğu gibi kodlar ardışıl komutlardan oluşmaktadır. Declarative yaklaşımda ise sadece ne yapılacağı tariflenir nasıl yapılacağı tariflenmez. İki yaklaşım arasında en büyük fark declarative yaklaşımda altyapınız, kodunuzda tanımlı altyapı ile birebir uyumlu olarak oluşturulmaya çalışılır ve sadece gerekli değişiklikler(yerine göre kaynağı sıfırdan yaratma, yerine göre güncelleme vb..) yapılır. Prosedürel yaklaşımda eğer ek kontrol adımları koymaz iseniz aynı kodu ikinci kez çalıştırdığınızda bazı adımlar ilk çalıştırmada tamamlandığı için hata alabilirsiniz.

Gelelim bu yazımızın konusu olan Terraform’a. Terraform HashiCorp firması tarafından geliştirilen açık kaynak kodlu IaC araçtır. İlk sürüm 2014 yılında duyrulmuştur. Terraformu API’si olan herşeyi yönetebileceğiniz universal bir araç gibi düşünebilirsiniz. Terraform VmWare, AWS, Azure, GCP gibi 100’den fazla farklı provider teknolojiyi desteklemektedir ve declarative kod yaklaşımını kullanır. Herhangi bir ajana gereksim olmaksızın çalışır, kullanmak için sadece bir terraform sunucusunun kurulması yeterlidir.

https://www.terraform.io/downloads.html linkinden hedef işletim sistemini seçerek ürünü indirip kurulumu gerçekleştirebilirsiniz. Doğru kurulup kurulmadığını terraform –version komutu ile kontrol edebilirsiniz.

terraform –version

Terraform v0.12.0

Your version of Terraform is out of date! The latest version is 0.12.3. You can update by downloading from www.terraform.io/downloads.html

En basit anlamda terraform ile çalışmak için Terraform sunucusu üzerinde bir dizin yaratın ve bu dizin içinde uzantısı .tf olacak şekilde bir konfigürasyon dosyası oluşturmak gerekiyor. Genelde main.tf dosyası kullanılır. Eğer JSON bazlı bir dil ile çalışmak istiyorsanız .tf.json uzantısında JSON formatında konfigürasyon tanımları yapabilirsiniz. Ayrıca belirli bir dizin içindeki birden fazla template dosyasını birbirlerine referans vererek tekrar kullanılabilir, kompleks altyapıları ayağa kaldırabilen Terraform module’ler tanımlanabilmektedir.

Konfigürasyonları tanımlamak için HasihCorp Configuration Language(HCL) dilinde tanım yapmalısınız. HCL, bloklardan oluşan bir dildir, blokları resource gibi diğer içerikleri içinde barındıran bir konteyner gibi düşünebilirsiniz, her blokun bir tipi vardır. Bloklar iç içe başka blokları içerebilir. Ayrıca argument ve expressionlar da konfigürasyon tanımları içinde kullanılabilmektedir. HCL ile ilgili detay bilgilere aşağıdaki linkten ulaşabilirsiniz.

https://www.terraform.io/docs/configuration/syntax.html

Bir Terraform template dosyası temelde 3 ana bileşenden oluşur.

· Resources

· Providers

· Provisioners

Resources:

Terraformda en önemli tanım resource bilgisidir. Her resource bloğu bir veya daha fazla altyapı bileşen veya servisine ait tanımları içerir.

Aşağıdaki örnekte aws_instance tipinde ve “web” ile adlandırılan bir ec2 sunucu ile ilgili AMI (Amazon Machine Image) ve instance tipi bilgisini içeren bir resource tanımı yer almaktadır. Template içinde bu resource başka yerlerde referans olarak kullanılacaksa bu isimle (web) kullanılmalıdır.

Yukarıdaki örnekte instance_type bilgisini aynı template içinde başka bir yerde referans olarak kullanacak isek ${aws_instance.web.instance_type} şeklinde tanımlayabiliriz buna interpolation denir.

Benzer şekilde String, Map, List veya Boolean tipinde variable’ler tanımlayıp bunları interpolation ile kullanabilirsiniz.

Aşağıdaki örnekte string tipinde default olarak myserver değerini alan instance_name değişkeni tanımlamış olduk.

Instance_name değişkenini önceki örnekteki aws_instance tanımı içinde kullanabilirsiniz. Böylece Name tag’ine değer olarak insance_name değişkenindeki değeri atamış olduk.

Variable’ların eğer default değeri yoksa plan ve apply komutlarında ekranda prompt olarak değer girilmesi sorulur. Eğer her defasında değişkenlerin değerinin girilmesi istenmiyorsa komutlara –var seçeneği ile birlikte değişken olarak aktarılabilir

Ya da terraform.tfvars adında bir dosya yaratılıp içinde bu atamaları yapabilirsiniz. Terraform bu dosya içindeki değişken atamalarını otomatik kullanır.

Providers:

Bir diğer önemli kavram Provider’dir. Terraform ile farklı tipte birçok altyapı kaynaklarını yaratabilir, günceller veya yönetebilirsiniz. Provider farklı tipteki kaynakları yönetmek için gerekli API etkileşimini sağlayan Terraform bileşenleridir. Desteklenen tüm provider’ları aşağıdaki linkten inceleyebilirsiniz.

https://www.terraform.io/docs/providers/index.html

Aşağıdaki örnekte template içinde AWS provider’ını kullanılacağını ifade eden bir tanımı yer olmaktadır. Provider tanımlarken o provider’a özel ek tanımlamalar yapılabilmektedir.

Örnekte region olarak “eu-west-1” kullanılacağı ifade edilmiştir.

Bu tanımı yaptıktan sonra template’de aws provider’ına ait resource tanımlarını kullanabilirsiniz, eğer provider tanımı yapılmaz ise bu provider’a ait resource’ları kullanamaz ve hata alırsınız. aws_instance tanımından önce bu provider tanımı yapmalıyız ki AWS ile ilgi kaynaklara erişebilelim.

Azure ile ilgili bir çalışma yapacaksınız öncesinde aşağıdaki tanımı kullanmalısınız.

Provisioners:

Altyapıyı için gerekli kaynakları yarattıktan sonra bir script veya shell komutu çalıştırmak için Provisioner’lar kullanılır. Örneğin bir altyapıyı yarattıktan sonra bir NGIX uygulamasını kurup NGINX servisini start etmek için Provisioner’ları kullanabilirsiniz.

Konfigürasyon dosyasını oluşturduktan sonra bunu Terraform üzerinden nasıl çalıştıracağınız. Bunun için terraform init, terraform plan ve terraform apply komutlarını kullanmak gerekiyor.

terraform init: konfigürasyon dosyasınının içinde bulunduğu dizini Terraform’un kullanımı için initialize eder. Eğer bir provider kullanıyorsanız bunun için gerekli plugin’leri download eder kullanıma hazır eder.

terraform init

terraform plan: Terraform mevcut infrastructure ile konfigürasyon dosyasındaki hedeflenen durum arasındaki farklılıkları hesaplayıp aradaki farkları algılayarak çalışır. Terraform plan gerçek çalıştırma için gerekli bir execution plan yaratmak ve hangi değişikliklerin yapılacağını önizlemek için kullanılır. Bunu bir prova gibi düşünebilirsiniz. Planının çalıştırılması sonrasında kalıcı bir değişiklik yapılmaz kaynaklar üzerinde yapılacak değşikliklerin bir listesi çıktı olarak gösterilir.

Sırası gelmişken Terraform bir kaynak üzerinde 4 farklı işlem gerçekleştirebilir:

· Create (Ekranda + ile gösterilir)

· Change (Ekranda ~ ile gösterilir)

· Chage with force create (Destroy and Create) (Ekranda -/+ ile gösterilir)

· Destroy (Ekranda — ile gösterilir)

Örnek:

terraform apply komutu ile bu template içindeki konfigürasyon tanımları esas alınarak altyapı değişiklikleri kalıcı uygulanır. Apply komutunu planın kalıcı olarak uygulanması olarak düşünebilirsiniz.

Terraformu kullanırken en önemli kavramlardan biri de state bilgisidir. State gerçek hayattaki altyapı kaynakları ile tanımlı konfigürasyonlar arasındaki ilişkiyi ve metabilgisini saklayan dosyadır. Konfigürasyon dosyasının içinde bulunduğu dizinde terraform.tfstate adlı dosyada saklanır. İstenirse takım halinde çalışmayı desteklemek için remote ortamlarda da saklanabilir.

Terraform local state’i plan yaratırken veya değişiklikleri güncellemek için kullanır. Herhangi bir işlemden önce terraform gerçek hayattaki nesnelerin son durumu update ederek state’i refresh eder.

Gelelim Terraformun sevmediğim taraflarına. Eğer sıfırdan bir uygulamaya ait altyapı bileşenlerini Terraform ile yaratıp sonradan da Terraform ile güncelleyecekseniz state bilgisi sürekli güncel kaldığı için sorunsuz istediğiniz işlemleri gerçekleştirebilirsiniz. Peki daha önce Terraform ile yaratılmayan bir altyapı ile çalışmak zorunda kaldığınızda ne yapmanız gerekiyor? Örneğin manuel kurulan bir sunucu üzerinde Terraform ile bir değişiklik yapmak istersek ne olur? Bu durumda sunucu Terraform tarafından yaratılmadığı için bir state bilgisi tanımlı değildir dolayısı ile sunucunun gerçekte var olup olmadığını Terraform bilmediği için aynı resource’dan yeni bir instance yaratır. Bu da mükerrerliğe neden olur bunu engellemek için sunucunun son durumunu state dosyasına kaydetmek için terraform import kullanılmaktadır.

Örneğin: terraform import aws_instance.example i-abcd1234

Örnekte i-abcd1234 instance id’sine sahip bir AWS ec2 sunucunun mevcut özelliklerini state dosyasına aws_instance.example olarak kaydeder, artık bu işlemden sonra bu sunucu üzerinde Terraform ile değişiklik yapabilirsiniz.

Bu kısıttan dolayı bir altyapı ve gerekli bileşenler sıfırdan kurulacak ve güncellenecekse Terraformu kullanmanızı öneririm. Ama eğer altyapı daha önce manuel oluşturulmuş ve bunun üzerinde değişiklik yapacaksanız bunu terraform ile otomatik yapmanız zor, tavsiyem Ansible gibi bir konfigürasyon yönetim aracı ile bunu yapmanızdır.

Bir diğer kısıt aynı anda ekibinizdeki iki kişi aynı konfigürasyon dosyası ile bir altyapı ayağa kaldırmaya çalışırsa ortaya çıkan durum. Bu durumda işlemi ilk gerçekleştiren state dosyasına corruption’ı engellemek için kilit koyar ve işlem bitene kadar diğer ekip üyesi state dosyası lock oluştuğu için hata alır ve beklemek zorunda kalır.

Remote state tanımı ile state dosyasını lokal dosya sistem yerine örneğin AWS S3 üzerinde saklayabilir birden fazla takım elemanının kullanımına açabilirsiniz. Örneğin iki ayrı geliştirici kendi bilgisayarlarına terraform kurup aynı infrastructure bileşenleri üzerinde çalışırsa en son değişikliği yapan geliştiricinin bilgisayarında güncel state bilgisi saklanır diğerindeki state bilgisi güncel değildir. Bunu engellemek için state bilgisi local sunuculardan S3 gibi shared ortamlara taşınabilir. Böylece geliştiriciler her zaman güncel state bilgisine paylaşımlı bir ortamdan erişip kullanabilirler.

Başlangıç düzey için bu kadar bilgi yeterli sanırım, detayda çok sayıda konu var, daha fazla bilgi almak için internet üzerinden Terraform ile ilgili kaynakları takip edebilirsiniz.

Aşağıda VMWare VSphere üzerinde sanal bir sunucunun nasıl provizyon edileceği ile ilgili bir örnek bulacaksınız. Bunun için VSphere Server IP, username, password ve VM Server Name variables.tf dosyası içinde değişken olarak tanımlanmıştır. Provider olarak vsphere seçilmiştir.

Örnekte 2 CPU, 4 GB Ram’li bir Linux sunucusu Centos_Template kullanılarak ayağa kaldırılmaktadır. Template’i kullanabilmek için template içindeki değişkenlere kendi VSphere ortamınıza uygun değerler atamanız gereklidir.

main.tf içinde tanımlı data blokları konfigürasyon dosyası dışında dış bir ortamdan (provider içinden) bu verinin alınacağını gösterir. Bu ifadeleri ön tanımlı veri kaynakları olarak değerlendirebilirsiniz.

--

--

Hakan Ungan
SabancıDx

Bulut, Yazılım geliştirme ve BT Operasyon yönetimi konusunda deneyimli kıdemli uzman ve yönetici. Cloud, DevOps, ITIL, ITOM, Microservices ilgi alanlarım.