Mengisolasi workload satu sama lain di dalam jaringan: NetworkPolicy default-deny, isolasi multi-tenancy yang benar-benar bekerja, dan segmentasi ke zona yang mempersempit jalur serangan

Di episode 19 kita memastikan image yang masuk cluster sudah terverifikasi. Tapi ada pertanyaan besar yang tersisa: setelah masuk, apakah service boleh bicara dengan service mana pun? Di Kubernetes, defaultnya adalah semuanya boleh bicara ke semua — jaringan datar yang membuat satu service yang dibobol bisa menjangkau seluruh cluster. Episode ini membangun network policy & isolation: NetworkPolicy default-deny, isolasi multi-tenancy, dan segmentasi yang mempersempit jalur serangan.
Mengapa ini penting? Isolasi jaringan adalah pertahanan kedua setelah identitas (episode 18): mTLS membuktikan siapa, NetworkPolicy menentukan siapa boleh bicara dengan siapa. Tanpa isolasi, satu container yang di-compromise adalah pintu masuk ke seluruh fleet — database, secret, dan service internal lainnya. Dengan default-deny, blast radius serangan menyusut drastis.
Kubernetes NetworkPolicy mengatur lalu lintas antar pod berdasarkan label. Kuncinya: default harus deny. Cluster tanpa NetworkPolicy default-deny berarti semua pod saling terbuka.
# Kebijakan global: tidak ada traffic masuk/keluar tanpa izin
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressDengan default-deny aktif, lalu lintas yang diizinkan harus dinyatakan eksplisit. Contoh: payments-api hanya boleh diakses gateway, dan hanya boleh ke database:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: payments-api-allow
namespace: team-payments
spec:
podSelector:
matchLabels:
app: payments-api
policyTypes: [Ingress, Egress]
ingress:
- from:
- namespaceSelector:
matchLabels:
tier: gateway
- podSelector:
matchLabels:
app: api-gateway
ports:
- port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
tier: data
- podSelector:
matchLabels:
app: payments-db
ports:
- port: 5432Perhatikan dua selector (namespace + pod): ini membentuk pasangan "hanya dari namespace gateway, hanya pod api-gateway". Isolasi tidak bekerja jika hanya memakai satu selector yang longgar.
Di episode 15 kita memilih model tenancy; sekarang jaringannya kita kunci. Prinsipnya: namespace tenant A tidak boleh bicara ke namespace tenant B kecuali lewat jalur yang disetujui.
| Tenancy model | Pola NetworkPolicy |
|---|---|
| Namespace per tenant | Policy per namespace: izinkan traffic dalam namespace, tolak lintas namespace |
| Cluster per tenant | Isolasi alami (jaringan terpisah); tetap pasang default-deny di tiap cluster |
| vCluster | NetworkPolicy virtual per vCluster + policy fisik di bawahnya |
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: block-cross-tenant
namespace: team-payments
spec:
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
- podSelector: {} # sesama namespace boleh
- namespaceSelector:
matchLabels:
shared: ingress # jalur gateway disetujuiSelain per tenant, bagi jaringan menjadi zona berdasarkan fungsi — lalu atur lintas zona secara ketat:
| Zona | Isi | Aturan lintas zona |
|---|---|---|
| Ingress | Gateway, edge proxy | Hanya boleh ke zona aplikasi |
| Aplikasi | Workload bisnis | Hanya ke data + egress terbatas |
| Data | Database, cache | Tidak boleh memulai koneksi keluar; hanya menerima dari aplikasi |
Segmentasi zona membuat penyerang yang berhasil di satu zona tidak otomatis melihat zona lain. Ini melengkapi NetworkPolicy dengan konteks arsitektur.
CNI modern seperti Cilium menaikkan NetworkPolicy dari layer 3/4 ke layer 7 — membatasi metode HTTP dan path, bukan hanya port:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: payments-api-l7
namespace: team-payments
spec:
endpointSelector:
matchLabels:
app: payments-api
ingress:
- fromEndpoints:
- matchLabels:
app: api-gateway
toPorts:
- ports:
- port: "8080"
rules:
http:
- method: GET
path: "/payments"Layer 7 menutup celah yang tidak bisa dilihat policy layer 3: port 8080 terbuka, tapi hanya GET /payments yang diizinkan — bukan DELETE.
namespaceSelector tanpa pod label; satu namespace bisa di-bypass via pod lain.Important
Pasang NetworkPolicy default-deny di hari pertama, bukan setelah insiden. Menutup jaringan yang sudah terbuka jauh lebih menyakitkan daripada membuka jalur eksplisit satu per satu — dan eksplisit adalah tujuan kita: tidak ada satu byte pun lalu lintas yang tidak disengaja.
Inti yang harus dibawa pulang:
Di episode 21 selanjutnya kita membawa platform menghadapi gelombang berikutnya: platform engineering AI — platform untuk AI workloads dengan GPU scheduling, LLM serving, dan MLOps, plus bagaimana AI menjadi fitur platform itu sendiri!