Bir DevOps Yolculuğu-S1/E02-Terraform- { Püf Noktalar }

Serkan Bingöl
AWS Certified User Group Turkey
11 min readFeb 3, 2019

Merhabalar önceki yazımız ile devops ile ilgili birçok konuya değineceğimiz “ Bir DevOps Yolculuğu” serimize başladık. Her yeni yazıda bir devops aracını tanıtarak devam edeceğimiz bir kurgu üzerinde yol haritası çıkarmıştım. Serinin en sonunda ise tüm incelediğimiz araçları kullanarak tam bir senaryoyu test edeceğimizden bahsetmiştik.

image from Lynda.com

Serimize her devops aracı için 2 şer yazı planlayarak devam etmek istiyorum. Birinci yazılarda incelediğimiz araçların genel kullanımı üzerinde yoğunlaşırken, takip eden yazılar da ise o araç ile ilgili püf noktalara değineceğiz. Terraform ile ilgili olarak bahsedeceğimiz püf noktaları AWS üzerinde örneklendirerek anlatacağız. AWS bileşenleri için temel seviyede bilgileri kısımlar içinde vermeye çalışacağım. Detaylı bilgiler için bu link üzerinden gerekli kısımları inceleyebilirsiniz.

Tüm konfigürasyon işlemlerine içinde barındıran “terraform-hints” dosyasına aşağıdaki repository üzerinden ulaşabilirsiniz. Her bölümün içindeki screenshots klasöründen o bölüm ile ilgili detaylı resimleri bulabilirsiniz.

Terraform Interpolation Kullanımı

Terraform kullanarak altyapımızı kurgulamak istediğimiz de , aynı konfigürasyon planı içinde bir çok bileşeni ayaklandırmamız gereken işlemlerimiz olacaktır. Bu bileşenler kendi içlerinde bir çok noktadan birbirlerine bağımlı olarak oluşmak durumunda olacaklardır.

Örnek olarak aşağıdaki resimde oluşturmak istediğimiz security group içinde kullanılacak bir elastic ip yi oluşturduğumuz bir konfigürasyon kurgumuz olsun. 2 işlem birden aynı anda yapılacağı için ilk oluşan elastic ip yi security group içinde tanımlamak istiyoruz.Burada oluşan ilk kaynaktaki değerleri aynı anda oluşan ikinci kaynak üzerinde kullanmamız gerekiyor.Oluşabilecek ip tamamen rastgele oluştuğu için bu ip yerine “0.0.0.0” ip aralığını kullanıyoruz.

Interpolation kavramı kelime anlamı olarak “ara değeri bulmak” demektir. Dinamik oluşan anlık konfigürasyon çıktılarını kullanmak istediğimizde terraform üzerindeki interpolation kavramından yararlanıyoruz. Oluşan kaynaktaki değeri yakalayıp bir tanımlama ile bir değişken üzerinden veriyi kullanmamıza olanak tanıyor.Söz dizimi olarak [“${terraform_amazon_tanımı.kullanıcı_tanımı.özellik}”] şeklinde bir kullanımı mevcuttur.

Aşağıdaki resimde interpolation kullanarak oluşan security group içinde aynı anda oluşaşan elastic ip yi [“${aws_eip.interpolation_eip.public_ip}/32”] tanımını kullanarak oluşturmuş bulunmaktayız. Sağ taraftaki terraform plan komutu ile oluşturduğumuz çıktıya baktığımızda değerin dinamik olarak hesaplanacağını görebilmekteyiz.

Interpolation kullanımı için aşağıdaki link üzerinden detaylı bilgilere ulaşabilirsiniz.

Terraform Provisioners Kullanımı

IaC yaklaşımı ile konfigüre ettiğimiz sistemlerde sadece altyapı bileşenlerini oluşturup bunları izlemek ile ilgilenmeyiz. Kimi zaman bu bileşenlerin üzerinde gerek kendi komutlarımızı gerekse dış kaynaklarda bulunan komutları çalıştırmamız, bu kaynaklar üzerine uygulamalar kurarak bu uygulamaları konfigüre etmemiz gerekecektir. (Bir sonraki yazımızda bu konu ile ilgili daha detaylı bir araç olan ANSIBLE konusunda duracağız.) Şimdilik daha basit şekilde scriptler üzerinden işlem yapacağız.

Provisioner kavramı bileşenleri oluştururken ya da sistemden kaldırırken lokalden veya dış kaynaklar üzerinden script çalıştırmamıza olanak tanıyan bir terraform tanımlamasıdır. Local çalıştırılanlara local-exec, dış kaynak üzerinden çalıştırılanlara remote-exec isimlendirmesi yapılmıştır. Bu kısım üzerinde 2 konuyu da anlatabilmek adına öncelikli olarak ortak bir bileşen oluşturacağız.

Terraform kullanarak AWS üzerinde bir adet security group , bir tane ec2 makinesi ve 1 adet elastic ip oluşturacağız.Daha sonra oluşan bu makineye bağlanıp ayrı ayrı local-exec ve remote-exec komutlarını kullanarak scriptler üzerinden işlemlerimizi gerçekleştireceğiz.Burada dikkat edilmesi gereken bir kısım olarak oluşturulan bu ec2 makinelerine bağlanmak için AWS hesabımız üzerinde güvenli bağlantı adına kullanacağımız bir token key oluşturmamız gerekmektedir.

AWS yönetim panelimiz üzerinden Network&Security sekmesinden Key Pairs alanını kullanarak bu gerekli güvenli bağlantıyı sağlayabiliriz.

Key Pair oluşturma işleminde dikkat edilmesi gereken en önemli husus oluşturduğumuz key pair için oluşturulan bölge ile oluşturulmak istenen bileşenin bölgesinin aynı olması gerekmektedir. Aşağıdaki resimde İrlanda (eu-west-1) bölgesinde bu işlemi yaptığımızı görebilirsiniz.

Oluşturduğumuz pair key bileşenimizi indirerek terraform projemizde kullanmak üzere terraform apply çalıştıracağımız dosya yoluna kopyalıyoruz.

AWS kullandığımız için provider.tf dosyamız içinde bölge ve access ayarlamasını yapıyorum.

Konfigürasyon kurgumuz içinde değişebilecek alanları yönetmek adına variables.tf dosyasını oluşturup ileride security group içinde ip tanımlamasında kullanmak istediğimiz default ip yi burada tanımlıyorum.

Don olarak security group için gerekli ingress ve egress kurallarımızı tanımlayarak port ve protokol tanımlamalarını yapıyorum.Daha önceden belirlemiş olduğumuz default ip için bir ${var.infra_ip} üzerinden 0.0.0.0/0 olarak belirliyorum.

Bu kısımdan itibaren yukarıda oluşturduğumuz bileşenleri kullanarak 2 ayrı konfigürasyon kurgusunu anlatıyor olacağım.

Remote-exec Provisioner

Bu senaryomuzda daha önce oluşturduğumuz bileşenleri kullanarak bir ec2 imaji ayaklandırmayı ve bu makine üzerinde paket yöneticisini kullanarak nginx kurulumu gerçekleştirip firewall ayarlarını kapatarak bir web sunucusunu yayına açmak istiyorum.Öncelikli olarak eip.tf dosyası içinde elastic ip mizin oluşturacağımız ec2 instance için kullanılacağını bir interpolation tanımlaması yardımı ile tanımlıyorum.

Artık ec2 kurulumu için kullanacağımız ec2.tf dosyasında gerekli tanımlamaları yapıyorum.Kod bloğu içinde resource alanında genel resource tanımlaması yaparken key_name için oluşturduğumuz pair key için belirlediğimiz ad olan “remoteconnection” adını kullanıyoruz.

Kod bloğu içinde provisioner bölümü ile bu makine üzerinde bir script çalıştırıp dış kaynaklardan (burada ubuntu paket yöneticisi) gerekli indirme işlemlerini yapıp nginx web sunucumuzun çalışır halde olmasını konfigüre ediyorum. Burada connection alanında ubuntu user üzerinden ssh bağlantı tipi için indirmiş olduğum remoteconnection.pem dosyasını kullanarak gerekli güvenli bağlantı işlemini yapıyorum. ${file(“./remoteconnection.pem”)} kodunu kullanarak key pair dosyamızın yolunu belirliyorum. Ayrıca inline ile ec2 makinesi üzerinde paket yöneticisini kullanarak paketleri güncellemek için yes |sudo apt-get update, nginx sunucu kurulumu için yes |sudo apt-get install nginx, ve firewall portlarını disable etmak adına sudo ufw disable komutlarını kullanıyoruz. Script kodlarının başındaki yes tanımlaması gelebilecek karar sorularına default olarak evet cevabının verilmesi için yazılmaktadır.

Öncelikli olarak terraform init komutu ile hazır hale getirdiğimiz terraform konfigürasyon dosyasını terraform apply komutunu kullanarak çalıştırıyoruz.

İşlemler devam ederken output üzerinden 18.202.197.146 ip sinde pair key üzerinden ubuntu makinesine bağlantı yapıldığını kontrol ediyorum.

Devam eden output çıktısından komutların çalıştığını ,nginx kurulumunun gerçekleştiğini ayrıca firewall un devre dışı bırakıldığını takip ediyoruz.

Kurulumlar tamamlandıktan sonra 1 adet ec2 instance, elastic ip, default security group ile bizim oluşturduğumuz security grubunun oluştuğunu takip ediyoruz.

Ec2 makinemiz için public ip adresimi aws yönetim konsolu içindeki instances alanından yeni oluşturduğum ec2 instancena ait description alanından öğreniyorum.

Öğrenmiş olduğum ip adresini web browser üzerinden request ettiğimde nginx web sunucusunun yayında olduğunu görüyorum.

Tüm işlemlerimizi github reposundaki 02_Provisioners bölümünde ki remote-exec klasörü içinde bulunan screenshots klasöründe ki resimlerden takip edebilirsiniz.

Local-exec Provisioner

Bu senaryomuzda ise daha önce oluşturduğumuz bileşenleri kullanarak bir ec2 imaji ayaklandırmayı ve lokal üzerinde çalıştığım terraform dosyası içine oluşan ec2 instance için o anda üretilen public ipnin adresini kaydetmeyi sağlayacağız.Yanı aslında local makinemde bir script komutu çalıştırarak aws üzerindeki bir değişkeni yakalama işlemi gerçekleştireceğim.Öncelikli olarak eip.tf dosyası içinde elastic ip mizin oluşturacağımız ec2 instance için kullanılacağını bir interpolation tanımlaması yardımı ile tanımlıyorum.

Bir üstteki (remote-exec) senaryosu için yaptığımız gibi ec2 kurulumu için kullanacağımız ec2.tf dosyasında gerekli tanımlamaları yapıyorum.Kod bloğu içinde resource alanında genel resource tanımlaması yaparken key_name için oluşturduğumuz pair key için belirlediğimiz ad olan “remoteconnection” adını kullanıyoruz.

Kod bloğu içinde provisioner bölümü ile local çalıştığım makine üzerinde bir script çalıştırıp oluşturulan ec2 makinasının public ipsini bir interpolation tanımı yardımıyla infra_info.txt adlı yeni oluşacak olan dosyamıza kaydetmeyi planlıyoruz.

Öncelikli olarak terraform init komutu ile hazır hale getirdiğimiz terraform konfigürasyon dosyasını terraform plan komutunu kullanarak bir kontrol gerçekleştiriyorum.

Terraform apply komutu ile gerekli konigürasyon işlemimizi başlatıyorum.

Oluşan infra_info.txt dosyasına baktığımızda makinemizin kaydedilen ip sini görebiliyoruz.

AWS konsolu üzerinden gerekli kontrolleri yaptığımızda infra_info.txt dosyasına kaydettiğimiz public ip yi görebiliriz.

Provisioners kullanımı için aşağıdaki link üzerinden detaylı bilgilere ulaşabilirsiniz.

Terraform Module Kullanımı

Terraform ile birlikte altyapımızı yönetmek istediğimizde aynı özelliklere sahip bileşenlerin, farklı çıktılarına ihtiyaç duyduğumuz zamanlar oluyor. Örneğin aynı security group içinde aynı elastic ip ye dahil bir EC2 makinesi imajı 3 ayrı projede kullanılmak isteniyor olabilir. Fakat bu imaja ait instance type lar her projede farklı olsun isteniyor olabilir. Böyle bir durumla karşılaştığımız zaman her projede aynı konfigürasyonları tekrar tekrar yazmak yerine terraform üzerinde bir modül kurgusu yapmak bizlere çok büyük avantaj sağlayacaktır. Aşağıdaki şema üzerinde aslında bir modül kullanarak proje a üzerinde t2.micro, proje b üzerinde t2.medium ve proje c üzerinde t2.large typeları kullanılmak isteniyor. Bu senaryo üzerinde gerekli konfigürasyon dosyalarımızı oluşturalım.

Öncelikli olarak variables.tf dosyasını oluşturup burada ami ve instance type için 2 adet değişken belirlemek istiyorum. Sonra mod_ec2.tf dosyası üzerinde aws instance için genel ayarların yapıldığı ve variables.tf üzerindeki değişkenlerin kullanıldığı bir resource bloğu oluşturuyoruz. Burada oluşturduğumuz konfigurasyon dosyası, ayrıma gitmek zorunda olduğumuz projeler için bizlere bir ortak altyapı kazandırmış olmaktadır.

Projects klasörü içinde Infra_A, Infra_B ve Infra_C dosyalarını oluşturup proje ayrımlarına ait kırılımları oluşturuyoruz. Her proje içinde bir adet provider.tf ve 1 adet projeadi_ec2.tf dosyası oluşturuyoruz.

Tüm ec2.tf dosyaları içinde module bölümü içindeki source kısmı ile daha önceden tanımladığımız ortak mod_ec2.tf dosyasının yolunu belirliyorum. Ayrıca instance_type kısmı ile gerekli instance type için hangi aws ec2 type kullanılacağını özellikle belirtiyorum.

Tüm projeler içinde terraform init komutunu bir kez çalıştırarak, terraform cli üzerinden yönetmek üzere gerekli altyapıyı sağlamış oluyorum.Tüm projeler içinde terraform apply komutunu çalıştırıp oluşturduğumuz konfigürasyonları ayaklandırıyorum.

Aws konsoldan kontrol ettiğimizde her proje için ayrı instance type üzerinden ayaklandırılmış 3 adet ec2 makinesi görebilmekteyiz.

Module kullanımı için aşağıdaki link üzerinden detaylı bilgilere ulaşabilirsiniz.

Terraform Workspace Kullanımı

Altyapısını kurguladığımız projelerimizi geliştirilirken bir çok deneme yapmamız gerekebilir , bir çok farklı araç kullanmak gerekebilir yada müşteri tarafından test edilecek bir özel alana ihtiyaç duyulabilir. Bu gibi ihtiyaçları karşılayabilmek adına genellikle konfigürasyonarın isteklere göre şekillendirildiği development, test ve production gibi ortamlarımız bulunmaktadır. Bu kısımda ortak ayarlamalarımızın olduğu fakat çalıştığımız geliştirme ortamlarına göre farklılıklar gösterebilen bir terraform çözümünü workspace kavramı ile ele alacağız. Aynı terraform module bölümünde yaptığımız ec2 makinesi instance type farklılaşmasını burada proje bazlı ele almak yerine geliştirme ortamı üzerinden ele alacağız.

Bu kısımda aslında module yaklaşımı kullanarak işlem yapacağız. Öncelikle variables.tf dosyası içinde variable olarak default alanı içinde farklı ec2 typlerı için default, test ve prod geliştirme alanlarını tanımlıyoruz. Sonra mod_ec2.tf dosyası içinde ise genel tanımlamaların yanında instance_type = “${lookup(var.instance_type, terraform.workspace)}” ile aslında workspace değişikliğine göre variable içindeki instance_type tanımlamalarından lookup olarak okuma yapacağımızı belirttik.

Aşağıdaki kısımda ise terraform workspace new istenilen_ad komutu ile workspacelerimizi oluşturuyoruz.Oluşturulan workspaceleri görüntülemek için terraform workspace list komutunu kullanıyorum. Şu an içinde işlem yapmakta olduğumuz workspace başında “*” karakteri ile bu listede gözükmektedir.

Bu ksımda workspacelerimizi terraform workspace select ortam_ismi komutunu kullanarak ortamlar arasında geçişlerimizi yaparak her ortamımız için bir kez terraform apply komutu ile gerekli konfigürasyon kodlarımızı çalıştırıp tüm bileşenlerimizi oluşturuyoruz.

Aws konsoldan kontrol ettiğimizde her geliştirme ortamı için için ayrı instance type üzerinden ayaklandırılmış 3 adet ec2 makinesi görebilmekteyiz.

Workspace kullanımı için aşağıdaki link üzerinden detaylı bilgilere ulaşabilirsiniz.

Terraform Multiple Provider Kullanımı

Altyapılarımızı kurgularken gerek sistemin downtime sürelerinin daha kısalması gerekse felaket senaryolarına hazırlanması amaçlı cluster yapılarımız always-on çalışmak zorundadır. Bu high availability durumunu bazı zamanlarda coğrafi olarakda kurgulamak isteriz. Farklı bölgelerde , kıtalarda aynı konfigürasyonları kurgulak istediğimizde terraform üzerinde multi provider kavramı karşımıza çıkıyor. Aynı credentialları kullanarak farklı regionlarda işlem yapmak istediğimizde terraform üzerinde tek provider alanına izin verildiği için bu işlemi gerçekleştiremiyoruz. Aşağıdaki resim üzerinden 2 adet provider oluşturduğumuzda oluşturulacak elastic ip resource için hangisini kullanacağını bilemediği için aldığımız hatayı inceleyebilirsiniz.

Bunu aşarak multi-provider kullanımını sağlamak adına 2 provider alanımız içine alias ile bir takma isim tanımlaması yapıyorum. Oluşturmak istediğimiz kaynakların içine ise provider alanını ekleyip aws.alias_tanımı komutunu kullanarak hangi provider üzerinden bu işlemi yapacağımızı belirliyoruz. Sonra terraform plan ile konfigurasyon kodlarımızı çalıştırdığımızda gerekli işlemlerin sorunsuz gerçekleştiğini takip edebiliriz.

Tüm bileşenlerimizi oluşturmak için terraform apply komutu ile işlemlerimizi yapıyoruz.

Gerekli kontrolleri yaptığımızda hem us-west regionda hem de eu-west regionda elastic iplerimizin oluştuğunu görebilmekteyiz.

Terraform Import Resource Kullanımı

Terraform ile altyapı kurgularımızı konfigüre etmeyi ve yönetmeyi yeni sistemlerimizde kurguladıktan sonra eski sistemlerimizide bu yönetim aracı ile oluşturduğumuz proje dosyalarına eklemek isteyebiliriz. Gerekli konfigurasyon alanlarına oluşturmak istediğimiz bileşenlerimizin kodlarını eklediğimizde aslında istemediğimiz bir şekilde yeni bileşenleri tekrardan oluşturmuş oluyoruz.Dolayısı ile bu kısım için farklı yol izlememiz gerekmektedir. Aşağıdaki resimde AWS üzerinden önceden açtığımız t2.micro ec2 instance na ait bilgileri görmekteyiz.

Bu bilgileri oluşturmuş olduğumuz provider.tf ve existing_ec2.tf dosyasına yazarak bu bileşeni terraform konfigürasyonuna ekliyoruz.

Bu kısımda terraform plan komutu ile gerekli işlemleri kontrol ettiğimizde bu bileşenin eklenmesi gerektiğini geri dönen bir sonuçla karşılaşıyoruz.

terraform import aws_instance.existing_ec2 existing_ec2_id komutu ile AWS konsol üzerinde bu ec2 ye ait id yi existing_ec2_id alanına yazarak bu sistemi tfstate dosyası üzerinde gerekli değişikliklerin yapılarak bu bileşenin yeni eklenmemesi sadece sisteme dahil edilmesi ile ilgili ayarlamaları yapmış bulunmaktayız.

Tekrardan terraform plan komutu ile işlem yaptıktan sonra ,artık bu bileşenin yeniden oluşturulmayacağı sadece gerekli değişikliklerin sisteme yansıtılacağı bir kurgu işletilecetir.

Import Resource kullanımı için aşağıdaki link üzerinden detaylı bilgilere ulaşabilirsiniz.

Lambaya püf de…

Hem konuların püf noktalarını anlamamız ile ilgili hem de tüm Türkiye’nin 7'den 70 ‘e “Barış Abisi” olmuş olan Barış Manço’nun ölüm yıl dönümü olması nedeni ile sonuç kısmında “Lambaya püf de” başlığını kullanmak istedim. Herkesin bir evresinde ,gerek şarkıları gerekse programları ile yer alan Barış abimizi bu vesile ile hem hatırlamış hem hatırlatmış olalım.

Lambaya püf de..

Bir yazımızın sonuna daha geldik bir daha ki yazımızda yeni devops aracımız olan ANSIBLE incelemesine kadar “Lambaya püf de…”

--

--

Serkan Bingöl
AWS Certified User Group Turkey

Muzur bir oğlan babası, hayvan sever, Harry Potter hayranı, bazen maceracı düz yazılımcı.