Masalah yang Diselesaikan Service
IP pod bersifat sementara. Setiap kali pod dibuat ulang — karena rilis, karena node dikuras, karena crash — IP-nya berubah. Menyimpan IP pod di konfigurasi aplikasi adalah jaminan kerusakan.
Service memberi satu alamat tetap beserta nama DNS yang selalu menunjuk ke kumpulan pod yang sehat saat itu.
apiVersion: v1
kind: Service
metadata:
name: layanan-pesanan
spec:
selector:
app: layanan-pesanan # pod mana yang dilayani
ports:
- name: http
port: 80 # port Service
targetPort: 8080 # port di dalam pod
type: ClusterIP
Empat Jenis Service
| Jenis | Terjangkau dari | Dipakai untuk |
|---|---|---|
| ClusterIP | Dalam kluster saja | Bawaan; komunikasi antar layanan internal |
| NodePort | IP node mana pun di port 30000–32767 | Pengembangan; jarang tepat untuk produksi |
| LoadBalancer | Internet, lewat LB penyedia cloud | Mengekspos satu layanan ke luar |
| ExternalName | Alias DNS ke host di luar | Merujuk basis data terkelola di luar kluster |
Setiap Service bertipe LoadBalancer membuat load balancer cloud tersendiri, dan tiap load balancer punya biaya bulanan. Sepuluh layanan berarti sepuluh tagihan dan sepuluh alamat IP publik. Pola yang benar: satu Ingress Controller di belakang satu LoadBalancer, lalu arahkan semua layanan melaluinya berdasarkan host dan path.
DNS Internal
<service>.<namespace>.svc.cluster.local # Dari pod di namespace yang sama: http://layanan-pesanan # Dari namespace berbeda: http://layanan-pesanan.produksi # Nama lengkap (paling eksplisit): http://layanan-pesanan.produksi.svc.cluster.local
Nama pendek diselesaikan lewat daftar search di /etc/resolv.conf, yang berarti beberapa kali kueri DNS gagal sebelum yang benar ditemukan. Pada aplikasi dengan trafik tinggi ini menambah latensi yang terukur. Untuk panggilan antar layanan yang panas, gunakan nama lengkap berakhiran titik: layanan-pesanan.produksi.svc.cluster.local. — titik di akhir mencegah pencarian tambahan sepenuhnya.
Endpoint: Yang Sebenarnya Terjadi
Service tidak ajaib. Sebuah controller mengawasi pod yang cocok dengan selector, dan memasukkan yang Ready ke dalam objek EndpointSlice. Itulah daftar tujuan yang dipakai kube-proxy.
kubectl get endpointslices -l kubernetes.io/service-name=layanan-pesanan kubectl describe svc layanan-pesanan
Bila kubectl describe svc menampilkan Endpoints: <none>, masalahnya hampir selalu salah satu dari tiga hal ini: (1) selector tidak cocok dengan label pod, (2) tidak ada pod yang Ready karena readiness probe gagal, atau (3) targetPort tidak sesuai dengan port yang benar-benar didengarkan aplikasi. Periksa ketiganya sebelum menyalahkan jaringan.
Headless Service
spec:
clusterIP: None # ← headless
selector:
app: basisdata
Dengan clusterIP: None, DNS tidak mengembalikan satu IP virtual, melainkan daftar IP semua pod. Ini yang dipakai StatefulSet agar tiap replika bisa dialamati satu per satu — penting untuk database dan sistem yang butuh mengetahui anggota kluster secara individual.
Menelusuri Masalah Jaringan
# Pod sementara untuk mendiagnosis dari dalam kluster kubectl run debug --rm -it --image=nicolaka/netshoot -- bash # Di dalamnya: nslookup layanan-pesanan.produksi.svc.cluster.local curl -v http://layanan-pesanan/healthz dig +search layanan-pesanan # Meneruskan port ke mesin lokal — melewati Service sepenuhnya kubectl port-forward svc/layanan-pesanan 8080:80 kubectl port-forward pod/pesanan-abc123 8080:8080
Bila port-forward ke pod berhasil tetapi ke Service gagal, masalahnya ada pada Service — biasanya selector atau targetPort. Bila port-forward ke pod juga gagal, masalahnya ada di aplikasi itu sendiri. Langkah sederhana ini memisahkan dua kemungkinan besar dalam satu menit.