GCP Compute Engine’de Özel Görüntü Oluşturma ve Yönetme

Üretim ortamında onlarca, yüzlerce sanal makine ayağa kaldırmanız gerektiğinde her birini sıfırdan yapılandırmak gerçek bir kabus olabilir. İşte tam bu noktada GCP’nin özel görüntü (custom image) özelliği hayat kurtarıcı oluyor. Bir makineyi istediğiniz gibi yapılandırıyor, üzerine kurduğunuz yazılımları, güvenlik ayarlarını, monitoring agent’larını hazırlıyor ve bu yapıyı bir görüntü olarak kaydediyorsunuz. Bundan sonra her yeni makine bu görüntüden dakikalar içinde ayağa kalkıyor, tutarlı ve güvenilir bir şekilde.

Bu yazıda GCP Compute Engine’de özel görüntü oluşturmanın tüm detaylarını, gerçek dünya senaryolarıyla birlikte ele alacağız.

Neden Özel Görüntü Kullanmalısınız?

GCP’nin sunduğu hazır görüntüler (Debian, Ubuntu, CentOS, Windows Server vb.) iyi bir başlangıç noktası sunuyor ama üretim ortamı için genellikle yeterli gelmiyor. Şirketinizin güvenlik politikaları, kurulu olması gereken agent’lar, özel yapılandırma dosyaları ve sertifikalar düşünüldüğünde her VM başlatıldığında bunları yeniden uygulamak hem zaman kaybı hem de hata riski yaratıyor.

Özel görüntülerin size sağladıkları:

  • Tutarlılık: Her VM aynı temel yapılandırmadan başlıyor, insan hatasının önüne geçiyorsunuz
  • Hız: Provisioning süresi dramatik biçimde kısalıyor, startup scriptlerin boyutu küçülüyor
  • Uyumluluk: Şirket güvenlik politikaları görüntünün içine gömülü geliyor
  • Maliyet: Kurulum süreleri kısalınca compute maliyetleri de düşüyor
  • Disaster Recovery: Hızlı kurtarma senaryoları için hazır şablon elinizde oluyor

Ön Koşullar ve Hazırlık

Başlamadan önce birkaç şeyin yerli yerinde olması gerekiyor. gcloud CLI kurulu ve yapılandırılmış olmalı, uygun IAM izinlerine sahip olmalısınız.

Gerekli roller:

  • compute.imageAdmin: Görüntü oluşturma ve yönetme
  • compute.instanceAdmin.v1: VM yönetimi
  • compute.storageAdmin: Disk işlemleri için
# Mevcut gcloud yapılandırmanızı kontrol edin
gcloud config list

# Proje ayarlayın
gcloud config set project YOUR_PROJECT_ID

# Gerekli API'ların aktif olduğunu doğrulayın
gcloud services enable compute.googleapis.com
gcloud services enable storage-api.googleapis.com

Temel Görüntü Seçimi ve VM Oluşturma

İlk adım, özelleştireceğimiz temel VM’i oluşturmak. Bu VM’i production’da kullanmayacağız, sadece görüntü oluşturmak için bir araç olarak kullanacağız. Bu yüzden küçük bir makine tipi yeterli.

# Temel VM oluşturun
gcloud compute instances create image-builder-vm 
  --zone=europe-west1-b 
  --machine-type=e2-medium 
  --image-family=ubuntu-2204-lts 
  --image-project=ubuntu-os-cloud 
  --boot-disk-size=50GB 
  --boot-disk-type=pd-ssd 
  --tags=image-builder 
  --metadata=enable-oslogin=true

# VM'in hazır olduğunu kontrol edin
gcloud compute instances list --filter="name=image-builder-vm"

Burada dikkat edilmesi gereken nokta boot disk boyutu. Eğer kurulacak yazılımlar büyükse disk boyutunu buna göre ayarlayın ama gereğinden fazla büyük disk de görüntü boyutunu şişirir.

VM Yapılandırması

Şimdi asıl işe geliyoruz. VM’e bağlanıp yapılandırmalarımızı uygulayalım. Ben bu örnekte tipik bir web uygulama sunucusu için görüntü oluşturuyorum.

# VM'e SSH ile bağlanın
gcloud compute ssh image-builder-vm --zone=europe-west1-b

# Bağlandıktan sonra sistem güncellemelerini yapın
sudo apt-get update && sudo apt-get upgrade -y

# Gerekli paketleri kurun
sudo apt-get install -y 
  nginx 
  python3-pip 
  python3-venv 
  git 
  curl 
  wget 
  unzip 
  htop 
  vim 
  fail2ban 
  ufw 
  logrotate

# Timezone ayarı
sudo timedatectl set-timezone Europe/Istanbul

# NTP yapılandırması
sudo apt-get install -y chrony
sudo systemctl enable chronyd
sudo systemctl start chronyd

Güvenlik Sertleştirmesi

Güvenlik ayarları görüntünün en kritik parçalarından biri. Şirketteki tüm makinelerin aynı güvenlik baseline’ını paylaşmasını istiyorsunuz.

# SSH güvenlik ayarları
sudo tee /etc/ssh/sshd_config.d/hardening.conf << 'EOF'
PermitRootLogin no
PasswordAuthentication no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 60
AllowAgentForwarding no
AllowTcpForwarding no
PrintLastLog yes
EOF

# UFW firewall yapılandırması
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable

# Fail2ban yapılandırması
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
EOF

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

# Gereksiz servisleri devre dışı bırakın
sudo systemctl disable avahi-daemon 2>/dev/null || true
sudo systemctl disable bluetooth 2>/dev/null || true
sudo systemctl disable cups 2>/dev/null || true

Monitoring Agent Kurulumu

GCP’nin Ops Agent’ını kurmak, tüm makinelerinizin Cloud Monitoring’e otomatik olarak veri göndermesini sağlar.

# Google Cloud Ops Agent kurulumu
curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
sudo bash add-google-cloud-ops-agent-repo.sh --also-install

# Agent'ın servis olarak başlatılmasını sağlayın
sudo systemctl enable google-cloud-ops-agent
sudo systemctl start google-cloud-ops-agent

# Ops Agent yapılandırması
sudo tee /etc/google-cloud-ops-agent/config.yaml << 'EOF'
logging:
  receivers:
    nginx_access:
      type: files
      include_paths:
        - /var/log/nginx/access.log
    nginx_error:
      type: files
      include_paths:
        - /var/log/nginx/error.log
    syslog:
      type: files
      include_paths:
        - /var/log/syslog
  service:
    pipelines:
      default_pipeline:
        receivers: [nginx_access, nginx_error, syslog]

metrics:
  receivers:
    hostmetrics:
      type: hostmetrics
      collection_interval: 60s
  service:
    pipelines:
      default_pipeline:
        receivers: [hostmetrics]
EOF

sudo systemctl restart google-cloud-ops-agent

Görüntü Oluşturma Öncesi Temizlik

Bu adım çok kritik. VM’i görüntüye almadan önce makineyi temizlemeniz gerekiyor. Geçici dosyalar, log’lar, SSH host key’leri ve kullanıcıya özel veriler görüntünün içinde olmamalı. Aksi halde tüm makineleriniz aynı SSH host key’ini paylaşır ki bu büyük bir güvenlik açığıdır.

# Log dosyalarını temizleyin
sudo find /var/log -type f -name "*.log" -exec truncate -s 0 {} ;
sudo find /var/log -type f -name "*.gz" -delete
sudo find /var/log -type f -name "*.1" -delete

# Bash geçmişini temizleyin
history -c
sudo -i history -c
cat /dev/null > ~/.bash_history
sudo bash -c 'cat /dev/null > /root/.bash_history'

# SSH host key'lerini kaldırın (yeni VM başladığında otomatik oluşacak)
sudo rm -f /etc/ssh/ssh_host_*

# Temporary dosyaları temizleyin
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*

# apt cache'i temizleyin
sudo apt-get clean
sudo apt-get autoremove -y

# cloud-init verilerini sıfırlayın
sudo cloud-init clean --logs

# Machine ID'yi sıfırlayın (her VM benzersiz ID alacak)
sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id

echo "Temizlik tamamlandı, VM kapatılıyor..."
sudo shutdown -h now

Disk’ten Görüntü Oluşturma

VM kapandıktan sonra artık görüntüyü oluşturabiliriz. Bunu yaparken VM’in durdurulmuş (stopped) durumda olması gerekiyor.

# VM'in durumunu kontrol edin
gcloud compute instances describe image-builder-vm 
  --zone=europe-west1-b 
  --format="get(status)"

# Boot disk adını öğrenin
DISK_NAME=$(gcloud compute instances describe image-builder-vm 
  --zone=europe-west1-b 
  --format="get(disks[0].source)" | awk -F/ '{print $NF}')

echo "Disk adı: $DISK_NAME"

# Görüntüyü oluşturun
gcloud compute images create ubuntu-webserver-v1-$(date +%Y%m%d) 
  --source-disk=$DISK_NAME 
  --source-disk-zone=europe-west1-b 
  --family=ubuntu-webserver 
  --description="Ubuntu 22.04 LTS Web Sunucu Görüntüsü - Nginx, Ops Agent, Güvenlik Sertleştirmesi" 
  --labels=env=production,app=webserver,os=ubuntu2204,version=1 
  --storage-location=europe-west1

Parametrelerin açıklamaları:

  • –family: Görüntüyü bir aileye dahil eder, en son görüntüyü family adıyla çağırabilirsiniz
  • –storage-location: Görüntünün nerede depolanacağını belirtir, veri egemenliği için önemli
  • –labels: Görüntülerinizi organize etmek ve maliyet takibi için kritik

Görüntüden VM Oluşturma

Artık görüntümüz hazır. Yeni bir VM’i bu görüntüden dakikalar içinde başlatabiliriz.

# Belirli görüntüden VM oluşturma
gcloud compute instances create web-server-01 
  --zone=europe-west1-b 
  --machine-type=e2-standard-2 
  --image=ubuntu-webserver-v1-20240115 
  --image-project=YOUR_PROJECT_ID 
  --boot-disk-size=50GB 
  --boot-disk-type=pd-ssd 
  --network-interface=network=default,subnet=default 
  --tags=web-server,http-server,https-server 
  --scopes=cloud-platform

# Görüntü ailesi kullanarak (her zaman en güncel görüntüyü alır)
gcloud compute instances create web-server-02 
  --zone=europe-west1-c 
  --machine-type=e2-standard-2 
  --image-family=ubuntu-webserver 
  --image-project=YOUR_PROJECT_ID 
  --boot-disk-size=50GB 
  --boot-disk-type=pd-ssd 
  --tags=web-server,http-server,https-server 
  --scopes=cloud-platform

Görüntü Sürümleme ve Yönetimi

Üretim ortamında görüntülerinizi düzgün sürümlemeniz ve yönetmeniz şart. Bir görüntü güncelleme stratejisi olmadan kaos kaçınılmaz.

# Mevcut görüntüleri listeleyin
gcloud compute images list 
  --project=YOUR_PROJECT_ID 
  --filter="family=ubuntu-webserver" 
  --format="table(name,family,status,creationTimestamp)"

# Görüntü detaylarını görüntüleyin
gcloud compute images describe ubuntu-webserver-v1-20240115 
  --project=YOUR_PROJECT_ID

# Eski görüntüyü deprecated (kullanım dışı) olarak işaretleyin
gcloud compute images deprecate ubuntu-webserver-v1-20231201 
  --state=DEPRECATED 
  --replacement=ubuntu-webserver-v1-20240115 
  --project=YOUR_PROJECT_ID

# Görüntüyü tamamen silin (artık ihtiyaç yoksa)
gcloud compute images delete ubuntu-webserver-v1-20230901 
  --project=YOUR_PROJECT_ID 
  --quiet

Görüntüleri Farklı Projelerle Paylaşma

Büyük organizasyonlarda görüntülerinizi merkezi bir projede tutup diğer projelere paylaşmanız gerekebilir. Bu yaklaşım “golden image” veya “image factory” pattern olarak da bilinir.

# Görüntüyü başka bir projeyle paylaşmak için IAM izni verin
gcloud compute images add-iam-policy-binding ubuntu-webserver-v1-20240115 
  --project=IMAGE_PROJECT_ID 
  --member="serviceAccount:[email protected]" 
  --role="roles/compute.imageUser"

# Tüm organizasyona görüntü erişimi verin
gcloud compute images add-iam-policy-binding ubuntu-webserver-v1-20240115 
  --project=IMAGE_PROJECT_ID 
  --member="domain:yourcompany.com" 
  --role="roles/compute.imageUser"

# Başka projeden bu görüntüyü kullanarak VM oluşturma
gcloud compute instances create app-server-01 
  --zone=us-central1-a 
  --machine-type=e2-standard-4 
  --image=ubuntu-webserver-v1-20240115 
  --image-project=IMAGE_PROJECT_ID 
  --project=TARGET_PROJECT_ID

Packer ile Otomatik Görüntü Oluşturma

Manuel görüntü oluşturma süreçleri için bu yöntemler işe yarasa da CI/CD pipeline’larınıza entegre etmek istediğinizde HashiCorp Packer vazgeçilmez oluyor. Packer, görüntü oluşturma sürecini tamamen otomatize etmenizi sağlıyor.

# Packer kurulumu (Ubuntu/Debian)
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install packer -y

# Packer şablon dosyası oluşturun (webserver.pkr.hcl)
cat > webserver.pkr.hcl << 'PACKER_EOF'
packer {
  required_plugins {
    googlecompute = {
      version = ">= 1.1.1"
      source  = "github.com/hashicorp/googlecompute"
    }
  }
}

variable "project_id" {
  type    = string
  default = "YOUR_PROJECT_ID"
}

variable "zone" {
  type    = string
  default = "europe-west1-b"
}

source "googlecompute" "ubuntu_webserver" {
  project_id          = var.project_id
  source_image_family = "ubuntu-2204-lts"
  source_image_project = "ubuntu-os-cloud"
  zone                = var.zone
  machine_type        = "e2-medium"
  disk_size           = 50
  disk_type           = "pd-ssd"
  image_name          = "ubuntu-webserver-v{{timestamp}}"
  image_family        = "ubuntu-webserver"
  image_description   = "Ubuntu 22.04 Otomatik Web Sunucu Goruntüsü"
  image_labels = {
    env     = "production"
    app     = "webserver"
    os      = "ubuntu2204"
    builder = "packer"
  }
  image_storage_locations = ["europe-west1"]
  ssh_username            = "packer"
  use_iap                 = true
}

build {
  sources = ["source.googlecompute.ubuntu_webserver"]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get upgrade -y",
      "sudo apt-get install -y nginx python3-pip fail2ban ufw",
      "sudo systemctl enable nginx",
      "sudo ufw --force enable",
    ]
  }

  provisioner "shell" {
    script = "scripts/install_ops_agent.sh"
  }

  provisioner "shell" {
    script = "scripts/cleanup.sh"
  }
}
PACKER_EOF

# Packer ile görüntü oluşturun
packer init webserver.pkr.hcl
packer validate webserver.pkr.hcl
packer build webserver.pkr.hcl

Gerçek Dünya Senaryosu: Otomatik Aylık Görüntü Güncelleme

Üretimde karşılaştığım yaygın bir senaryo şu: Güvenlik yamalarının otomatik olarak görüntüye uygulanması. Bunun için Cloud Scheduler + Cloud Functions kombinasyonu kullanılabilir ama basit bir shell script ile de başlayabilirsiniz.

#!/bin/bash
# update_base_image.sh - Aylık görüntü güncelleme scripti

set -euo pipefail

PROJECT_ID="YOUR_PROJECT_ID"
ZONE="europe-west1-b"
IMAGE_FAMILY="ubuntu-webserver"
BUILDER_VM="image-builder-$(date +%Y%m%d)"
DATE_TAG=$(date +%Y%m%d)

echo "=== Görüntü Güncelleme Başlıyor: $(date) ==="

# Mevcut en güncel görüntüden builder VM oluştur
LATEST_IMAGE=$(gcloud compute images describe-from-family $IMAGE_FAMILY 
  --project=$PROJECT_ID 
  --format="get(name)")

echo "Temel görüntü: $LATEST_IMAGE"

gcloud compute instances create $BUILDER_VM 
  --zone=$ZONE 
  --machine-type=e2-medium 
  --image=$LATEST_IMAGE 
  --image-project=$PROJECT_ID 
  --boot-disk-size=50GB 
  --metadata=startup-script='#!/bin/bash
    apt-get update
    apt-get upgrade -y
    apt-get autoremove -y
    apt-get clean
    # Ops Agent güncelle
    apt-get install --only-upgrade google-cloud-ops-agent -y
    # Temizlik
    find /var/log -type f -name "*.log" -exec truncate -s 0 {} ;
    history -c
    rm -f /etc/ssh/ssh_host_*
    cloud-init clean --logs
    truncate -s 0 /etc/machine-id
    shutdown -h now'

echo "Builder VM oluşturuldu, güncellemeler uygulanıyor..."

# VM'in kapanmasını bekle (max 10 dakika)
for i in $(seq 1 20); do
  sleep 30
  STATUS=$(gcloud compute instances describe $BUILDER_VM 
    --zone=$ZONE --format="get(status)" 2>/dev/null || echo "NOT_FOUND")
  echo "VM durumu: $STATUS"
  if [ "$STATUS" = "TERMINATED" ]; then
    break
  fi
done

# Yeni görüntü oluştur
DISK_NAME=$(gcloud compute instances describe $BUILDER_VM 
  --zone=$ZONE 
  --format="get(disks[0].source)" | awk -F/ '{print $NF}')

gcloud compute images create "${IMAGE_FAMILY}-v${DATE_TAG}" 
  --source-disk=$DISK_NAME 
  --source-disk-zone=$ZONE 
  --family=$IMAGE_FAMILY 
  --description="Otomatik güncelleme: $(date)" 
  --labels=env=production,updated=auto,date=$DATE_TAG 
  --storage-location=europe-west1

echo "Yeni görüntü oluşturuldu: ${IMAGE_FAMILY}-v${DATE_TAG}"

# Builder VM'i temizle
gcloud compute instances delete $BUILDER_VM 
  --zone=$ZONE 
  --delete-disks=all 
  --quiet

echo "=== Görüntü Güncelleme Tamamlandı: $(date) ==="

Görüntü Boyutunu Optimize Etme

Büyük görüntüler hem depolama maliyeti yaratır hem de VM başlatma sürelerini uzatır. Birkaç pratik öneri:

  • Gereksiz paketleri kurmayın: Her kurulum görüntü boyutunu artırır, sadece gerçekten gerekli olanları ekleyin
  • Katmanlı yaklaşım kullanın: Temel bir “base image” yapın, üzerine uygulama spesifik görüntüler oluşturun
  • apt cache temizleyin: apt-get clean && apt-get autoremove -y görüntü boyutunu önemli ölçüde düşürür
  • Log dosyalarını kesin: Görüntüde log bırakmayın, truncate -s 0 kullanın
  • pd-ssd kullan: SSD diskler görüntü oluşturma ve başlatmayı hızlandırır

Yaygın Sorunlar ve Çözümleri

VM başlatılmıyor, SSH key sorunu: Görüntüden VM oluşturduktan sonra bağlanamıyorsanız, büyük ihtimalle SSH host key’lerini temizlemeyi unutmuşsunuzdur. Tüm makineler aynı host key’e sahip olursa SSH bağlantısı reddeder.

cloud-init ikinci çalışmada beklenen ayarları uygulamıyor: cloud-init clean --logs komutunu görüntü oluşturmadan önce mutlaka çalıştırın. Aksi halde cloud-init “bu zaten yapılandırıldı” sanarak bazı adımları atlayabilir.

machine-id çakışması: /etc/machine-id aynı kalırsa bazı systemd servisleri ve DHCP client’ları sorun yaşayabilir. Görüntü temizleme adımında bu dosyayı sıfırlamayı unutmayın.

Görüntü çok büyük: Boot disk boyutunu minimum tutun, görüntü oluşturduktan sonra VM’leri daha büyük diskle başlatabilirsiniz. Görüntü boyutu boot disk boyutundan etkilenir.

Sonuç

GCP’de özel görüntü oluşturma, olgun bir cloud altyapısının temel taşlarından biri. Doğru yapıldığında tutarlılık, güvenlik ve hız açısından ciddi kazanımlar sağlıyor. Manuel yöntemle başlayıp süreci anladıktan sonra Packer ile otomatize etmenizi ve CI/CD pipeline’larınıza entegre etmenizi şiddetle tavsiye ederim.

Görüntü stratejinizi oluştururken şu prensipleri aklınızda tutun: Temel görüntülerinizi sade tutun, uygulama spesifik katmanlar ekleyin, sürümlemenizi disiplinli yapın ve aylık güvenlik güncellemelerini ihmal etmeyin. Bu prensipleri takip ettiğinizde hem ekibiniz hem de sisteminiz size teşekkür edecek.

Son olarak, özellikle büyük organizasyonlarda görüntü yönetimini ayrı bir “image factory” projesinde merkezi olarak yönetmenizi öneririm. Böylece hangi projenin hangi görüntüyü kullandığını takip etmek ve güncellemeleri koordineli biçimde yaymak çok daha kolay oluyor.

Bir yanıt yazın

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