Terraform 101

Hakan Bakacak
Dolap Tech
Published in
7 min readJun 15, 2022

Merhaba, Bu yazıda sizlere terraform temellerinden bahsetmeye çalışacağım. Eğer Terraform hakkında temel düzeyde bilgi sahibi olmak istiyorsanız bu yazı sizin için faydalı olabilir. Bu yazıda, AWS üstünde bir EC2 ayağa kaldıracağız.

Terraform, Hashicorp tarafından Go programlama dili kullanılarak geliştirilmiş bir Infrastructure as Code aracıdır. uygulamalarınızın altyapılarını yönetmenizi sağlar. Örneğin AWS üzerinde bir mikroservisin ihtiyacı olan load balancer, security group, veri tabanı, ECR gibi servisleri arayüz üzerinden elle ayarlamaktansa, bu işlemleri Terraform aracılığıyla kodlayabilirsiniz. Bu sayede insan kaynaklı hatalar azaltılabilir ve uygulamalarınızın altyapı takibi kolaylaşır. Özellikle kalabalık ekipler ile çalışırken bulut servislerde yapılan güncellemelerin takip edilmesi zorlaşıyor. Infrastructure as code sayesinde hem geçmişte neler yapıldığını bir versiyon kontrol aracı aracılığıyla takip edebiliyor hem de son yapılan değişiklikleri code review gibi kontrol mekanizmalarından geçirebiliyorsunuz. Ayrıca Terraform sadece AWS değil, Google Cloud, Azure gibi başka bulut servis sağlayıcıları ile çalışabilir. Örnek kullanım senaryolarına buradan ulaşabilirsiniz

Şimdi AWS üzerinde bir EC2 instance ile bir örnek yapalım. Öncelikle Terraform ile bir EC2 ayağa kaldıralım, EC2'da değişiklik yapalım ve son olarak EC2'yu tamamen kapatalım. Yani aşağıdaki döngüyü tamamlayalım.

Kurulum ve Hazırlık

Öncelikle AWS üzerinde çalışacağımız için AWS CLI ve Terraform’u bilgisayarımıza kurmamız gerekiyor. Sonrasında AWS’e erişim için aws_access_key_id ve aws_secret_access_key’e ihtiyacımız var. Bu adımda ben Terraform için bir AWS IAM kullanıcısı oluşturmayı tercih ediyorum böylece Terraform’a özel bir AWS kullanıcısına sahip oluyoruz ve gerekirse bu kullanıcıyı devre dışı bırakabiliriz. Bunun için öncelikle AWS console üzerinde IAM (Identity and Access Management) servisin users sekmesinden bir IAM user oluşturuyoruz. Bu adımda aşağıdaki görselde de görebileceğiniz üzere konsol yetkisi vermiyorum çünkü ihtiyacımız olmayacak.

Sonrasında oluşturduğumuz kullanıcının yetkilerini seçiyoruz. Bu aşamada ben AdministratorAccess isimli policy ile bir kullanıcı oluşturdum. Kullanıcı oluşturduktan sonra karşımıza çıkan ekranda Access Key Id ve Secret Access Key bulunuyor (Sayfayı kapattıktan sonra bu bilgileri bir daha göremeyeceksiniz). Şimdi credentials isimli bir dosya oluşturup içine secret access key id ve secret access key’i yazmamız gerekiyor. Bu işlem sonrasında dosya içeriği aşağıdaki gibi olmalı.

[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key

Oluşturduğumuz dosyanın yeri Windows kullanıyorsanız “%USERPROFILE%\.aws\” dizininde, Herhangi bir linux dağıtımı ya da MacOS kullanıcısıysanız “$HOME/.aws/” dizininde olmalıdır. Bu kısımlar için daha ayrıntılı bilgiyi bu dokümanda bulabilirsiniz.

cd .aws
>> credentials

üstteki iki komutunu çalıştırdıktan sonra dosya içeriğini terminale yazıp ctrl+c yaparsanız credentials dosyası kullanıma hazır olacaktır.

Başlıyoruz

Kurulumlarımızı tamamladık, ayarlarımızı yaptık ve şimdi uygulamamızın altyapısını oluşturmaya başlayabiliriz. Yazının başında da belirttiğim gibi biz bir EC2 ayağa kaldıracağız. Ben bu işlemleri yaparken Visual Studio Code kullanacağım. Eklenti olarak da bu eklentiyi kullanıyorum.

Öncelikle bir main.tf dosyası oluşturuyoruz. Bu dosya herhangi bir yazılım dilindeki main fonksiyon olarak düşünülebilir. Bu dosya içerisinde farklı görevler için bloklar bulunuyor. Bunlardan ilki terraform bloğu.

Terraform bloğu, terraform’un kendisini yapılandırmak için kullanılır. Örneğin kullanılacak terraform versiyonu, Terraform Cloud ya da terraform backend ayarları bu blokta yapılır. Sadece sabit değerler kullanılabilir. Değişkenler ya da farklı blokların Terraform bloğu içerisinde kullanılmaması gerekir. Bizim senaryomuzdaki Terraform bloğu şöyle olacak:

terraform {  
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.20.0"
}
}
required_version = ">0.14.9"
}

Sonrasında kullanacağımız bulut sağlayıcıya özel ayarları yapmak için provider bloğu oluşturuyoruz:

provider "aws" 
{
profile = "default"
region = "eu-central-1"
}

son adımda ise EC2 instance oluşturuyoruz. Buradaki isimlendirmedeki “aws_instance” EC2'yu ifade ediyor. Hemen yanındaki ise herhangi bir dildeki değişken ismi olarak düşünebilirsiniz. Bu durumda soldaki de değişkenin tipi olarak düşünülebilir.

resource "aws_instance" "app_server"
{
ami = "ami-015c25ad8763b2f11"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServerInstance"
}
}

Hazırlıklıkları tamamladığımıza göre artık EC2 ayağa kaldırabiliriz. Şu anda sadece bir main.tf dosyamız var ve içeriği tam olarak böyle:

terraform {  
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.20.0"
}
}
required_version = ">0.14.9"
}provider "aws"
{
profile = "default"
region = "eu-central-1"
}
resource "aws_instance" "app_server"
{
ami = "ami-015c25ad8763b2f11"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServerInstance"
}
}

Main dosyamızı oluşturduktan sonra sırada kullanılacak gereklilikleri indirme adımı var. Bu adımda terraform init komutunu çalıştırıyoruz. Bunu yaptığımızda .terraform klasörü ve terraform.lock.hcl dosyası oluşuyor.

terraform init komutunun çıktısı

.terraform: Bu klasörde, kullanılan paketler depolanır. Bu sayede her seferinde tüm paketleri baştan indirmeye gerek kalmaz.

terraform.lock.hcl: Bu dosya kullanılan bağımlılıkların versiyonlarını kaydeder ve herkesin ortak versiyonlar ile çalışmasını sağlar. Bu dosyayı versiyon kontrol sisteminize eklerseniz herkes aynı versiyonları kullanacağından ekip çalışmasını kolaylaştırabilirsiniz. Ayrıca terraform init -upgrade komutu ile buradaki paketleri güncelleyebilirsiniz. Bu dosya ile ilgili ayrıntılı bilgiye bu bağlantıdan ulaşabilirsiniz

Sonraki adımda ise terraform plan komutunu çalıştırıyoruz. Bu komutu çalıştırdıktan sonra uzunca bir çıktı ile karşılaşıyoruz. Bu komut sayesinde terraform kodu çalıştığında oluşacak değişiklikleri görebiliyoruz.

Siz de terraform plan komutunu çalıştırdığınızda aşağıdaki gibi başlayan bir çıktı göreceksiniz. Bu çıktıda “+” ile başlayan kısımlar oluşturulacak olan kaynaklar, “-” olanlar silinecekler ve “~” olanlar ise değiştirilecek olanlar. Bu terraform kodunu henüz deploy almadığımız için halihazırda hiç kaynak yok. Bu yüzden hepsi “+” ile başlıyor.

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:+ createTerraform will perform the following actions:# aws_instance.app_server will be created+ resource "aws_instance" "app_server" {+ ami                                  = "ami-015c25ad8763b2f11"+ arn                                  = (known after apply)+ associate_public_ip_address          = (known after apply)+......
}
Plan: 1 to add, 0 to change, 0 to destroy.──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

Bu çıktı bizim için hayati önem taşıyor. Örneğin bir veri tabanı yönetiyorsanız yanlış bir işlem sonucu tüm verileriniz saniyeler içerisinde silinebilir. Ya da Load Balancer’ın kurallarındaki bir değişiklik ile uygulamanız erişilemez hale gelebilir. Bu yüzden her ne kadar uzun olsa da terraform plan komutunun çıktılarını dikkatlice incelemek çok önemli.

https://tenor.com/10VY.gif

Note: You didn’t use the -out option to save this plan, so Terraform can’t guarantee to take exactly these actions if you run “terraform apply” now.

Yukarıda gördüğünüz, çıktının sonunda bulunan notu atlıyorum fakat merak ederseniz şuradan ayrıntılı bilgiye ulaşabilirsiniz.

Uygulama Zamanı

Şimdi kodu çalıştırmak için hazırız 🎉 Az önceki planı hayata geçirmek için terraform apply komutunu çalıştırıyoruz. Komutu çalıştırdıktan sonra çıktıda öncelikle plan görüyoruz sonrasında aşağıdaki resimde olduğu gibi bizden onay istiyor.

Onay verdikten sonra EC2 hazırlanmaya başlıyor. Yazdığınız terraform koduna göre çalışma süresi değişebilir. Biz sadece bir EC2 istediğimiz için uzun sürmesini beklemiyoruz. Eğer hatasız bir şekilde tamamlanırsa aşağıdaki gibi bir çıktı ile karşılaşmayı bekliyoruz:

İşlem tamamlandığına göre AWS Consol üzerinden oluşan EC2'yu görebiliriz

EC2 instance oluştu fakat terraform’un görevi burada bitmiyor. Örneğin EC2 makinemizin türünü değiştirmek istediniz. Bu işlemi yine terraform kullanarak yapabilirsiniz. Bunun için terraform apply komutunu çalıştırdıktan sonra oluşan terraform.state dosyası bizim için çok önemli. Bu dosya sayesinde şu anda hazırladığımız altyapı üzerinde değişiklikler yapabilir, istersek tümünü durdurabiliriz. Örneğin terraform plan komutunu şu an çalıştırırsak aşağıdaki gibi bir çıktı ile karşılaşmamız gerekiyor

Terraform plan yaptığımızda:

  • Şu anda çalışmakta olan servislerin durumu ile terraform.state dosyasının durumu karşılaştırılarak terraform.state dosyasının güncel olup olmadığı kontrol edilir
  • Terraform koduna yeni eklenen kısımların etkileri kontrol edilir
  • Terraform plan çıktısı oluşturulur

Yani bizim senaryomuz için şu anda bir EC2 çalışır vaziyette ve terraform kodumuzda herhangi bir değişiklik yapmadık. Bu durumda terraform plan yukarıdaki çıktıda da görüldüğü üzere hiçbir değişiklik göstermiyor.

Terraform döngüsünün son adımı olarak terraform destroy komutuna geldik. Bu komut sayesinde açtığımız tüm kaynakları kapatıcaz. Bu işlem çok tehlikeli olabilir. Projenizin tüm altyapısını saniyeler içerisinde silebilirsiniz. Yine de faydalı bir komut olduğunu düşünüyorum. Örneğin manuel kapatma işlemleri diğer servisleri etkileyecek büyük hatalara sebebiyet verebilir. Terraform destroy bu aşamada daha güvenli bir seçenek olabilir.

Yine apply komutunda olduğu gibi burada da bizden onay istiyor. terraform destroy komutunu çalıştırdığımızda aşağıdaki gibi silinecek kaynakları gösteren bir plan sonrasında da onay adımı ile karşılaşıyoruz.

destroy işlemini onayladıktan sonra terraform şu an yapılan işlemi belirli aralıklarla yazıyor. Burası için önemli bir nokta var. Terraform hem apply komutunda hem de destroy komutunda kaynakları belirli bir sıra ile açıp kapatıyor. (terraform destroy aslında terraform apply -destroy demek oluyor) Bu sıralama önemli çünkü bir bazen bir kaynağı silmek için o kaynağın bağımlılıklarının silinmiş olması gerekiyor.

terraform destroy komutunun çıktısı
terraform destroy çalıştıktan sonra aws console üzerindeki son durum

Böylece bir terraform döngüsü tamamlamış olduk. Benim anlatacaklarım bu kadar. Sonraki yazıda görüşmek üzere. hoşçakalın

Kaynakça

--

--