יצירת עומסי עבודה עם שמירת מצב

בדף הזה מוסבר איך ליצור ולנהל עומסי עבודה עם שמירת מצב באשכול Kubernetes של מכשיר Google Distributed Cloud ‏ (GDC) עם בידוד פיזי. עומסי עבודה עם שמירת מצב מאפשרים לכם להרחיב את פריסת האפליקציה באמצעות אחסון מתמיד. אחסון מתמיד מספק לאפליקציה זהויות עקביות ושמות מארחים יציבים, לא משנה איפה מתוזמנים עומסי העבודה שלה.

הדף הזה מיועד למפתחים בקבוצת מפעילים של אפליקציות, שאחראים על יצירת עומסי עבודה של אפליקציות בארגון שלהם.

לפני שמתחילים

כדי להשלים את המשימות שמתוארות במאמר הזה, צריך לבקש את ההרשאות הנדרשות ולהכין את הסביבה.

שליחת בקשה לתפקידי IAM

כדי ליצור, למחוק, לערוך או להציג עומסי עבודה עם שמירת מצב באשכול Kubernetes, צריך לבקש מאדמין ה-IAM בארגון להקצות לכם את התפקיד אדמין במרחב שמות (namespace-admin). התפקיד הזה משויך למרחב השמות של הפרויקט.

הכנת הסביבה

כדי להריץ פקודות באשכול Kubernetes בשרת פיזי שהוגדר מראש, צריך לוודא שיש לכם את המשאבים הבאים:

  1. מאתרים את שם אשכול Kubernetes או שואלים את מנהל הפלטפורמה מה שם האשכול.

  2. אם אין לכם קובץ kubeconfig, אתם צריכים להיכנס וליצור אותו עבור אשכול Kubernetes.

  3. משתמשים בנתיב kubeconfig של אשכול Kubernetes כדי להחליף את הערך CLUSTER_KUBECONFIG בהוראות האלה.

יצירת משאב StatefulSet

יוצרים אובייקט StatefulSet על ידי כתיבת מניפסט StatefulSet והפעלת הפקודה kubectl apply ליצירת המשאב. כדי לספק ללקוחות דרך יציבה לשליחת בקשות ל-pods של משאב StatefulSet, צריך גם ליצור אובייקט Service.

הפקודה kubectl apply משתמשת בקובצי מניפסט כדי ליצור, לעדכן ולמחוק משאבים באשכול. זו שיטה הצהרתית להגדרת אובייקט. בשיטה הזו, הכתיבות שבוצעו באובייקטים פעילים נשמרות בלי למזג את השינויים בחזרה לקובצי ההגדרות של האובייקט.

כדי ליצור משאב StatefulSet ומשאב Service, מריצים את הפקודה:

kubectl --kubeconfig CLUSTER_KUBECONFIG -n NAMESPACE \
    apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: SERVICE_NAME
  labels:
    app: APP_NAME
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: APP_NAME
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: STATEFULSET_NAME
spec:
  selector:
    matchLabels:
      app: APP_LABEL_NAME
  serviceName: "SERVICE_NAME"
  replicas: NUMBER_OF_REPLICAS
  template:
    metadata:
      labels:
        app: APP_LABEL_NAME
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: CONTAINER_NAME
        image: CONTAINER_IMAGE
        resources:
          requests:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
          limits:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: CONTAINER_STORAGE_VOLUME_PATH
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
EOF

מחליפים את מה שכתוב בשדות הבאים:

  • CLUSTER_KUBECONFIG: קובץ ה-kubeconfig של אשכול Kubernetes שבו פורסים עומסי עבודה של קונטיינרים.

  • NAMESPACE: מרחב השמות של הפרויקט שבו יפרסו עומסי העבודה של הקונטיינר.

  • SERVICE_NAME: השם של אובייקט Service. מוודאים שאובייקט StatefulSet מגדיר את אובייקט Service גם ב-serviceName שלו.

  • APP_NAME: השם של האפליקציה שרוצים להפעיל בפריסה.

  • APP_LABEL_NAME: בורר התוויות שקובע אילו פודים שייכים לאובייקט StatefulSet.

  • STATEFULSET_NAME: השם של אובייקט StatefulSet.

  • NUMBER_OF_REPLICAS: מספר האובייקטים המשוכפלים Pod שהפריסה מנהלת.

  • CONTAINER_NAME: השם של הקונטיינר.

  • CONTAINER_IMAGE: השם של קובץ האימג' בקונטיינר. חובה לכלול את הנתיב של מאגר הקונטיינרים ואת הגרסה של התמונה, כמו REGISTRY_PATH/nginx:1.23. מידע נוסף על הגדרת הנתיב של מאגר התמונות זמין במאמר סקירה כללית על שירות Harbor המנוהל.

  • CONTAINER_STORAGE_VOLUME_PATH: הנתיב בתוך הקונטיינר שבו מותקן נפח אחסון.

לדוגמה, אובייקט StatefulSet הבא ואובייקט Service התואם יוצרים עומסי עבודה של קונטיינרים עם שמירת מצב:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: REGISTRY_PATH/nginx:1.23
        resources:
          requests:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
          limits:
            nvidia.com/gpu-pod-NVIDIA_A100_80GB_PCIE: 1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

בדוגמה הזו:

  • נוצר אובייקט Service בשם nginx, שמוצג בשדה metadata: name. האובייקט Service מכוון לאפליקציה בשם nginx, שמצוינת על ידי labels.app: nginx ו-selector.app: nginx. האובייקט Service חושף את יציאה 80 ונותן לה את השם web. אובייקט Service הזה שולט בדומיין של הרשת ומנתב את תנועת האינטרנט לאפליקציה שמופעלת בתוך קונטיינר, שנפרסה על ידי אובייקט StatefulSet.
  • נוצר StatefulSet בשם web עם שלושה אובייקטים משוכפלים של Pod, כפי שמוגדר בשדה replicas: 3.
  • התבנית Pod, שמוגדרת על ידי הקטע .spec.template, מציינת שהאובייקטים Pod שלה מסומנים בתווית app: nginx.
  • המפרט Pod, שמוגדר בקטע .template.spec, מציין שהפודים של StatefulSet מריצים קונטיינר אחד, nginx, שמריץ את התמונה nginx בגרסה 1.23.
  • Pod המפרט משתמש ביציאת האינטרנט שנפתחה על ידי האובייקט Service.
  • בקטע .template.spec.volumeMounts מצוין השדה mountPath, שנקרא www. ‫mountPath הוא הנתיב בקונטיינר שבו מותקן נפח אחסון.
  • StatefulSet מספק שלושה אובייקטים של PersistentVolumeClaim, בשמות web-www-0, web-www-1 ו-web-www-2, עם נפח אחסון מוקצה של 1GB לכל אחד.

אחרי שיוצרים את StatefulSet, הוא מוודא שמספר האובייקטים שנבחרו Pod פועלים וזמינים בכל רגע. המערכת StatefulSet מחליפה באופן אוטומטי אובייקטים מסוג Pod שנכשלו או שסולקו מהצמתים שלהם, ומשייכת אובייקטים חדשים מסוג Pod למשאבי האחסון, לבקשות ולמגבלות של המשאבים ולהגדרות אחרות שמוגדרות במפרט Pod של אובייקט StatefulSet.

בקשה לאחסון מתמיד במשאב StatefulSet

אפשר להקצות נפח אחסון מתמיד באופן דינמי, כך שהנפחים הבסיסיים נוצרים לפי דרישה. אפליקציות יכולות לבקש אחסון מתמיד באמצעות אובייקט PersistentVolumeClaim.

בדרך כלל, צריך ליצור PersistentVolumeClaim אובייקטים בנוסף ליצירת האובייקט Pod. עם זאת, אובייקטים מסוג StatefulSet כוללים מערך volumeClaimTemplates שיוצר את האובייקטים PersistentVolumeClaim. כל עותק StatefulSet מקבל אובייקט PersistentVolumeClaim משלו.

מידע נוסף זמין במאמר בנושא הגדרת אחסון של קונטיינרים.