Proxmox'ta Docker vs LXC: Production'da Gerçekten Ne Çalıştırıyorum
Yeni bir Proxmox host'unu bir müşteri için ayağa kaldırdığımda er ya da geç aynı soru geliyor: "Neden her şeyi Docker'da çalıştırmıyorsun?" Mantıklı bir soru, Docker image'leri taşınabilir, ekosistem çok büyük ve neredeyse her developer Dockerfile yazmayı biliyor. Ama yıllardır karışık workload'lar çalıştırıyorum, MariaDB Galera cluster'ları, PostgreSQL, Redis, RabbitMQ, üstüne müşterinin getirdiği uygulama stack'i ne olursa olsun, ve bir noktada şu ayrıma yerleştim, pek de sapmıyorum.
State tutan ve uzun süre yaşayan her şey için LXC
Veritabanları, cache'ler ve message queue'lar için doğrudan Proxmox host'unda LXC container kullanıyorum. LXC, host ile kernel'i paylaşır, yani virtualization tax yok: disk I/O ve memory davranışı bare metal'e neredeyse aynı. Bir MariaDB Galera node'unda ya da Redis instance'ında bu fark benchmark sayılarında direkt görünüyor, özellikle her overhead'in önemli olduğu küçük VPS'lerde.
Diğer sebep ise operasyonel. Bu servisler genelde yıllarca yaşıyor, ve pct enter ile container'a girip iostat kontrol edebilmek, innodb_buffer_pool_size'ı ayarlamak ya da hızlıca bir pg_dump alabilmek istiyorum, araya ekstra bir container runtime girmeden. Proxmox seviyesindeki snapshot ve backup'lar (vzdump) sorunsuz çalışıyor, ve tek bir LXC'yi geri almak beş dakikalık bir iş.
Docker-in-LXC neden hiç listede değil
Docker-in-LXC'yi başlarda denedim, çünkü iki dünyanın en iyisi gibi görünüyordu: LXC'nin hafifliği plus Docker'ın paketleme avantajı. Pratikte bu, bir kernel'i paylaşan iki container katmanı, ve bu kombinasyon en kötü anında ortaya çıkan bir kırılganlığa sahip. Nesting'i açmanız ve container'ın AppArmor profilini gevşetmeniz gerekiyor, bu da LXC'nin sağladığı güvenlik avantajını zaten ciddi şekilde azaltıyor. Sonra host'taki bir kernel update'i, nested Docker daemon'ı içindeki overlay storage driver'ını sessizce bozuyor, ve bunu ancak rutin bir pct reboot sonrası bir container ayağa kalkmadığında fark ediyorsunuz.
Daha yeni Proxmox sürümleri LXC içinde native OCI image desteği ekledi, bu da gerçekten kullanışlı bir orta yol: standart bir image'i çekip Docker daemon'ı olmadan LXC olarak çalıştırabiliyorsunuz. Küçük, çoğunlukla stateless servisler için bunu kullanmaya başladım, eskiden küçük bir Docker container'ına gittiğim yerlerde. Ama arkasında bir veritabanı varsa, hâlâ uzak duruyorum.
Docker, ama bir VM içinde
Bir müşteri bana Dockerfile veya docker-compose stack'i olarak paketlenmiş bir uygulama verdiğinde, ki günümüzde çoğu öyle, bu stack kendi Proxmox VM'ine gidiyor, LXC'ye değil. VM, Docker'a kendi kernel'ini veriyor, böylece Proxmox host'unun kernel güncellemeleri container runtime'a sıçramıyor, ve Docker'ın sevdiği şekilde yeniden yazdığı iptables/nftables kuralları o VM içinde kalıyor, host'un firewall config'i ile çakışmıyor.
Evet, Docker-in-LXC'ye kıyasla bu ekstra bir virtualization katmanı. Karşılığında, host'taki bir kernel update'inin birinin container'larını bozduğu için gece yarısı arandığım hiç olmadı. Müşteri işlerinde bu trade-off her zaman buna değiyor.
Gerçekte yaptığım ayrım
Kural olarak yazarsam: state tutan altyapı (veritabanları, queue'lar, cache'ler) Proxmox üzerinde direkt LXC olarak çalışıyor, uygulama container'ları bir VM içinde Docker olarak çalışıyor, ve küçük stateless yardımcı servisler artık native OCI-in-LXC olarak çalışıyor, bu seçenek var olduğuna göre. Bu bir dogma değil, bir workload gerçekten Kubernetes veya belirli bir orchestration katmanı gerektiriyorsa, o ayrı bir konu. Ama yönettiğim küçük-orta ölçekli altyapı için bu ayrım bulduğum en sıkıcı, en öngörülebilir kurulum, ve altyapıdan istediğiniz şey de zaten tam olarak bu: sıkıcı olması.