העברות נתונים יכולות להתבצע בין המקורות הבאים:
- דרישת נפח אחסון מתמיד (PVC) ואחסון אובייקטים
- אחסון אובייקטים ואחסון אובייקטים (ב-GDC)
אחסון האובייקטים ב-GDC תואם ל-S3 ומכונה סוג s3 בקובצי YAML של Kubernetes.
סוגים של מקורות ויעדים של נתונים
- אחסון אובייקטים (נקרא 's3'): אחסון אובייקטים שקיים ב-GDC
- אחסון מקומי (נקרא 'מקומי'): אחסון ב-PVC מצורפים
העתקה מאחסון אובייקטים לאחסון אובייקטים
ודאו שמתקיימות הדרישות המוקדמות הבאות:
- נקודת קצה של S3 עם הרשאות קריאה למקור, ונקודת קצה של S3 עם הרשאות כתיבה ליעד.
- אם לפרטי הכניסה שלכם אין הרשאה ליצור קטגוריות, ההעברה תיכשל אם קטגוריית היעד לא קיימת. אם זה המצב, צריך לוודא שקטגוריית היעד קיימת.
- הרשאות ליצירת משימות וליצירה או לקריאה של סודות בתוך האשכול או מרחב השמות. בדוגמה הבאה מפורטות ההרשאות.
הגדרת העברת הנתונים
כדי להגדיר את העברת הנתונים:
יצירת מרחב השמות של ההעברה
יוצרים את מרחב השמות שבו תפעל משימת ההעברה:
apiVersion: v1
kind: Namespace
metadata:
name: NAMESPACE
הגדרת פרטי כניסה
מכינים את פרטי הכניסה להעברה. פועלים לפי האפשרות שהכי מתאימה לתרחיש ההעברה.
העברה מ-GDC ל-GDC
אם ההעברה מתבצעת באופן מלא בתוך אותה סביבת GDC, הסודות כבר קיימים. חשוב לזכור שהשיטה הזו מיועדת רק להעברות בתוך יקום יחיד, ולא להעברות בין יקומים שונים.
כדי לקבל את פרטי הכניסה של S3, פועלים לפי ההוראות להענקת גישה לקטגוריה.
יוצרים חשבון שירות (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
אם ההעברה כוללת מערכת חיצונית, צריך לציין את פרטי הגישה באופן מפורש.
יוצרים פרטי כניסה במרחב השמות של היעד:
--- 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 ---יוצרים חשבון שירות (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 לדוגמה שמפורט בקטע הבא.
איסוף מטא-נתונים
כדי לאסוף את המטא-נתונים שנדרשים ליצירת משימת העברת הנתונים, פועלים לפי השלבים הבאים:
מוצאים את הצומת עם ה-Pod המתוזמן:
kubectl get pod POD_NAME -o jsonpath='{.spec.nodeName}'מתעדים את הפלט של הפקודה הזו כ-NODE_NAME לשימוש בקובץ ה-YAML של משימת העברת הנתונים.
מאתרים את ה-UID של ה-Pod:
kubectl get pod POD_NAME -o 'jsonpath={.metadata.uid}'מתעדים את הפלט של הפקודה הזו כ-POD_UID לשימוש בקובץ ה-YAML של משימת העברת הנתונים.
מאתרים את השם של ה-PVC:
kubectl get pvc www-web-0 -o 'jsonpath={.spec.volumeName}'מתעדים את הפלט של הפקודה הזו כ-PVC_NAME לשימוש בקובץ ה-YAML של משימת העברת הנתונים.
מחפשים את ספק האחסון של ה-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
כדי לשחזר אחסון בלוקים מנקודת קצה של אחסון אובייקטים, פועלים לפי השלבים הבאים:
הקצאת נפח מתמשך ליעד בשחזור. משתמשים ב-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.בודקים את הסטטוס של ה-PVC:
kubectl get pvc restore-pvc -n restore-nsאחרי ש-PVC נמצא במצב
Bound, הוא מוכן לשימוש בתוך ה-Pod שמבצע בו הידרציה.אם בסופו של דבר קבוצת StatefulSet צורכת את ה-PV, צריך להתאים את ה-PVCs של StatefulSet שעברו עיבוד. ה-Pods שנוצרים על ידי StatefulSet צורכים את הנפחים המאוחסנים. בדוגמה הבאה מוצגים תבניות של תביעות לשימוש בנפח אחסון ב-StatefulSet בשם
ss.volumeClaimTemplates: - metadata: name: pvc-name spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "default" resources: requests: storage: 1Giכדי לוודא שה-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 נפרד יוכל לצרוך את הנתונים.