ReplicaSet

Cara ReplicaSet memelihara jumlah Pod yang diinginkan dan hubungan kepemilikan Pod di dalamnya.

Daftar isi

ReplicaSet adalah objek Kubernetes yang memelihara sekelompok Pod yang identik agar jumlahnya selalu sesuai dengan nilai yang dideklarasikan. Apabila sebuah Pod mati atau dihapus, ReplicaSet membuat penggantinya secara otomatis, dan apabila Pod berlebih, kelebihannya dihapus. Topik ini membahas mekanisme rekonsiliasi tersebut, peran selector dan label pod-template-hash dalam kepemilikan Pod, serta alasan Deployment lebih tepat digunakan daripada ReplicaSet yang berdiri sendiri.

Cara ReplicaSet memelihara jumlah Pod#

Inti kerja ReplicaSet adalah sebuah perbandingan yang diulang terus-menerus. Objek ini menyimpan jumlah Pod yang diinginkan pada bidang spec.replicas, menghitung Pod yang benar-benar berjalan, lalu mengoreksi selisihnya. Perhitungan dan koreksi tersebut dikerjakan oleh controller, yakni komponen di control plane yang mengamati keadaan objek melalui API server dan menggerakkannya menuju keadaan yang dideklarasikan. Siklus pembandingan ini disebut rekonsiliasi, dan hasil akhirnya selalu sama, yaitu jumlah Pod aktual mendekati jumlah yang diinginkan.

Cara paling umum membuat ReplicaSet adalah menulis manifest lalu menerapkannya dengan kubectl. Manifest berikut mendeklarasikan tiga replika untuk aplikasi catatan dengan image nginx sebagai isinya:

yaml replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: catatan
  labels:
    app: catatan
spec:
  replicas: 3
  selector:
    matchLabels:
      app: catatan
  template:
    metadata:
      labels:
        app: catatan
    spec:
      containers:
        - name: catatan
          image: nginx:1.26
          ports:
            - containerPort: 80

Tiga bagian manifest menentukan perilakunya. Bidang spec.replicas menyatakan jumlah Pod yang dipelihara, sedangkan spec.selector.matchLabels menentukan Pod mana yang dihitung ke dalam ReplicaSet ini. Bidang spec.template memuat definisi Pod yang akan dibuat, lengkap dengan label dan container-nya. API server menolak manifest apabila label pada template tidak cocok dengan selector, karena kombinasi keduanya yang membuat Pod dapat ditemukan kembali.

bash
# tidak-dijalankan
# terapkan manifest ReplicaSet ke kluster
kubectl apply -f replicaset.yaml

# lihat keadaan rekonsiliasi pada ReplicaSet
kubectl get rs
text Contoh keluaran
replicaset.apps/catatan created
NAME      DESIRED   CURRENT   READY   AGE
catatan   3         3         3       8s

Perintah kubectl get rs menampilkan kondisi rekonsiliasi dalam tiga kolom. Kolom DESIRED adalah jumlah yang diinginkan, CURRENT adalah jumlah Pod yang sudah dibuat, dan READY adalah jumlah yang siap melayani. Selama CURRENT berbeda dengan DESIRED, proses koreksi masih berlangsung, sedangkan nilai yang sama pada ketiga kolom menandakan keadaan stabil.

Rekonsiliasi dalam praktik#

Selisih antara jumlah yang diinginkan dan jumlah aktual menentukan tindakan controller. Apabila Pod aktual lebih sedikit, ReplicaSet membuat Pod baru dari spec.template melalui API server. Apabila Pod aktual lebih banyak, ReplicaSet menghapus kelebihannya. Pod yang dipilih untuk dihapus mengikuti urutan preferensi internal, misalnya Pod yang belum terjadwal atau belum siap didahulukan, sehingga Pod yang sedang melayani cenderung dipertahankan.

Skrip Python berikut meniru perhitungan inti tersebut tanpa kluster. Jumlah yang diinginkan ditetapkan tiga, lalu keadaan kluster diuji dalam tiga kondisi yang berbeda:

python
DESIRED = 3  # jumlah pod yang diinginkan pada spec.replicas

def rekonsiliasi(aktual: int) -> str:
    """Hitung tindakan controller terhadap selisih pod."""
    selisih = DESIRED - aktual
    if selisih > 0:
        return f"buat {selisih} pod baru"
    if selisih < 0:
        return f"hapus {-selisih} pod berlebih"
    return "tidak ada tindakan"

for aktual in (5, 1, 3):
    print(f"aktual {aktual} pod -> {rekonsiliasi(aktual)}")
text Keluaran
aktual 5 pod -> hapus 2 pod berlebih
aktual 1 pod -> buat 2 pod baru
aktual 3 pod -> tidak ada tindakan

Keluaran di atas memperlihatkan pola yang selalu mengarah ke jumlah yang diinginkan. Keadaan dengan lima Pod menghasilkan dua penghapusan, sedangkan keadaan dengan satu Pod menghasilkan dua pembuatan. Nilai yang diinginkan tidak pernah disentuh oleh rekonsiliasi, karena keputusan tersebut hanya berubah melalui manifest atau perintah penskalaan dari pengguna.

Selector, pod-template-hash, dan kepemilikan Pod#

ReplicaSet tidak menyimpan daftar Pod yang dikelolanya, melainkan menemukannya kembali pada setiap siklus dengan selector, yaitu kriteria label yang harus dipenuhi Pod agar dihitung. Pod yang labelnya cocok tetapi belum memiliki pemilik akan diadopsi, dan kepemilikan yang sudah terbentuk dicatat pada bidang metadata.ownerReferences di dalam Pod. Dari catatan tersebut, API server mengetahui Pod mana yang harus dihapus ketika ReplicaSet-nya dihapus.

Satu masalah muncul apabila dua ReplicaSet menangkap Pod yang sama melalui selector yang tumpang tindih. Untuk mencegahnya, Deployment menambahkan label unik bernama pod-template-hash pada template Pod yang dibuatnya, lalu menyertakan label tersebut ke dalam selector ReplicaSet. Nilai hash dihitung dari isi template, sehingga dua template yang berbeda selalu menghasilkan label yang berbeda pula dan setiap ReplicaSet hanya menghitung Pod miliknya.

Simulasi berikut menguji pencocokan selector terhadap empat Pod yang keadaan pemiliknya berbeda:

python
SELECTOR = {"app": "catatan"}  # matchLabels pada spec.selector

def cocok(label: dict) -> bool:
    """Periksa apakah label pod memenuhi selector."""
    return all(label.get(k) == v for k, v in SELECTOR.items())

PODS = [
    {"nama": "catatan-7xk2p", "label": {"app": "catatan"}, "pemilik": None},
    {"nama": "catatan-9d4fq", "label": {"app": "catatan"}, "pemilik": None},
    {"nama": "catatan-lama-0", "label": {"app": "catatan"}, "pemilik": "Job/arsip"},
    {"nama": "web-5ghrc", "label": {"app": "web"}, "pemilik": None},
]

for pod in PODS:
    if cocok(pod["label"]) and pod["pemilik"] is None:
        status = "diadopsi masuk ReplicaSet"
    elif cocok(pod["label"]):
        status = "selector cocok, tetapi sudah dimiliki controller lain"
    else:
        status = "selector tidak cocok, dibiarkan"
    print(f"{pod['nama']}: {status}")
text Keluaran
catatan-7xk2p: diadopsi masuk ReplicaSet
catatan-9d4fq: diadopsi masuk ReplicaSet
catatan-lama-0: selector cocok, tetapi sudah dimiliki controller lain
web-5ghrc: selector tidak cocok, dibiarkan

Dua Pod tanpa pemilik diadopsi karena labelnya cocok, Pod milik controller lain dibiarkan meskipun labelnya sama, dan Pod dengan label berbeda tidak tersentuh. Pod yang diadopsi kemudian diperlakukan sama seperti Pod yang dibuat sendiri, mulai dari penggantian saat mati hingga penghapusan saat jumlah dikurangi. Perilaku ini menjelaskan mengapa Pod yang dibuat manual dengan label yang kebetulan sama dapat tiba-tiba terhitung ke dalam ReplicaSet dan menjadi tanggung jawabnya.

Mengapa Deployment dianjurkan#

ReplicaSet yang berdiri sendiri hanya menjamin jumlah Pod, bukan cara Pod diperbarui. Mengganti versi image langsung pada ReplicaSet menuntut penghapusan Pod satu per satu secara manual, dan kegagalan di tengah proses meninggalkan kluster dalam keadaan campuran yang tidak tercatat. Tidak ada objek yang menyimpan template sebelumnya, sehingga kembali ke versi lama berarti menulis ulang manifest dari awal.

Deployment menyelesaikan masalah tersebut dengan membuat dan mengelola ReplicaSet. Perubahan template menghasilkan ReplicaSet baru, sementara ReplicaSet lama dipertahankan dengan jumlah nol sebagai catatan revisi. Mekanisme peralihan antar ReplicaSet inilah yang menghasilkan rollout bertahap dan kemampuan rollback, dan keduanya diproses Deployment secara otomatis. Panduan resmi Kubernetes menyatakan Deployment sebagai cara yang disarankan untuk menjalankan beban kerja yang tidak berhenti, sedangkan penggunaan langsung ReplicaSet dianggap kasus lanjutan.

Ringkasan#

  • ReplicaSet membandingkan jumlah Pod yang diinginkan dengan jumlah aktual pada setiap siklus rekonsiliasi, lalu membuat atau menghapus Pod untuk menutup selisihnya.
  • Pod ditemukan kembali melalui selector, sedangkan kepemilikan dicatat pada metadata.ownerReferences dan Pod tanpa pemilik yang labelnya cocok diadopsi.
  • Label pod-template-hash memisahkan Pod milik tiap ReplicaSet agar selector tidak pernah tumpang tindih.
  • Deployment dianjurkan untuk mengelola ReplicaSet karena menyediakan rollout bertahap, riwayat revisi, dan rollback.

Referensi#

  • ReplicaSet — Kubernetes — Dokumentasi konsep ReplicaSet, termasuk contoh manifest dan penjelasan kepemilikan Pod.
  • Pod — Kubernetes — Dokumentasi konsep Pod yang menjadi objek yang direplikasi oleh ReplicaSet.