Altyapı kodunuzu her ortam için baştan mı yazıyorsunuz? Tek bir değer değişikliği için onlarca dosya mı düzenlemeniz gerekiyor? Terraform değişkenleri, bu karmaşıklığı ortadan kaldırarak altyapı kodunuzu dinamik, esnek ve yeniden kullanılabilir hale getirir. Bu kapsamlı rehberde, Terraform değişkenlerini sıfırdan öğrenin, nasıl tanımlayacağınızı, farklı türlerini ve gerçek dünya senaryolarında nasıl kullanacağınızı adım adım keşfedin.
Modern bulut altyapılarının yönetimi, giderek karmaşıklaşan bir süreçtir ve “Altyapı Kod Olarak” (Infrastructure as Code – IaC) prensibi, bu karmaşayı yönetmek için vazgeçilmez bir yaklaşım sunar. Terraform, bu alanda lider araçlardan biridir. Ancak Terraform ile bile, kodunuzda sürekli tekrar eden veya ortama özel değişen değerler kullandığınızda, hızla yönetilemez bir durum ortaya çıkabilir. Örneğin, bir sanal sunucunun boyutunu veya bir veritabanının adını her dağıtım için ayrı ayrı kodun içine gömmek, hem hata yapma olasılığını artırır hem de kodunuzun esnekliğini ciddi şekilde kısıtlar. İşte tam bu noktada Terraform değişkenleri devreye girer ve altyapı kodunuzu kuru (DRY – Don’t Repeat Yourself) ve uyarlanabilir hale getirmenin anahtarı olur.
Peki, Terraform değişkenleri tam olarak nedir ve neden bu kadar önemlidir? En basit ifadeyle, Terraform değişkenleri, modüllerinizin veya konfigürasyonlarınızın dışından değerler kabul etmesini sağlayan birer giriş (input) mekanizmasıdır. Tıpkı bir programlama dilindeki fonksiyonlara argüman geçirmek gibi düşünebilirsiniz. Bu değişkenler sayesinde, aynı Terraform kod bloğunu farklı ortamlar (geliştirme, test, üretim), farklı bölgeler veya farklı müşteri projeleri için özelleştirilmiş değerlerle defalarca kullanabilirsiniz. Bu durum, altyapınızın versiyon kontrolünü kolaylaştırır, manuel hataları azaltır ve dağıtım süreçlerinizi hızlandırır. Altyapı kodunuzda sabitlenmiş (hardcoded) değerlerden kurtularak, daha modüler, okunabilir ve bakımı kolay çözümler geliştirebilirsiniz.
Örneğin, bir web uygulamasını farklı bulut ortamlarına (AWS, Azure, GCP) dağıttığınızı varsayalım. Her ortamda farklı bir sanal makine tipi, farklı bir depolama boyutu veya farklı güvenlik grubu kuralları gerekebilir. Değişkenler olmadan, her ortam için ayrı Terraform dosyaları yazmanız gerekebilir, bu da tekrarlayan kod ve yüksek bakım maliyeti anlamına gelir. Ancak değişkenler kullanarak, ana Terraform kodunuzu genel tutabilir, ortam spesifik detayları ise dışarıdan sağlanan değişken dosyalarıyla yönetebilirsiniz. Bu sayede, “geliştirme” ortamında daha küçük ve uygun maliyetli kaynaklar kullanırken, “üretim” ortamında yüksek performanslı ve yedekli kaynakları aynı kod temeli üzerinden kolayca provision edebilirsiniz. Dolayısıyla, Terraform değişkenleri sadece bir kolaylık değil, aynı zamanda sağlam ve ölçeklenebilir bulut altyapısı otomasyonunun temel taşıdır. Bu kavramları sindirerek, Terraform yolculuğunuzda çok daha ileri adımlar atabileceksiniz.
Terraform’da Değişken Tanımlama: İlk Adımlarınız Nasıl Olmalı?
Terraform değişkenlerini kullanmaya başlamanın ilk adımı, onları tanımlamaktır. Değişken tanımlamaları genellikle ayrı bir variables.tf dosyasında yapılır; bu, kodunuzun düzenini ve okunabilirliğini artırır. Ancak aynı dosya içinde de tanımlayabilirsiniz. Bir değişkeni tanımlamak için, variable anahtar kelimesini ve ardından değişkenin adını kullanırız. Her değişken bloğu, o değişkenin davranışını ve beklenen değerini açıklayan çeşitli argümanlar içerebilir. Bu argümanlar, değişkenin türünü belirtmekten, varsayılan değerler atamaya ve hatta değer doğrulama kuralları eklemeye kadar geniş bir yelpazeyi kapsar.
En temel haliyle, bir değişken bloğu aşağıdaki gibi görünür:
variable "region" {
description = "Dağıtımın yapılacağı AWS bölgesi."
type = string
default = "us-east-1"
}
Yukarıdaki örnekte:
variable "region": Yeni bir değişken tanımladığımızı ve adının "region" olduğunu belirtir.description: Bu değişkenin ne işe yaradığını açıklayan kullanıcı dostu bir metindir. Özellikle takım çalışmasında veya gelecekteki bakımda çok değerlidir.type: Değişkenin beklediği veri tipini belirtir. Terraform'dastring,number,bool,list,map,objectvesetgibi çeşitli temel ve karmaşık veri tipleri bulunur. Bu, yanlış veri tipi girişlerini engellemeye yardımcı olur.default: Eğer bu değişkene harici bir değer sağlanmazsa kullanılacak varsayılan değeri belirler.defaultdeğeri tanımlandığında, değişken isteğe bağlı hale gelir. Eğerdefaulttanımlanmazsa, Terraform dağıtım sırasında bu değişken için bir değer girilmesini bekler.
Bir değişken tanımlandıktan sonra, Terraform konfigürasyonunuzun herhangi bir yerinde ona var.değişken_adı formatında erişebilirsiniz. Örneğin, tanımladığımız "region" değişkenini bir AWS sağlayıcısı bloğunda kullanmak istersek:
provider "aws" {
region = var.region
}
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890" # Örnek AMI ID
instance_type = "t2.micro"
tags = {
Name = "MyWebServer"
Environment = "Dev"
}
}
Bu örnekte, provider "aws" bloğundaki region argümanına doğrudan var.region atamasını yaparak, bölge değerini dinamik hale getirdik. Artık bu Terraform konfigürasyonunu farklı bir AWS bölgesine dağıtmak istediğimizde, kodda değişiklik yapmamız gerekmez; sadece region değişkenine yeni bir değer sağlamamız yeterli olur. Bu temel yaklaşım, Terraform ile altyapı yönetiminizi çok daha verimli ve hatasız hale getirmenizi sağlar. İlerleyen bölümlerde, farklı değişken türlerini ve bunlara nasıl değer atayacağınızı daha detaylı inceleyeceğiz.
description alanları ekleyin. Bu, özellikle büyük ve karmaşık projelerde, diğer ekip üyelerinin (veya gelecekteki sizin) değişkenlerin amacını hızlıca anlamasına yardımcı olur.
Farklı Değişken Türlerini Tanıyalım: Hangi Veri Tipi Nerede Kullanılır?
Terraform, altyapı kodunuzu daha esnek hale getirmek için farklı türlerde değişkenleri destekler. Bu veri tipleri, değişkenlerin alabileceği değerleri kısıtlayarak hata yapma olasılığını azaltır ve kodunuzun daha öngörülebilir olmasını sağlar. Doğru veri tipini seçmek, altyapı kodunuzun sağlamlığı ve okunabilirliği açısından kritik öneme sahiptir. Şimdi, en sık kullanılan değişken tiplerini ve nerede kullanılabileceklerini detaylıca inceleyelim.
string(Metin): En yaygın kullanılan tiptir. Tek bir metin değeri için kullanılır. Örneğin, kaynakların adları, açıklayıcı etiketler, bölge adları gibi.
variable "instance_name" {
description = "EC2 instance'ın adı."
type = string
default = "web-server"
}
number (Sayı): Tam sayı veya ondalık sayı değerleri için kullanılır. Örneğin, disk boyutları, port numaraları, kaynak adetleri gibi.
variable "instance_count" {
description = "Oluşturulacak EC2 instance sayısı."
type = number
default = 1
}
bool (Mantıksal): true veya false gibi mantıksal değerler için kullanılır. Bir özelliğin etkinleştirilip devre dışı bırakılması gibi durumlarda idealdir.
variable "enable_public_ip" {
description = "EC2 instance'a public IP atanıp atanmayacağını belirtir."
type = bool
default = true
}
list (Liste): Aynı tipte birden çok değeri sıralı bir koleksiyon olarak tutmak için kullanılır. Örneğin, bir güvenlik grubuna eklenecek IP adresleri listesi veya bir ASG'nin kullanacağı alt ağ kimlikleri listesi.
variable "allowed_cidrs" {
description = "Güvenlik grubuna erişim izni verilecek IP CIDR blokları listesi."
type = list(string)
default = ["0.0.0.0/0"]
}
Kullanımı:
resource "aws_security_group_rule" "ingress_http" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = var.allowed_cidrs
security_group_id = aws_security_group.web_sg.id
}
map (Harita): Anahtar-değer çiftlerinden oluşan bir koleksiyon için kullanılır. Her anahtar bir dize olmalı ve değerler aynı tipte olmalıdır. Genellikle kaynak etiketleri (tags) veya genel ayar kümeleri için idealdir.
variable "instance_tags" {
description = "EC2 instance için etiketler."
type = map(string)
default = {
Environment = "Development"
Project = "WebApp"
}
}
Kullanımı:
resource "aws_instance" "web" {
# ... diğer ayarlar ...
tags = var.instance_tags
}
object (Nesne): Farklı tiplerde anahtar-değer çiftlerini tutabilen karmaşık, yapılandırılmış bir veri tipidir. Map'ten farklı olarak, object içindeki her anahtarın belirli bir tipi olmalıdır ve bu tip tanımlama sırasında belirtilir. Daha karmaşık veri yapılarını tanımlamak için kullanılır, örneğin bir EC2 instance'ın tüm konfigürasyonunu tek bir değişkende tutmak gibi.
variable "ec2_config" {
description = "EC2 instance konfigürasyonu."
type = object({
ami_id = string
instance_type = string
disk_size_gb = number
tags = map(string)
})
default = {
ami_id = "ami-0abcdef1234567890"
instance_type = "t2.micro"
disk_size_gb = 30
tags = {
Name = "DefaultServer"
}
}
}
Kullanımı:
resource "aws_instance" "web" {
ami = var.ec2_config.ami_id
instance_type = var.ec2_config.instance_type
root_block_device {
volume_size = var.ec2_config.disk_size_gb
}
tags = var.ec2_config.tags
}
set (Küme): Aynı tipte ve benzersiz değerlerden oluşan sırasız bir koleksiyondur. Listeden farkı, elemanların sırasının önemli olmaması ve her elemanın benzersiz olması gerektiğidir. Nadiren kullanılır ancak belirli senaryolarda faydalı olabilir, örneğin bir kullanıcı grubuna atanacak izinlerin listesi gibi.
variable "unique_ids" {
description = "Benzersiz kimliklerin kümesi."
type = set(string)
default = ["id1", "id2", "id3"]
}
Doğru değişken tipini seçmek, Terraform kodunuzun daha güçlü ve hataya karşı daha dirençli olmasını sağlar. Özellikle object tipi, karmaşık ve ilişkili veri kümelerini tek bir yapıda gruplandırarak kodunuzun modülerliğini ve okunabilirliğini önemli ölçüde artırabilir. Bir sonraki bölümde, bu değişkenlere nasıl değer atayacağımızı ve bu değerlerin Terraform tarafından nasıl işlendiğini inceleyeceğiz.
Terraform Değişkenlerine Değer Atama: Esnekliği Nasıl Yakalarsınız?
Değişkenleri tanımlamak kadar, onlara değer atamak da Terraform kodunuzun esnekliği için hayati öneme sahiptir. Terraform, bir değişkene değer sağlamak için birden fazla yöntem sunar ve her yöntemin kendi kullanım senaryosu ve öncelik sırası vardır. Bu yöntemleri doğru bir şekilde anlamak, farklı ortamlar için dinamik ve uyarlanabilir altyapı dağıtımları yapmanızı sağlar. İşte Terraform'da değişkenlere değer atamanın başlıca yolları:
1. Varsayılan Değerler (default anahtar kelimesi)
Bir değişken tanımlarken bir default değeri belirtirseniz, bu değişkene harici bir değer sağlanmadığında bu varsayılan değer kullanılır. Bu, değişkeni isteğe bağlı hale getirir ve kullanıcıların yalnızca temel kurulumdan farklı bir şey istediklerinde değer sağlamasını gerektirir.
variable "region" {
description = "Dağıtımın yapılacağı AWS bölgesi."
type = string
default = "us-east-1"
}
2. Komut Satırı Bağımsız Değişkenleri (-var bayrağı)
Tek seferlik veya hızlı testler için, Terraform komutlarına doğrudan değer geçirebilirsiniz. Bu yöntem, özellikle otomasyon betiklerinde veya hızlı geçici değişiklikler yaparken kullanışlıdır.
terraform plan -var="region=eu-central-1" -var="instance_count=2"
Bu yöntem, değişken adına ve değerine doğrudan erişim sağlar ancak çok sayıda değişken için yorucu olabilir.
3. Ortam Değişkenleri (TF_VAR_ ön eki)
Terraform, TF_VAR_ ön ekiyle başlayan tüm ortam değişkenlerini otomatik olarak Terraform değişkenlerine dönüştürür. Bu, özellikle CI/CD boru hatlarında hassas veya ortama özel değerleri gizli tutmak için popüler bir yöntemdir.
export TF_VAR_region="ap-southeast-2"
terraform apply
Burada, TF_VAR_region ortam değişkeni, Terraform'daki region değişkenine değerini iletir.
4. Değişken Tanımlama Dosyaları (.tfvars uzantılı dosyalar)
Bu, değişken değerlerini yönetmenin en yaygın ve tavsiye edilen yoludur. Bir veya daha fazla .tfvars dosyası oluşturarak değişken değerlerini organize edebilirsiniz. Örneğin, farklı ortamlar için ayrı dosyalar:
dev.tfvars:
region = "us-east-1"
instance_type = "t2.micro"
instance_count = 1
prod.tfvars:
region = "us-west-2"
instance_type = "m5.large"
instance_count = 3
Bu dosyaları Terraform'a *-var-file bayrağı ile belirtirsiniz:
terraform plan -var-file="dev.tfvars"
terraform apply -var-file="prod.tfvars"
5. Otomatik Yüklenen Değişken Tanımlama Dosyaları (*.auto.tfvars veya terraform.tfvars)
Terraform, çalışma dizinindeki terraform.tfvars veya terraform.tfvars.json adlı dosyaları ve *.auto.tfvars veya *.auto.tfvars.json uzantılı tüm dosyaları otomatik olarak yükler. Bu, temel veya global değişkenler için kullanışlıdır.
# terraform.tfvars dosyası içeriği
region = "eu-west-1"
Bu dosya, herhangi bir ek bayrak olmadan terraform plan veya terraform apply çalıştırıldığında otomatik olarak okunur.
Değişken Yükleme Önceliği
Birden fazla yöntemle aynı değişkene değer atandığında, Terraform belirli bir öncelik sırasına göre karar verir (en yüksek öncelikten en düşüğe):
- Komut satırı bağımsız değişkenleri (
-varve-var-filesırasına göre sağdan sola) - Ortam değişkenleri (
TF_VAR_) *.auto.tfvarsveya*.auto.tfvars.jsonuzantılı dosyalar (alfabetik sıraya göre)terraform.tfvarsveyaterraform.tfvars.jsondosyası- Değişken tanımlamasındaki
defaultdeğerleri
Bu öncelik sırasını anlamak, beklenmedik davranışlardan kaçınmak ve değişken değerlerinizin nasıl çözümlendiğini tam olarak kontrol etmek için kritik öneme sahiptir. Örneğin, komut satırı ile verilen bir değer, .tfvars dosyasındaki veya varsayılan değerleri geçersiz kılacaktır. Bu esneklik, Terraform kullanıcılarına, altyapı dağıtımlarını her senaryoya uyarlamak için güçlü bir kontrol sağlar.
Karmaşık Yapılar ve Doğrulama Kuralları: Güvenli Değişken Yönetimi Nasıl Yapılır?
Terraform değişkenleri sadece basit değerler için değil, aynı zamanda karmaşık yapıları temsil etmek ve bu yapıların belirli kurallara uygunluğunu kontrol etmek için de kullanılabilir. Bu, altyapı kodunuzun daha sağlam, güvenilir ve hata toleranslı olmasını sağlar. Özellikle büyük ekiplerde ve kritik altyapılarda, değişkenlerin doğru formatta ve beklenen aralıkta olmasını sağlamak, olası sorunları henüz dağıtım aşamasında engellemek anlamına gelir.
Karmaşık Değişken Türleri: object ile Yapılandırılmış Veri
Önceki bölümde object tipine değinmiştik, ancak derinlemesine incelemek, karmaşık konfigürasyonları nasıl yönettiğinizi önemli ölçüde geliştirecektir. object tipi, farklı veri tiplerine sahip birden fazla özelliği tek bir değişkende gruplandırmanıza olanak tanır. Bu, örneğin bir EC2 instance'ın tüm detaylarını (AMI, instance tipi, disk boyutu, etiketler vb.) tek bir mantıksal birimde tutmak için mükemmeldir. Bu yaklaşım, ilgili ayarları bir arada tutarak kodun modülerliğini ve okunabilirliğini artırır.
variable "server_configuration" {
description = "Web sunucusunun detaylı konfigürasyonunu içerir."
type = object({
ami_id = string
instance_type = string
disk_size_gb = number
tags = map(string)
enable_monitoring = bool
})
default = {
ami_id = "ami-0abcdef1234567890" # Örnek AMI
instance_type = "t2.micro"
disk_size_gb = 20
tags = { Name = "WebServer-Default", Environment = "Dev" }
enable_monitoring = true
}
}
Bu server_configuration değişkenini kullanarak, bir EC2 instance'ını aşağıdaki gibi yapılandırabilirsiniz:
resource "aws_instance" "web" {
ami = var.server_configuration.ami_id
instance_type = var.server_configuration.instance_type
root_block_device {
volume_size = var.server_configuration.disk_size_gb
}
tags = var.server_configuration.tags
monitoring = var.server_configuration.enable_monitoring
}
Gördüğünüz gibi, tüm ilgili ayarlar tek bir değişkenden çekilir, bu da kodunuzu çok daha düzenli hale getirir.
Doğrulama Kuralları (validation bloğu)
Değişkenlere harici değerler sağlandığında, bu değerlerin geçerli olduğundan emin olmak önemlidir. Terraform'un validation bloğu, bir değişkenin değerinin belirli koşulları karşılayıp karşılamadığını kontrol etmenizi sağlar. Eğer koşul sağlanmazsa, Terraform dağıtımı durdurur ve özel bir hata mesajı gösterir.
variable "instance_type" {
description = "EC2 instance tipi."
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t3.medium", "m5.large"], var.instance_type)
error_message = "Geçersiz EC2 instance tipi. Desteklenen tipler: t2.micro, t2.small, t3.medium, m5.large."
}
}
variable "min_disk_size_gb" {
description = "EBS diski için minimum boyut (GB)."
type = number
default = 20
validation {
condition = var.min_disk_size_gb >= 10 && var.min_disk_size_gb <= 1000
error_message = "Disk boyutu 10 GB ile 1000 GB arasında olmalıdır."
}
}
Bu örneklerde, instance_type değişkeni için belirli bir liste içinde olup olmadığını kontrol ederken, min_disk_size_gb için sayısal bir aralık kontrolü yapıyoruz. condition alanı, bir boolean ifade içermelidir ve error_message ise koşulun sağlanmaması durumunda gösterilecek mesajdır. Bu, hatalı konfigürasyonların yanlışlıkla dağıtılmasını önler.
Hassas Değişkenler (sensitive = true)
Veritabanı şifreleri, API anahtarları gibi hassas bilgiler Terraform değişkenleri aracılığıyla sağlanabilir. Ancak bu bilgilerin konsol çıktılarında veya Terraform state dosyasında açıkça görünmesi güvenlik riski oluşturur. sensitive = true bayrağı, bu tür değişkenlerin değerlerinin Terraform plan çıktısında, apply çıktısında ve bazen state dosyasında gizlenmesini sağlar.
variable "db_password" {
description = "Veritabanı yöneticisi şifresi."
type = string
sensitive = true
}
Bu değişkenin değerini komut satırında veya .tfvars dosyasında verdiğinizde, Terraform plan çıktısında bu değer (sensitive value) olarak görünür. Ancak, bu bayrak sadece görüntüyü gizler; değerler hala state dosyasında depolanır (eğer doğrudan state'e yazılıyorsa) ve dikkatli yönetim gerektirir. Hassas verileri yönetirken ek güvenlik önlemleri (örneğin, bulut sağlayıcının gizli yönetimi hizmetleri - AWS Secrets Manager, Azure Key Vault) kullanmak her zaman önerilir.
sensitive = true ile işaretlemek iyi bir başlangıçtır, ancak en iyi uygulama, bu verileri doğrudan state dosyasına yazmaktan kaçınmaktır. Bunun yerine, bunları bulut sağlayıcınızın gizli yönetim hizmetlerinde saklayın ve Terraform ile çalışma zamanında bu hizmetlerden çekin.
Gerçek Dünya Senaryosu: Çok Ortamlı Dağıtımlar İçin Değişkenleri Kullanma
Terraform değişkenlerinin gerçek gücü, çok ortamlı dağıtım senaryolarında ortaya çıkar. Çoğu kuruluş, uygulamalarını geliştirme (dev), test (test) ve üretim (prod) gibi farklı ortamlara dağıtır. Her ortamın kendine özgü gereksinimleri (örneğin, farklı sunucu tipleri, veritabanı boyutları, güvenlik kuralları) vardır. Değişkenler olmadan, her ortam için neredeyse aynı olan ayrı ayrı Terraform kod setleri tutmak zorunda kalırsınız ki bu da bir kabus senaryosudur: kod tekrarı, yüksek bakım maliyeti ve hata yapma olasılığının artması anlamına gelir.
Peki, Terraform değişkenlerini kullanarak bu durumu nasıl zarifçe çözebiliriz? Yaklaşımımız, ana Terraform yapılandırma dosyalarımızı (örneğin, main.tf, security.tf) genel ve ortamdan bağımsız tutmak, ortam spesifik değerleri ise ayrı .tfvars dosyalarında yönetmektir. Bu sayede, "bir kez yaz, her yerde dağıt" felsefesini benimseyebiliriz.
Vaka Analizi: AWS Üzerinde Bir Web Uygulamasının Çok Ortamlı Dağıtımı
Bir web uygulamasını AWS'ye dağıttığımızı varsayalım. Bu uygulama için bir EC2 instance'ı, bir S3 bucket'ı ve bazı güvenlik grupları gerekiyor. Geliştirme, test ve üretim ortamları için aşağıdaki farklılıkları yöneteceğiz:
- EC2 Instance Tipi: Dev için
t2.micro, Test içint3.small, Prod içinm5.large. - S3 Bucket Adı: Ortam adına göre değişmeli (örn.
my-app-dev-bucket). - EC2 Instance Sayısı: Dev için 1, Test için 2, Prod için 4.
- Genel Etiketler: Her kaynağa ortamı ve projeyi belirten etiketler.
Adım 1: Değişkenleri Tanımlayın (variables.tf)
Tüm ortamlar için gerekli olabilecek değişkenleri tanımlayalım:
# variables.tf
variable "environment" {
description = "Dağıtımın yapılacağı ortam (dev, test, prod)."
type = string
}
variable "aws_region" {
description = "AWS bölgesi."
type = string
default = "us-east-1"
}
variable "instance_type" {
description = "EC2 instance tipi."
type = string
}
variable "instance_count" {
description = "Oluşturulacak EC2 instance sayısı."
type = number
default = 1
}
variable "app_name" {
description = "Uygulama adı."
type = string
default = "my-webapp"
}
variable "common_tags" {
description = "Tüm kaynaklara uygulanacak ortak etiketler."
type = map(string)
default = {}
}
Adım 2: Ana Terraform Kodunu Yazın (main.tf)
Bu dosya, ortamdan bağımsız olacak ve değişkenleri kullanarak dinamikleşecektir.
# main.tf
provider "aws" {
region = var.aws_region
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = merge(
var.common_tags,
{
Name = "${var.app_name}-${var.environment}-vpc"
}
)
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "${var.aws_region}a"
tags = merge(
var.common_tags,
{
Name = "${var.app_name}-${var.environment}-public-subnet"
}
)
}
resource "aws_instance" "web" {
count = var.instance_count
ami = "ami-0abcdef1234567890" # Lütfen geçerli bir AMI ID ile değiştirin
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
associate_public_ip_address = true
tags = merge(
var.common_tags,
{
Name = "${var.app_name}-${var.environment}-web-instance-${count.index}"
Environment = var.environment
}
)
}
resource "aws_s3_bucket" "app_bucket" {
bucket = "${var.app_name}-${var.environment}-data"
acl = "private"
tags = merge(
var.common_tags,
{
Name = "${var.app_name}-${var.environment}-bucket"
Environment = var.environment
}
)
}
Adım 3: Ortama Özel Değişken Dosyalarını Oluşturun
Şimdi her ortam için ayrı .tfvars dosyaları oluşturalım:
dev.tfvars
environment = "dev"
instance_type = "t2.micro"
instance_count = 1
aws_region = "us-east-1"
common_tags = {
Project = "WebApp"
Owner = "DevTeam"
}
test.tfvars
environment = "test"
instance_type = "t3.small"
instance_count = 2
aws_region = "eu-west-1"
common_tags = {
Project = "WebApp"
Owner = "TestTeam"
CostCenter = "1234"
}
prod.tfvars
environment = "prod"
instance_type = "m5.large"
instance_count = 4
aws_region = "us-west-2"
common_tags = {
Project = "WebApp"
Owner = "OpsTeam"
CostCenter = "5678"
Criticality = "High"
}
Adım 4: Ortama Özel Dağıtımı Gerçekleştirin
Şimdi her ortam için dağıtımı kolayca yapabiliriz:
- Geliştirme ortamı için:
terraform init terraform plan -var-file="dev.tfvars" terraform apply -var-file="dev.tfvars" - Test ortamı için:
terraform plan -var-file="test.tfvars" terraform apply -var-file="test.tfvars" - Üretim ortamı için:
terraform plan -var-file="prod.tfvars" terraform apply -var-file="prod.tfvars"
Bu yaklaşım sayesinde, aynı ana Terraform kodunu kullanarak, farklı ortamlara özel yapılandırmaları kolayca uygulayabildik. Kod tekrarını önledik, her ortam için özelleştirme sağladık ve bakım yükünü önemli ölçüde azalttık. Bu, Terraform değişkenlerinin altyapı otomasyonunda sunduğu esnekliğin ve gücün somut bir örneğidir.
.tfvars dosyalarınızı bir dizin yapısı içinde düzenlemeyi düşünebilirsiniz (örn. environments/dev.tfvars, environments/prod.tfvars). Bu, projeniz büyüdükçe daha iyi bir organizasyon sağlar.
Sonuç: Değişkenlerle Terraform Ustalığına Doğru İlk Adımlar
Bu makale boyunca, Terraform değişkenlerinin neden altyapı kodunuzun olmazsa olmaz bir parçası olduğunu derinlemesine inceledik. Değişkenlerin, statik altyapı tanımlarını dinamik, yeniden kullanılabilir ve ortama duyarlı çözümlere dönüştürme gücüne sahip olduğunu gördük. Basit string değerlerden karmaşık object yapılarına, varsayılan değerlerden güçlü doğrulama kurallarına kadar pek çok konuyu ele aldık. Özellikle çok ortamlı dağıtım senaryolarında değişkenlerin sağladığı esneklik ve kod tekrarını önleme kabiliyeti, modern DevOps pratiklerinin temelini oluşturur. Artık altyapınızı her senaryoya uyarlanabilir, hatasız ve ölçeklenebilir bir şekilde yönetmek için gerekli araçlara sahipsiniz. Değişkenleri etkin bir şekilde kullanarak, Terraform projelerinizin kalitesini ve sürdürülebilirliğini önemli ölçüde artıracaksınız.
Sıkça Sorulan Sorular (SSS)
1. Değişkenlere varsayılan değer atamak her zaman iyi bir fikir mi?
Değişkenlere varsayılan değer atamak, değişkeni isteğe bağlı hale getirir ve kullanıcıların yalnızca temel kurulumdan farklı bir şey istediklerinde değer sağlamasını gerektirir. Bu durum, modülün kullanımını kolaylaştırır. Ancak, kritik veya ortama özel olması gereken değerler için varsayılan değer atamamak, kullanıcıyı bu değerleri açıkça sağlamaya zorlayarak yanlış konfigürasyonları engellemeye yardımcı olabilir. Kısacası, kullanım senaryosuna göre karar verilmelidir.
2. Hangi değişken atama yöntemini ne zaman tercih etmeliyim?
defaultdeğerler: İsteğe bağlı, yaygın kullanılan veya test ortamları için başlangıç değerleri.terraform.tfvars/*.auto.tfvars: Projeye özgü, genel ve tüm ortamlarda geçerli olması beklenen temel konfigürasyonlar.-var-file: Ortama özel (dev, test, prod) veya müşteri bazlı yapılandırmalar. CI/CD boru hatlarında sıklıkla kullanılır.-varbayrağı: Hızlı testler, geçici değişiklikler veya tek seferlik dağıtımlar için.TF_VAR_ortam değişkenleri: CI/CD ortamlarında hassas verileri (API anahtarları, şifreler) veya ortam değişkenlerine bağımlı konfigürasyonları güvenli bir şekilde iletmek için.
3. Sensitive değişkenleri state dosyasında nasıl korunur?
sensitive = true olarak işaretlenen değişkenler, Terraform plan ve apply çıktılarında gizlenir. Ancak bu, değişkenin değerinin her zaman state dosyasında da gizlendiği anlamına gelmez. Eğer değişkenin değeri doğrudan bir kaynağın özniteliğine atanırsa ve bu öznitelik Terraform state dosyasına kaydedilirse, değer orada görünür olabilir. Hassas verileri en iyi şekilde korumak için, bunları bulut sağlayıcınızın gizli yönetim hizmetlerinde (AWS Secrets Manager, Azure Key Vault, Google Secret Manager) saklayın ve Terraform ile çalışma zamanında bu hizmetlerden değerleri çekin.
4. Değişken tiplerini belirtmek zorunlu mu?
Terraform'da değişken tiplerini belirtmek zorunlu değildir. Eğer bir tip belirtmezseniz, Terraform değeri dinamik olarak algılamaya çalışır. Ancak, tipleri açıkça belirtmek (örneğin, type = string veya type = number), kodunuzun okunabilirliğini artırır, hata ayıklamayı kolaylaştırır ve yanlış veri girişi nedeniyle oluşabilecek hataları en aza indirir. Bu nedenle, iyi bir pratik olarak her zaman değişken tiplerini belirtmeniz önerilir.
5. List veya map değişkenler içinde nasıl döngü yapabilirim?
Terraform'da for_each veya count meta-argümanlarını kullanarak list veya map değişkenleri üzerinde döngü yapabilirsiniz. for_each, benzersiz anahtar-değer çiftleri veya benzersiz string listeleri üzerinde yineleme yapmak için idealdir ve daha esnektir. count ise basit sayısal yinelemeler için kullanılır. Örneğin, bir listeyi kullanarak birden fazla EC2 instance'ı oluşturmak veya bir map'i kullanarak birden fazla etiket tanımlamak mümkündür.
# main.tf (for_each örneği)
resource "aws_instance" "app_servers" {
for_each = var.instance_configs # instance_configs bir map değişkeni olabilir
ami = each.value.ami_id
instance_type = each.value.instance_type
tags = {
Name = each.key
}
}
