Vagrant İle Kubernetes Cluster’ı Oluşturma (Öğrenilen Dersler)

Konuya “tl;dr” tadında bir giriş yapmakta fayda var. Bu yazıda “Vagrant ile Kubernetes kümesi nasıl oluştururuz?” sorusuna cevap aramaktan ziyade oluşturma eylemi esnasında karşılaşılan sorunlar ve üretilen çözümler üzerine tartışmalar yürütmektir niyetim. Başlığın sonuna da Öğrenilen Dersler eklememin sebebi budur.

Görsel Kaynağı

İnternette küçük bir “kubernetes cluster vagrant” anahtar kelimeli arama ile onlarca ve hepsi birbirinden değerli örnek/makale/forum mesajı edinmek mümkün. Ben de bu aramalardan edindiğim bilgi ve deneyimleri harmanlayarak, lokal ortamda Kubernetes çalıştırmak ve çalışmak üzere bir altyapı tasarlamak istedim. Bunun için de şu repoyu oluşturdum ve kolları sıvadım:

Repository'deki Readme.md içerisinde cluster’ın nasıl çalışabilir hale geleceğiyle ilgili gerekli açıklamalar hali hazırda mevcut. Yapılması gereken tek şey cd Provisioning komutu ilgili dizine gidip vagrant up diyerek makineleri oluşturmak. Ön gereksinimlerimiz ise bilgisayarımızda Vagrant ve VirtualBox’ın kurulu olması.

Sorunlar ve Çözümler

Bu çalışmayı yaparken karşılaştığım ilk ve temel sorun şuydu:

Master makinede cluster oluşturulamıyor!

İlerlemek için tüm yolların kapalı olduğu senaryo. Bu konuyla bir süre cebelleştim açıkçası. Hatta şu mesajla Twitter alemine haber saldım:

Bir yandan haber gelir mi diye beklerken bir yandan da sorunun çözümünü araştırıyordum — ki bu araştırma deneme/yanılma ile ilerliyordu — . Bir denememde sorunum çözüldü. Yukarıdaki mesajın devamında yaptığım açıklamada da belirttiğim üzere;

kubelet.service, üzerinde çalıştığı node “swap” aktivitesinde bulunduğunda çalışmaz hale geliyor. Vagrant dosyamda, node olarak oluşturduğum makinelere 512MB olarak hafıza atadım (cimrilik sanal da olsa böyle bir şey :). Dolayısıyla makineler henüz kurulum aşamasında swap işlemi gerçekleşiyor, kubelet.service duruyor ve kubeadm init başarısız oluyor. Çözüm ise tahmin edeceğiniz üzere bu değeri arttırmak.

Makineler birbiri ile haberleşemiyor!

İlk sorunu çözüp yola devam ettiğimde CNI eklentisi olarak Flannel kullanmaya karar verdim. Bu konuyla ilgili alternatifler ve üzerine dönen tartışmalara yine internet mecrasından erişebilirsiniz.

Flannel kurulduktan sonra, her node’da cni0 adı verilen bir interface kuruluyor. Bu interface aracılığıyla da node’lar ve node içerisindeki pod’lar birbiriyle haberleşebilir hale geliyor. Benim sorunum ise haberleşebilir hale gelememesi.

Bu sorunun kaynağını araştırırken şu adresteki cevap yönlendirici oldu. Flannel, varsayılan olarak host’taki ilk interface’i referans alıyor ancak Vagrant ortamındaki ilk interface, dış network’ten Vagrant makinelere ulaşmak için kullanılan NAT adresine işaret ediyor. Haliyle Flannel’ı ikinci (enp0s8 ) interface üzerinden çalışacak şekilde konfigüre etmek gerekiyor.

Bu sorunun çözümü için de, şu adreste yer alan flannel.yml dosyasını indirerek 126. satıra — --iface=enp0s8 ifadesini ekleme yolunu izledim. İkinci yapılması gereken işlem ise /etc/systemd/system/kubelet.service.d/10-kubeadm.conf dosyasında, kubelet servisine node ip’sini parametre olarak geçmek.

Uygulamaları dış dünyaya nasıl açabilirim?

Kişisel fikrim, Kubernetes evreni için bu büyük bir sorun. ClusterIP, NodePort, LoadBalancer, Ingress gibi kavramlar, bu sorunun içine düşünce; insanın dünyasında koca bir yer kaplıyor.

Bu konuyla ilgili okuduğum en iyi yazıyı buraya referans vermekten mutluluk duyuyorum: Sandeep Dinesh — Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

Bu soruna, Nginx Ingress Controller ve MetalLB kullanımının çözüm olacağını düşündüm. Kubernetes servisini bir Cloud Provider üzerinden alırsak hemen hemen hepsi bir Load Balancer hizmeti sunuyor. Ancak bunu bare-metal olarak kurgulamak istersek, meşaketli bir yol bizi bekliyor. Bu meşaketli yolu kısaltan ise MetalLB. Google tarafından geliştirilen ve Kubernetes’te servis olarak konumlanabilen bir load-balancer uygulaması.

Özetle, aşağıdaki gibi bir konfigürasyonla çalışan; bir servis LoadBalancer tipindeki expose edildiğinde ona otomatik olarak External IP tanımlaması gerçekleştiren bir üründen bahsediyoruz.

Tabii bu durumda yine bir sorun karşımıza çıkıyor:

Her servis oluştuğunda yeni bir External IP ihtiyacı

IP havuzumuz yeterince genişse bir sorun olmayabilir elbette (eğer Cloud servisi alıyorsanız pahalı bir seçim olabilir). Ancak benim bu senaryomda sadece 2 IP adresim var. Bu durum çok kısa sürede canımı sıkabilir. Onun yerine çözüm olarak şunu düşünüyorum: Bir Ingress servis oluşturarak bu servisi LoadBalancer olarak dışarı açmak. Böylece, gelen tüm trafiği bu servis üzerinden geçirebilirim (bazı kural setleri dahi tanımlayabilirim; örneğin response’a header basmak gibi) ve böylece tek bir IP üzerinden birden fazla servisi dış dünyaya açabilirim.

Sonuç

Çalışma ortamını hazırlarken karşılaştığım sorunlara — elbette bu sorunlarla ilk defa ben karşılaşmadım — ürettiğim — esinlenip uyguladığım — çözümlere dair aldığım notlar bu şekilde idi. Not almayı unuttuğum ve sonrada anımsadıklarım olursa bu yazı altına ekleyeceğim.

Kubernetes evreni herkesin de söylediği üzere sonsuz bir evren. En başta CNI ve CRI başlı başına uzmanlık gerektiren konular. Haliyle bu evrende atılan her adım ve gelişim doğrusuyla/yanlışıyla paylaşılmayı gerektiriyor diye düşündüm. Eksik ya da hatalı olduğunu düşündüğünüz konularla ilgili düzeltme yaparsanız hem ben hem de bu yazıya uğrayanlar eminim mutlu olacaktır.

Bir sonraki yazıya dek, sorun çözmeye çalışırken ağrı kesicileri yanınıza almayı unutmayın :)