Bir DevOps Yolculuğu-S1/E01-Terraform- {Infrastructure Kodda Düzülür…}

Serkan Bingöl
AWS Certified User Group Turkey
10 min readJan 22, 2019

Merhabalar herkese , “DevOps” süreçleri ile ilgili birkaç konu üzerinde örneklemeler yaptıktan sonra , tüm bu süreçlerin ( Altyapı Otomasyonu, Konfigürasyon Yönetimi, Dağıtım Otomasyonu, Altyapı İzleme, Log Yönetimi, Uygulama ve Performans Yönetimi ) yer aldığı uçtan uca kurguladığım bir örneği çalışmak istediğim yeni bir seriye başlıyorum. “Kervan yolda düzülür.” sözümüzden yola çıkarak tüm ilgili süreçleri bu söze dayandırıp ilk yazımıza başlayalım istiyorum.

Burada kullanacağımız araçları serinin her bölümünde ayrı ayrı ele almayı planlıyorum.Her bölüm içinde kullandığım araçları genel hatları ile ele alarak serinin sonunda kullanmamız gereken temel bilgileri elde etmiş olmayı planlamaktayım. Bu yazımız altyapı otomasyonu ve bu konunun çözümü için seçmiş olduğumuz Terraform ile ilgili olacak.

image from cloudsigma.com (cloud-orchestration-at-the-level-of-application/)

Infrastructure as Code (IaC) Nedir ?

Ali Can Kuştemur ‘un “Everything as Code” başlığı altında kaleme aldığı yazı dizisinin ilk bölümünde belirttiği gibi “ Sisteme ek olarak konfigurasyonların yönetilmesi ve altyapının sağlanmasının otomatikleştirilmesi için kod yazılması” anlamına gelir. İlgili seride IaC ile ilgili tüm detaylar verilmiştir.. Bu konu üzerinde detaylara ihtiyaç duyan arkadaşlar şiddetle bu seriye başvurmalı.

Neden Terraform ?

Bilindiği üzere bulut savaşlarında bir çok hizmet sağlayıcı , pastadan büyük dilimi kendine ayırmak için çaba gösteriyor. Gerek sistem yöneticileri gerek yazılım mimarı olarak bizler , bu hizmet sağlayıcılardan birine ya da bir kaçına hizmetlerini tüketmek için başvurmak durumunda oluyoruz. Her hizmet sağlayıcı aslında alt yapı otomasyonu için bizlere kendi çözümlerini sunuyorlar.( Google Cloud Platform- Deployment Manager, AWS- CloudFormation, Azure- Resource Manager vb) Bu üç hizmet sunucudan da bazı hizmetleri kullandığımız bir senaryoda bir altyapı otomasyonuna ihtiyaç duyulduğunda , hepsini tek tek konfigure etmek bizim açımızdan maliyetli bir hal alacaktır. Terraform , “Multivendor” desteği ve açık kaynaklı olması sayesinde burada bizlere bir ayrıcalık sunuyor.

giphy.com

Terraform için Yardımcı Bilgiler

Bu bölümde en basit şekli ile ayrı hizmet sağlayıcılar için alt yapılar ayağa nasıl kaldırılır ve konfigüre edilir bu konulara değineceğiz. Azure , AWS ve Digital Ocean üzerinde denemelerimizi gerçekleştireceğiz.İlk adım da tüm altyapıyı oluşturmadan Digital Ocean ve AWS üzerinde birer sanal makine oluşturacağız. Azure üzerinde tüm alt yapıyı ele alabileceğimiz bir yapıyı konfigüre edeceğiz. Bu sistemleri tasarlarken aşağıda linki bulunan terraform dökümantasyonundan bir çok kez faydalanacağız.

Terraform kullanmak adına gerekli çalıştırılabilir dosyayı aşağıdaki linkten kullanmakta olduğunuz işletim sistemi için indirebilirsiniz.

Terraform kurulumunu gerçekleştirdikten sonra hangi text editörünü kullanacağımıza karar veriyoruz. Ben genel olarak özelliklerini çok beğendiğim VS Code kullanarak terraform ile ilgili tüm ayarlama işlemlerini buradan hallediyorum. ”Terraform.exe” dosyasının yolunu ,global bir değişken olarak tutarak, çalıştığımız tüm projelerin bulunduğu klasörlerde terraform komutlarını kullanabiliyoruz.

Terraform için tüm ayarlamaların yapıldığı dosyalar tf uzantılı olarak oluşturulmaktadır. Biz burada provider.tf isimli bir dosya oluşturarak terraformun ilgili altyapı elemanlarımızı oluşturmasını ve yönetmesini amaçlamaktayız.Bu dosya içinde 2 ana alan mevcuttur. Provider, kullanmak istediğimiz hizmet sağlayıcı ile ilgili genel tanımlamaların yapıldığı alanları barındırır.( Secret Key , versiyon,token vb…) Resource, ise kullanmak istediğimiz hizmete ait ayarlamaların yapıldığı alan olarak tanımlanabilir.

provider "hizmet_saglayici" {

# hizmet_saglayici = Hizmet_Saglayici için terraform.io da belirlenen isimlendirme

}

resource "hizmet_adi" "terraform_isimlendirmesi" {

# hizmet_adi = hizmet sağlayicidan kullanılacak hizmetin adi
# terraform_isimlendirmesi = terraform içinde kullanılan isim
}

İstenir ise içeride tanımlanacak değişkenler ayrı bir vars.tf , kullanılacak hizmet sağlayıcılar provider.tf ve kullanılan hizmetler instance.tf gibi ayrı dosyalarda tanımlanabilmektedir.Biz bu yazımızda tek konfigurasyon dosyası üzerinden işlem yapacağız.Hizmet sağlayıcılar içinde IaC yapısı için en geniş spektrumu Azure üzerinde tutmaya çalıştım. Azure üzerinde kurgulanmış bir konfigürasyon kurgusuna türkçe olarak rastlamak pek mümkün değil bundan dolayı geniş yapı için Azure platformunu tercih ettim. AWS için Ali Can Kuştemur’ un yazı dizisinde gereken detayları bulabileceksiniz.

Digital Ocean ile Terraform kullanımı

Digital Ocean, bulut tabanlı altyapı sağlayıcısı olarak kendini konumlandıran, geliştirme, sürüm kontrolü ve test ortamları gibi bir çok ihtiyaca cevap veren dünyanın en büyük bulut sunucu sağlayıcılarından biri olarak geçmektedir. Biz bu kısımda Digital Ocean üzerinden bizlere hizmet olarak sunulan Droplet altyapı hizmetini terraform üzerinden oluşturup ,kullanacağız.

İlk olarak Digital Ocean yönetim paneli üzerinden sol taraftaki API linki ile bu uygulamada güvenli işlem yapmamızı sağlayan bir adet token üretmek durumundayız.

Üretmiş olduğumuz bu token sayesinde terraform üzerinden güvenli bir şekilde Digital Ocean API sine ulaşabileceğiz.Bu tokeni daha sonra kullanmak üzere bir kenarda tutuyoruz.

Artık provider.tf dosyamızı oluşturup gerekli ayarlamaları yapabiliriz. $ terraform init komutunu kullanarak, provider.tf dosyamızda belirttiğimiz digital ocean kurulumu için gereken pluginleri indiriyoruz.

Aşağıdaki resimden ilgili pluginlerin indirildiğini ve terraform kullanımının bu proje için hazır hale geldiğini takip edebiliriz.

Yapmış olduğumuz ayarları genel olarak kontrol etmek ve nasıl bir çıktı üreteceğini göstermek amaçlı $ terraform plan komutunu kullanıyoruz.

$ terraform plan

Digital Ocean portalımıza girerek “Terraform-Droplet-1” isimli bir dropletimiz olmadığını kontrol etmiş oluyoruz.

Yapılan bu konfigürasyon ayarlarını $ terraform apply komutu ile tüm işlemleri terraform üzerinden gerçekleştiriyoruz.

$ terraform apply

Tekrardan digital ocean portala girip baktığımızda Terraform-Droplet-1 isimli bir sunucu oluşturmuş bulunmaktayız..

Amazon Web Services (AWS) ile Terraform kullanımı

Amazon Web Services , yazılım geliştiricilerin uygulamalarını geliştirmelerini kolaylaştırmak için sunucu hizmeti (EC2), veritabanı servisleri (DynamoDb, RDS), içerik dağıtımı (CloudFront) ve daha bir çok servisi bir arada sununan bir bulut hizmet sağlayıcısıdır. Biz IaC kavramını ele alırken burada EC2 hizmeti üzerinde duracağız.

İlk kısım için AWS üzerinden bir developer hesabı açarak ilgili işlemlerimiz için AWS de bir kullanıcı oluşturmamız gerekmektedir.Bu işlem için AWS Management Console üzerinde Security, Identity, & Compliance sekmesinden Identity and Access Management (IAM) ekranlarına ulaşıyoruz.

Bu ekranlar üzerinden Terraform kullanırken AWS üzerindeki işlemlerimizi yönetecek ve gerekli izinlere sahip bir kullanıcı oluşturmamız gerekmektedir. Bu kullanıcıyı Add User altından şimdilik bir yetki kısıtlaması yapmadan administrator yetkisi ile oluşturuyoruz.

Oluşturmuş olduğumuz bu kullanıcının “Access Key Id ve Secret Access Key” değerlerini daha sonra kullanmak adına bir kenarda tutalım.

AWS Management Console üzerinden herhangi bir EC2 sunucusuna sahip olmadığımızı kontrol ediyoruz.

Daha önceden oluşturmuş olduğumuz provider.tf dosyasına AWS EC2 makinesi için gereken kod yapımızı oluşturuyoruz. $ terraform init komutunu kullanarak AWS için gereken pluginleri indiriyoruz.Ayrıca Aşağıdaki link üzerinden Ubuntu sürümleri için EC2 imaj dosyalarına ulaşabilirsiniz.

Bu yapmış olduğumuz konfigürasyon dosyası üzerinde $ terraform apply komutunu kullanarak AWS üzerinde bir EC2 sunucusu ayağa kaldırmak istiyoruz.

İşlemler tamamlandıktan sonra AWS Management Console üzerinde EC2 Dashboard sekmesinden artık çalışan bir sunucumuz olduğunu gözlemliyoruz.

Detaylı olarak EC2 instance’ ımızı running instances üzerinden inceleyebiliyoruz. Gerekli ayarların yapıldığını bu alanda kontrol ediyoruz.

Microsoft Azure için Terraform kullanımı

AWS ve Digital Ocean üzerinde sadece sanal makine ayaklandırma işlemlerini gerçekleştirmiştik. IaC ile ilgili daha geniş bir spektrum üzerinden çalışma yapmak için azure platformunu kullanacağımızı belirtmiştik. Aşağıda oluşturmak istediğimiz altyapı topolojisi ile ilgili detaylı bir çizimi bulabilirsiniz.

Burada öncelikli olarak tüm bileşenleri içinde bulunduracak bir resource-group, bu resource group içinde gerekli iletişimi sağlayacak virtual network ve subnet, bir adet sunucu ve bu sunucunun dataları için bir adet storage oluşturmak istiyoruz.

İşlemlerimize başlamadan önce azure portal üzerinden VM lerimizi kontrol ederek oluşturmak istediğimiz alt yapıya ait olan Terraform-VM sunucusunun henüz oluşturulmadığını kontrol ediyoruz.

Terraform üzerinden Azure provider kullanımı için gerekli tüm bilgilerin bulunduğu alana aşağıdaki link üzerinden ulaşabilirsiniz.Burada terraform azure provider için gerekli authentication’ı sağlamak için birkaç yol bulunmakta.

Ben authentication için Azure CLI üzerinden işlem yapmayı tercih ettim. Ve bunun için gerekli CLI tool kurulumunu gerçekleştirdim.

AZzure CLI tool üzerinden az login komutunu kullanarak gerekli authentication adımını tamamlamış olduk.

Authenticate olduğunuz kullanıcı üzerinden hangi subscriptionlara sahip olduğumuzu kontrol etmek için az account list komutunu kullanarak aşağıdaki json çıktısına ulaşabiliriz.

Artık giriş ve kullanıcı doğrulama işlemlerimizi gerçekleştirdiğimize göre azure için gereken provider’ımızı kendi subscription-id imiz ile oluşturuyoruz.

provider "azurerm" {
subscription_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Tüm bileşenlerimizi içinde tutacağımız bir Azure Resource Group oluşturmak için gerekli adımları provider.tf dosyamıza ekliyorum. Burada tüm bileşenlerin ön takısını oluşturmak adına variable “prefix” {} ile bir değişken tanımlıyorum. resource için bir ad ve hangi azure lokasyonu üzerinde çalışacağımızı ayarlıyorum. Burada ileride oluşturmak istediğimiz “Standard_D1_v2” tipindeki sunucumuz için desteklenen bir lokasyon belirlemek adına “North Europe” tercih ettim.

variable "prefix" {
default = "TERRAFORM"
}

resource "azurerm_resource_group" "main" {
name = "${var.prefix}-RG"
location = " North Europe"
}

Azure sanal makinelerimizin (VM) ya da diğer azure kaynak türlerinin birbiriyle, internetle ve iç ağlarla güvenli şekilde iletişim kurmasına olanak sağlayan bir virtual network (VN) oluşturmak için gerekli ayarlamaları resource alanında tanımlıyoruz. address_space ile iç ip bloğu için bir aralık oluşturarak ,location ile daha önce oluşturmuş olacağımız resource group için tanımlanan lokasyona bu sanal ağımızıda oluşturuyoruz. Ayrıca resource_group_name ile bu resource group içinde yer aldığını belirtiyoruz.

resource "azurerm_virtual_network" "main" {
name = "${var.prefix}-NETWORK"
address_space = ["10.0.0.0/16"]
location = "${azurerm_resource_group.main.location}"
resource_group_name = "${azurerm_resource_group.main.name}"
}

Mevcut virtual network’ün mantıksal alt alanlara bölüp yönetilebilirliğini kolaylastirma ve güvenliği saglamak üzere alt ağlara bölme işlemini bu resource alanında tanımlıyoruz. name ve resource_group_name değişkenler şekilde atanarak önce oluşturduğumuz resource group üzerinden atamaları yapılmıştır.

resource "azurerm_subnet" "internal" {
name = "internal"
resource_group_name = "${azurerm_resource_group.main.name}"
virtual_network_name = "${azurerm_virtual_network.main.name}"
address_prefix = "10.0.2.0/24"
}

Ağ ile oluşturacağımız VM arasındaki fiziksel bağlantıyı sağlamak amacı ile olusturduğumuz network interface card (NIC) için gerekli ayarlamaları bu resource alanında tanımlıyoruz. name, location ve resource_group_name değişkenler şekilde atanarak önce oluşturduğumuz resource group üzerinden atamaları yapılmıştır. ip_configuration alanı ile NIC için subnete göre otomatik atanan iç ipnin ayarlamalarının yapıldığı alandır.

resource "azurerm_network_interface" "main" {
name = "${var.prefix}-NIC"
location = "${azurerm_resource_group.main.location}"
resource_group_name = "${azurerm_resource_group.main.name}"

ip_configuration {
name = "testconfiguration1"
subnet_id = "${azurerm_subnet.internal.id}"
private_ip_address_allocation = "Dynamic"
}
}

Yapmış olduğumuz ayarlamalar doğrultusunda oluşturmak istediğimiz sanal makinanın tüm ayarlarını resource “azurerm_virtual_machine kod bloğu içinde tanımlamaya başlıyoruz. Gerekli ayarlamaları yaparak location, resource group , network ve açılmak istenen makinenin tipini daha önceki resource alanlarından atıfta bulunarak değişken olarak atıyoruz.

Azure platformu üzerindeki depolama gereksinimlerinin barındırılması için kullanılan storage üzerinde bu VM için bir alan kullanılması gerektiğini storage_os_disk tanımlama alanında belirtiyoruz. storage_image_reference tanımlaması ile bu disk üzerinde VM için hangi işletim sistemi ve hangi sürümünün kullanılacağını belirtiyoruz. os_profile_linux_config ile SSH mı yoksa kullanıcı adı ve şifre doğrulaması mı kullanılacağını belirliyoruz. os_profile ile kullanıcı bilgilerini tanımlamış oluyoruz.delete_os_disk_on_termination ve delete_data_disks_on_termination ayarlamaları VM kaldırılırken dataların tutulması mı yoksa silinmesi mi gerektiğinin belirlendiği alanlar olarak kullanıyoruz.

resource "azurerm_virtual_machine" "main" {
name = "${var.prefix}-VM"
location = "${azurerm_resource_group.main.location}"
resource_group_name = "${azurerm_resource_group.main.name}"
network_interface_ids = ["${azurerm_network_interface.main.id}"]
vm_size = "Standard_D1_v2"
delete_os_disk_on_termination = true
delete_data_disks_on_termination = true

storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
storage_os_disk {
name = "TerraformStorage"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "hostname"
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
}

Burada azure cli ile bir kullanıcı doğrulama işlemi yaptığımız ve bu doğrulamayı kullanmak adınaterraform komutları için powershell kullanıyoruz.Gerekli ayarlamaları yaptıktan sonra terraform apply komutunu kullanarak yapmış olduğumuz tüm ayarları işleme alıyoruz.

Powershell ekranından , provider.tf üzerinde tanımladığımız işlemlerin sırası ile gerçekleştirdiğini takip ediyoruz.

Terraform üzerinden başarı ile tamamlanan işlemlerimizi azure portal üzerinden kontrol ettiğimizde “TERRAFORM-” ön takısı ile oluşturduğumuz resource group bileşenini görebiliyoruz.

Son noktada ise VM ler arasından TERRAFORM-VM sunucumuzun ayakta olduğunu görebilmekteyiz.

Topolojisini çizdiğimiz tüm altyapıyı terraform üzerinden sağlıklı bir şekilde oluşturduk.

Bir Efsanenin Sonu - {terraform destroy}

Tüm işlemlerimizi yapıp altyapımızı tek komutla oluşturduktan sonra sistemlerimizi temizlemek adına $ terraform destroy komutunu kullanıp provider.tf dosyasındaki ayarlara göre oluşturmuş olduğumuz sistemleri kaldırabiliriz.

giphy.com

Komutu kullandıktan sonra yapılan işlemlerin sayısını bize output olarak dönmektedir.

Digital Ocean üzerindeki dropletimiz silinmiş gözükmekte.

AWS de bulunan EC2 makinemiz silinmiş olarak gözükmekte.

Azure üzerindeki resource group içindeki tüm bileşenlerimiz sistem içinden temizlenmiş olarak bizlere gözükmektedir.

Tüm konfigürasyon işlemlerine içinde barındıran “provider.tf” dosyasına aşağıdaki repository üzerinden ulaşabilirsiniz.

Terraform Senaryosu aşamaları : https://1drv.ms/b/s!AskWoAU3NqUuhIB9tyPK8HP1vZDybg

Bir yazımızın daha sonuna geldikten sonra bir daha ki yazımızda Konfigürasyon Yönetimi için seçmiş olduğum Ansible ile ilgili genel bilgilendirmeleri ve örnekleri paylaşmaya çalışıyor olacağım.

Yazımı Terraform’ un mottosu ile bitirmek istiyorum.

Write, Plan and Create Infrastructure as Code

--

--

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ı.