NetworkPolicy Nedir?¶
Kubernetes'te varsayilan olarak cluster icindeki butun podlar birbiriyle serbestce konusabilir. Hangi namespace'te olursa olsun bir pod, baska bir podun IP adresini ve portunu biliyorsa ona istek atabilir. Bu "duz ag" (flat network) modeli baslangicta pratiktir ama guvenlik acisindan risklidir: ele gecirilen tek bir pod, tum cluster'daki servislere ulasabilir hale gelir.
NetworkPolicy, bu serbest trafigi kisitlamak icin kullanilan objedir. Podlar arasindaki (ve podlarla dis dunya arasindaki) trafige kural koyar; hangi kaynaktan gelen trafige izin verilecegini, hangi hedefe cikis yapilabilecegini belirler.
NetworkPolicy, podlar seviyesinde calisan bir guvenlik duvari (firewall) gibidir; label'lara gore hangi trafige izin verilecegini tanimlar.
Onemli: CNI Gereksinimi¶
NetworkPolicy objesini olusturmak tek basina yeterli degildir. Bu kurallari fiilen uygulayan, cluster'da kullanilan CNI (ag eklentisi)'dir. Calico, Cilium ve Weave gibi eklentiler NetworkPolicy'yi destekler. Ancak yaygin kullanilan bazi basit eklentiler (ornegin varsayilan Flannel) bunu desteklemez.
Not: NetworkPolicy destegi olmayan bir CNI kullaniyorsaniz, olusturdugunuz policy objeleri sessizce hicbir sey yapmaz. Obje kubectl get ile gorunur ama trafik hicbir sekilde kisitlanmaz. Kurallarin gercekten uygulandigini test etmeden guvenli oldugunuzu varsaymayin.
Varsayilan Davranis: Allow¶
Bir pod hicbir NetworkPolicy tarafindan secilmediginde, o pod icin tum trafik aciktir (allow all). Yani NetworkPolicy olusturana kadar hersey serbesttir.
Ama bir podu secen en az bir NetworkPolicy olustugu anda kural degisir: artik o pod icin yalnizca policy'de acikca izin verilen trafik gecerli olur, geri kalan her sey engellenir. Bu mantik NetworkPolicy'nin en cok karistirilan noktasidir:
- Policy yoksa: her sey serbest.
- Bir podu secen policy varsa: o policy'nin izin verdigi disindaki her sey kapali.
Yani NetworkPolicy bir kez devreye girdiginde "izin verilenler listesi" (whitelist) gibi calisir.
Ingress ve Egress Farki¶
Bir NetworkPolicy iki yonde trafigi kontrol eder. Bu iki kavram NetworkPolicy'nin kalbidir:
| Yon | Anlami | Kimin bakis acisiyla? |
|---|---|---|
| Ingress | Pod'a gelen (inbound) trafik | Policy'nin sectigi pod hedeftir; "bana kim baglanabilir?" |
| Egress | Pod'dan cikan (outbound) trafik | Policy'nin sectigi pod kaynaktir; "ben nereye baglanabilirim?" |
Onemli olan bakis acisidir: her ikisi de her zaman policy'nin sectigi pod'un perspektifinden tanimlanir.
- Bir web sunucusuna "sadece frontend podlari 8080 portundan baglanabilsin" demek istiyorsan → bu bir ingress kuralidir (web sunucusuna gelen trafik).
- Bir uygulamanin "sadece veritabanina ve DNS'e cikabilmesi, baska hicbir yere gidememesi" istiyorsan → bu bir egress kuralidir (uygulamadan cikan trafik).
Cogu senaryoda once ingress kurallari yazilir, cunku asil amac genellikle bir servise kimlerin ulasabilecegini sinirlamaktir.
Policy Yapisi¶
Bir NetworkPolicy uc ana parcadan olusur:
podSelector: Bu policy'nin hangi podlara uygulanacagini secer. Bos birakilirsa ({}) namespace'teki tum podlari secer.policyTypes: Bu policy'ninIngress,Egressveya her ikisini birden kontrol ettigini belirtir.ingress/egress: Izin verilen trafik kurallarinin listesi (from/toveports).
Ornek 1: Belirli Bir Porta Gelen Trafige Izin Vermek¶
En sik ihtiyac duyulan senaryo: bir container'in belirli bir portuna, yalnizca belirli podlardan gelen trafige izin vermek. Asagidaki ornek, app: web etiketli podlarin 8080 portuna, yalnizca app: frontend etiketli podlardan gelen trafige izin verir. Baska her yerden gelen trafik engellenir.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-ingress-izni
namespace: dev
spec:
podSelector:
matchLabels:
app: web # Bu kural app=web podlarina uygulanir (hedef)
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # Sadece app=frontend podlarindan
ports:
- protocol: TCP
port: 8080 # Sadece 8080/TCP portuna
Bu policy devreye girdiginde:
app: frontendpodlari →app: webpodlarinin 8080 portuna erisebilir.- Baska bir pod (ornegin
app: test) →app: webpodlarina erisemez. app: frontendbile olsa, 8080 disindaki bir porta (ornegin 3000) erisemez.
Not: Buradaki port, container'in dinledigi porttur (yani pod'un containerPort degeri), Service portu degildir. NetworkPolicy podlar seviyesinde calisir; Service'in port/targetPort esleme mantigina karismaz.
Birden fazla porta izin vermek istersen ports listesine ekleme yaparsin:
Ornek 2: Her Seyi Engelle (Default Deny)¶
Guvenli bir baslangic noktasi genellikle "once her seyi kapat, sonra ihtiyac oldukca ac" yaklasimidir. Asagidaki policy, namespace'teki tum podlara gelen trafigi engeller:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: dev
spec:
podSelector: {} # Bos selector = namespace'teki TUM podlar
policyTypes:
- Ingress
# ingress kurali yok = hicbir gelen trafige izin yok
podSelector: {} tum podlari secer, ingress altinda hicbir kural olmadigi icin de hicbir gelen trafik gecemez. Bu policy'yi olusturduktan sonra, yukaridaki Ornek 1 gibi policy'ler ekleyerek yalnizca ihtiyac duyulan trafigi tek tek acarsin. Ayni policy'ler birbirinin uzerine eklenir (additive); biri engelleyip digeri acmaz, izin verilenlerin birlesimi gecerli olur.
Ornek 3: Egress ile Cikis Trafigini Kisitlamak¶
Asagidaki ornek, app: web podlarinin sadece app: db podlarina 5432 portundan cikis yapmasina izin verir. Ayrica DNS calismasi icin 53 portuna izin eklenmistir (aksi halde pod isim cozumlemesi yapamaz):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-egress-izni
namespace: dev
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: db
ports:
- protocol: TCP
port: 5432
- to: [] # Tum hedefler, ama sadece asagidaki portlar
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Not: Egress kisitlarken DNS (53/UDP ve 53/TCP) icin izin vermeyi unutmak cok yaygin bir hatadir. Egress kapatildiginda pod, kube-dns/CoreDNS'e ulasamaz ve nslookup/servis isimleri calismaz. Bir servise db.dev.svc.cluster.local gibi isimle baglaniyorsan once DNS'in acik oldugundan emin ol.
from / to Secim Yontemleri¶
from (ingress) ve to (egress) altinda kaynagi/hedefi uc farkli sekilde secebilirsin:
- podSelector: Ayni namespace icindeki label'a uyan podlari secer.
- namespaceSelector: Belirli label'a sahip namespace'lerdeki podlari secer (namespace'ler arasi trafik icin).
- ipBlock: Cluster disindaki IP araliklarini secer (CIDR ile). Dis dunyaya/dis dunyadan trafik icin.
ingress:
- from:
- namespaceSelector:
matchLabels:
ekip: backend
- ipBlock:
cidr: 10.0.0.0/16
except:
- 10.0.5.0/24
Dikkat: Bir from elemaninda podSelector ve namespaceSelector ayni tire (-) altinda birlikte yazilirsa "VE" (AND) mantigi calisir: "su namespace'teki, su label'a sahip podlar". Ayri tirelerle yazilirsa "VEYA" (OR) olur. Bu ince fark, cogu NetworkPolicy hatasinin kaynagidir.
Kullanisli Komutlar¶
# Policy'leri listele
kubectl get networkpolicy -n dev
kubectl get netpol -n dev # kisa adi
# Detayli inceleme (hangi podlari sectigini ve kurallari gorur)
kubectl describe netpol web-ingress-izni -n dev
# Bir podun hangi label'lara sahip oldugunu gor (selector'lar bununla eslesir)
kubectl get pods -n dev --show-labels
# Trafigi hizlica test etmek icin gecici bir pod acip baglanti dene
kubectl run test --rm -it --image=nicolaka/netshoot -n dev -- /bin/bash
# iceride: curl web:8080 veya nc -zv web 8080
Not: NetworkPolicy'ler yalnizca yeni baglantilari kontrol eder ve TCP/UDP/SCTP seviyesinde calisir; HTTP yolu (path) veya metod gibi katman-7 detaylarina bakmaz. URL bazinda yetkilendirme istiyorsan bir service mesh (ornegin Istio, Cilium) veya Ingress seviyesinde kural kullanman gerekir.