Pengikatan lambat penyimpanan dinamis memungkinkan Anda menyuntikkan volume agen Filestore langsung ke pod Sandbox Agen Google Kubernetes Engine (GKE) yang sedang berjalan dan telah dipanaskan sebelumnya saat klaim. Dengan melewati siklus proses pemasangan volume Kubernetes standar, pengikatan lambat dinamis mencapai latensi pemasangan penyimpanan di bawah 100 md tanpa memerlukan mulai ulang pod.
Arsitektur ini memungkinkan platform agen berlatensi rendah dan kepadatan tinggi untuk:
- Menghilangkan cold start pod dan penundaan inisialisasi container.
- Melampirkan dan melepaskan ruang kerja persisten secara dinamis sesuai permintaan.
- Menjeda atau membuat sesi agen yang tidak aktif menjadi hibernasi dan melanjutkannya di pod sandbox yang sudah dipanaskan sebelumnya dan tersedia sambil mempertahankan status sistem file.
Sebelum memulai
- Selesaikan penyiapan awal di Menyiapkan lingkungan GKE untuk volume agen Filestore.
- Verifikasi bahwa cluster GKE Anda menjalankan versi
1.36.0-gke.3302001atau yang lebih baru. Versi ini mendukung anotasiforce-sharedyang diperlukan untuk propagasi pemasanganemptyDirgVisor. - Verifikasi bahwa
volume-pool-scStorageClassAnda menentukanvolumeBindingMode: ImmediatedanreclaimPolicy: Delete.
Ringkasan arsitektur
Arsitektur late-binding terdiri dari empat komponen:
- Orkestrator platform atau pengontrol kustom: Layanan bidang kontrol atau pengontrol Kubernetes yang mengelola siklus proses sesi. Operator ini memantau peristiwa
SandboxClaim, menyelesaikan metadata volume tenant, memanggil API daemon node penyimpanan untuk mengikat atau melepaskan penyimpanan, dan mengelola finalizer penghapusan. - Daemon node penyimpanan:
DaemonSetdengan hak istimewa yang berjalan di setiap node gVisor yang mengekspos API pemasangan. SandboxTemplatedenganforce-shared: Template pod sandbox gVisor yang memungkinkan propagasi pemasangan host secara dinamis ke dalam container sandbox gVisor.SandboxWarmPool: Kumpulan pod sandbox yang sudah di-warm up dan berjalan, siap menerima permintaan pemasangan secara instan setelah diklaim.
Men-deploy daemon node penyimpanan
Buat manifes bernama storage-node-daemon.yaml yang berisi
DaemonSet istimewa:
Terapkan manifes:
kubectl apply -f storage-node-daemon.yaml
Deploy SandboxTemplate dan SandboxWarmPool
Buat manifes bernama sandbox-latebind.yaml yang berisi template dan
warm pool:
Terapkan manifes:
kubectl apply -f sandbox-latebind.yaml
Mengklaim sandbox dan mengikat penyimpanan secara dinamis
Buat manifes klaim bernama
late-bind-claim.yamlyang menyertakan finalizer penghapusan (agent.sandbox/storage-cleanup):apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxClaim metadata: name: late-bind-session-1 namespace: default finalizers: - agent.sandbox/storage-cleanup spec: sandboxTemplateRef: name: late-bind-templateTerapkan klaim:
kubectl apply -f late-bind-claim.yaml
Sediakan volume secara dinamis menggunakan manifes PVC bernama
agent-volume-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: session-1-pvc namespace: default spec: accessModes: [ReadWriteMany] storageClassName: volume-pool-sc resources: requests: storage: 1GiTerapkan PVC:
kubectl apply -f agent-volume-pvc.yaml
Ambil detail ekspor PV pendukung, node, dan UID pod yang ditetapkan:
POD_NAME=$(kubectl get pods \ -l extensions.agents.x-k8s.io/claimed-by=late-bind-session-1 \ -o jsonpath='{.items[0].metadata.name}') POD_UID=$(kubectl get pod "${POD_NAME}" -o jsonpath='{.metadata.uid}') NODE_NAME=$(kubectl get pod "${POD_NAME}" -o jsonpath='{.spec.nodeName}') PV_NAME=$(kubectl get pvc session-1-pvc -o jsonpath='{.spec.volumeName}') NFS_IP=$(kubectl get pv "${PV_NAME}" \ -o jsonpath='{.spec.csi.volumeAttributes.ip}') NFS_PATH="/$(kubectl get pv "${PV_NAME}" \ -o jsonpath='{.spec.csi.volumeAttributes.volume}')"Kirim sinyal pemasangan ke daemon node di host pod:
DAEMON_POD=$(kubectl get pods -l app=storage-node-daemon \ --field-selector spec.nodeName="${NODE_NAME}" \ -o jsonpath='{.items[0].metadata.name}') kubectl exec "${DAEMON_POD}" -c daemon -- python3 -c " import urllib.request, json payload = json.dumps({ 'action': 'bind_nfs', 'pod_uid': '${POD_UID}', 'volume_name': 'workspace-volume', 'sub_dir': 'user_data', 'nfs_server': '${NFS_IP}', 'nfs_path': '${NFS_PATH}' }).encode() req = urllib.request.Request( 'http://localhost:9090', data=payload, headers={'Content-Type': 'application/json'}) print(urllib.request.urlopen(req).read().decode()) "Terapkan finalizer penghapusan ke pod yang diklaim untuk mencegah pembersihan prematur saat pemasangan host aktif:
kubectl patch pod "${POD_NAME}" --type=merge \ -p '{"metadata":{"finalizers":["agent.sandbox/storage-cleanup"]}}'Verifikasi pemasangan volume di dalam pod yang sedang berjalan:
kubectl logs "${POD_NAME}" -c agentOutput mengonfirmasi bahwa volume berhasil dipasang:
Waiting for late-bind signal... Filestore volume mounted successfully! drwxr-xr-x 2 1000 1000 4096 ... user_data
Menjeda dan melanjutkan sesi
Saat sesi agen berakhir atau memasuki hibernasi, orkestrator Anda harus melepas penyimpanan host sebelum mengizinkan Kubernetes menghentikan atau mendaur ulang pod.
Mulai penghapusan
SandboxClaimdi latar belakang. Karena finalizer, Kubernetes menandai klaim untuk dihapus, tetapi menghentikan penghentian pod:kubectl delete sandboxclaim late-bind-session-1 --wait=false
Lepaskan pemasangan berbagi NFS di node host:
kubectl exec "${DAEMON_POD}" -c daemon -- python3 -c " import urllib.request, json payload = json.dumps({ 'action': 'unbind', 'pod_uid': '${POD_UID}', 'volume_name': 'workspace-volume', 'sub_dir': 'user_data' }).encode() req = urllib.request.Request( 'http://localhost:9090', data=payload, headers={'Content-Type': 'application/json'}) print(urllib.request.urlopen(req).read().decode()) "Hapus finalizer dari
SandboxClaimdan pod untuk menyelesaikan penghentian:kubectl patch sandboxclaim late-bind-session-1 --type=merge \ -p '{"metadata":{"finalizers":[]}}' kubectl patch pod "${POD_NAME}" --type=merge \ -p '{"metadata":{"finalizers":[]}}'
Untuk melanjutkan sesi nanti, klaim pod yang telah dipanaskan sebelumnya dan kirim permintaan pengikatan menggunakan PVC yang ada (session-1-pvc). Pod sandbox baru akan langsung mendapatkan akses ke status ruang kerja yang dipertahankan.
Pertimbangan produksi dan desain pengontrol kustom
Perintah manual dalam dokumen ini menunjukkan mekanisme tingkat rendah dari pengikatan terlambat dinamis. Untuk menjalankan arsitektur ini secara andal dalam produksi, Anda harus mengembangkan pengontrol Kubernetes kustom atau orkestrator platform yang disesuaikan dengan siklus proses sesi aplikasi Anda.
Saat mendesain pengontrol produksi dan daemon node, terapkan pola arsitektur berikut:
Mengotomatiskan siklus proses rekonsiliasi dan finalizer
Karena daemon node penyimpanan melakukan pemasangan tingkat host di luar pengelolaan siklus proses Antarmuka Penyimpanan Container (CSI) Kubernetes standar, Kubelet tidak mengetahui pemasangan aktif di dalam emptyDir pod. Jika pod dihapus saat
pemasangan aktif, Kubelet gagal menghapus direktori emptyDir dan memunculkan
error Device or resource busy, sehingga pod tetap berada dalam status Terminating.
Pengontrol kustom Anda harus mengotomatiskan mesin status yang ketat menggunakan finalizer
(seperti agent.sandbox/storage-cleanup):
- Pembuatan dan pengaitan klaim:
- Lampirkan finalizer statis ke setiap
SandboxClaimsaat pembuatan. - Pantau Kubernetes API untuk mengetahui update status
SandboxClaim. Saat klaim terikat ke pod kumpulan data hangat, ekstrak atribut volume Filestore pendukung,pod_uid, dannodeNameyang ditetapkan. - Kirim permintaan
bindyang diautentikasi ke daemon node penyimpanan yang berjalan di node target. - Segera patch objek
Podyang sedang berjalan untuk menambahkan finalizer dinamis. Karena spesifikasiSandboxTemplatetidak mendukung finalizer pod statis, patching pod secara dinamis diperlukan untuk melindungi pod selama peristiwa pengurasan node atau penjadwalan ulang saat pod dikeluarkan, tetapiSandboxClaimtetap aktif.
- Lampirkan finalizer statis ke setiap
- Penanganan penghentian dan pengusiran yang benar:
- Pantau
deletionTimestampdi resourceSandboxClaimdanPod. - Saat penghapusan atau pengusiran terdeteksi, panggil endpoint
unbinddaemon node untuk melepas direktori host dengan benar (umount -l). - Pastikan pelepasan berhasil dan semua penulisan yang tertunda telah
dibersihkan sebelum menambal
PoddanSandboxClaimuntuk menghapus finalizer-nya. Hal ini dapat membantu Anda melakukan penonaktifan yang bersih di seluruh penghapusan klaim yang benar, upgrade node GKE, penghentian sementara Spot VM, dan penghentian karena kehabisan memori (OOM).
- Pantau
Mengamankan dan memperkuat daemon node penyimpanan
- Ganti
kubectl execdengan API yang diautentikasi: Dalam produksi, jangan gunakankubectl execatau ikat daemon kelocalhost. Konfigurasi daemon node penyimpanan untuk mengekspos endpoint gRPC atau HTTPS khusus melalui jaringan cluster yang diamankan dengan autentikasi TLS bersama (mTLS) atau token KubernetesServiceAccount. - Mengisolasi namespace daemon dan akses jaringan: Deploy
storage-node-daemonDaemonSetdengan hak istimewa di namespace administratif yang dibatasi (misalnya,sandbox-storage-system), bukan di namespacedefaultatau tenant. Terapkan aturanNetworkPolicyKubernetes yang mengizinkan ingress ke API daemon secara eksklusif dari pod pengontrol kustom Anda dan memblokir semua traffic dari pod agen yang di-sandbox. - Gunakan image container yang telah disimulasikan: Hindari penginstalan paket seperti
nfs-commonsaat runtime diinitContainer. Gunakan image container bawaan yang tidak dapat diubah dengan semua utilitas pemasangan yang diperlukan telah diinstal sebelumnya untuk menghilangkan penundaan startup node dan dependensi repositori eksternal.
Menerapkan kuota penyimpanan dan isolasi multi-tenant
- Memantau penggunaan penyimpanan per agen: Saat Anda memasang-mengikat subdirectory secara dinamis dari volume Filestore
ReadWriteMany(RWX) bersama keemptyDir, setelanemptyDir.sizeLimitKubernetes standar tidak dapat menerapkan kuota penyimpanan per agen di jalur NFS yang di-mount. Untuk mencegah satu agen yang tidak terkendali menghabiskan volume bersama dan menyebabkan penolakan layanan (DoS), terapkan pemantauan kuota direktori di orkestrator Anda atau sediakan volume khusus menggunakan kumpulan volume. - Menyesuaikan payload pemasangan untuk berbagai mode akses ruang kerja: Pengontrol
Anda dapat mendukung beberapa topologi penyimpanan agen dengan memvariasikan
parameter yang dikirim ke daemon node:
- Ruang kerja pribadi yang terisolasi: Mengikat subdirektori tenant unik atau PVC khusus ke satu pod sandbox dengan izin baca-tulis.
- Ruang kerja kolaboratif: Secara bersamaan mengikat subdirektori RWX bersama yang sama di beberapa pod agen yang berkoordinasi untuk berbagi file secara real time.
- Ruang kerja percabangan eksplorasi: Pasang direktori template dasar sebagai hanya baca (
ro) sehingga agen dapat membaca aset bersama tanpa mengubah salinan master, sekaligus merutekan penulisan baru ke jalur sementara yang dapat ditulis atau direktori salin saat dipulihkan yang terpisah.
Mengoordinasikan snapshot point-in-time dan pembersihan
- Mencapai keheningan penulisan sebelum snapshot: Untuk mengambil snapshot ruang kerja yang konsisten pada satu titik waktu tanpa merusak data, orkestrator Anda harus menjeda penulisan aktif dengan memulai alur kerja pelepasan (atau mengosongkan buffer sistem file) sebelum mengarsipkan direktori ruang kerja atau memicu snapshot Filestore.
- Mengotomatiskan penghapusan penyediaan tenant: Saat sesi pengguna atau ruang kerja berakhir secara permanen, pastikan pengontrol Anda terlebih dahulu membatalkan pengikatan semua pemasangan aktif di semua node sebelum menjalankan tugas latar belakang asinkron untuk menghapus direktori persisten tenant dari volume pendukung.
Untuk mengetahui implementasi referensi lengkap yang menunjukkan pengelolaan finalizer dinamis, isolasi multi-tenant, dan alur kerja pemulihan snapshot, lihat contoh penyimpanan dengan binding lambat GKE Sandbox di GitHub.
Langkah berikutnya
- Pelajari integrasi Sandbox Agen statis.
- Deploy workload GKE yang dikelola sendiri.
- Pelajari cara membuat dan mengelola kumpulan volume.