במסמך הזה מפורטות דוגמאות להטמעה של ניהול אחסון בארגזי חול של סוכנים, בהתאם לצרכים של מחזור החיים של נתוני הסוכנים.
בהתאם לצרכים של מחזור החיים של הנתונים של הסוכנים, בוחרים אחת מההגדרות הבאות:
מידע נוסף על בחירת פתרון אחסון זמין במאמר בחירת אחסון לעומסי עבודה של סוכני AI.
במסמך הבא נעשה שימוש ב-dynamic-rwo StorageClass לצורך בחירה אוטומטית של סוג הדיסק כדי להקצות דיסקים שתואמים לסוגי המכונות של הצמתים שבהם מתוזמנים פודים של Agent Sandbox. כדי לוודא ש-GKE יקצה נפחי אחסון Hyperdisk Balanced לאחסון של הסוכנים, צריך לתזמן את ארגזי החול של הסוכנים בצמתים של משפחות מכונות תואמות, כמו N4. אחרת, GKE יחזור ל-pd-balanced.
במסמך הזה מוטמע מצב הגישה לנתונים Private Isolated Workspace באמצעות גישת ReadWriteOnce (RWO). במצב הזה, סוכן מופעל עם ספריית אחסון פרטית ומבודדת, שיש לו גישת קריאה וכתיבה בלעדית אליה.
אלא אם צוין אחרת, הטמעות ההפניה במסמך הזה משתמשות ביצירה ישירה של ארגז חול, שמתאימה לסוכנים שסובלים חביון הפעלה של כמה שניות. כדי להשיג זמן אחזור של פחות משנייה להפעלה של סביבות עבודה עם שמירת מצב או שחזור לנקודת זמן מסוימת, צריך להשתמש ב-GKE Agent Sandbox Warm Pools. כדי לקשר אחסון ל-Pod של מאגר חם שנוצר, צריך סקריפטים בהתאמה אישית ו-DaemonSet עם הרשאות. דוגמה להטמעה אפשר לראות בדוגמה הזו ב-GitHub.
מצבי גישה חלופיים
כדי לתמוך במצבי גישה חלופיים, אפשר לשנות את ההגדרות של עוצמת הקול ושל הצילום:
- סביבת עבודה שיתופית: משנים את
accessModesל-ReadWriteManyומשתמשים ב-StorageClass עם יכולת RWX, כמו Filestore Multishares (Enterprise) (enterprise-multishare-rwx). - סביבת עבודה של הסתעפות לניתוח נתונים: טוענים את תיקיית התבניות במצב קריאה בלבד ומספקים פנקס טיוטה נפרד עם הרשאת כתיבה.
בתבנית הבסיסית, צריך להשתמש באמצעי אחסון שתומך בכמה קבצים מצורפים לקריאה בלבד, כמו Hyperdisk ML עם מצב גישה
ReadOnlyMany(ROX) או Filestore Multishares עם מצב גישה RWX.
לפני שמתחילים
מפעילים את ארגז החול של הסוכן באשכול.
הגדרת סביבת עבודה עם שמירת מצב
אפשר להשתמש בתבנית הזו כדי לשמור את המצב העדכני של קבצי הסוכן. התכונה הזו שימושית כשצריך לשמור את המצב של הסוכן כשמשהים או מסיימים את הסשן שלו (ארגז החול של הסוכן נמחק), ולשחזר את הנתונים מהמצב האחרון כשהסשן של הסוכן מופעל (ארגז החול של הסוכן נוצר מחדש).
ההטמעה לדוגמה בקטע הזה משתמשת ביצירה ישירה של ארגז חול, והיא מתאימה לסוכנים שסובלים חביון הפעלה של כמה שניות.
הגישה הזו משתמשת במשאבי PersistentVolumeClaim (PVC) רגילים של GKE כדי לקשר בין ארגז חול לבין PVC קיים שמכיל את הנתונים של המשתמש.
התבנית של סביבת עבודה עם שמירת מצב פועלת לפי רצף האירועים הבא:
- הקצאת משאבים: האדמין או הכלי לניהול תהליכים מקצים באופן ידני PVC פרטי לכל סשן של סוכן באמצעות מזהה דטרמיניסטי (לדוגמה,
pvc-agent-1). - הפניה: במשאב ארגז החול, משתמשים בשדה
persistentVolumeClaimבתוך הבלוקvolumesכדי לציין אתclaimNameהמדויק של נפח האחסון הקיים. - זמן האחזור: כשיוצרים את ארגז החול, מערכת GKE צריכה לצרף באופן דינמי את דיסק Compute Engine למכונת ה-VM של הצומת, מה שגורם לעיכוב סטנדרטי של כמה שניות.
- עקביות: בסיום הסשן (מחיקת ארגז החול), GKE מנתק את הדיסק אבל לא מוחק את ה-PVC, וכך מבטיח שהמצב האחרון יישמר לסשן הבא.
כדי להגדיר סביבת עבודה עם שמירת מצב ששומרת נתונים בין סשנים, צריך לבצע את השלבים שמתוארים בקטעי המשנה הבאים.
הקצאת נפח אחסון קבוע (PVC) בסביבת עבודה
יוצרים בקשה פרטית ל-PersistentVolume (PVC) שמשתמשת במזהה דטרמיניסטי, כמו pvc-agent-1.
שומרים את קובץ המניפסט הבא בשם
pvc-agent-1.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-agent-1 # Derived directly from the deterministic assignment ID namespace: default spec: accessModes: - ReadWriteOnce storageClassName: dynamic-rwo # Selects disk type compatible with the node machine family resources: requests: storage: 10Giהחלת המניפסט:
kubectl apply -f pvc-agent-1.yaml
מכיוון שסוג האחסון משתמש בקישור דינמי של נפח האחסון, הדיסק עדיין לא מצורף לאף צומת. הוא נשאר במצב Pending עד שמתבצע תזמון של Pod שמבקש אותו.
פריסת ארגז החול של הסוכן
מבצעים פריסה של המשאב המותאם אישית של ארגז החול, עם הפניה ל-PVC הדטרמיניסטי.
שומרים את קובץ המניפסט הבא בשם
sandbox-agent-1.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-agent-1 # Traceable sandbox name namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor # Required automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace-disk mountPath: /workspace # Mounts the private disk into the container resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace-disk persistentVolumeClaim: claimName: pvc-agent-1 # Binds this specific Sandbox to Agent 1's PVC restartPolicy: OnFailureהחלת המניפסט:
kubectl apply -f sandbox-agent-1.yaml
GKE מאמת את קיבולת הצומת ומצרף את הדיסק, והתהליך הזה נמשך כמה שניות. המאגר עובר אתחול בתוך ליבת gVisor של מרחב משתמש.
כתיבת נתונים מהסוכן
כדי לדמות סוכן AI פעיל שמבצע שינויים בקבצים בסביבת העבודה שלו, צריך לכתוב קובץ טקסט לדיסק המותקן.
# Set the active Pod name
POD_NAME=sandbox-agent-1
# Write a state file to the persistent directory
kubectl exec $POD_NAME -- sh -c "echo 'Workspace State Saved - Agent 1' > /workspace/modified_data.txt"
# Confirm the file exists on the disk
kubectl exec $POD_NAME -- cat /workspace/modified_data.txt
סיום הסשן עם הנציג
כדי לדמות צמצום אנכי או סיום של הפעילות כשהסוכן בלי פעילות, מוחקים את משאב ארגז החול אבל משמרים את האחסון הבסיסי.
kubectl delete sandbox sandbox-agent-1
מערכת GKE מבטלת את הטעינה של הדיסק ומנתקת אותו. pvc-agent-1 PVC
נשאר, והנתונים נשמרים.
הפעלה מחדש של סשן עם נציג
כדי להפעיל מחדש את הסשן, פורסים מחדש משאב Sandbox חדש שמפנה לאותו PVC.
kubectl apply -f sandbox-agent-1.yaml
הדיסק מצורף מחדש (עם השהיית הצירוף), והקונטיינר מופעל.
אימות של שמירת הנתונים
בודקים את מאגר ארגז החול החדש כדי לוודא שנתוני הסשן הקודם נשמרו.
# Set the active Pod name of the new session
NEW_POD_NAME=sandbox-agent-1
# Read the file from the newly booted sandbox
kubectl exec -it $NEW_POD_NAME -- cat /workspace/modified_data.txt
הפלט אמור להראות Workspace State Saved - Agent 1.
פינוי משאבים
מחיקת ארגז החול של הסוכן ואת התביעה המשויכת לנפח אחסון מתמשך:
kubectl delete sandbox sandbox-agent-1
kubectl delete pvc pvc-agent-1
הגדרה של שחזור מנקודה מסוימת בזמן והעברת בעלות
אפשר להשתמש בתבנית הזו כדי לשכפל קבוצות נתונים להרצת ניסויים מקבילים, לניפוי באגים או לעבודה עצמאית. סביבת העבודה של הנציג מאותחלת ממערך נתונים היסטורי (או ממצב משותף), והשינויים הבאים נשמרים בשכבת כתיבה נפרדת ופרטית בלי לשנות את תבנית הבסיס.
ההטמעה לדוגמה בקטע הזה משתמשת ביצירה ישירה של ארגז חול, והיא מתאימה לסוכנים שסובלים חביון הפעלה של כמה שניות. הגישה הזו מסתמכת על כלי התזמור כדי להקצות באופן דינמי טענות חדשות של PersistentVolume (PVC) מתוך היסטוריית VolumeSnapshots לפני הפעלת סשן חדש של ארגז חול.
יצירת VolumeSnapshotClass
יוצרים VolumeSnapshotClass שמציין את מנהל התקן ה-CSI ומדיניות המחיקה.
ב-Hyperdisk, משתמשים במנהל ההתקן pd.csi.storage.gke.io.
שומרים את קובץ המניפסט הבא בשם
1-snapshot-class.yaml:apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: standard-rwo-snapshot driver: pd.csi.storage.gke.io deletionPolicy: Deleteהחלת המניפסט:
kubectl apply -f 1-snapshot-class.yaml
הקצאת סביבת העבודה הראשונית
יוצרים נפח אחסון שבו הסוכן יבצע את העבודה הראשונית שלו.
שומרים את קובץ המניפסט הבא בשם
2-source-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-source-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10Giהחלת המניפסט:
kubectl apply -f 2-source-pvc.yaml
יצירת נתוני מדינה
פריסת Pod של ארגז חול כדי לכתוב נתונים לנפח.
שומרים את קובץ המניפסט הבא בשם
3-source-sandbox.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v1 namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-source-pvc restartPolicy: OnFailureהחלת המניפסט:
kubectl apply -f 3-source-sandbox.yamlמחכים שה-Pod יפעל, ואז כותבים קובץ מצב:
POD_NAME=agent-session-v1 kubectl exec $POD_NAME -- sh -c "echo 'Point-in-Time Snapshot - v1' > /workspace/state.txt"
העברה לארכיון של המצב ההיסטורי (CSI VolumeSnapshot)
מפעילים CSI VolumeSnapshot כדי להקפיא את המצב הנוכחי. כשמצלמים תמונת מצב, חשוב לפעול לפי השיטות המומלצות לצילום תמונות מצב של דיסקים.
שומרים את קובץ המניפסט הבא בשם
4-volume-snapshot.yaml:apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: agent-session-v1-snapshot spec: volumeSnapshotClassName: standard-rwo-snapshot source: persistentVolumeClaimName: agent-source-pvcהחלת המניפסט:
kubectl apply -f 4-volume-snapshot.yaml
שחזור הנפח מתמונת המצב
פורסים PVC חדש עם dataSource שמצביע על CSI VolumeSnapshot.
שומרים את קובץ המניפסט הבא בשם
5-restored-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: agent-restored-pvc spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo dataSource: name: agent-session-v1-snapshot kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io resources: requests: storage: 10Giהחלת המניפסט:
kubectl apply -f 5-restored-pvc.yaml
הפעלת סשן משוחזר של ארגז חול לנציגים
הקצאת משאב חדש של ארגז חול שמפנה אל ה-PVC ששוחזר.
שומרים את קובץ המניפסט הבא בשם
6-restored-sandbox.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: agent-session-v2-restored namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false # Required securityContext: runAsNonRoot: true # Required runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor # Required tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" # Required containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: workspace mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumes: - name: workspace persistentVolumeClaim: claimName: agent-restored-pvc restartPolicy: OnFailureהחלת המניפסט:
kubectl apply -f 6-restored-sandbox.yaml
אימות של התמדה ושחזור
מוודאים שהסוכן יכול לקרוא את הנתונים ההיסטוריים.
NEW_POD_NAME=agent-session-v2-restored
kubectl exec $NEW_POD_NAME -- cat /workspace/state.txt
הפלט המצופה: Point-in-Time Snapshot - v1
פינוי משאבים
מוחקים את ארגז החול של הסוכן, את ה-PVC ואת ה-VolumeSnapshot:
kubectl delete sandbox agent-session-v1
kubectl delete sandbox agent-session-v2-restored
kubectl delete pvc agent-source-pvc
kubectl delete pvc agent-restored-pvc
kubectl delete volumesnapshot agent-session-v1-snapshot
kubectl delete volumesnapshotclass standard-rwo-snapshot
הגדרת סביבת עבודה זמנית
משתמשים בתבנית של סביבת עבודה זמנית כשסוכן צריך נפח אחסון לאחסון קבצים זמניים בזמן שהסוכן פעיל. אין צורך לשמור נתונים במחיקה של ארגז החול של הסוכן.
הגדרה עם הפעלה תוך פחות משנייה
שימוש במאגרי חום של ארגז חול של סוכן כדי להקצות מראש נפחים ריקים ברקע.
הגדרת SandboxTemplate
מגדירים את האחסון הזמני בבלוק volumeClaimTemplate.
שומרים את קובץ המניפסט הבא בשם
stateless-template.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxTemplate metadata: name: stateless-sandbox-template namespace: default spec: podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo # Selects disk type compatible with node machine family resources: requests: storage: 10Gi
הפעלת מאגר חם של ארגז חול
שומרים את קובץ המניפסט הבא בשם
stateless-warmpool.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxWarmPool metadata: name: stateless-warmpool namespace: default spec: replicas: 5 # Keep five standby Pods with pre-attached empty disks sandboxTemplateRef: name: stateless-sandbox-templateמחילים את שני קובצי המניפסט:
kubectl apply -f stateless-template.yaml kubectl apply -f stateless-warmpool.yaml
הצהרת בעלות על ארגז החול
מגדירים SandboxClaim שמופעל כשמשתמש מתחיל סשן.
שומרים את קובץ המניפסט הבא בשם
stateless-sandbox-claim.yaml:apiVersion: extensions.agents.x-k8s.io/v1alpha1 kind: SandboxClaim metadata: name: agent-1-claim spec: sandboxTemplateRef: name: stateless-sandbox-templateהחלת המניפסט:
kubectl apply -f stateless-sandbox-claim.yaml
אימות של ביצוע תוך פחות משנייה
מציינים את שם ה-Pod של Agent Sandbox ומוודאים שספריית /workspace מותקנת ומוכנה לשימוש מיידי:
export POD_NAME=$(kubectl get sandboxclaim agent-1-claim -o jsonpath='{.status.sandbox.name}')
kubectl exec $POD_NAME -- ls -la /workspace
סיום הסשן עם הסוכן
כדי לסיים את הסשן של הסוכן ולשחרר את ארגז החול שתבעתם, מוחקים את המשאב SandboxClaim:
kubectl delete sandboxclaim agent-1-claim
פינוי משאבים
מוחקים את מאגר החימום של ארגז החול ואת תבנית ארגז החול:
kubectl delete sandboxwarmpool stateless-warmpool
kubectl delete sandboxtemplate stateless-sandbox-template
הגדרה עם הפעלה של כמה שניות
כדי להטמיע סביבת עבודה זמנית שמאפשרת השהיה של כמה שניות, צריך ליצור ארגז חול ישירות לסוכן בלי להשתמש במאגר חם.
הגדרה של ארגז חול של סוכן ללא שמירת מצב
שומרים את קובץ המניפסט הבא בשם
sandbox-direct-stateless.yaml:apiVersion: agents.x-k8s.io/v1alpha1 kind: Sandbox metadata: name: sandbox-direct-stateless namespace: default spec: replicas: 1 podTemplate: spec: runtimeClassName: gvisor automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 # Grant group access to the volume nodeSelector: sandbox.gke.io/runtime: gvisor tolerations: - key: "sandbox.gke.io/runtime" value: "gvisor" effect: "NoSchedule" containers: - name: agent image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0 ports: - containerPort: 8888 volumeMounts: - name: ephemeral-disk mountPath: /workspace resources: limits: cpu: "500m" memory: "1Gi" # Required securityContext: capabilities: drop: ["ALL"] # Required restartPolicy: OnFailure volumeClaimTemplates: - metadata: name: ephemeral-disk spec: accessModes: ["ReadWriteOnce"] storageClassName: dynamic-rwo resources: requests: storage: 10Gi
פריסת ארגז החול של הסוכן
כדי להקצות את הדיסק באופן דינמי ולצרף אותו לצומת המתוזמן, מפעילים את המניפסט:
kubectl apply -f sandbox-direct-stateless.yaml
אימות של זמן האחזור והביצוע של ההפעלה
עוקבים אחרי הסטטוס של ה-Pod כדי לראות את העיכוב בצירוף לפני שה-Pod עובר למצב Running:
kubectl get pods -w
אחרי שה-Pod פועל, צריך לתעד את שם ה-Pod ולוודא שהספרייה /workspace
זמינה:
POD_NAME=sandbox-direct-stateless
kubectl exec $POD_NAME -- ls -la /workspace
סיום הסשן עם הסוכן
כדי להפסיק אוטומטית את הפוד ולמחוק את האחסון הזמני שלו, צריך למחוק את משאב ארגז החול:
kubectl delete sandbox sandbox-direct-stateless
המאמרים הבאים
- מידע נוסף על GKE Agent Sandbox
- מידע נוסף על בידוד של ביצוע קוד AI באמצעות Agent Sandbox
- איך שומרים ומשחזרים סביבות ארגז חול של סוכנים באמצעות תמונות מצב של Pod