IaC Dünyası-1: Terraform 101

Ozan Eren
Devops Türkiye☁️ 🐧 🐳 ☸️
14 min readNov 4, 2020

Merhabalar,

Bugün itibariyle, IaC (Infrastructure as Code) yaklaşımına dahil olabilecek konuları ele alan yeni bir seri başlatmayı düşündüm. Bu seriye ilk olarak Terraform ile başlamak istedim. Aslında artık çoğu kişi tarafından duyulmuş ve bilinen Terraform’u birkez de benden okumanızı dilerim. Serinin bu ilk yazısında IaC ile ilgili genel bilgiler, Terraform ile ilgili genel bilgiler, ve Terraform için giriş seviyesinde bazı senaryo örnekleri göreceksiniz. Ayrıca planlarıma göre bu seri içerisinde herhangi bir tool için birden fazla yazıyı da sizlerle paylaşmayı düşünüyorum.

IaC Hakkında

Infrastructure as Code (IaC) isminden anlaşılacağı gibi kısaca altyapının code a dönüştürülmesidir. Burada bahsettiğimiz “code”, ortamlarımızın (infrastructures) ihtiyaç duyabileceği tüm runtime environmentlar, network ayarları, kaynak ihtiyaçları ve bunların parametrelerini içerir. Kodun zaman içerisinde değişmesine bağlı olarak da Git gibi bir VCS(Version Control System) içerisinde tutulması ve versiyonlanması gerekliliği de doğmaktadır. Bu ön tanımlı dosyalar(manifests) daha sonradan farklı toollar yardımıyla infrastructure ı hızlıca ve hatasız olarak kurgulamak için kullanılır. Code un tasarım ve oluşturma süreçleri, kullanılan aracın yetkinliklerine ve kurallarına bağlı olarak değişkenlik gösterebilir. Örneğin, geçmişte IT çalışanlarının scripting veya komutları ardı ardına çalıştırabilmesiyle IaC mantığı kullanılmaya başlanmıştı. Fakat bugün geçerli olan yöntemler, bu işin tamamen başka çerçevede tool lar ile gelişmesi ve kodlamaya dökülmesi ile alakalıdır. Burada bu tool ların kuralları ve yetkinlikleri çerçevesinde kodlarımızı oluşturuyor ve execute ediyoruz.

Peki bunu neden ve nasıl yapıyoruz? Var olan araçların sağladığı faydalar, farklılıklar nelerdir? Bu sorulara cevaplar arayak IaC’ı daha iyi anlamaya çalışalım.

Sorunlarımız… Neden ve Nasıl IaC?

Geçmişte ve günümüzde olduğu gibi gelecekte de her zaman ön planda olacak en önemli şeylerden biri var olan yazılımın-hizmetin nasıl sunulacağıdır. Yapılan işin başarısı büyük oranda buna göre şekillenir. Geçmişte şirketler çoğunlukla fiziksel sunucularda hizmetler verirken sahip oldukları altyapı static diyebileceğimiz türdeydi. Static infrastructure dediğimizde bir data center ı düşünelim. Server üzerindeki diskler, RAM’ler; network elemanlarından router lar, switchler … Bunları büyük hizmetler veren, büyük şirketler için sıfırdan kurmanın,configure etmenin getirdiği maliyeti düşünelim… Kapasite arttırımı amacıyla(horizantal-vertical scale) yeni hardware alınabilmesini için geçmesi gereken approval süreçlerini, donanım teslimlerini düşünelim…Sonra bu donanımları bu çooook sayıdaki serverlara-routerlara entegre ve configure etme süreçlerini düşünelim… Neyse daha fazla düşünmeyelim :):) Bunlar gerçekten zaman, cash kaybettiren sorunlar.

Neyse ki, günümüzde bunları çözen dynamic türde olan altyapılar var. Artık yukarıdaki sorunlar bizim gözümüzde büyümüyor. Bunları cloud provider lar, sanallaştırma teknolojileri, configuration management toolları sayesinde kolaylıkla belki de tek tıkla hallediyoruz. Yine de dynamic diyebileceğimiz bu türdeki yapılar için de sorunlar bulunmaktadır. Birkaç örnek vermek gerekirse:

  • Her ne kadar infrastructure yapısını cloud providerlar veya diğer sanallaştırma ortamlarında kolayca oluştursak da bu sürecin hızı ve güvenirliği bizim için hala çok önemli.
  • Infrastructure hazır. Fakat hala configure edilmemiş halde. Birçok VM’miz olan bir mimaride bunu el ile yapmak büyük bir zaman kaybı.
  • Peki örneğin AWS üzerine kurduğumuz bir mimarinin aynısını hızlıca Azure, GCP üzerine de kurmamız gerekirse?
  • Altyapımızı hazırladık fakat oldu ki bir sorun oldu ve tüm bu altapıyı tekrar kurmamız gerekiyor. Başa dönerek bu infrastructure ın ilk saf-değişmez(immutable) halini nasıl kurarız?

İşte bu bahsettiğimiz sorunlar “neden IaC kavramını geliştirdik ve kullanıyoruz” sorusunun cevabı olabilir. Aslında, geçmişte IT çalışanlarının scripting veya komutları ardı ardına çalıştırabilmesiyle IaC mantığı kullanılmaya başlanmıştı. Fakat bugün bahsettiğimiz şey, bu işin tamamen başka çerçevede tool lar ile gelişmesi ve kodlamaya dökülmesi ile alakalıdır.

Bazı IaC Kavramları

IaC’dan bashetmişken, bazı konularda anlam kargaşasına düşmememiz için birkaç kavramı açıklamak istiyorum. Eğer bu konuda birşeyler okumaya başlarsanız, bu kavramları görmeniz çok muhtemel.

→ Mutable — Immutable Infrastructure

İlk olarak “mutable” ve “immutable” ne demektir bunu bakalım.
“mutable” kelime olarak “değişken”, “immutable” ise zıttı olarak “sabit,değişken olmayan” anlamına gelir. “mutable” infrastructure dediğimizde configurasyon ve diğer değişikliklere her zaman açık olan tradational sistemleri örnek verebiliriz. Düşündüğümüzde bir traditional bir sistemi kurduğumuzda, daha sonra bu sistem üzerinde SSH ile bağlanarak yazılım paketlerinde güncellemeler, environment eklemeler vb. gibi işlemleri tek tek yapıyorduk. Açıkçası çoğu yerde durum hala böyle. Bu yüzden bu sistemlere değişken yani “mutable infrastructure” diyoruz. Ayrıca böyle bir ortamda bir grup server kümesi için yaptığımız işlemler aynı da olsa sonuç olarak bazı server lar birbirinden tamamen farklı, benzersiz olabiliyor. Bu teşhis edilmesi ve yeniden oluşturulması zor ince konfigürasyonla hatalarına “configuration drift” deniyor.

Diğer yandan “immutable infrastructure”; Terraform, CloudFormation gibi toollar tarafından VM veya container image ı gibi hazır yapılar kullanılarak oluşturulur. Docker, VMware gibi tool lar yardımıyla oluşturulmuş bu hazır image ler kurulacak altyapının gerekli tüm konfigürsayonlarını içerir. Böylece kurulum sonrasında infrastructure üzerinde büyük konfigürasyon değişiklikliklerine ihtiyaç duyulmaz. Eğer infrastructure da büyük konfigürasyonlarına değişikliklerine ihtiyaç duyulursa yeni image ler oluşturulur ve best practice olarak image ler bir source control(örneğin Git) sayesinde versiyonlanır. Serverlar oluşturulan yeni image ile tekrardan boot edilir ve eski olanlar terminate edilir. Böylece “configuration drift” durumu ortadan kalkar, yapılan değişiklikler daha güvenilir olur. Bu süreç yine de biraz yavaştır.

Mutable ve immutable infrastructure kavramları arasında tek bir doğru olmasa da, bu iki altyapı türünün getiri ve götürüleri birbirinden farklıdır. Konuyla alakalı daha fazla detaylı bilgiye ulaşmak isterseniz buradaki yazıya bakmanızı mutlaka tavsiye ederim.

→ Declarative-Imperative(Procedural) Code

Diğer kavramlardan ikisi ise “declarative” ve “imperative(procedural)” kavramları… IaC yaklaşımında her şeyden önce uygun araç seçimi çok önemlidir. Sizin için uygun olan aracı ise yetkinliklerinize, amaçlarınıza ve bu aracın kullandığı dilin özelliğine göre seçmelisiniz. Aksi halde hedeflenilen amaçlara ulaşılamayabilir veya bu yolda zorluklar çekebilirsiniz. Bu yüzden bu iki kavram tool seçiminde yardımcı olacaktır.

Kısaca “declarative” yaklaşımda, ne ihtiyacımız olduğunu tüm detaylarıyla listeleyerek code execution sonrasında elimizde ne olması gerektiğini kullandığımız aracın dilinde kodlayarak belirtiriz. Bunu yaparken ise aracın bu işi nasıl yapabileceğini kullandığımız araca söylememize gerek yoktur. Bir nevi “ne gerekli” sorusunun cevabını veriyoruz. “imperative” (bazen “procedural” olarak da bahsedilir.) yaklaşımda ise gerekli olan kaynakların nasıl oluşturulacağını kodlayarak belirtmiş oluruz. Burada da “nasıl yapılmalı” sorusuna cevap vermiş oluyoruz.

Ufak bir örnek ile bu iki kavramı daha iyi anlayabiliriz. Örneğin, masanızda bu yazıyı okurken bir kahve içmek istediniz. Bunu “declarative” ve “imperative” yaklaşımlarla nasıl ifade edersiniz…? Böyle bir durumu “declarative” yaklaşımla ifade etmek için:

“ Ozan’ın ‘IaC Dünyası-1: Terraform' başlıklı Medium yazısını okurken flat white kahvemi masama alabilir miyim?” şeklinde belirtmeniz declarative yaklaşım için yeterlidir. Kafedeki garson birazdan kahvenizi masanıza getirecektir :)

Imperative(procedural) yaklaşımla ise bu durumu şöyle ifade edebilirdik:

“ Ozan’ın ‘IaC Dünyası-1: Terraform’ başlıklı Medium yazısını okurken flat white kahve içmek istiyorum. Bunu yapabilmen için şunları yapmalısın: 40ml double espressoyu hazırla, 80ml sütü ısıt krema haline getir, krema sütü yavaşça double espresso üzerine dök. Masaya getir.” şeklinde belirtmeniz imperative(procedural) yaklaşım için gereklidir. Kafedeki garson birazdan kahvenizi masanıza getirecektir. :)

Son olarak aşağıdaki resim üzerinden declarative-imperative yaklaşmını anlayabiliriz:

Source: https://www.copebit.ch/how-declarative-and-imperative-styles-differ-in-infrastructure-as-code/

Yine “mutable-immutable” konusunda olduğu gibi burada da “net bir doğru” yoktur. Bazen “declarative” olarak bazen ise “imperative(procedural)” olarak altyapınızı tanımlamak sizin için daha iyi olabilir. Her iki yaklaşımı da kullanan farklı toollar bulunmaktadır. Hatta bazen bu toolları beraber bile kullanıyoruz. Buna case inize göre siz karar vermelisiniz. Sonuç olarak o kahve her türlü geliyor yani :)

→ Configuration Management Tools — Provisioning Tools

Son olarak da bu iki farklı araç kategorisinin anlamlandırılmasına bakalım. IaC dünyasında kullanılan araçlar genel olarak “Configuration Management Tools” ve “Provisioning Tools” olarak ikiye ayrılır.

“Configuration Management Tools”, var olan infrastructure üzerinde konfigürasyonlar yapmaya yönelik tasarlanmış araçlardır. Bu araçlar ile yapabileceğimiz işlerden bazıları: OS üzerinde kullanıcıları tanımlamak, servislerin durumunu değiştirmek(start-stop-restart), yazılımı ortamı için paketleri kurmak, güncellemek vb… Bunlara örnek olarak:

  • Chef
  • Puppet
  • Ansible
  • SaltStack

gibi araçları verebiliriz.

“Provisining Tools” ise planlanılan infrastructure ınızı oluşturan öğeleri(VM, database servers, load balancers, VPC, subnet, firewall etc.) hazırlayan araçların tümünü bu kategoriye dahil edebiliriz. Bu araçlar genellikle provider ların (VMware,AWS,k8s etc.) API larına call yaparak gerekli infrastructure ı oluştururlar. Bunlara örnek olarak:

  • Terraform
  • CloudFormation
  • OpenStack Heat

Buraya kadar olan tüm başlıkların özetini ve daha fazlasını aşağıdaki resimde görebiliriz:

Yukarıdaki tabloda da görebileceğiniz gibi, birçok tool alternatifi bulunmaktadır. Bunların hangisinin kullanılması gerektiği ise tamamen size kalmış. Gerekli olan değerlendirmeyi her açıdan yapıp ona göre karar vermelisiniz. Ortak olan düşüncelerden birisi ise işin en zor ve önemli kısmının burası olduğuyla alakalı… Doğru araç seçimi… Ayrıca, IaC dünyasında bilinmesi faydalı olabilecek başka kavramlar da bulunmaktadır. Fakat bu yazının daha fazla uzamaması için onları diğer yazılarda sizlere açıklamayı daha doğru buldum.

Şimdi son zamanlarda öğrenmeye çalıştığım “Terraform” nedir ona bakalım…

Kısa bir giriş…

Terraform, initial release olarak 28 Temmuz 2014 yılında Hashicorp şirketi tarafından yayımlanmıştır. Open source bir tool olmasıyla beraber “Terraform Enterprise” versiyonu da mevcuttur. “Go” dili ile yazılmıştır. En basit haliyle ne iş yaptığından bahsedecek olursak, sizin için var olan veya yeni oluşturacağınız infrastructure yapılarınızı declerative kod olarak tanımlayarak bu kod üzerinde değişikler yapmanıza ve yaptığınız değişiklikleri de ortam türünüze göre( test/prod vb.) tag lenmesini sağlar. Burada kod olarak bahsettiğimiz, HashiCorp şirketi tarafından geliştirilmiş, okunması, yazılması ve anlaşılması oldukça kolay olan “HCL(Hashicorp Configuration Language) dir. HCL, ayrıca HashiCorp şirketinin diğer ürünlerinde de kullanılan bir syntax. Tabii ki bu size aktarabileceğim en basit tanımlardan biri.

Bana göre, neden Terraform?

Terraform bakıldığında, birçok DevOps tool uyla entegre çalışmasının yanı sıra trend alanlardan olan SDN(Software-Defined-Networking), multi cloud yapılarının kurulması gibi farklı birçok farklı alanlarda mission-critic görevleri yüksek güvenilirlikle yerine getirmek , gereksiz iş yükünden kurtulmak için tercih edilen bir tooldur. Kendi adıma, IaC dünyasında belirgin bir özelliğinden dolayı kullanmaya zorunlu kaldığım spesifik bir tool henüz olmadı. Fakat IaC yaklaşımını öğrenmeye neden Terraform gibi bir provisioning tool u ile başladığımdan biraz bahsetmek isterim. Bu nedenleri kısaca söyle sıralayabilirim:

  • Terraform’un yazıldığı dil olan HCL, bana anlaşılabilir-human readable gelmişti.
  • Ayrıca bundan daha da önemlisi, Terraform çok çeşitli ve sayıda provider ile entegre olabiliyordu.
  • Dökümantasyonları bana gayet anlaşılır ve basit geldi. Detaylı dökümantasyon sayfasını ise buradan görebilirsiniz.
  • Sorunsuz şekilde infrastructure üzerinde değişiklik sağlayarak immutable infrastructure oluşturması
  • Çok sayıda provider ile çalışabilmesi. Terraform’un çalışabildiği tüm providerların listesini buradan görebilirsiniz.

Tüm bu nedenlerden ötürü öğrenmeye Terraform ile başladım.

Terraform Core Consepts

Terraform içinde bilmemiz gereken birkaç konsept var. Bu konseptlere göre infrastructure ımızı yaratacak olan kodu yazıyoruz. Bu kısmı açıklarken aşağıdaki Github repository imi kullanıyor olucam. İsteğinize göre göz atabilirsiniz:

Bu konseptler aşağıdaki gibidir:

  • Variables

Terraform içerisinde kullandığımız inputları ifade eder. İsteğimize göre tanımladığımız variables, her türlü özelleştirmeyi yapmamızı sağlayan key-value şeklindeki yapılardır. Terraform’da bunları “variables.tf” gibi bir dosyada saklayabiliriz. Örneğin, ext_port, storage adı, container adı vb. Aşağıda Terraform’da “int_port” ve “ext_port” değişkenlerinin Terraform’da main code u tanımladığımız yer olan “main.tf” dosyasında nasıl kullanıldığına dair bir örnek görebilirsiniz:

Variables Usage

Ayrıca yukarıdaki code örneğinde “dev” ve “prod” olarak 2 farklı şekilde bir variable’ın değerini verebiliyoruz. Hangisini kullanacağımızı nasıl söylediğimizi ise yazının ilerleyen kısımlarında inceleyeceğiz.

Ufak bir not: “$” sembolü ile aslında farklı bir değeri çağırıyormuşuz gibi düşünebiliriz. Buna “Interpolation syntax” denir ve Terraform’da sıkça kullanılan bir durumdur. Daha fazla detaylı bilgiye buradan ulaşabilirsiniz.

  • Provider

Terraform’un servisleri kullanmak için yaptığı API call larını gerçekleştirmesini sağlayan pluginler diyebiliriz. Bu pluginler sayesinde aslında istediğimiz servisler ile iletişime geçerek buralarda infrastructure ımızı oluşturuyoruz. “Provider” a örnek olarak Docker, Vmware veya AWS gibi cloud servislerini verebiliriz. Daha önce de bahsettiğim gibi Terraform’un çalışabildiği tüm provider ları buradan görebilirsiniz.

  • Modules

Infrastructure ın tanımlandığı Terraform dosyalarının hiyerarşik olarak oluşturulduğu klasör yapılarını ifade eder. Böylece Terraform’da code tekrarı olmadan konfigürasyonları tekrar tekrar çağırarak kullanabilirsiniz.Terraform’daki kodunuzu efektif olarak kullanmanın, kodunuzu test etmenin ve modüler bir infrastructure yaratmanın en iyi yolu “modules” yapısını kullanmaktır.

Default olarak aslında her bir Terraform konfigürasyonu “Root Module” olarak adlandırılan bir module içerisinde tanımlanır. Bunu aşağıdaki gibi düşünebiliriz:

root-module (Tabii bu şekilde adlandırma gibi bir zorunluluğumuz yok.)
└ main.tf
└ outputs.tf
└ variables.tf

Terraform’da birçok farklı amaçla module oluşturabiliriz. Örneğin staging ve production environmentları için ayrı modüller oluşturabiliriz. Başka bir örnek olarak Docker provider ı ile çalışırken “image” ve “container” gibi modüller tanımlayarak bunları bir root module içerisinde çağırabiliriz. Aşağıdaki örnekte de bunu görüyoruz:

Modules Usage

Aşağıdaki linkten dosya hiyerarşisini görerek daha iyi anlayabilirsiniz:

  • State

Terraform tarafından yönetilen altyapı ve ilgili konfigürasyonlar hakkında önbelleğe alınmış bilgileri içerir. Terraform’un çalışma mantığını açıklayacağım bir sonraki başlıkta “Terraform Core” adında bir bileşen göreceğiz. “Terraform Core” infrastructure ın güncel son halini bir state üzerinde tutarak kodunuzu bir sonraki çalıştırışınızda eğer infrastructure konfigürasyonlarınız üzerinde bir değişiklik(ekleme,silme, güncelleme vs.) varsa bunu uygular. Eğer yok ise infrastructure ınız olduğu şekliyle kalır. Ayrıca manuel olarak infrastructure ınızı değiştirmeniz durumda, Terraform bir sonraki çalıştırmada state ti referans alarak, infrastructure ı buradaki haline göre yeniden düzenler. Böylece “immutable infrastructure” sağlanmış olur.

  • Resources

Infrastructure ı oluşturan, configure ettiğimiz objeleri(VM, container, DNS records, sanal ağlar etc.) tanımlar. Aslında resource lar bloklar şeklinde tanımlanır ve her blok bir veya birden fazla obje içerebilir. Her resource birçok farklı özelliği sahip olabilir fakat sadece ufak bir kısmı ilk kullanım (initial use) için yeterlidir. Örneğin AWS üzerinde bir instance yaratacaksak bunu aşağıdaki gibi yapabiliyoruz:

Resources Usage
  • Outputs

Bir module içerisinde Terraform’un diğer Terraform modülleri tarafından da kullanılabilen dönüş değerleridir. Aşağıdaki örnekle daha iyi anlayabiliriz:

Outputs Usage

Terraform Çalışma Prensibi

Terraform kullanarak infrastructure oluşturmak istediğimizde konfigürasyon dosyalarımız temelde 4 aşamadan geçer ve bunun sonucunda infrastructure ımız hazır gelir:

Source: https://www.ovh.com/blog/private_cloud_and_hashicorp_terraform_part1/
  • Init → Workspace üzerindeki tüm Terraform dosyalarını initialize eder.
  • Plan → Infrastructure ın istenen bir durumuna ulaşmak için bir execution plan oluşturulur. Bazen konfigürasyon dosyalarında değişiklikler yapılır veya farklı ortamlar için(dev veya prod) farklı parametreler ile plan oluşturulabilir. Böyle bir durumda “Plan” adımı tekrar yapılır ve farklı planlara sahip olunur.
  • Apply → İstenilen durumu elde etmek için infrastructure ın gerçek / mevcut durumundaki değişiklikleri uyguladığı aşamalardan biridir. Apply bir Terraform “Plan” üzerinden yapılır. Bu aşamadan sonra elimizde arzu edilen infrastructure a sahip oluyoruz.
  • Destroy → “Apply” aşamasından sonra, terminate edilmesi gerekli olan tüm eski altyapı kaynaklarını silmek için kullanılır.

Terraform’un mimarisine baktığımızda yukarıda bashedilen tüm adımlar aslında “Terraform Core” adı verilen bileşen tarafından “terraform init”, “terraform plan”, “terraform apply”, “terraform destroy” gibi komutlar ile CLI üzerinden yapılır. Hatırlarsanız yazının yukariki kısımlarında bunu “state” i tutan bir yapı olarak görmüştük. Aşağıdaki Terraform mimarisi diyagramıyla Terraform’un adım adım nasıl çalıştığına bakalım:

Source: https://geekflare.com/terraform-for-beginners/

İlk olarak “Terraform Core” sizin oluşturduğunuz konfigürasyon dosyalarını işler. Böylece ikinci adımda, “Terraform Core”, “Terraform State” i update ederek infrastructure ın istenilen güncel şeklinin state etmesini sağlar. Daha sonrasında ise yapılması gereken ne ise(güncelleme, ekleme, silme) infrastructure üzerinde bunları belirleyerek uygular. Bunları yaparken, tabii ki yukari kısımda bahsettiğimiz 4 aşamayı (init-plan-apply-destroy) duruma göre gerçekleştirir. Sonuç olarak da elimizde hangi provider ile çalışıyorsak onun üzerinde bir infrastructure objesi oluşmuş olur.

Son olarak tamamlayıcı nitelikte olan şağıdaki videoyu izleyebilirsiniz. HashiCorp Co-Founder’ı Armon Dadgar, Terraformu gayet basit ve anlaşılır anlatıyor. Böylece kafanızda eksik kalan yerleri tamamlayabilirsiniz.

Terraform ile Docker Container Provisioning

Bu kısımda Terraform’un provider larından biri olan Docker ile basic bir örnek göstermiş olacağım.

Önemli Not! → Bu yazıyı yazarken Terraform v0.11.13 ile çalıştım. Bu versiyon eski bir Terraform versiyonu. Github repositroyimdeki syntax yazımında güncel versiyon ile farklılıklar olabilir. Bu yüzden sizin denemelerinizde eğer farklı bir sürüm kullanıyorsanız hatalar alabilirsiniz. Gerekli açıklamayı burada ve burada bulabilirsiniz. Ayrıca “interpolation syntax deprecated” hatalarına çözüm olarak buraya da bakabilirsiniz. Repository içeriğini zaman zaman güncelliyor olacağım. Anlayışınız için teşekkür ederim…

Öncelikle, eğer ortamınızda Terraform yüklü değil ise aşağıdaki adımları izleyerek kolayca yükleyebilirsiniz:

  • Buradan tercih ettiğiniz ortam türüne göre en son release dosyasını kurmak için indirebilirsiniz. Ben Linux ortamını tercih ettim. Windows, MacOS gibi ortamlara da kurabilirsiniz:
  • Daha sonra indirilen dosyayı unzip ederek çıkan binary dosyasını “/usr/local/bin” altına atmalıyız:
  • Artık Terraform’u kullanmaya hazırız. Aşağıdaki gibi test edebilirsiniz:
  • Demo için aşağıdaki Github repostory imi (docker →basics) kullanıyor olacağım:

Senaryomuz şu şekilde olacak: “Prod” ve “Dev” adında iki farklı ortamımız için farklı özelliklere sahip containerlar oluşturucağız. Bunu yaparken tabiki farklı Terraform planları oluşturup, apply edeceğiz. Detayları diğer adımlarda belirtmeye çalışıcam. Aşağıda bunun için kullanılan dosyaları görebilirsiniz:

Biraz yukarıdaki koddan bahsetmek istersek şunları söyleyebiliriz:

→ İki farklı ortam için farklı external portlar kullanacağız. “dev” ortamı için 8081 ve “prod” ortamı için ise 80 portunu kullanıyor olacağız. Kullandığımız internal port ise her iki ortam için de aynı olacak.
→ Aynı şekilde “dev” ortamı için “ghost:latest”, “prod” ortamı için “ghost:alpine” imajını kullanıyor olacağız.
→ Ayrıca “container_name”, “image_name” gibi değişkenler de ortam türüne göre değişiyor olacak.

Aslında incelediğinizde tüm bu özellikler “variables.tf” altında “map” türünde değişken tanımlanarak yapılmıştır.

  • Öncelikle ilgili klasöre giderek ilk komutumuz olan “terraform init” komutunu çalıştıracağız. Böylece Terraform artık burada çalışıyor olduğumuzu bilmiş olacak.
  • Daha sonrasında ilk olarak “dev” ortamı için planımızı oluşturabiliriz. Bunu yapmak için terraform plan -out=tfdev_plan -var env=dev komutunu çalıştırmalıyız. Burada -var env=dev olarak daha önce Terraform konfigürasyonu içerisinde tanımlanmamış fakat gerekli olan bir değişkeni input olarak veriyoruz. Bunu oluşturalacak plan için, destroy edilecek resourcelar için her seferinde yapmamız gerekiyor.(Terraform version 0.11.3 için). Gördüğünüz gibi Terraform bizim için oluşturulacak resource ları tanımladı:
  • Gördüğünüz gibi “tfdev_plan” adında bir plan oluşturmuş olduk. Şimdi bu oluşturduğumuz planı uygulayabiliriz. Aşağıdaki resimde gördüğünüz gibi planlanan tüm resourcelar Terraform tarafından bizim için oluşturulmuş oldu. Ayrıca en altta “Outputs” altında daha önce “outputs.tf” dosyasında tanımlandığımız değişken çıktılarını görebiliriz:
  • Docker üzerinde kontrol ettiğimizde container’ın oluştuğunu görebiliyoruz. Terraform’da konfigure ettiğimiz gibi “dev” ortamı için “8081” portunu external port olarak kullandık ve bu port internal olarak 2368'e map ediliyor. Container ımız ayağa kalktığında “dev” ortamı için “IP:8081” şeklinde, “prod” için “IP:80” yazılarak örnek Ghost Blog sayfasına ulaşılabilir:
  • Daha sonrasında diğer ortamımızı oluşturmak için “dev” ortamını destory edebiliriz veya direk olarak yeni “prod” planımızı oluştururak Terraform’un infrastructure ı buna göre yeniden modifiye etmesini sağlayabiliriz. Ben burada daha graceful olarak destroy etmeyi tercih ediyorum. Bunu yapmak için aşağıdaki komutu çalıştırmalıyız:
  • Bu aşamada elimizde yine fresh bir ortam var. Yani önceki “dev” ortamı resourcelarını sildik. Şimdi “prod” ortamı için bir plan oluşturalım:
  • Oluşturduğumuz bu planı aynı şekilde aşağıdaki gibi apply edebiliriz:
  • Aşağıda da görüldüğü gibi containerımız oluşmuş olacak:
  • İşimiz bittikten sonra bu ortamı da istersek kaldırabiliriz. Bunu yine terraform destroy komutuyla yapacağız fakat bu sefer -auto-approve flag i vererek bizden onay beklemeden direk silmesini sağlayabiliriz.

Bu yazının burada sonuna geldik. Terraform ile Kubernetes, Docker vb. providerlar ile nasıl çalışacabileceğimizin farklı örneklerini diğer yazılarda inceleyeceğiz.

Bir sonraki yazıda görüşmek üzere !

--

--