LXD Üzerinde On-Prem Kubernetes: Mikro-Segmentasyon, Gözlemlenebilirlik ve MetalLB Mimarisi
Siber güvenlik çalışmalarında sadece uygulamaları çalıştıran bir ortam kurmak yeterli değildir. Bize gereken; saldırı senaryolarının…
LXD Üzerinde On-Prem Kubernetes: Mikro-Segmentasyon, Gözlemlenebilirlik ve MetalLB Mimarisi
Siber güvenlik çalışmalarında sadece uygulamaları çalıştıran bir ortam kurmak yeterli değildir. Bize gereken; saldırı senaryolarının kontrollü üretilebildiği, ağ seviyesinde izole edilebildiği ve oluşan telemetrinin ölçülebildiği bir laboratuvar altyapısıydı.
Peki bu yazıda kurduğumuz şey tam olarak neye hazırlık?
Nihai hedefe bakarsak: Elasticsearch, Kibana, Logstash/Filebeat ve Wazuh’tan oluşan merkezi bir güvenlik gözlem platformu kurmak istiyoruz. Bu platform; ürettiğimiz saldırı senaryolarından gelen ağ trafiğini, uygulama loglarını ve sistem çağrılarını tek bir noktada toplayan, indeksleyen ve analiz eden bir yapı olacak. Ancak böyle bir yapıyı tek bir makinede veya düz bir Docker ortamında kurmak, hem kaynak yönetimi hem de izolasyon açısından bizi ciddi kısıtlamalara sokar.
Bu nedenle önce orkestrasyon katmanını doğru kurmak gerekiyordu. Bu yazı, o katmanın hikâyesi: LXD VM’leri üzerinde Kubernetes.
Altyapı: LXD Nedir, Biz Ne Yaptık?
Projede sanallaştırma katmanı olarak LXD kullanılıyor. LXD, Canonical tarafından geliştirilen bir sistem container ve VM yöneticisidir. Geleneksel VM’lere kıyasla çok daha az kaynak tüketerek tam izolasyon sağlar; OpenStack gibi alternatiflerin gerektirdiği çoklu sunucu altyapısına ihtiyaç duymadan tek bir fiziksel makine üzerinde gerçekçi bir çok düğümlü topoloji kurulabilir. LXD’nin web tabanlı dashboard’u üzerinden VM’ler dakikalar içinde ayağa kaldırılabiliyor.
Bu yazıda LXD kurulumunu ve VM oluşturma adımlarını anlatmıyoruz — o altyapı danışmanımız tarafından önceden hazırlandı. Bize teslim edilen şey: biri Master, ikisi Worker olmak üzere üç adet Ubuntu VM. Bizim işimiz bu VM’lerin içine girerek Kubernetes’i kurmak ve yapılandırmaktı.
Mimari Karar: Neden Kubernetes?
Kuruluma geçmeden önce, neden bu yolu seçtiğimizi paylaşmak istiyoruz. Çünkü “nasıl yaptık” kadar “neden yaptık” da önemli.
Docker tek bir host üzerinde konteyner çalıştırmak için mükemmeldir. Ama bize gereken şey konteyner çalıştırmak değil, orkestrasyon ve servis izolasyonu katmanıydı.
Micro-segmentation: Kubernetes’in yerleşik Network Policy mekanizması, pod-to-pod trafiğini Katman 3/4 seviyesinde granular biçimde kısıtlamamıza imkân tanır. Docker ile bu düzeyde kontrol sağlamak çok daha karmaşık bir yapı gerektirir.
Lateral Movement simülasyonu: Kurumsal ağlardaki yanal hareket tekniklerini test edebilmek için servislerin farklı düğümlere dağıtılmış olması gerekiyordu. Kubernetes, namespace izolasyonu ve scheduler politikalarıyla bunu doğal olarak sağlar.
Gözlemlenebilirlik: Elasticsearch, Kibana ve Wazuh gibi güvenlik araçlarını Kubernetes üzerinde çalıştırmak; sidecar container’lar, init hook’lar ve DaemonSet toplayıcılar aracılığıyla çok daha zengin bir log ve telemetri katmanı oluşturmamızı mümkün kılıyor. Docker Compose ile aynı araçları ayağa kaldırsaydık bu gözlemlenebilirlik derinliğine ulaşamazdık.
Mimari Tasarım
LXD dashboard’u üzerinden oluşturulan üç VM’e SSH ile bağlandık. Topoloji şu şekilde:
1 Control Plane (Master) ve 2 Worker Node. Amaç yüksek erişilebilirlik (HA) değil; kontrol düzlemi ile veri düzlemi arasındaki ayrımı net biçimde gözlemlemek ve tüm workload’ları Worker düğümlerine yönlendirerek trafiği izole etmektir.
Control Plane bilinçli olarak workload’suz bırakıldı. Üzerinde yalnızca kube-apiserver, controller-manager, scheduler ve etcd çalışmaktadır. Tüm uygulama pod’ları Worker düğümlere schedule edildi.
Ortak Hazırlık Aşaması (Tüm Düğümlerde Uygulandı)
Aşağıdaki adımlar; Master ve her iki Worker düğümünde eksiksiz biçimde çalıştırıldı.
1. Swap’in Kapatılması
Kubelet bellek yönetimini deterministik yapabilmek için swap alanının kapalı olmasını zorunlu tutar.
Bash
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
2. Kernel Modülleri
Pod trafiğinin düğümler arasında köprülenmesi ve iptables entegrasyonu için overlay ve br_netfilter modüllerinin yüklü olması gerekir.
Bash
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
3. Ağ Parametreleri
Güvenlik izleme araçlarının trafiği eksiksiz görebilmesi için sysctl ayarları yapılandırıldı:
Bash
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
4. Container Runtime: containerd Kurulumu
Runtime olarak containerd seçildi. Kurulum sonrası en kritik adım SystemdCgroup sürücüsünü aktif etmektir.
İşletim sistemi ile Kubernetes farklı cgroup sürücüleri kullanırsa şu sorunlar ortaya çıkar:
- Kaynak limitlerinin yanlış uygulanması
- İzleme araçlarının hatalı metrik üretmesi
- Kubelet başlatma hataları
Bu nedenle tüm düğümlerde aşağıdaki yapılandırmayı uyguladık:
Bash
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# SystemdCgroup = true olarak güncelleme
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
5. kubeadm, kubelet, kubectl Kurulumu
Bash
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Control Plane Başlatılması (Yalnızca Master’da)
Cluster, Master node’un yerel IP adresi üzerinden başlatıldı. Pod CIDR seçimi, ilerleyen aşamadaki mikro-segmentasyon ve Network Policy testleri gözetilerek yapıldı:
Bash
sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=<MASTER_IP>
Kurulum tamamlandıktan sonra kubectl erişimi için:
Bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Worker Düğümlerin Cluster’a Katılması
kubeadm init çıktısındaki join komutu Worker düğümlerde çalıştırıldı:
Bash
sudo kubeadm join <MASTER_IP>:6443 \
--token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<HASH>
Token süresi dolarsa Master’da yeniden üretilir: kubeadm token create --print-join-command
Ağ Katmanı: Flannel CNI
Neden Flannel?
CNI seçiminde önceliğimiz hız ve sadelikti. Flannel, overlay ağ kurarak düğümler arasında VXLAN tüneli sağlar; kurulumu tek bir manifest ile tamamlanır ve pod-to-pod bağlantısı anında çalışır.
Bash
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flanne
Lab ortamımızda bize gereken şey düğümlerin birbirini görmesi ve servisler arasındaki trafiğin yönlendirilebilmesiydi. Flannel bu ihtiyacı ekstra yapılandırma gerektirmeden karşıladı.
Flannel’ın Bir Sınırını Bilmek
Flannel’ı seçerken bilinçli olarak kabul ettiğimiz bir kısıt var: Flannel, Kubernetes Network Policy kurallarını kernel seviyesinde enforce edemez. Politika nesnesi tanımlanabilir, ancak trafik engellenmez; sadece metadata olarak kalır.
Bu, ilerleyen aşamada mikro-segmentasyon testleri yaparken göz önünde bulundurulması gereken bir noktadır. Flannel’ın üzerinde çalışan namespace izolasyonu ve servis bazlı RBAC kuralları hâlâ geçerlidir; ancak granular pod-to-pod trafik kısıtlaması için bu aşamada bağımlılığımız Kubernetes’in üst katman mekanizmalarına kaymaktadır. Network Policy enforcement ihtiyacı net biçimde ortaya çıktığında, CNI geçişi doğal bir sonraki adım olacaktır.
Yük Dengeleme: MetalLB
Kubernetes, bir cloud ortamında çalıştığında LoadBalancer tipindeki servislere otomatik olarak harici IP atar. On-premises ortamda ise bu mekanizma yoktur; servisler <pending> durumunda kalır.
Bu sorunu çözmek için MetalLB kuruldu. MetalLB, on-premises cluster’lara yazılım tabanlı yük dengeleme yeteneği kazandırır. L2 modunda çalışacak şekilde yapılandırdık: belirlenen bir IP aralığından servislere gerçek IP adresleri atanır ve bu adresler ARP üzerinden yerel ağa duyurulur.
Bash
kubectl create namespace metallb-system
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
IP havuzu ve L2 duyuru kuralı yapılandırması:
YAML
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.3.200-192.168.3.220
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default-pool
MetalLB olmadan ilerleyen aşamada kuracağımız Kibana, Wazuh ve diğer servislere LAN’dan ulaşmak mümkün olmazdı. Bu nedenle altyapı kurulumunun ayrılmaz bir parçası haline geldi.
Yönetim Katmanı: Portainer ve Kubernetes Dashboard
Cluster hazır olduktan sonra iki farklı yönetim arayüzü kurduk: Kubernetes Dashboard ve Portainer.
Kubernetes Dashboard, cluster durumunu namespace bazında görselleştiren resmi Kubernetes aracıdır. Pod durumları, event logları ve kaynak kullanımını tek ekranda görmek için kullandık. Erişim için bir ServiceAccount ve ClusterRoleBinding tanımlanması gerekir:
Bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.y
YAML
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
Giriş token’ı: kubectl -n kubernetes-dashboard create token admin-user
Portainer ise container-native bir yönetim platformudur. Kubernetes Dashboard’a kıyasla daha görsel bir arayüz sunar; özellikle volume yönetimi, servis düzenleme ve manifest editörü açısından pratik bulduğumuz bir araç oldu. Ayrıca Portainer agent mimarisi sayesinde birden fazla cluster’ı tek noktadan yönetme imkânı sağlar — ilerleyen aşamada birden fazla lab ortamı kurduğumuzda bu önemli bir avantaj haline gelecek.
Bash
kubectl apply -f https://downloads.portainer.io/ee2-33/portainer-agent-k8s-nodeport.y
Her iki araç da MetalLB IP havuzundan aldıkları adresler üzerinden LAN’dan erişilebilir duruma getirildi.
Telemetri Toplama Katmanı: Kubernetes Burada Neden Kritik?
Elasticsearch ve Wazuh gibi SIEM araçlarını bir Docker Compose dosyasıyla da ayağa kaldırabilirsiniz. Ancak bunu yaptığınızda şu soruyla yüz yüze gelirsiniz: “Bu araçlar gerçekten ne görüyor?”
Kubernetes, bu soruya çok daha zengin bir cevap verebilmemizi sağlıyor.
Sidecar Container Yaklaşımı: Her pod’un yanına eklenen bir log toplayıcı container, uygulamanın stdout/stderr çıktısını dinler ve merkezi log katmanına (Filebeat aracılığıyla Elasticsearch’e) iletir. Bu sayede uygulama davranışı ile ağ olayları aynı zaman damgası altında ilişkilendirilebilir. Docker’da bunu elle yapılandırmak gerekir; Kubernetes’te ise pod tanımına birkaç satır eklenerek çözülür.
Hook Script ve Init Container Kullanımı: Kubernetes, bir pod başlamadan önce veya kapanırken özel scriptlerin çalıştırılmasına izin verir. Bu mekanizma sayesinde; bir workload ayağa kalktığında otomatik olarak Wazuh agent kaydı yapılabilir, kapanırken de temizlik logu üretilebilir. Saldırı simülasyonu ortamında bu, olayların başlangıç ve bitiş noktalarını kesin olarak damgalama imkânı tanır.
Port ve Servis Yönetimi: Her güvenlik aracı farklı portlar üzerinden iletişim kurar. Kubernetes Service nesneleri, bu portları merkezi olarak tanımlamayı ve gerektiğinde namespace izolasyonuyla erişimi kısıtlamayı mümkün kılar. Wazuh manager portları, Elasticsearch API’si ve Kibana arayüzü ayrı namespace’lerde çalıştırılıp yalnızca gerekli servislerle explicit allow kurallarıyla ilişkilendirilebildi.
Node-Level DaemonSet Collector: Düğüm seviyesinde container aktiviteleri ve sistem çağrıları toplanmaktadır. Bu katman ilerleyen aşamada eBPF tabanlı syscall gözlemi ile zenginleştirilecektir.
Tüm bu katmanların bir arada çalışmasıyla elde ettiğimiz şey şudur: uygulama logu, ağ davranışı ve sistem çağrıları arasındaki ilişkiyi tek bir altyapıda, tutarlı biçimde kurabilmek.
Karşılaşılan Teknik Sorunlar ve Çözümleri
1. Cgroup Sürücü Çakışması
Belirti: Kubelet servisi başlamıyor, journalctl -u kubelet hata üretiyor. Neden: containerd ve kubelet farklı cgroup sürücüleri kullanıyordu. Çözüm: config.toml içindeki SystemdCgroup değeri true yapılarak iki katman senkronize edildi.
Mevcut durumu kontrol etmek için
Bash
sudo cat /etc/containerd/config.toml | grep SystemdCgroup
Çıktı “false” ise düzeltme gerekir
Bash
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
Sonuç
Elde ettiğimiz yapı, yalnızca bir Kubernetes kümesi değildir.
Mikro-segmentasyonun uygulandığı, kontrol ve veri düzlemlerinin ayrıştırıldığı, container runtime ile işletim sisteminin uyumlu yapılandırıldığı ve telemetri üretiminin tasarlandığı bu yapı; Blue Team detection ve log analizi katmanlarının üzerine inşa edileceği bir mühendislik platformudur.
Bu süreçteki asıl kazanımımız komutları çalıştırmak değil, bu komutların işletim sistemi, ağ ve kaynak yönetimi katmanlarında neyi değiştirdiğini anlamak oldu.
Sistem şu an Ready durumundadır.
Bir sonraki yazıda bu altyapı üzerine Elasticsearch, Kibana, Logstash/Filebeat ve Wazuh’u konuşlandıracak; Kubernetes’in servis izolasyonu ve hook mekanizmalarının bu araçların gözlem kalitesini nasıl artırdığını somut örneklerle ele alacağız.
메타데이터
- post_id
- 2256d46860f6
- slug
- lxd-üzerinde-on-prem-kubernetes-mikro-segmentasyon-gözlemlenebilirlik-ve-metallb-mimarisi-2256d46860f6
- url
- https://medium.com/@silaabahadir/lxd-%C3%BCzerinde-on-prem-kubernetes-mikro-segmentasyon-g%C3%B6zlemlenebilirlik-ve-metallb-mimarisi-2256d46860f6
- canonical_url
- https://medium.com/@silaabahadir/lxd-%C3%BCzerinde-on-prem-kubernetes-mikro-segmentasyon-g%C3%B6zlemlenebilirlik-ve-metallb-mimarisi-2256d46860f6
- author_url
- https://medium.com/@silaabahadir
- status
- ok
- fetched_at
- 2026-06-12 07:40:50