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ü
familyadı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 -ygörüntü boyutunu önemli ölçüde düşürür - Log dosyalarını kesin: Görüntüde log bırakmayın,
truncate -s 0kullanı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.
