Terraform ile vSphere Üzerinde Otomatik VM Provisioning: Windows Server Clone Rehberi

1. Adım: Yeni Proje Klasörü Oluştur

Docker demo’sundan ayrı tutmak için yeni bir klasör açıyoruz.

Komutlar:

cd ~
mkdir terraform-vsphere-demo
cd terraform-vsphere-demo

Sonuç:
Şu konumda olmalısın: ~/terraform-vsphere-demo

2. Adım: main.tf ve terraform.tfvars Dosyalarını Oluştur

vSphere ortamında güvenlik en önemli konu olduğundan, kullanıcı adı ve şifreyi kodun içinde değil, ayrı bir dosyada tutuyoruz.

1. main.tf Dosyasını Oluştur

Komut (tamamı tek blok halinde çalıştır):

cat <<EOF > main.tf
# --- Değişken Tanımlamaları ---
variable "vsphere_user" {}
variable "vsphere_password" {}
variable "vsphere_server" { default = "vcenter.dataflowx.int" }

# --- vSphere Provider ---
provider "vsphere" {
  user                 = var.vsphere_user
  password             = var.vsphere_password
  vsphere_server       = var.vsphere_server
  allow_unverified_ssl = true  # Self-signed sertifika için gerekli
}

# --- Data Sources: vCenter'daki Nesneleri Bul ---
data "vsphere_datacenter" "dc" {
  name = "datacenter"
}

data "vsphere_host" "host" {
  name          = "192.168.x.x"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_datastore" "datastore" {
  name          = "x.x_Datastore4"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "network" {
  name          = "vlan1"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine" "template" {
  name          = "Template Windows Server"
  datacenter_id = data.vsphere_datacenter.dc.id
}

# --- Yeni VM Oluştur (Template'ten Clone) ---
resource "vsphere_virtual_machine" "vm" {
  name             = "terraform-test-vm"
  resource_pool_id = data.vsphere_host.host.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id

  num_cpus = 2
  memory   = 4096
  guest_id = data.vsphere_virtual_machine.template.guest_id
  firmware = data.vsphere_virtual_machine.template.firmware
  scsi_type = data.vsphere_virtual_machine.template.scsi_type

  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }

  disk {
    label            = "disk0"
    size             = data.vsphere_virtual_machine.template.disks[0].size
    thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      timeout = 30

      windows_options {
        computer_name    = "TERRAWIN01"
        workgroup        = "WORKGROUP"
        admin_password   = "Sifre123!"
        time_zone        = 90          # Türkiye (GMT+3)
        auto_logon       = true
        auto_logon_count = 1
      }

      network_interface {
        ipv4_address = "192.168.x.x"
        ipv4_netmask = 24
      }

      ipv4_gateway    = "192.168.x.1"
      dns_server_list = ["8.8.8.8", "8.8.4.4"]
    }
  }
}
EOF

2. terraform.tfvars Dosyasını Oluştur (Gizli Bilgiler Buraya!)

Komut:

cat <<EOF > terraform.tfvars
vsphere_user     = "administrator@vsphere.local"
vsphere_password = "BURAYA_GERÇEK_VCENTER_ŞİFRENİ_YAZ"
EOF

DİKKAT ÖNEMLİ:

  • terraform.tfvars dosyasını açıp (nano terraform.tfvars) şifre kısmını gerçek vCenter şifren ile değiştir.
  • Eğer kullanıcı adın farklıysa onu da düzelt (örneğin: user@domain.com).
  • Bu dosya asla GitHub’a veya başkasına gönderilmemeli.

Ayrıca Kontrol Et:

  • ipv4_address = "192.168.x.x" → Bu IP vlan1 segmentinde boş mu?
  • ipv4_gateway = "192.168.x.1" → Gateway doğru mu?

3. Adım: Terraform’u Başlat (Init)

vSphere provider’ını indirip projeyi hazır hale getiriyoruz.

Komut:

terraform init

Beklenen Çıktı:

Initializing provider plugins...
- Finding hashicorp/vsphere versions...
- Installing hashicorp/vsphere vX.X.X...
Terraform has been successfully initialized!

4. Adım: Plan Oluştur (Önizleme)

Terraform vCenter’a bağlanıp tüm nesneleri (datacenter, host, datastore, network, template) bulmaya çalışacak.

Komut:

terraform plan

Beklenen İyi Sonuç:

Plan: 1 to add, 0 to change, 0 to destroy.

+ resource "vsphere_virtual_machine" "vm" { ... }

Olası Hatalar ve Çözümleri:

  • x509: certificate signed by unknown authorityallow_unverified_ssl = true zaten var, sorun olmamalı.
  • Authentication failed → Kullanıcı adı/şifre yanlış.
  • Unable to find datacenter/network/datastore/template → İsimleri tam olarak vCenter’daki gibi yazdığından emin ol (büyük/küçük harf duyarlı olabilir).
  • Host not found → Host IP yerine host adı (FQDN) deneyebilirsin.

5. Adım: Uygula (Apply)

Her şey düzgünse VM’yi gerçekten oluşturalım.

Komut:

terraform apply

Ne yapmalısın?

  • Plan tekrar gösterilecek.
  • En altta Do you want to perform these actions? sorusu gelecek.
  • yes yazıp Enter’a bas.

Beklenen Sonuç:

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

VM artık vCenter’da terraform-test-vm adıyla görünmeli ve birkaç dakika içinde açılmalı.

6. Adım: Sonuçları Doğrula

vCenter konsoluna girip:

  • VM’nin datacenter192.168.x.x host’unda çalıştığını,
  • IP’sinin 192.168.x.x olduğunu,
  • Otomatik login ile masaüstünün açıldığını kontrol et.

7. Adım: Temizleme (Destroy)

İşin bittiğinde VM’yi silmeyi unutma!

Komut:

terraform destroy

yes yazıp onay ver.

Sonuç:

Destroy complete! Resources: 1 destroyed.

Artık:

  • vSphere provider ile gerçek bir kurumsal ortamda VM clone’layabiliyorsun.
  • Gizli bilgileri güvenli şekilde yönetiyorsun.
  • Infrastructure as Code prensibini hipervizör seviyesinde uyguladın.

Bu aynı mantıkla yüzlerce VM, farklı template’ler (Linux/Windows), farklı network’ler ve hatta linked clone ile dev ortamlar kurabilirsin.

Terraform ile vSphere – Daha Modüler ve Yeniden Kullanılabilir Yapı

Bu demo’yu daha profesyonel, bakım yapılabilir ve yeniden kullanılabilir hale getiriyoruz. Tüm sabit değerleri değişkenlere taşıyarak:

  • Aynı kodu farklı ortamlar/lab’lar için kolayca kullanabileceksin.
  • Gizli bilgileri daha güvenli yöneteceksin.
  • Kodun okunabilirliği ve sürdürülebilirliği artacak.

8. Adım: Modüler Yapıya Geçiş – Dosyaları Güncelle

Hâlen ~/terraform-vsphere-demo klasöründeysen devam et. Aşağıdaki 3 dosyayı sırasıyla oluştur/güncelle.

1. variables.tf Dosyasını Oluştur

Bu dosya tüm değişkenleri tanımlar ve açıklama ekler.

Komut:

cat <<EOF > variables.tf
variable "vsphere_user" {
  description = "vSphere kullanıcı adı"
  type        = string
}

variable "vsphere_password" {
  description = "vSphere şifresi"
  type        = string
  sensitive   = true
}

variable "vsphere_server" {
  description = "vCenter sunucu adı veya IP"
  type        = string
}

variable "vsphere_datacenter" {
  description = "Datacenter adı"
  type        = string
}

variable "vsphere_host" {
  description = "ESXi host adı veya IP"
  type        = string
}

variable "datastore_name" {
  description = "Datastore adı"
  type        = string
}

variable "network_name" {
  description = "Network (port group) adı"
  type        = string
}

variable "template_name" {
  description = "Klonlanacak template adı"
  type        = string
}

variable "vm_name" {
  description = "Oluşturulacak VM adı"
  type        = string
}

variable "num_cpus" {
  description = "CPU sayısı"
  type        = number
  default     = 2
}

variable "memory" {
  description = "RAM miktarı (MB)"
  type        = number
  default     = 4096
}

variable "disk_label" {
  description = "Disk etiketi"
  type        = string
  default     = "disk0"
}

variable "computer_name" {
  description = "Guest OS bilgisayar adı"
  type        = string
}

variable "workgroup" {
  description = "Workgroup adı (domain yoksa)"
  type        = string
  default     = "WORKGROUP"
}

variable "admin_password" {
  description = "Guest OS yönetici şifresi"
  type        = string
  sensitive   = true
}

variable "time_zone" {
  description = "Zaman dilimi kodu (Türkiye = 90)"
  type        = number
  default     = 90
}

variable "auto_logon" {
  description = "Otomatik login aktif mi?"
  type        = bool
  default     = true
}

variable "auto_logon_count" {
  description = "Otomatik login sayısı"
  type        = number
  default     = 1
}

variable "ipv4_address" {
  description = "VM'ye atanacak statik IP"
  type        = string
}

variable "ipv4_netmask" {
  description = "Netmask (CIDR formatında, örn: 24)"
  type        = number
}

variable "ipv4_gateway" {
  description = "Gateway IP"
  type        = string
}

variable "dns_server_list" {
  description = "DNS sunucu listesi"
  type        = list(string)
  default     = ["8.8.8.8", "8.8.4.4"]
}
EOF

2. terraform.tfvars Dosyasını Güncelle

Tüm değerleri buraya taşıyoruz. Bu dosya yine gizli kalacak.

Komut:

cat <<EOF > terraform.tfvars
vsphere_user         = "administrator@vsphere.local"
vsphere_password     = "GERÇEK_VCENTER_ŞİFRENİ_BURAYA_YAZ"
vsphere_server       = "vcenter.dataflowx.int"

vsphere_datacenter   = "datacenter"
vsphere_host         = "192.168.x.x"
datastore_name       = "x.x_Datastore4"
network_name         = "vlan1"
template_name        = "Template Windows Server"

vm_name              = "terraform-test-vm"
num_cpus             = 2
memory               = 4096

computer_name        = "TERRAWIN01"
admin_password       = "Sifre123!"

ipv4_address         = "192.168.x.x"
ipv4_netmask         = 24
ipv4_gateway         = "192.168.x.1"
dns_server_list      = ["8.8.8.8", "8.8.4.4"]
EOF

DİKKAT:
vsphere_password ve admin_password satırlarını gerçek şifrelerinle güncelle (nano terraform.tfvars ile).

3. main.tf Dosyasını Güncelle

Tüm sabit değerleri değişkenlerle değiştiriyoruz.

Komut:

cat <<EOF > main.tf
# --- vSphere Provider ---
provider "vsphere" {
  user                 = var.vsphere_user
  password             = var.vsphere_password
  vsphere_server       = var.vsphere_server
  allow_unverified_ssl = true
}

# --- Data Sources ---
data "vsphere_datacenter" "dc" {
  name = var.vsphere_datacenter
}

data "vsphere_host" "host" {
  name          = var.vsphere_host
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_datastore" "datastore" {
  name          = var.datastore_name
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "network" {
  name          = var.network_name
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine" "template" {
  name          = var.template_name
  datacenter_id = data.vsphere_datacenter.dc.id
}

# --- VM Resource ---
resource "vsphere_virtual_machine" "vm" {
  name             = var.vm_name
  resource_pool_id = data.vsphere_host.host.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id

  num_cpus = var.num_cpus
  memory   = var.memory
  guest_id = data.vsphere_virtual_machine.template.guest_id
  firmware = data.vsphere_virtual_machine.template.firmware
  scsi_type = data.vsphere_virtual_machine.template.scsi_type

  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }

  disk {
    label            = var.disk_label
    size             = data.vsphere_virtual_machine.template.disks[0].size
    thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      timeout = 30

      windows_options {
        computer_name    = var.computer_name
        workgroup        = var.workgroup
        admin_password   = var.admin_password
        time_zone        = var.time_zone
        auto_logon       = var.auto_logon
        auto_logon_count = var.auto_logon_count
      }

      network_interface {
        ipv4_address = var.ipv4_address
        ipv4_netmask = var.ipv4_netmask
      }

      ipv4_gateway    = var.ipv4_gateway
      dns_server_list = var.dns_server_list
    }
  }
}
EOF

9. Adım: Değişiklikleri Uygula

Dosyaları güncellediğine göre Terraform’un yeni yapıyı tanıması lazım.

Komutlar sırasıyla:

terraform init    # Eğer daha önce init yapılmadıysa veya provider güncellendiyse
terraform fmt     # Kod formatını otomatik düzelt (isteğe bağlı ama tavsiye edilir)
terraform validate # Syntax kontrolü
terraform plan    # Değişiklikleri önizle

terraform plan çıktısında yine Plan: 1 to add... görmelisin (eğer VM daha önce silindiyse).

Ardından:

terraform apply

yes yazıp onay ver.

Avantajları Neler Oldu?

  • Aynı klasörü kopyalayıp sadece terraform.tfvars dosyasını değiştirerek **farklı lab’lardaaynı kodu kullanabilirsin.
  • Yeni bir VM istiyorsan sadece terraform.tfvars‘a yeni değerler ekleyip apply yapman yeterli.
  • Kod çok daha temiz ve profesyonel görünüyor.

10. Adım: Proje Klasör Yapısını İnceleme ve Dosyaları Anlama

Şimdi terraform apply işlemini başarıyla tamamladığımıza göre (ve belki bir destroy da yaptığımıza göre), proje klasörümüz biraz daha kalabalık hale geldi.

Klasörün mevcut durumunu görmek için şu komutu çalıştır:

tree -a

Tipik Çıktı:

root@srv-netbox:~/terraform-vsphere-demo# tree -a
.
├── main.tf
├── variables.tf
├── terraform.tfvars
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── vsphere
│                   └── 2.12.0
│                       └── linux_amd64
│                           ├── LICENSE.txt
│                           └── terraform-provider-vsphere_v2.12.0_x5
├── .terraform.lock.hcl
├── terraform.tfstate
├── terraform.tfstate.backup
└── .terraform.tfstate.backup  (bazen olur)

8 directories, 8 files

Biz sadece 3 dosya oluşturduk: main.tf, variables.tf, terraform.tfvars.
Peki geri kalanlar ne işe yarıyor? DevOps dünyasında “temiz repo” yönetimi için bunları bilmek şart.

Hepsini tek tek açıklayalım:

.terraform/ (Klasör)

  • Ne işe yarar?
    Terraform’un init komutuyla indirdiği provider eklentileri (bizim durumumuzda vSphere provider) burada saklanır.
  • Neden oluşur?
    terraform init çalıştırdığın anda otomatik indirilir. İşletim sistemi ve mimariye göre farklı dosyalar olur (Linux_amd64, Darwin_arm64 vs.).
  • Git’e eklenir mi?
    HAYIR. Herkes kendi makinesinde terraform init yaparak bunları kendisi indirir. Git’e atarsan repo şişer ve platform uyumsuzluğu yaratır.

.terraform.lock.hcl (Dosya)

  • Ne işe yarar?
    Provider’ların tam sürümünü kilitler (örneğin vSphere 2.12.0). Böylece ekipteki herkes aynı sürümü kullanır ve “bende çalışıyor, sende çalışmıyor” sorunu önlenir.
  • Git’e eklenir mi?
    EVET (tavsiye edilir). Özellikle takım çalışmasında mutlaka Git’e commit edilmelidir. Tek kişilik basit projelerde opsiyonel ama iyi alışkanlık için ekle.

terraform.tfstate (En kritik dosya!)

  • Ne işe yarar?
    Terraform’un hafızası. Oluşturduğun VM’nin gerçek ID’si, IP’si, disk UUID’si, hatta bazı durumlarda şifrelerin hash’lenmiş hali burada saklanır. Terraform bir sonraki plan veya apply‘da “ne değişti?” sorusunu bu dosyaya bakarak cevaplar.
  • Git’e eklenir mi?
    **ASLA HAYIR! **
    Bu dosya sadece Terraform tarafından yönetilir. Git’e atılırsa state çakışmaları (conflict) olur, yanlışlıkla VM silinebilir veya gizli bilgiler sızabilir.

terraform.tfstate.backup

  • Ne işe yarar?
    Her apply veya destroy işleminden önce Terraform otomatik olarak önceki state’in yedeğini alır.
  • Git’e eklenir mi?
    HAYIR. Aynı nedenlerle: gereksiz ve tehlikeli.

Özet Tablo: Git’e Eklemeli miyiz?

Dosya/KlasörAçıklamaGit’e Eklenir mi?
main.tfAna konfigürasyon koduEVET
variables.tfDeğişken tanımlamalarıEVET
terraform.tfvarsDeğerler (şifreler dahil)HAYIR (gizli bilgi var)
.terraform/İndirilen provider’larHAYIR
.terraform.lock.hclProvider sürüm kilidiEVET (takım için)
terraform.tfstateGerçek altyapı durumuASLA HAYIR
terraform.tfstate.backupState yedeğiASLA HAYIR

Temiz Repo İçin .gitignore Önerisi

Git’e “Ben bunları takip etme, yok say” demek için .gitignore dosyası oluştururuz. İçine bilinmeyen, şifreli veya gereksiz dosyaları yazarız.

Sunucunda şu komutu çalıştır:

cat <<EOF > .gitignore
# Terraform Çalışma Dosyaları
.terraform/
.terraform.lock.hcl

# Terraform State (Asla yükleme)
*.tfstate
*.tfstate.*
*.tfstate.backup
crash.log

# Değişken Dosyaları (Şifre içerir)
*.tfvars
!example.tfvars # Örnek (boş) tfvars varsa atabilirsin, ama bizde yok

# Gezici Dosyalar
.terraform/
*.swp
*.swo
*~
EOF

Bu dosya, Git’e şunu der: _”Lütfen .terraform klasörünü, terraform.tfstate dosyasını ve *.tfvars dosyalarını görmezden gel.”

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir