Volume

Volume efemeral pada Pod, mulai dari emptyDir sampai mounting berkas ke dalam container.

Daftar isi

Volume adalah direktori yang dibagikan di antara container sebuah Pod dan disangga oleh jenis penyimpanan tertentu, sehingga data yang ditulis ke sana tidak hilang setiap kali container dihidupkan ulang. Topik ini membahas cara volume dideklarasikan pada Pod, volume efemeral emptyDir, mounting satu berkas dengan subPath, serta daftar jenis volume yang paling umum. Manifest Pod pada akhir topik dibaca ulang secara terprogram untuk memeriksa peta volume ke setiap container.

Volume sebagai direktori pada Pod#

Filesystem container bersifat sementara dan menempel pada umur containernya, sehingga berkas yang ditulis di dalamnya hilang saat container dihidupkan ulang. Volume mengatasi hal itu dengan hidup pada tingkat Pod, sedikit lebih lama dari container di dalamnya. Deklarasinya berada pada bidang volumes di tingkat Pod, dan setiap container memilih bagian mana yang di-mount melalui volumeMounts miliknya. Satu volume dapat di-mount oleh beberapa container sekaligus pada jalur yang sama maupun berbeda, dan mekanisme inilah yang menjadi dasar pola sidecar, yaitu container penolong yang bekerja bersama container utama melalui berkas bersama. Namun, volume biasa tidak bertahan lintas Pod, karena seluruh direktorinya dihapus ketika Pod itu sendiri dihapus.

Volume dengan nama yang sama dapat di-mount oleh beberapa container dengan mountPath yang berbeda, dan setiap container melihat direktori yang sama persis di belakangnya. Bidang readOnly: true menurunkan risiko kesalahan, karena penulisan yang tidak sengaja ke volume baca-saja langsung ditolak oleh container runtime. Pembagian volumeMounts per container inilah yang memungkinkan dua container pada satu Pod menjalankan tugas yang saling melengkapi tanpa berbagi seluruh filesystem.

emptyDir#

Jenis volume paling dasar adalah emptyDir, yaitu direktori kosong yang dibuat saat Pod ditempatkan pada sebuah Node dan dihapus saat Pod berpindah atau dihapus. Volume ini cocok untuk cache, berkas sementara, dan titik tukar data antar-container. Manifest berikut membagi satu emptyDir bernama cache ke dua container sekaligus:

yaml pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: catatan
spec:
  containers:
    - name: aplikasi
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: cache
          mountPath: /var/cache/catatan
        - name: konfigurasi
          mountPath: /etc/catatan/pengaturan.properties
          subPath: pengaturan.properties
          readOnly: true
    - name: pengumpul
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: cache
          mountPath: /var/cache/catatan
  volumes:
    - name: cache
      emptyDir:
        sizeLimit: 64Mi
    - name: konfigurasi
      configMap:
        name: catatan-config
        items:
          - key: pengaturan.properties
            path: pengaturan.properties

Kedua container melihat isi yang persis sama pada /var/cache/catatan, karena keduanya menunjuk volume yang sama. Bidang sizeLimit membatasi pertumbuhan direktorinya sebesar 64 MiB, dan penulisan yang melewati batas tersebut menggagalkan penulisan berikutnya. Volume kedua bertipe configMap memperlihatkan sisi lain dari keluarga volume, yaitu volume yang isinya berasal dari objek lain dan bukan dari penulisan container. Berbagi isi volume dapat diverifikasi langsung pada kluster:

bash
# tidak-dijalankan
# tulis berkas ke volume dari container aplikasi
kubectl exec catatan -c aplikasi -- sh -c 'echo draf-1 > /var/cache/catatan/draf.txt'

# baca berkas yang sama dari container pengumpul
kubectl exec catatan -c pengumpul -- cat /var/cache/catatan/draf.txt
text Contoh keluaran
draf-1

Mounting satu berkas dengan subPath#

Secara default, volume yang di-mount menutupi seluruh direktori tujuan, sehingga berkas lama pada mountPath tidak lagi terlihat. Bidang subPath mengatasi masalah ini dengan me-mount satu entri di dalam volume, misalnya satu berkas, ke satu jalur tujuan. Pada manifest sebelumnya, berkas pengaturan.properties dari volume konfigurasi ditempatkan tepat pada /etc/catatan/pengaturan.properties, sehingga berkas lain di direktori /etc/catatan milik image tetap utuh.

Pola ini berguna saat aplikasi menuntut berkas konfigurasi pada jalur tetap, tetapi berkas tersebut harus berasal dari ConfigMap atau Secret. Perlu dicatat bahwa mount dengan subPath bersifat statis, dan sifat tersebut berdampak pada pembaruan konfigurasi:

Jenis volume yang umum#

Kubernetes menyediakan banyak jenis volume, dan sebagian besar penggunaan sehari-hari berada pada beberapa jenis berikut:

Jenis volumeSumber isinyaPeruntukan yang lazim
emptyDirdirektori kosong pada Nodecache dan berkas sementara antar-container
hostPathberkas atau direktori Nodealat diagnostik per Node dan lab belajar
configMapnilai sebuah ConfigMapberkas konfigurasi aplikasi
secretnilai sebuah Secretkredensial dan token
persistentVolumeClaimPersistentVolume yang terikatdata yang harus bertahan
projectedgabungan beberapa sumbermenggabungkan secret, configMap, dan token dalam satu mount
csidriver CSIpenyimpanan eksternal melalui antarmuka standar

Jenis hostPath menuntut kehati-hatian karena isinya bergantung pada Node tempat Pod dijadwalkan, sehingga Pod yang pindah Node menjumpai direktori yang berbeda. Jenis persistentVolumeClaim menjadi jembatan ke penyimpanan yang bertahan dan dibahas pada topik PV dan PVC.

Volume juga muncul secara tidak langsung pada setiap Pod. Kubernetes menambahkan volume internal berisi token ServiceAccount tanpa perlu dideklarasikan, dan mekanisme yang sama inilah yang membuat berkas di dalam /var/run/secrets/kubernetes.io/serviceaccount terbaca di setiap container. Mengetahui keberadaan volume bawaan ini menghindarkan kebingungan ketika daftar mount pada container tidak sepenuhnya cocok dengan manifest yang ditulis.

Membaca manifest volume dengan Python#

Peta volume ke container mudah keliru apabila nama volume pada volumeMounts tidak sama dengan nama pada volumes. Pod dengan nama yang tidak cocok menolak dimulai, dan penyebabnya hanya terlihat pada event Pod. Skrip berikut membaca pod-volume.yaml dari bundle menggunakan PyYAML dan mencetak setiap volume beserta container yang me-mountnya:

python
import yaml

# baca manifest pod dari bundle topik
with open("pod-volume.yaml") as f:
    pod = yaml.safe_load(f)

print(f"Pod {pod['metadata']['name']} mendeklarasikan {len(pod['spec']['volumes'])} volume:")
for volume in pod["spec"]["volumes"]:
    jenis = next(k for k in volume if k != "name")
    print(f"  {volume['name']} ({jenis})")
    for kontainer in pod["spec"]["containers"]:
        for mount in kontainer.get("volumeMounts", []):
            if mount["name"] == volume["name"]:
                if "subPath" in mount:
                    cara = f"subPath {mount['subPath']}"
                else:
                    cara = "direktori penuh"
                print(f"    di-mount {kontainer['name']} -> {mount['mountPath']} ({cara})")
text Keluaran
Pod catatan mendeklarasikan 2 volume:
  cache (emptyDir)
    di-mount aplikasi -> /var/cache/catatan (direktori penuh)
    di-mount pengumpul -> /var/cache/catatan (direktori penuh)
  konfigurasi (configMap)
    di-mount aplikasi -> /etc/catatan/pengaturan.properties (subPath pengaturan.properties)

Keluaran memperlihatkan volume cache di-mount oleh dua container pada jalur yang sama, sedangkan volume konfigurasi hanya di-mount satu container dengan subPath satu berkas. Pemeriksaan semacam ini menghemat satu putaran percobaan dan error pada kluster, karena kesalahan nama volume tertangkap sebelum manifest diaplikasikan.

Skrip dengan bentuk yang sama dapat dijadikan bagian dari pengujian otomatis sebelum manifest dikirim ke repositori. Apabila aturannya ditulis sebagai kode, kesepakatan penamaan volume antara container tidak lagi bergantung pada ketelitian pembacaan manual, dan penyimpangannya dilaporkan sebelum Pod sempat gagal berjalan.

Ringkasan#

  • Volume hidup pada tingkat Pod dan dapat di-mount oleh satu atau beberapa container, sehingga isinya bertahan terhadap hidup ulang container tetapi hilang bersama Pod.
  • emptyDir menyediakan direktori kosong efemeral yang sering digunakan sebagai cache dan titik tukar antar-container, dengan opsi medium: Memory yang bersangga tmpfs.
  • subPath me-mount satu berkas dari volume ke jalur tetap, dengan konsekuensi berkas tersebut tidak menerima pembaruan ConfigMap atau Secret.
  • Volume yang bertahan lintas Pod dibangun di atas persistentVolumeClaim, yang menghubungkan Pod ke penyimpanan nyata di kluster.

Referensi#

  • Volumes — Kubernetes — Dokumentasi konsep volume, mencakup emptyDir, subPath, dan daftar jenis volume yang didukung.