העברת נתונים

העברות נתונים יכולות להתבצע בין המקורות הבאים:

  1. דרישת נפח אחסון מתמיד (PVC) ואחסון אובייקטים
  2. אחסון אובייקטים ואחסון אובייקטים (ב-GDC)

אחסון האובייקטים ב-GDC תואם ל-S3 ומכונה סוג s3 בקובצי YAML של Kubernetes.

סוגים של מקורות ויעדים של נתונים

  1. אחסון אובייקטים (נקרא 's3'): אחסון אובייקטים שקיים ב-GDC
  2. אחסון מקומי (נקרא 'מקומי'): אחסון ב-PVC מצורפים

העתקה מאחסון אובייקטים לאחסון אובייקטים

ודאו שמתקיימות הדרישות המוקדמות הבאות:

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

הגדרת העברת הנתונים

כדי להגדיר את העברת הנתונים:

יצירת מרחב השמות של ההעברה

יוצרים את מרחב השמות שבו תפעל משימת ההעברה:

apiVersion: v1
kind: Namespace
metadata:
  name: NAMESPACE

הגדרת פרטי כניסה

מכינים את פרטי הכניסה להעברה. פועלים לפי האפשרות שהכי מתאימה לתרחיש ההעברה.

העברה מ-GDC ל-GDC

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

  1. כדי לקבל את פרטי הכניסה של S3, פועלים לפי ההוראות להענקת גישה לקטגוריה.

  2. יוצרים חשבון שירות (SA) במרחב השמות של היעד עבור עבודת ההעברה. לאחר מכן, מוסיפים הרשאות כדי לאפשר לחשבון הזה לקרוא סודות במרחבי השמות של המקור והיעד באמצעות RoleBindings חוצי-מרחבי שמות.

    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: SOURCE_NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-source-secrets-rolebinding
      namespace: SOURCE_NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: DESTINATION_NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-dest-secrets-rolebinding
      namespace: DESTINATION_NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    

העברה מ-GDC ל-non-GDC

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

  1. יוצרים פרטי כניסה במרחב השמות של היעד:

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: src-secret
      namespace: NAMESPACE
    data:
      access-key-id: NkFDTUg3WDBCVDlQMVpZMU5MWjU= # base 64 encoded version of key
      access-key: VkRkeWJsbFgzb2FZanMvOVpnSi83SU5YUjk3Y0Q2TUdxZ2d4Q3dpdw== # base 64 encoded version of secret key
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: dst-secret
      namespace: NAMESPACE
    data:
      access-key-id: NkFDTUg3WDBCVDlQMVpZMU5MWjU= # base 64 encoded version of key
      access-key: VkRkeWJsbFgzb2FZanMvOVpnSi83SU5YUjk3Y0Q2TUdxZ2d4Q3dpdw== # base 64 encoded version of secret key
    ---
    
  2. יוצרים חשבון שירות (SA) שמשמש להעברה, ואז מוסיפים לחשבון הרשאות לקריאה ולכתיבה של סודות באמצעות תפקידים והקצאות תפקידים. לא צריך להוסיף הרשאות אם לחשבון השירות (SA) במרחב השמות שמוגדר כברירת מחדל או לחשבון השירות המותאם אישית כבר יש את ההרשאות האלה.

    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: transfer-service-account
      namespace: NAMESPACE
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-secrets-rolebinding
      namespace: NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    

השגת אישורי CA

מקבלים את אישורי ה-CA של מערכות האחסון של האובייקטים. אפשר לקבל את אותם אישורים מה-AO או מה-PA על ידי ביצוע ההוראות לאחזור חבילות של אישורים.

---

apiVersion: v1
kind: Secret
metadata:
  name: src-cert
  namespace: NAMESPACE
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBekNDQWV1Z0F3SUJBZ0lSQUpHM2psOFZhTU85a1FteGdXUFl3N3d3RFFZSktvWklodmNOQVFFTEJRQXcKR3pFWk1CY0dBMVVFQXhNUVltOXZkSE4wY21Gd0xYZGxZaTFqWVRBZUZ3MHlNekF5TVRVd01USXlNakZhRncweQpNekExTVRZd01USXlNakZhTUJzeEdUQVhCZ05WQkFNVEVHSnZiM1J6ZEhKaGNDMTNaV0l0WTJFd2dnRWlNQTBHCkNTcUdTSWI== # base 64 encoded version of certificate

---

apiVersion: v1
kind: Secret
metadata:
  name: dst-cert
  namespace: NAMESPACE
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBekNDQWV1Z0F3SUJBZ0lSQUtoaEJXWWo3VGZlUUZWUWo0U0RpckV3RFFZSktvWklodmNOQVFFTEJRQXcKR3pFWk1CY0dBMVVFQXhNUVltOXZkSE4wY21Gd0xYZGxZaTFqWVRBZUZ3MHlNekF6TURZeU16TTROVEJhRncweQpNekEyTURReU16TTROVEJhTUJzeEdUQVhCZ05WQkFNVEVHSnZiM1J6ZEhKaGNDMTNaV0l0WTJFd2dnRWlNQTBHCkNTcUdTSWIzRFFF== # base 64 encoded version of certificate. Can be same OR different than source certificate.

---

(אופציונלי) יצירת LoggingTarget

כדי לראות את היומנים של שירות ההעברה ב-Loki, צריך ליצור LoggingTarget.

apiVersion: logging.gdc.goog/v1
kind: LoggingTarget
metadata:
  namespace: NAMESPACE # Same namespace as your transfer job
  name: logtarg1
spec:
  # Choose matching pattern that identifies pods for this job
  # Optional
  # Relationship between different selectors: AND
  selector:

    # Choose pod name prefix(es) to consider for this job
    # Observability platform will scrape all pods
    # where names start with specified prefix(es)
    # Should contain [a-z0-9-] characters only
    # Relationship between different list elements: OR
    matchPodNames:
      - transfer-job # Choose the prefix here that matches your transfer job name
  serviceName: transfer-service

יצירת עומס העבודה להעברה

אפשר להפעיל את ההעברה כפעולה חד-פעמית באמצעות Job, או לתזמן אותה להפעלה חוזרת באמצעות CronJob.

בוחרים את השיטה שהכי מתאימה לתרחיש השימוש שלכם:

יצירת משימה חד-פעמית

ההגדרה הזו מתאימה להעברת נתונים ידנית חד-פעמית.

---
apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: NAMESPACE
spec:
  template:
    spec:
      serviceAccountName: transfer-service-account # The service account created in the previous step
      containers:
        - name: storage-transfer-pod
          image: gcr.io/private-cloud-staging/storage-transfer:latest
          imagePullPolicy: Always
          command:
            - /storage-transfer
          args:
            # The S3 endpoints for your source and destination
            - '--src_endpoint=SRC_ENDPOINT'
            - '--dst_endpoint=DST_ENDPOINT'
            # The Fully Qualified Names (FQN) of the buckets
            - '--src_path=SRC_BUCKET_FQN/'
            - '--dst_path=DST_BUCKET_FQN/'
            # Cross-namespace mapping: point directly to the live credentials using NAMESPACE/SECRET_NAME
            - '--src_credentials=NAMESPACE/SRC_SECRET_NAME'
            - '--dst_credentials=NAMESPACE/DST_SECRET_NAME'
            # Point to the CA certificate Secret created in the destination namespace
            - '--src_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
            - '--dst_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
            - '--src_type=s3'
            - '--dst_type=s3'
            - '--bandwidth_limit=BANDWIDTH_LIMIT' # Optional. Examples: '10K', '100M', '1G'
      restartPolicy: OnFailure
---

יצירת משימת Cron מתוזמנת

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

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: transfer-cronjob
  namespace: NAMESPACE
spec:
  schedule: "0 * * * *"  # Runs at the top of every hour. Adjust the cron schedule as needed.
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: transfer-service-account # The service account created in the previous step
          containers:
            - name: storage-transfer-pod
              image: gcr.io/private-cloud-staging/storage-transfer:latest
              imagePullPolicy: Always
              command:
                - /storage-transfer
              args:
                # The S3 endpoints for your source and destination
                - '--src_endpoint=SRC_ENDPOINT'
                - '--dst_endpoint=DST_ENDPOINT'
                # The Fully Qualified Names (FQN) of the buckets
                - '--src_path=SRC_BUCKET_FQN/'
                - '--dst_path=DST_BUCKET_FQN/'
                # Cross-namespace mapping: point directly to the live credentials using NAMESPACE/SECRET_NAME
                - '--src_credentials=NAMESPACE/SRC_SECRET_NAME'
                - '--dst_credentials=NAMESPACE/DST_SECRET_NAME'
                # Point to the CA certificate Secret created in the destination namespace
                - '--src_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
                - '--dst_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
                - '--src_type=s3'
                - '--dst_type=s3'
                - '--bandwidth_limit=BANDWIDTH_LIMIT' # Optional. Examples: '10K', '100M', '1G'
          restartPolicy: OnFailure
---

מעקב אחרי העברת הנתונים

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

מריצים את הפקודה הבאה כדי לבדוק את הסטטוס של עומס העבודה:

# If you created a one-time Job:
kubectl describe job transfer-job -n NAMESPACE

# If you created a scheduled CronJob:
kubectl describe cronjob transfer-cronjob -n NAMESPACE

הפקודה הקודמת מציגה את סטטוס העבודה.

העבודה גורמת להעברת הנתונים מתוך ה-pod. אפשר לקבל את שם ה-Pod ולעיין ביומנים כדי לראות אם יש שגיאות במהלך ההעברה.

כדי לראות את היומנים של ה-pod, מריצים את הפקודה הבאה:

# 1. First, find the exact pod name generated by your Job
kubectl get pods -n NAMESPACE | grep transfer

# 2. Then, view the logs for that specific pod
kubectl logs POD_NAME -n NAMESPACE

יומני משימות שהסתיימו בהצלחה:

DEBUG : Starting main for transfer
I0607 21:34:39.183106       1 transfer.go:103]  "msg"="Starting transfer "  "destination"="sample-bucket" "source"="/data"
2023/06/07 21:34:39 NOTICE: Bandwidth limit set to {100Mi 100Mi}
I0607 21:34:49.238901       1 transfer.go:305]  "msg"="Job finished polling "  "Finished"=true "Number of Attempts"=2 "Success"=true
I0607 21:34:49.239675       1 transfer.go:153]  "msg"="Transfer completed."  "AvgSpeed"="10 KB/s" "Bytes Moved"="10.0 kB" "Errors"=0 "Files Moved"=10 "FilesComparedAtSourceAndDest"=3 "Time since beginning of transfer"="1.0s"

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

העתקת אחסון בלוקים לאחסון אובייקטים

צריך לוודא שמתקיימות הדרישות המוקדמות הבאות:

  • נקודת קצה של S3 עם מזהה מפתח S3 ומפתח גישה סודי עם הרשאות WRITE לפחות לקטגוריה הייעודית שאליה רוצים להעביר את הנתונים.
  • אשכול פעיל עם קישוריות לנקודת הקצה של S3.
  • הרשאות ליצירת משימות וסודות בתוך האשכול.
  • לשכפול של אחסון בלוקים, צריך Pod עם PersistentVolumeClaim (PVC) מצורף שרוצים לגבות לאחסון אובייקטים, והרשאות לבדיקת משימות ו-PVC שפועלים.
  • לשכפול של אחסון הבלוקים, נדרש חלון שבו לא מתבצעות פעולות כתיבה ל-PersistentVolume (PV).
  • לשחזור של אחסון בלוקים מנקודת קצה של אחסון אובייקטים, צריך הרשאות להקצאת PV עם קיבולת מספקת.

כדי לשכפל PV לאחסון אובייקטים, צריך לצרף נפח ל-Pod קיים. במהלך חלון ההעברה, אסור לבצע פעולות כתיבה ב-Pod. כדי למנוע את ניתוק ה-PV המצורף מהמשימה, תהליך העברת הנתונים פועל על ידי הרצת משימת ההעברה באותה מכונה שבה פועל ה-Pod, ושימוש ב-hostPath mount כדי לחשוף את הנפח בדיסק. כדי להתכונן להעברה, צריך קודם למצוא את הצומת שבו פועל ה-Pod, ומטא-נתונים נוספים כמו ה-UID של ה-Pod וסוג ה-PVC, כדי להפנות לנתיב המתאים בצומת. צריך להחליף את המטא-נתונים האלה בקובץ ה-YAML לדוגמה שמפורט בקטע הבא.

איסוף מטא-נתונים

כדי לאסוף את המטא-נתונים שנדרשים ליצירת משימת העברת הנתונים, פועלים לפי השלבים הבאים:

  1. מוצאים את הצומת עם ה-Pod המתוזמן:

    kubectl get pod POD_NAME -o jsonpath='{.spec.nodeName}'
    

    מתעדים את הפלט של הפקודה הזו כ-NODE_NAME לשימוש בקובץ ה-YAML של משימת העברת הנתונים.

  2. מאתרים את ה-UID של ה-Pod:

    kubectl get pod POD_NAME -o 'jsonpath={.metadata.uid}'
    

    מתעדים את הפלט של הפקודה הזו כ-POD_UID לשימוש בקובץ ה-YAML של משימת העברת הנתונים.

  3. מאתרים את השם של ה-PVC:

    kubectl get pvc www-web-0 -o 'jsonpath={.spec.volumeName}'
    

    מתעדים את הפלט של הפקודה הזו כ-PVC_NAME לשימוש בקובץ ה-YAML של משימת העברת הנתונים.

  4. מחפשים את ספק האחסון של ה-PVC:

    kubectl get pvc www-web-0 -o jsonpath='{.metadata.annotations.volume\.v1\.kubernetes\.io\/storage-provisioner}'
    

    צריך לתעד את הפלט של הפקודה הזו כ-PROVISIONER_TYPE כדי להשתמש בו בקובץ ה-YAML של משימת העברת הנתונים.

יצירת סודות

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

כדי לבצע את ההעברה במרחב שמות קיים, אפשר לעיין בדוגמה הבאה ליצירת סודות במרחב השמות transfer:

apiVersion: v1
kind: Secret
metadata:
  name: src-secret
  namespace: transfer
data:
  access-key-id: c3JjLWtleQ== # echo -n src-key| base64 -w0
  access-key: c3JjLXNlY3JldA== # echo -n src-secret| base64 -w0
---
apiVersion: v1
kind: Secret
metadata:
  name: dst-secret
  namespace: transfer
data:
  access-key-id: ZHN0LWtleQ== # echo -n dst-key| base64 -w0
  access-key: ZHN0LXNlY3JldA== # echo -n dst-secret| base64 -w0

יצירת המשרה

בעזרת הנתונים שאספתם בקטע הקודם, יוצרים משימה באמצעות הכלי להעברת נתונים. ל-Job להעברת הנתונים יש hostPath mount שמפנה לנתיב של ה-PV הרלוונטי, ו-nodeSelector לצומת הרלוונטי.

דוגמה למשימת העברת נתונים:

apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: transfer
spec:
  template:
    spec:
      nodeSelector: NODE_NAME
      serviceAccountName: data-transfer-sa
      containers:
      - name: storage-transfer-pod
        image: storage-transfer
        command:
        - /storage-transfer
        args:
        - --dst_endpoint=https://your-dst-endpoint.com
        - --src_path=/pvc-data
        - --dst_path=transfer-dst-bucket
        - --dst_credentials=transfer/dst-secret
        - --src_type=local
        - --dst_type=s3
      volumeMounts:
      - mountPath: /pvc-data
        name: pvc-volume
      volumes:
      - name: pvc-volume
      hostPath:
        path: /var/lib/kubelet/pods/POD_UID/volumes/PROVISIONER_TYPE/PVC_NAME
      restartPolicy: Never

בדומה להעברת נתונים מ-S3, צריך ליצור Secret שמכיל את מפתחות הגישה לנקודת היעד בקלאסטר Kubernetes, ולבצע את העברת הנתונים באמצעות חשבון שירות עם הרשאות מתאימות לקריאת ה-Secret משרת ה-API. עוקבים אחרי הסטטוס של ההעברה באמצעות פקודות kubectl סטנדרטיות שפועלות על המשימה.

כשמעבירים אחסון בלוקים לאחסון אובייקטים, חשוב לשים לב לפרטים הבאים:

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

שחזור מאחסון אובייקטים לאחסון בלוקים

הקצאת PV

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

  1. הקצאת נפח מתמשך ליעד בשחזור. משתמשים ב-PVC כדי להקצות את נפח האחסון, כמו בדוגמה הבאה:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: restore-pvc
      namespace: restore-ns
    spec:
      storageClassName: "default"
      accessModes:
    ReadWriteOnce
      resources:
        requests:
          storage: 1Gi # Need sufficient capacity for full restoration.
    
  2. בודקים את הסטטוס של ה-PVC:

    kubectl get pvc restore-pvc -n restore-ns
    

    אחרי ש-PVC נמצא במצב Bound, הוא מוכן לשימוש בתוך ה-Pod שמבצע בו הידרציה.

  3. אם בסופו של דבר קבוצת StatefulSet צורכת את ה-PV, צריך להתאים את ה-PVCs של StatefulSet שעברו עיבוד. ה-Pods שנוצרים על ידי StatefulSet צורכים את הנפחים המאוחסנים. בדוגמה הבאה מוצגים תבניות של תביעות לשימוש בנפח אחסון ב-StatefulSet בשם ss.

      volumeClaimTemplates:
      - metadata:
          name: pvc-name
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "default"
          resources:
            requests:
              storage: 1Gi
    
  4. כדי לוודא שה-Pods שיתקבלו יצרכו את נפחי האחסון שהוקצו מראש, צריך להקצות מראש PVC עם שמות כמו ss-pvc-name-0 ו-ss-pvc-name-1.

הוספת נוזלים לתא הפוטו-וולטאי

אחרי ש-PVC נקשר ל-PV, מפעילים את ה-Job כדי לאכלס את ה-PV:

apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: transfer
spec:
  template:
    spec:
      serviceAccountName: data-transfer-sa
      volumes:
      - name: data-transfer-restore-volume
        persistentVolumeClaim:
          claimName: restore-pvc
      containers:
      - name: storage-transfer-pod
        image: storage-transfer
        command:
        - /storage-transfer
        args:
        - --src_endpoint=https://your-src-endpoint.com
        - --src_path=/your-src-bucket
        - --src_credentials=transfer/src-secret
        - --dst_path=/restore-pv-mnt-path
        - --src_type=s3
        - --dst_type=local
      volumeMounts:
      - mountPath: /restore-pv-mnt-path
        name: data-transfer-restore-volume

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