
Ansible ile Proxmox Üzerinde Sanal Makine Oluşturma
- Murat Akpınar
- Bilgi teknolojisi , Hypervisor
- 19 Mayıs 2024
İçindekiler
Proxmox arayüzünden bir sanal makine kurmak beş dakika sürer. Sorun beşinci makinede başlar: aynı disk boyutunu, aynı cloud-init kullanıcısını ve aynı SSH anahtarını her seferinde elle girmek hem yavaştır hem de er geç birinde yanlış değer yazarsınız — ve o yanlışı aylar sonra fark edersiniz.
Bu yazıda bu işi yapan bir Ansible rolünü inceliyoruz: ansible-role-vm-proxmox. Rolün Proxmox üzerinde imajdan şablona, şablondan sanal makineye giden akışını, kurulumunu ve — asıl önemlisi — ikinci kez çalıştırdığınızda ne olduğunu göreceğiz.
Rol Ne Yapıyor: İmajdan Şablona, Şablondan VM’e
Rol qm komutlarını Proxmox sunucusunda SSH üzerinden çalıştırır ve üç aşamalı bir zincir kurar:
- İmajı hazırla (
00_check_iso.yml) — bulut imajının Proxmox’ta/var/lib/vz/template/iso/altında olup olmadığına bakar. Yoksa önce rolünfiles/dizininden kopyalamayı dener, o da yoksa internetten indirir. - Şablon üret (
01_ubuntu_temp.yml,02_debian_temp.yml) — boş bir VM oluşturur, imajı disk olarak içeri alır, cloud-init sürücüsünü ekler veqm templateile şablona çevirir. - Şablondan klonla (
01_ubuntu_vm.yml,02_debian_vm.yml) — şablonu tam klonlar, CPU/RAM/disk değerlerini ayarlar ve cloud-init üzerinden kullanıcı, parola, IP ve SSH anahtarını yazar.
VM ID’leri rolün içinde sabittir:
| Dağıtım | Şablon ID | VM ID | İmaj |
|---|---|---|---|
| Debian 12 (bookworm) | 100 | 101 | debian-12-generic-amd64 |
| Ubuntu 22.04 (jammy) | 200 | 201 | jammy-server-cloudimg-amd64-disk-kvm |
Depodaki README, Debian 12’yi bullseye olarak yazıyor. Doğrusu bookworm; bullseye Debian 11’dir. İmaj URL’i zaten
bookwormdizinini gösteriyor, yani indirilen imaj doğru — yalnızca belgedeki ad yanlış.
Şablon üretme adımı şu komut dizisidir (Ubuntu için):
qm create 200 --name Ubuntu-template --memory 1024 --net0 virtio,bridge=vmbr0
qm importdisk 200 /var/lib/vz/template/iso/jammy-server-cloudimg-amd64-disk-kvm.img local-lvm
qm set 200 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-200-disk-0
qm set 200 --ide2 local-lvm:cloudinit --boot c --bootdisk scsi0 --serial0 socket --vga serial0
qm resize 200 scsi0 +2868M
qm template 200
Buradaki --serial0 socket --vga serial0 süs değildir: bulut imajları konsol çıktısını seri porta verecek şekilde derlenir, bu iki seçenek olmadan Proxmox’un noVNC konsolunda boş siyah ekran görürsünüz ve makinenin açılıp açılmadığını anlayamazsınız.
Kurulum: Envanteri Doldurun, Playbook’u Çalıştırın
Tek ön koşul, Proxmox sunucusuna parolasız SSH erişimidir:
ssh-copy-id -i ~/.ssh/mykey root@192.168.1.10
Ardından envanterde hipervizörün adresini ve klonlanacak makinenin cloud-init değerlerini yazarsınız:
hypervisor:
hosts:
proxmox:
ansible_host: 192.168.1.10
ansible_user: 'root'
ansible_connection: 'ssh'
vars:
cloud_init_user: murat
cloud_init_password: murat
cloud_init_ip: '192.168.1.135/24'
cloud_init_gw: '192.168.1.1'
ansible-playbook -i inventory/server_groups.yml site.yml
Dosya adına dikkat: README
inventory/cluster_inventory.ymldiyor, ama depoda duran dosyanın adıinventory/server_groups.yml. README’deki komutu olduğu gibi kopyalarsanız Ansible envanteri bulamaz.
Depodaki örnek envanter ansible_password: 'admin' satırını düz metin olarak taşıyor. Örnek olarak anlaşılır, ama kendi kurulumunuza taşımayın: SSH anahtarı zaten kurulduğu için o satıra ihtiyaç yoktur, saklamanız gereken bir sır varsa yeri ansible-vault‘tur.
Neden Modül Değil de qm CLI?
Ansible’ın community.general.proxmox_kvm diye bir modülü var ve akla ilk gelen soru bu rolün neden onu kullanmadığıdır. Rol bunun yerine shell: ile doğrudan qm çağırıyor. Bunun bir bedeli var, farkında olarak seçmek gerekir:
- Kazanç: Proxmox API belirteci,
community.generalkoleksiyonu ve Python bağımlılığı (proxmoxer) gerekmez. SSH yeter. Ayrıcaqm importdiskgibi modülde karşılığı olmayan işlemler doğrudan yapılabilir. - Bedel: Ansible’ın kendiliğinden gelen idempotency’si kaybolur.
shell:her koşulda çalışır; “zaten var mı” kontrolünü elle yazmanız gerekir. Rol bunuqm list | grep -q ' 200 'ile yapıyor vewhen: vm_exists.rc != 0koşuluyla şablon üretimini bir kez çalıştırıyor.
İkinci Çalıştırmada Ne Olur: Disk Her Seferinde 50 GB Büyür
Elle yazılan idempotency kontrolünün tuzağı şudur: koruma yalnızca korunan göreve uygulanır. Rolde klonlama korunuyor, klonlamadan sonraki ayarlama görevleri korunmuyor:
- name: Ubuntu Clone VM from template if not exists
shell: qm clone 200 201 --name ubuntu --full true
when: vm_exists.rc != 0 # ← korunuyor
- name: Ubuntu Set disk size
shell: "qm resize 201 scsi0 +50G"
# ← koşul yok, her çalıştırmada işler
qm resize‘ın + önekiyle çalıştığını hatırlayın: bu komut diski 50 GB yapmaz, 50 GB ekler. Playbook’u üç kez çalıştırdığınızda 201 numaralı makinenin diski 150 GB büyümüş olur ve bunu size kimse söylemez — LVM havuzu dolana kadar. Aynı şey CPU ve RAM ayarları için de geçerli, ama onlar mutlak değer yazdığı için zararsız kalır.
Düzeltmesi tek satırdır; klonlamayı koruyan koşulun aynısını boyutlandırmaya da vermek yeter:
- name: Ubuntu Set disk size
shell: "qm resize 201 scsi0 +50G"
when: vm_exists.rc != 0
İkinci tuzak IP çakışmasıdır. site.yml rolü çağırdığında tasks/main.yml hem Ubuntu hem Debian görevlerini içe aktarır, yani varsayılan bir çalıştırma 101 ve 201 olmak üzere iki makine kurar. İkisi de cloud-init IP’sini aynı değişkenden okur:
qm set 101 --ipconfig0 ip=192.168.1.135/24,gw=192.168.1.1 # debian
qm set 201 --ipconfig0 ip=192.168.1.135/24,gw=192.168.1.1 # ubuntu
İki makine aynı statik IP ile açılır. Proxmox bunu engellemez, hata da vermez; ağda hangisinin cevap verdiği ARP yarışına kalır. Tek dağıtım kuracaksanız tasks/main.yml içinde diğerinin import_tasks satırını yorumlayın; ikisini birden istiyorsanız her dağıtım için ayrı bir cloud_init_ip değişkeni tanımlayın.
Sonuç
shell:ile yazılan bir Ansible rolü idempotent değildir; siz yaparsanız öyle olur. Hershellgörevi için “bu ikinci kez çalışırsa ne olur” sorusunu ayrıca sormak gerekir — bu rolde cevabıqm resize +50Gveriyor.- Artımlı komutlar otomasyonun en sessiz hatasıdır.
+50Gbir hedef değil bir toplamadır; mutlak değer alan bir komut yanlış çalıştığında hata verir, artımlı olan sessizce birikir. - Aynı değişkenden beslenen iki makine aynı IP’yi alır. Şablonu çoğaltırken çoğalttığınız tek şey disk değildir; kimlik taşıyan her alanın (IP, hostname, MAC) makine başına ayrışması gerekir.
Rolün kaynağı ve güncel hâli: github.com/murat-akpinar/ansible-role-vm-proxmox. Proxmox’u sıfırdan kurmak isterseniz Evdeki Veri Merkezi: Proxmox ile Kendi Homelab’inizi Kurun yazısı başlangıç noktasıdır.


