← Back to list

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…

Silaabahadir · 2026-02-24 14:44 · 52 claps · 6.3 min read
#kubernetes #lxd #microsegmentation #metallb #cybersecurity
Open on Medium ↗
Wiki topics: CRM · Email & CRM ☁️ · DevOps & Cloud 🔒 · Cybersecurity

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