Pada artikel sebelumnya, kita telah membahas tentang Deployment yang mengatur ReplicaSet untuk mengelola Pod. Kita sudah bisa membuat aplikasi kita berjalan di dalam klaster Kubernetes dengan jumlah replika yang kita inginkan. Namun, bagaimana cara mengakses aplikasi tersebut? Bagaimana Pod bisa berkomunikasi dengan Pod lainnya? Di sinilah peran Service menjadi sangat penting.
Apa itu Service?
Service adalah abstraksi yang mendefinisikan sekumpulan Pod dan kebijakan untuk mengakses Pod-Pod tersebut. Dengan kata lain, Service adalah cara untuk mengekspos aplikasi yang berjalan pada sekumpulan Pod sebagai layanan jaringan.
Bayangkan kita memiliki aplikasi frontend yang perlu berkomunikasi dengan aplikasi backend. Tanpa Service, frontend perlu mengetahui IP dari setiap Pod backend. Masalahnya, IP Pod bisa berubah kapan saja, terutama ketika Pod dihapus dan dibuat ulang oleh ReplicaSet atau Deployment. Service menyelesaikan masalah ini dengan menyediakan alamat tetap yang bisa digunakan untuk mengakses Pod-Pod tersebut.
Mengapa Kita Membutuhkan Service?
Ada beberapa alasan mengapa Service sangat penting dalam ekosistem Kubernetes:
- Pod bersifat tidak permanen (ephemeral): Pod bisa dihapus dan dibuat ulang kapan saja, yang berarti IP-nya juga berubah.
- Load balancing: Service mendistribusikan traffic ke semua Pod yang menjadi bagian dari Service tersebut.
- Service discovery: Kubernetes menyediakan mekanisme untuk menemukan dan terhubung ke Service.
- Ekspos aplikasi: Service memungkinkan aplikasi diakses dari luar klaster.
Jenis-jenis Service
Kubernetes menyediakan beberapa jenis Service yang bisa kita gunakan sesuai kebutuhan:
1. ClusterIP
ClusterIP adalah jenis Service default di Kubernetes. Service ini mengekspos aplikasi pada IP internal di dalam klaster. Artinya, Service hanya bisa diakses dari dalam klaster.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Pada contoh di atas, kita membuat Service bernama backend-service yang akan mengarahkan traffic dari port 80 ke port 8080 pada Pod-Pod dengan label app: backend.
2. NodePort
NodePort mengekspos Service pada port tertentu di setiap node dalam klaster. Ini memungkinkan akses ke Service dari luar klaster menggunakan <NodeIP>:<NodePort>.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080
nodePort: 30080
type: NodePort
Dengan konfigurasi di atas, Service bisa diakses melalui port 30080 di setiap node dalam klaster.
3. LoadBalancer
LoadBalancer mengekspos Service menggunakan load balancer dari penyedia cloud. Ini adalah cara paling umum untuk mengekspos aplikasi ke internet.
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
4. ExternalName
ExternalName memetakan Service ke nama DNS eksternal, bukan ke selector Pod.
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName
externalName: api.example.com
Cara Kerja Service
Service bekerja menggunakan label selector untuk menentukan Pod mana yang akan menjadi bagian dari Service. Ketika request datang ke Service, Kubernetes akan mendistribusikan traffic ke Pod-Pod yang memiliki label yang sesuai.
Mari kita lihat contoh lengkap untuk memahami cara kerja Service:
- Pertama, kita buat Deployment untuk aplikasi backend:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: nginx:latest
ports:
- containerPort: 80
- Kemudian, kita buat Service untuk mengekspos Deployment tersebut:
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 80
type: ClusterIP
- Simpan kedua file YAML di atas dan terapkan ke klaster:
kubectl apply -f backend-deployment.yaml
kubectl apply -f backend-service.yaml
- Verifikasi bahwa Service telah dibuat:
kubectl get services
Output akan terlihat seperti ini:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
backend-service ClusterIP 10.104.123.456 <none> 80/TCP 1m
- Sekarang, Pod lain di dalam klaster bisa mengakses backend menggunakan nama Service
backend-serviceatau IP ClusterIP-nya.
Service Discovery di Kubernetes
Kubernetes menyediakan dua cara utama untuk service discovery:
- Environment Variables: Ketika Pod dibuat, Kubernetes menyuntikkan environment variables untuk setiap Service yang aktif.
- DNS: Kubernetes memiliki add-on DNS yang menciptakan record DNS untuk setiap Service.
Cara paling umum adalah menggunakan DNS. Misalnya, jika kita memiliki Service bernama backend-service di namespace default, Pod lain bisa mengaksesnya menggunakan nama DNS backend-service.default.svc.cluster.local atau cukup dengan backend-service jika berada di namespace yang sama.
Endpoint
Endpoint adalah objek Kubernetes yang melacak Pod mana yang menjadi bagian dari Service. Kubernetes secara otomatis membuat dan memperbarui Endpoint berdasarkan selector Service.
Kita bisa melihat Endpoint dengan perintah:
kubectl get endpoints backend-service
Output akan menunjukkan IP dari Pod-Pod yang menjadi bagian dari Service:
NAME ENDPOINTS AGE
backend-service 10.244.1.2:80,10.244.2.3:80,10.244.3.4:80 1m
Kesimpulan
Service adalah komponen penting dalam arsitektur Kubernetes yang memungkinkan komunikasi antar Pod dan mengekspos aplikasi baik di dalam maupun di luar klaster. Dengan memahami berbagai jenis Service dan cara kerjanya, kita bisa merancang aplikasi yang lebih tangguh dan mudah diakses.
Pada artikel berikutnya, kita akan membahas tentang ConfigMap - tempat konfigurasi aplikasi disimpan di Kubernetes. Jangan lupa untuk mencoba contoh-contoh di atas di klaster Minikube Anda!
Cappy Hoding! ๐๐พ