בדף הזה מופיעה סקירה כללית של Persistent Volumes (PVs), Persistent Volume Claims (PVCs) ו-Storage Classes ב-Google Kubernetes Engine (GKE). הוא מתמקד באחסון שמגובה על ידי דיסקים לאחסון מתמיד ב-Compute Engine.
תלמדו איך ליצור ולנהל אחסון מתמיד באשכולות GKE, ואיך לפתור בעיות שקשורות לאחסון מתמיד, כדי להבטיח אבטחת מידע, זמינות גבוהה וביצועים אופטימליים.
הדף הזה מיועד למומחי אחסון שיוצרים ומקצים אחסון, ומגדירים ומנהלים את אבטחת הנתונים, ההגנה עליהם והגישה וההרשאות. כדי לקבל מידע נוסף על תפקידים נפוצים ועל משימות לדוגמה שאנחנו מתייחסים אליהן בGoogle Cloud תוכן, אפשר לעיין במאמר תפקידים נפוצים של משתמשי GKE ומשימות.
PersistentVolumes
משאבי PersistentVolume משמשים לניהול אחסון עמיד באשכול. ב-GKE, PersistentVolume מגובה בדרך כלל בדיסק מתמשך.
במקום זאת, אפשר להשתמש בפתרונות אחסון אחרים כמו NFS. Filestore הוא פתרון NFS ב-Google Cloud. כדי ללמוד איך להגדיר מכונת Filestore כפתרון NFS PV לאשכולות GKE, אפשר לעיין במאמר גישה למכונות Filestore באמצעות מנהל התקן Filestore CSI במסמכי Filestore.
מחזור החיים של PersistentVolume מנוהל על ידי Kubernetes. אפשר להקצות PersistentVolume באופן דינמי, כך שלא צריך ליצור ולמחוק את האחסון הבסיסי באופן ידני.
משאבי PersistentVolume הם משאבי אשכול שקיימים באופן עצמאי מPods.
המשמעות היא שהדיסק והנתונים שמיוצגים על ידי PersistentVolume ממשיכים להתקיים כשהאשכול משתנה וכשמחיקת ה-Pods מתבצעת ונוצרים מחדש. אפשר להקצות משאבי PersistentVolume באופן דינמי דרך PersistentVolumeClaims, או ליצור אותם באופן מפורש על ידי אדמין של אשכול.
מידע נוסף על משאבי PersistentVolume זמין במאמרי העזרה בנושא Persistent Volumes ב-Kubernetes ובהפניית API בנושא Persistent Volumes.
PersistentVolumeClaims
PersistentVolumeClaim היא בקשה לגישה למשאב PersistentVolume. אובייקטים של PersistentVolumeClaim מבקשים מידה ספציפית, מצב גישה וStorageClass עבור PersistentVolume. אם קיים PersistentVolume שעונה על הבקשה או שאפשר להקצות אותו, PersistentVolumeClaim משויך לPersistentVolume הזה.
Pods משתמשים ב-claims כנפחים. האשכול בודק את הדרישה כדי למצוא את נפח האחסון המצורף, ומטמיע את נפח האחסון הזה ב-Pod.
יתרון נוסף בשימוש ב-PersistentVolumes וב-PersistentVolumeClaims הוא הניידות. אתם יכולים להשתמש באותו מפרט של Pod בכמה אשכולות וסביבות, כי PersistentVolume הוא ממשק לאחסון הנתונים בפועל.
StorageClasses
הטמעות של נפחי אחסון, כמו מנהל ההתקן של Container Storage Interface (CSI) של דיסק לאחסון מתמיד ב-Compute Engine, מוגדרות באמצעות משאבי StorageClass.
GKE יוצר בשבילכם StorageClass כברירת מחדל, שמשתמש בסוג דיסק אחסון מתמיד מאוזן (ext4). ברירת המחדל StorageClass משמשת כש-PersistentVolumeClaim לא מציין StorageClassName. אתם יכולים להחליף את ברירת המחדל StorageClass שמופיעה כאן בערך משלכם. הוראות מפורטות מופיעות במאמר שינוי סוג האחסון שמוגדר כברירת מחדל.
אתם יכולים ליצור משאבי StorageClass משלכם כדי לתאר סוגים שונים של אחסון. לדוגמה, יכול להיות שהסיווגים ימופו לרמות של איכות השירות או למדיניות גיבוי. המושג הזה נקרא לפעמים 'פרופילים' במערכות אחסון אחרות.
אם אתם משתמשים באוסף צמתים עם Windows, אתם צריכים ליצור StorageClass ולציין StorageClassName ב-PersistentVolumeClaim כי סוג מערכת הקבצים שמוגדר כברירת מחדל (ext4) לא נתמך ב-Windows. אם אתם משתמשים בדיסק אחסון מתמיד (persistent disk) של Compute Engine, אתם צריכים להשתמש ב-NTFS כסוג אחסון הקבצים.
כשמגדירים StorageClass, צריך לציין ספק הקצאות.
ב-GKE, מומלץ להשתמש באחד מהספקים הבאים:
הקצאה דינמית של נפח אחסון מתמיד
ברוב המקרים, לא צריך להגדיר ישירות אובייקטים של PersistentVolume או ליצור דיסקים קשיחים ב-Compute Engine. במקום זאת, אתם יכולים ליצור PersistentVolumeClaim ו-Kubernetes יקצה לכם באופן אוטומטי דיסק אחסון מתמיד.
במניפסט הבא מתוארת בקשה לדיסק עם נפח אחסון של 30 גיביבייט (GiB), שניתן להרכיב אותו כקריאה וככתיבה על ידי צומת יחיד. היא גם יוצרת Pod שמשתמש ב-PersistentVolumeClaim כנפח.
# pvc-pod-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Gi
storageClassName: standard-rwo
---
kind: Pod
apiVersion: v1
metadata:
name: pod-demo
spec:
volumes:
- name: pvc-demo-vol
persistentVolumeClaim:
claimName: pvc-demo
containers:
- name: pod-demo
image: nginx
resources:
limits:
cpu: 10m
memory: 80Mi
requests:
cpu: 10m
memory: 80Mi
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pvc-demo-vol
כשיוצרים את האובייקט PersistentVolumeClaim הזה באמצעות kubectl apply -f
pvc-pod-demo.yaml, Kubernetes יוצר באופן דינמי אובייקט PersistentVolume תואם.
מכיוון שסוג האחסון standard-rwo משתמש במצב של צירוף נפח WaitForFirstConsumer, ה-PersistentVolume לא ייווצר עד שתתבצע הקצאה של Pod לצריכת הנפח.
בדוגמה הבאה מוצג PersistentVolume שנוצר.
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/provisioned-by: pd.csi.storage.gke.io
finalizers:
- kubernetes.io/pv-protection
- external-attacher/pd-csi-storage-gke-io
name: pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
uid: d52af557-edf5-4f96-8e89-42a3008209e6
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 30Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc-demo
namespace: default
uid: c9a44c07-cffa-4cd8-b92b-15bac9a9b984
csi:
driver: pd.csi.storage.gke.io
csi.storage.k8s.io/fstype: ext4
volumeAttributes:
storage.kubernetes.io/csiProvisionerIdentity: 1660085000920-8081-pd.csi.storage.gke.io
volumeHandle: projects/xxx/zones/us-central1-c/disks/pvc-c9a44c07-cffa-4cd8-b92b-15bac9a9b984
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: topology.gke.io/zone
operator: In
values:
- us-central1-c
persistentVolumeReclaimPolicy: Delete
storageClassName: standard-rwo
volumeMode: Filesystem
status:
phase: Bound
בהנחה שלא החלפתם את סוג האחסון standard-rwo, הנפח PersistentVolume מגובה בדיסק אחסון מתמיד חדש וריק של Compute Engine.
מחיקת אחסון מתמיד
במהלך הקצאה דינמית, אתם יכולים לקבוע אם האחסון המתמיד יימחק כש-PersistentVolumeClaim (PVC) יימחק. כדי לעשות זאת, מגדירים את השדה reclaimPolicy בהגדרות של StorageClass לערך Delete או Retain.
reclaimPolicy: Delete: זו מדיניות ברירת המחדל. כשמוחקים את ה-PVC, אובייקטPersistentVolume(PV) ודיסק האחסון המתמיד (persistent disk) הבסיסי (כמו דיסק קבוע ב-Compute Engine) נמחקים באופן אוטומטי. אפשר להשתמש במדיניות הזו לעומסי עבודה זמניים או לדרישות תאימות שבהן צריך לנקות את הנתונים אחרי השלמת העבודה.
reclaimPolicy: Retain: אם מגדירים את המדיניות הזו, ה-PV והדיסק הבסיסי לא נמחקים כשמוחקים את ה-PVC. הסטטוס של ה-PV משתנה לReleased. הנתונים נשמרים, אבל אי אפשר להשתמש בנפח האחסון הזה ב-PVC חדש עד שאדמין יפנה אותו באופן ידני.
ניהול ידני של נפחי נתונים שנשמרו
כש-PersistentVolume נמצא במצב Released, צריך להחליט באופן ידני מה לעשות עם הנתונים ועם הדיסק.
כדי למחוק את האחסון באופן סופי: צריך למחוק גם את משאב Kubernetes
PersistentVolumeוגם את הדיסק הבסיסי של Compute Engine.- מחיקת
PersistentVolume:bash kubectl delete pv <your-pv-name> - כדי למצוא את השם של הדיסק הבסיסי, מתארים את קובץ התצורה של ה-PV בפורמט YAML ומחפשים את
volumeHandleאו שדה דומה. - מחיקת הדיסק לאחסון מתמיד ב-Compute Engine:
bash gcloud compute disks delete <your-disk-name> --zone=<your-zone>
- מחיקת
כדי לעשות שימוש חוזר בנפח האחסון: השבתה של נפח אחסון עם סטטוס
Releasedלשימוש על ידי PVC אחר היא משימה מתקדמת שכוללת ניקוי ידני של נתוני הדיסק ועריכה של אובייקטPersistentVolumeכדי להפוך אותו שוב ל-Available. מידע נוסף על התהליך המפורט זמין במסמכי Kubernetes הרשמיים בנושא שחזור PersistentVolume.
כדי למנוע אובדן נתונים או לצמצם אותו, מומלץ גם להפעיל את הגיבוי ל-GKE ולתזמן גיבויים קבועים של אשכול GKE.
פתרון בעיות שקשורות למחיקה לא צפויה של דיסקים
אם אתם רואים שהדיסקים הקשיחים הבסיסיים נמחקים כשלא ציפיתם לכך, הסיבה הנפוצה ביותר היא שדה reclaimPolicy שמוגדר לערך Delete בהגדרת StorageClass שבה נעשה שימוש ב-PersistentVolumeClaim.
כדי לאבחן את הבעיה, צריך לבצע את השלבים הבאים:
בודקים את
StorageClassשל ה-PVC:bash kubectl get pvc <your-pvc-name> -o jsonpath='{.spec.storageClassName}'בודקים את השדה
reclaimPolicy:bash kubectl get sc <your-storageclass-name> -o yamlהתאמת המדיניות לכוונתכם:
- אם המדיניות היא
Deleteוהאפליקציה דורשת שהנתונים יישמרו, צריך לעדכן את האפליקציה כך שתשתמש בהגדרה שלStorageClassשקובעת את המדיניות כ-Retain. - אם המדיניות היא
Deleteוהאפליקציה שלכם היא זמנית או כפופה לכללי תאימות שמחייבים ניקוי נתונים, אז ההגדרה נכונה והיא פועלת כמצופה.
- אם המדיניות היא
מידע נוסף מופיע במאמרי העזרה של Kubernetes בנושא שחזור נפח אחסון.
ניהול אחסון מתמיד במהלך מחיקת אשכול
כשמ删除 אשכול GKE, GKE שומר משאבי PersistentVolume עם מדיניות השחזור Delete או Retain.
כדי להסיר משאבי PersistentVolume כשמוחקים אשכול, אפשר למחוק ידנית את מרחב השמות של משאבי PersistentVolume, וכך להפעיל מחיקה של אובייקטים של PersistentVolume עם מדיניות Delete.PersistentVolumeClaim
אפשר גם למחוק משאבים ספציפיים של PersistentVolumeClaim.
עם זאת, GKE לא ממתין עד שהפעולות האלה של המחיקה יושלמו לפני שהוא מתחיל למחוק את האשכול. לכן, אם מוחקים מרחב שמות ואז מוחקים מיד את האשכול, יכול להיות שמשאבי PersistentVolume עם מדיניות Delete לא יימחקו.
אחרי מחיקת האשכול, אפשר לראות את משאבי PersistentVolume שנותרו במסוף Google Cloud .
כדי לראות משאבים שלא נעשה בהם שימוש, כמו משאבי PersistentVolume שלא נעשה בהם שימוש, אתם יכולים לראות המלצות לגבי משאבים לא פעילים.
מצבי גישה
PersistentVolume תומך במצבי הגישה הבאים:
- ReadWriteOnce: אפשר לטעון את אמצעי האחסון כקריאה וככתיבה על ידי צומת יחיד.
- ReadOnlyMany: אפשר לטעון את אמצעי האחסון לקריאה בלבד על ידי הרבה צמתים.
- ReadWriteMany: אפשר לטעון את אמצעי האחסון כקריאה וכתיבה על ידי צמתים רבים.
משאבי
PersistentVolumeשמגובים על ידי דיסקים קשיחים קבועים של Compute Engine לא תומכים במצב הגישה הזה. - ReadWriteOncePod: אפשר לטעון את אמצעי האחסון כקריאה וככתיבה רק על ידי Pod אחד.
שימוש בדיסקים לאחסון מתמיד של Compute Engine כ-ReadOnlyMany
התרחיש הנפוץ ביותר לשימוש בדיסקים קבועים הוא ReadWriteOnce, והוא פועל כמצב הגישה שמוגדר כברירת מחדל ברוב האפליקציות. דיסקים מתמידים של Compute Engine תומכים גם במצב ReadOnlyMany, כך שאפליקציות רבות או עותקים רבים של אותה אפליקציה יכולים להשתמש באותו דיסק בו-זמנית. תרחיש שימוש לדוגמה הוא הצגת תוכן סטטי בכמה עותקים משוכפלים.
הוראות מפורטות במאמר בנושא שימוש בדיסקים לאחסון מתמיד עם כמה קוראים.
שימוש בדיסקים קיימים של אחסון מתמיד (persistent disks) כ-PersistentVolumes
משאבי PersistentVolume שמוקצים באופן דינמי ריקים כשהם נוצרים. אם יש לכם דיסק לאחסון מתמיד ב-Compute Engine עם נתונים, אתם יכולים להוסיף אותו לאשכול על ידי יצירה ידנית של משאב PersistentVolume מתאים. דיסק האחסון המתמיד צריך להיות באותו אזור כמו צמתי האשכול.
אפשר לעיין בדוגמה הזו ליצירת נפח אחסון מתמיד (Persistent Volume) שמגובה על ידי דיסק אחסון מתמיד (Persistent Disk) קיים.
פריסות לעומת StatefulSets
אפשר להשתמש בתבניות PersistentVolumeClaim או VolumeClaim בבקרי רמה גבוהה יותר, כמו Deployments או StatefulSets בהתאמה.
פריסות מיועדות לאפליקציות ללא מצב, ולכן כל הרפליקות של פריסה חולקות את אותו PersistentVolumeClaim. מכיוון שפודים של רפליקות שנוצרו זהים זה לזה, רק אמצעי אחסון עם מצב ReadWriteMany יכולים לפעול בהגדרה הזו.
גם פריסות עם רפליקה אחת באמצעות נפח ReadWriteOnce לא מומלצות. הסיבה לכך היא שאסטרטגיית הפריסה שמוגדרת כברירת מחדל יוצרת Pod שני לפני שהיא משביתה את ה-Pod הראשון בתהליך היצירה מחדש. יכול להיות שהפריסה תיכשל בגלל חסימה, כי אי אפשר להפעיל את ה-Pod השני כי עוצמת הקול של ReadWriteOnce כבר בשימוש, וה-Pod הראשון לא יוסר כי ה-Pod השני עדיין לא הופעל. במקום זאת, צריך להשתמש ב-StatefulSet עם נפחים מסוג ReadWriteOnce.
StatefulSets היא השיטה המומלצת לפריסת אפליקציות עם מצב (stateful) שנדרש להן נפח אחסון ייחודי לכל עותק. באמצעות StatefulSets עם תבניות PersistentVolumeClaim, אפשר להגדיל את מספר העותקים של האפליקציות באופן אוטומטי עם PersistentVolumeClaims ייחודיים שמשויכים לכל עותק של Pod.
דיסקים לאחסון מתמיד אזורי
דיסקים לאחסון מתמיד אזורי הם משאבים אזוריים שכוללים מספר אזורים. הם משכפלים נתונים בין שני אזורים באותו אזור, ואפשר להשתמש בהם באופן דומה לדיסקים לאחסון מתמיד אזורי. במקרה של הפסקה זמנית בשירות באזור מסוים, או אם לא ניתן לתזמן צמתים באשכול באזור מסוים, Kubernetes יכול להעביר את עומסי העבודה באמצעות הנפח לאזור אחר. אפשר להשתמש בדיסקים קשיחים אזוריים כדי ליצור פתרונות עם זמינות גבוהה לעומסי עבודה עם שמירת מצב ב-GKE. צריך לוודא שגם האזורים הראשיים וגם אזורי הגיבוי מוגדרים עם קיבולת משאבים מספקת להרצת עומס העבודה.
דיסקים אזוריים לאחסון מתמיד מסוג SSD הם אפשרות טובה לאפליקציות כמו מסדי נתונים שנדרשת בהן גם זמינות גבוהה וגם ביצועים גבוהים. לפרטים נוספים, ראו השוואה בין ביצועי אחסון של בלוקים.
בדומה לדיסקים לאחסון מתמיד של תחום, אפשר להקצות דינמית דיסקים לאחסון מתמיד אזורי לפי הצורך, או להקצות אותם מראש באופן ידני על ידי האדמין של אשכול המחשבים. כך מקצים דיסקים לאחסון מתמיד אזורי.
אזורים בדיסקים לאחסון מתמיד
דיסקים לאחסון מתמיד של תחום מוגדר הם משאבים של תחום מוגדר, ודיסקים לאחסון מתמיד אזורי הם משאבים של כמה תחומים. כשמוסיפים אחסון קבוע לאשכול, מערכת GKE מקצה את הדיסק לאזור יחיד, אלא אם מציינים אזור. מערכת GKE בוחרת את האזור באופן אקראי. אחרי שמקצים דיסק אחסון מתמיד, כל ה-Pods שמפנים לדיסק מתוזמנים לאותו אזור כמו דיסק האחסון המתמיד. עם זאת, ל-Pods או ל-Deployments אין יכולת מובנית לזהות את האזור של דיסקים קיימים לאחסון מתמיד. כדי לוודא שה-Pods מתוזמנים בצורה נכונה עם דיסקים קשיחים קיימים, צריך להשתמש בשיטות מיקום אזוריות כמו nodeAffinity במפרטים של ה-Pod או הפריסה כדי לטרגט את האזורים המתאימים.
מצב של צירוף נפח אחסון WaitForFirstConsumer
אם אתם מקצים באופן דינמי דיסק אחסון מתמיד (persistent disk) באשכול, מומלץ להגדיר את WaitForFirstConsumer
מצב הקישור של אמצעי האחסון
ב-StorageClass. ההגדרה הזו מורה ל-Kubernetes להקצות דיסק אחסון מתמיד באותו אזור שבו מתוזמן ה-Pod. הוא פועל בהתאם למגבלות התזמון של ה-Pod, כמו anti-affinity ובוררי צמתים. התכונה 'דחייה של קרבה' באזורים מאפשרת לפרוס את ה-Pods של StatefulSet באזורים שונים יחד עם הדיסקים התואמים.
בדוגמה הבאה מוצג StorageClass להקצאת דיסקים לאחסון מתמיד של תחום שמוגדרים בו WaitForFirstConsumer:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-balanced
csi.storage.k8s.io/fstype: ext4
volumeBindingMode: WaitForFirstConsumer
דוגמה לשימוש בדיסקים לאחסון מתמיד אזורי מופיעה במאמר בנושא הקצאת דיסקים לאחסון מתמיד אזורי.
המאמרים הבאים
- מידע על StatefulSets, שיטה מומלצת לפריסת אפליקציות עם שמירת מצב.
- איך פורסים אפליקציה עם שמירת מצב באמצעות StatefulSet
- איך משתמשים בדיסקים לאחסון מתמיד באשכול
- איך יוצרים דיסק שאפשר לקרוא ממנו מכמה צמתים
- איך יוצרים דיסקים של אחסון מתמיד (persistent disks) שמגובים על ידי SSD
- איך מקצים דיסקים קשיחים אזוריים קבועים