Managed Airflow (דור 3) | Managed Airflow (דור 2) | Managed Airflow (דור 1 מדור קודם)
בדף הזה מוסבר איך להשתמש ב-KubernetesPodOperator כדי לפרוס Kubernetes Pods מ-Managed Service for Apache Airflow אל אשכול Google Kubernetes Engine שמהווה חלק מהסביבה של Managed Service for Apache Airflow.
האופרטור KubernetesPodOperator מפעיל קבוצות Pod של Kubernetes באשכול שבסביבה שלכם. לעומת זאת, אופרטורים של Google Kubernetes Engine מריצים Pods של Kubernetes באשכול שצוין, שיכול להיות אשכול נפרד שלא קשור לסביבה שלכם. אפשר גם ליצור ולמחוק אשכולות באמצעות אופרטורים של Google Kubernetes Engine.
KubernetesPodOperator היא אפשרות טובה אם אתם צריכים:
- יחסי תלות מותאמים אישית של Python שלא זמינים דרך מאגר PyPI הציבורי.
- תלויות בינאריות שלא זמינות בתמונת ה-worker של Managed Airflow.
לפני שמתחילים
אם משתמשים בגרסה 5.0.0 של CNCF Kubernetes Provider, צריך לפעול לפי ההוראות שמפורטות בקטע CNCF Kubernetes Provider.
ההגדרה של שיוך Pod לא זמינה ב-Managed Airflow (דור 2). אם רוצים להשתמש בהצמדה של Pod, צריך להשתמש באופרטורים של GKE כדי להפעיל Pods באשכול אחר.
מידע על KubernetesPodOperator ב-Managed Airflow (דור 2)
בקטע הזה מוסבר איך KubernetesPodOperator פועל ב-Managed Airflow (דור 2).
שימוש במשאבים
ב-Managed Airflow (דור 2), האשכול של הסביבה מתרחב אוטומטית. עומסי עבודה נוספים שאתם מריצים באמצעות KubernetesPodOperator מתרחבים באופן עצמאי מהסביבה שלכם.
הסביבה שלכם לא מושפעת מהגידול בביקוש למשאבים, אבל גודל האשכול בסביבה שלכם גדל וקטן בהתאם לביקוש למשאבים.
התמחור של עומסי העבודה הנוספים שמופעלים באשכול של הסביבה מבוסס על מודל התמחור של Managed Airflow (דור 2) ועל מקו"טים של Managed Airflow Compute.
Managed Airflow (דור 2) משתמש באשכולות Autopilot, שכוללים את המושג compute classes:
ב-Managed Airflow יש תמיכה רק בסוג המחשוב
general-purpose.כברירת מחדל, אם לא נבחרה כיתה, המערכת מניחה שמדובר בכיתה
general-purposeכשיוצרים תרמילים באמצעות KubernetesPodOperator.כל מחלקה משויכת למאפיינים ספציפיים ולמגבלות משאבים. אפשר לקרוא עליהם במסמכי Autopilot. לדוגמה, ל-Pods שפועלים בתוך המחלקה
general-purposeיכולים להיות עד 110 GiB של זיכרון.
גישה למשאבים של הפרויקט
Managed Airflow (דור 2) משתמש באשכולות GKE עם איחוד זהויות של עומסי עבודה ל-GKE. לפודים שפועלים במרחב השמות composer-user-workloads
יש גישה למשאבים Google Cloud בפרויקט בלי צורך בהגדרה נוספת. חשבון השירות של הסביבה שלכם משמש לגישה למשאבים האלה.
אם רוצים להשתמש במרחב שמות בהתאמה אישית, צריך למפות את חשבונות השירות ב-Kubernetes שמשויכים למרחב השמות הזה לחשבונות שירות ב- Google Cloud , כדי לאפשר אימות של זהות השירות לבקשות לממשקי API של Google ולשירותים אחרים. אם אתם מפעילים Pods במרחב שמות בהתאמה אישית באשכול של סביבת העבודה, לא נוצרים קישורי IAM בין Kubernetes לבין חשבונות שירות שלGoogle Cloud , ול-Pods האלה אין גישה למשאבים של פרויקט Google Cloud .
אם אתם משתמשים במרחב שמות בהתאמה אישית ורוצים שלקבוצות ה-Pod שלכם תהיה גישה למשאביGoogle Cloud , אתם צריכים לפעול לפי ההנחיות במאמר בנושא איחוד זהויות של עומסי עבודה ל-GKE ולהגדיר את הקישורים למרחב שמות בהתאמה אישית:
- יוצרים מרחב שמות נפרד באשכול של הסביבה.
- יוצרים קישור בין חשבון השירות של Kubernetes במרחב השמות המותאם אישית לבין חשבון השירות של הסביבה.
- מוסיפים את הערת חשבון השירות של הסביבה לחשבון השירות של Kubernetes.
- כשמשתמשים ב-KubernetesPodOperator, צריך לציין את מרחב השמות ואת חשבון השירות של Kubernetes בפרמטרים
namespaceו-service_account_name.
הגדרה מינימלית
כדי ליצור KubernetesPodOperator, נדרשים רק הפרמטרים name, image ו-task_id של Pod. /home/airflow/composer_kube_config
מכיל פרטי כניסה לאימות ב-GKE.
שלבי הגדרת תצורה נוספים
בדוגמה הזו מוצגים פרמטרים נוספים שאפשר להגדיר ב-KubernetesPodOperator.
מידע נוסף זמין במקורות המידע הבאים:
מידע על שימוש בסודות וב-ConfigMaps של Kubernetes זמין במאמר שימוש בסודות וב-ConfigMaps של Kubernetes.
מידע על שימוש בתבניות Jinja עם KubernetesPodOperator זמין במאמר שימוש בתבניות Jinja.
מידע על הפרמטרים של KubernetesPodOperator זמין בחומר העזר בנושא אופרטורים במסמכי Airflow.
שימוש בתבניות Jinja
Airflow תומך בתבניות Jinja ב-DAG.
צריך להצהיר על פרמטרים נדרשים של Airflow (task_id, name ו-image) באמצעות האופרטור. כמו שרואים בדוגמה הבאה, אפשר להשתמש ב-Jinja כדי ליצור תבנית לכל הפרמטרים האחרים, כולל cmds, arguments, env_vars ו-config_file.
הפרמטר env_vars בדוגמה מוגדר ממשתנה Airflow בשם my_value. ערך ה-DAG בדוגמה
מתקבל ממשתנה התבנית vars ב-Airflow. ל-Airflow יש עוד משתנים שמאפשרים גישה לסוגים שונים של מידע. לדוגמה, אפשר להשתמש במשתנה התבנית conf כדי לגשת לערכים של אפשרויות ההגדרה של Airflow. מידע נוסף ורשימת המשתנים שזמינים ב-Airflow מופיעים בחומר העזר בנושא תבניות במסמכי התיעוד של Airflow.
בלי לשנות את ה-DAG או ליצור את המשתנה env_vars, המשימה ex-kube-templates בדוגמה נכשלת כי המשתנה לא קיים. יוצרים את המשתנה הזה בממשק המשתמש של Airflow או באמצעות Google Cloud CLI:
ממשק המשתמש של Airflow
עוברים אל ממשק המשתמש של Airflow.
בסרגל הכלים, בוחרים באפשרות אדמין > משתנים.
בדף List Variable (משתנה רשימה), לוחצים על Add a new record (הוספת רשומה חדשה).
בדף Add Variable (הוספת משתנה), מזינים את הפרטים הבאים:
- מקש:
my_value - ערך:
example_value
- מקש:
לוחצים על Save.
gcloud
מזינים את הפקודה הבאה:
gcloud composer environments run ENVIRONMENT \
--location LOCATION \
variables set -- \
my_value example_value
מחליפים את:
-
ENVIRONMENTבשם הסביבה. -
LOCATIONעם האזור שבו הסביבה ממוקמת.
בדוגמה הבאה אפשר לראות איך משתמשים בתבניות Jinja עם KubernetesPodOperator:
שימוש בסודות וב-ConfigMaps של Kubernetes
סוד ב-Kubernetes הוא אובייקט שמכיל מידע רגיש. ConfigMap ב-Kubernetes הוא אובייקט שמכיל נתונים לא סודיים בצמדי מפתח-ערך.
ב-Managed Airflow (דור 2), אפשר ליצור Secrets ו-ConfigMaps באמצעות Google Cloud CLI, API או Terraform, ואז לגשת אליהם מ-KubernetesPodOperator.
מידע על קובצי הגדרות ב-YAML
כשיוצרים Kubernetes Secret או ConfigMap באמצעות Google Cloud CLI ו-API, צריך לספק קובץ בפורמט YAML. הפורמט של הקובץ הזה צריך להיות זהה לפורמט שבו משתמשים ב-Kubernetes Secrets וב-ConfigMaps. בתיעוד של Kubernetes יש הרבה דוגמאות קוד של ConfigMap ו-Secrets. כדי להתחיל, אפשר לעיין בדף הפצת פרטי כניסה בצורה מאובטחת באמצעות סודות ובמאמר בנושא ConfigMaps.
כמו ב-Kubernetes Secrets, צריך להשתמש בייצוג base64 כשמגדירים ערכים ב-Secrets.
כדי לקודד ערך, אפשר להשתמש בפקודה הבאה (זו אחת מתוך הרבה דרכים לקבל ערך מקודד בפורמט Base64):
echo "postgresql+psycopg2://root:example-password@127.0.0.1:3306/example-db" -n | base64
פלט:
cG9zdGdyZXNxbCtwc3ljb3BnMjovL3Jvb3Q6ZXhhbXBsZS1wYXNzd29yZEAxMjcuMC4wLjE6MzMwNi9leGFtcGxlLWRiIC1uCg==
בהמשך המדריך הזה נשתמש בשתי הדוגמאות הבאות של קובצי YAML. קובץ הגדרות לדוגמה ב-YAML בשביל סוד של Kubernetes:
apiVersion: v1
kind: Secret
metadata:
name: airflow-secrets
data:
sql_alchemy_conn: cG9zdGdyZXNxbCtwc3ljb3BnMjovL3Jvb3Q6ZXhhbXBsZS1wYXNzd29yZEAxMjcuMC4wLjE6MzMwNi9leGFtcGxlLWRiIC1uCg==
דוגמה נוספת שמראה איך לכלול קבצים. כמו בדוגמה הקודמת, קודם מקודדים את התוכן של קובץ (cat ./key.json | base64), ואז מספקים את הערך הזה בקובץ ה-YAML:
apiVersion: v1
kind: Secret
metadata:
name: service-account
data:
service-account.json: |
ewogICJ0eXBl...mdzZXJ2aWNlYWNjb3VudC5jb20iCn0K
קובץ הגדרות לדוגמה ב-YAML עבור ConfigMap. אין צורך להשתמש בייצוג base64 ב-ConfigMaps:
apiVersion: v1
kind: ConfigMap
metadata:
name: example-configmap
data:
example_key: example_value
ניהול סודות ב-Kubernetes
ב-Managed Airflow (דור 2), יוצרים סודות באמצעות Google Cloud CLI ו-kubectl:
קבלת מידע על האשכול בסביבה:
מריצים את הפקודה הבאה:
gcloud composer environments describe ENVIRONMENT \ --location LOCATION \ --format="value(config.gkeCluster)"מחליפים את:
ENVIRONMENTבשם של הסביבה.- מחליפים את
LOCATIONבאזור שבו נמצאת סביבת Managed Airflow.
הפלט של הפקודה הזו הוא בפורמט הבא:
projects/<your-project-id>/locations/<location-of-composer-env>/clusters/<your-cluster-id>.כדי לקבל את מזהה אשכול GKE, מעתיקים את הפלט אחרי
/clusters/(מסתיים ב--gke).
מתחברים לאשכול GKE באמצעות הפקודה הבאה:
gcloud container clusters get-credentials CLUSTER_ID \ --project PROJECT \ --region LOCATIONמחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_ID: מזהה האשכול של הסביבה. -
PROJECT_ID: מזהה הפרויקט. -
LOCATION: האזור שבו נמצאת הסביבה.
-
יצירת סודות של Kubernetes:
הפקודות הבאות מדגימות שתי גישות שונות ליצירת סודות של Kubernetes. בגישה
--from-literalמשתמשים בצמדי מפתח/ערך. הגישה--from-fileמשתמשת בתוכן הקובץ.כדי ליצור Kubernetes Secret על ידי ציון צמדי מפתח/ערך, מריצים את הפקודה הבאה. בדוגמה הזו נוצר סוד בשם
airflow-secretsעם שדהsql_alchemy_connוהערךtest_value.kubectl create secret generic airflow-secrets \ --from-literal sql_alchemy_conn=test_value -n composer-user-workloadsכדי ליצור סוד של Kubernetes על ידי ציון תוכן הקובץ, מריצים את הפקודה הבאה. בדוגמה הזו נוצר סוד בשם
service-accountעם השדהservice-account.jsonשהערך שלו נלקח מהתוכן של קובץ מקומי בשם./key.json.kubectl create secret generic service-account \ --from-file service-account.json=./key.json -n composer-user-workloads
שימוש ב-Kubernetes Secrets ב-DAG
בדוגמה הזו מוצגות שתי דרכים להשתמש ב-Kubernetes Secrets: כמשתנה סביבתי וכנפח שמוטמע על ידי ה-Pod.
הסוד הראשון, airflow-secrets, מוגדר כמשתנה סביבה של Kubernetes בשם SQL_CONN (בניגוד למשתנה סביבה של Airflow או Managed Airflow).
הסוד השני, service-account, מטמיע את service-account.json, קובץ עם טוקן של חשבון שירות, ב-/var/secrets/google.
כך נראים אובייקטים מסוג Secret:
השם של סוד Kubernetes הראשון מוגדר במשתנה secret_env.
הסוד הזה נקרא airflow-secrets. הפרמטר deploy_type מציין שהמשתנה צריך להיות חשוף כמשתנה סביבה. השם של משתנה הסביבה הוא SQL_CONN, כפי שצוין בפרמטר deploy_target. לבסוף, הערך של משתנה הסביבה SQL_CONN מוגדר לערך של המפתח sql_alchemy_conn.
השם של הסוד השני ב-Kubernetes מוגדר במשתנה secret_volume. הסוד הזה נקרא service-account. הוא נחשף כנפח, כפי שמצוין בפרמטר deploy_type. הנתיב של הקובץ שצריך לטעון, deploy_target, הוא /var/secrets/google. לבסוף, הערך key של הסוד שמאוחסן ב-deploy_target הוא service-account.json.
כך נראית הגדרת האופרטור:
מידע על ספק CNCF Kubernetes
האופרטור KubernetesPodOperator מיושם בספק apache-airflow-providers-cncf-kubernetes.
הערות מפורטות על הגרסה של ספק CNCF Kubernetes זמינות באתר של ספק CNCF Kubernetes.
גרסה 6.0.0
בגרסה 6.0.0 של חבילת הספק CNCF Kubernetes, נעשה שימוש בחיבור kubernetes_default כברירת מחדל ב-KubernetesPodOperator.
אם ציינתם חיבור בהתאמה אישית בגרסה 5.0.0, המפעיל עדיין משתמש בחיבור הזה. כדי לחזור לשימוש בחיבור kubernetes_default, יכול להיות שתצטרכו לשנות את הגדרות ה-DAG בהתאם.
גרסה 5.0.0
בגרסה הזו יש כמה שינויים שלא תואמים לאחור בהשוואה לגרסה 4.4.0. החשובים ביותר קשורים לkubernetes_defaultחיבור שלא נמצא בשימוש בגרסה 5.0.0.
- צריך לשנות את החיבור של
kubernetes_default. נתיב ההגדרה של Kubernetes צריך להיות מוגדר ל-/home/airflow/composer_kube_config(כמו שמוצג באיור הבא). לחלופין, צריך להוסיף אתconfig_fileלהגדרות של KubernetesPodOperator (כמו בדוגמת הקוד הבאה).
- כדי לשנות את הקוד של משימה באמצעות KubernetesPodOperator, פועלים לפי השלבים הבאים:
KubernetesPodOperator(
# config_file parameter - can be skipped if connection contains this setting
config_file="/home/airflow/composer_kube_config",
# definition of connection to be used by the operator
kubernetes_conn_id='kubernetes_default',
...
)
מידע נוסף על גרסה 5.0.0 זמין בהערות המוצר של ספק Kubernetes של CNCF.
פתרון בעיות
בקטע הזה מפורטות הצעות לפתרון בעיות נפוצות שקשורות ל-KubernetesPodOperator:
צפייה ביומנים
כשמנסים לפתור בעיות, אפשר לבדוק את היומנים בסדר הבא:
יומני משימות של Airflow:
נכנסים לדף Environments במסוף Google Cloud .
ברשימת הסביבות, לוחצים על שם הסביבה. הדף Environment details ייפתח.
עוברים לכרטיסייה DAGs.
לוחצים על השם של ה-DAG ואז על ההרצה של ה-DAG כדי לראות את הפרטים והיומנים.
יומנים של מתזמן Airflow:
עוברים לדף פרטי הסביבה.
עוברים לכרטיסייה יומנים.
בודקים את היומנים של מתזמן Airflow.
יומני Pod במסוף Google Cloud , בקטע GKE workloads. היומנים האלה כוללים את קובץ ה-YAML של הגדרת ה-Pod, אירועי ה-Pod ופרטי ה-Pod.
קודי החזרה שאינם אפס
כשמשתמשים ב-KubernetesPodOperator (וב-GKEStartPodOperator), קוד החזרה של נקודת הכניסה של הקונטיינר קובע אם המשימה נחשבת למוצלחת או לא. קודי החזרה שאינם אפס מציינים כשל.
דפוס נפוץ הוא להריץ סקריפט של מעטפת כנקודת הכניסה של הקונטיינר כדי לקבץ כמה פעולות בתוך הקונטיינר.
אם אתם כותבים סקריפט כזה, מומלץ לכלול את הפקודה set -e בראש הסקריפט, כדי שפקודות שנכשלו בסקריפט יסיימו את הסקריפט ויעבירו את הכשל למופע המשימה של Airflow.
הזמן הקצוב לתפוגה של Pod
זמן הקצוב לתפוגה (timeout) שמוגדר כברירת מחדל ב-KubernetesPodOperator הוא 120 שניות, מה שיכול לגרום לזמני קצוב לתפוגה לפני הורדה של תמונות גדולות יותר. אפשר להגדיל את הזמן הקצוב לתפוגה באמצעות שינוי הפרמטר startup_timeout_seconds כשיוצרים את KubernetesPodOperator.
כשפוד מגיע לזמן קצוב לתפוגה, היומן הספציפי למשימה זמין בממשק המשתמש של Airflow. לדוגמה:
Executing <Task(KubernetesPodOperator): ex-all-configs> on 2018-07-23 19:06:58.133811
Running: ['bash', '-c', u'airflow run kubernetes-pod-example ex-all-configs 2018-07-23T19:06:58.133811 --job_id 726 --raw -sd DAGS_FOLDER/kubernetes_pod_operator_sample.py']
Event: pod-name-9a8e9d06 had an event of type Pending
...
...
Event: pod-name-9a8e9d06 had an event of type Pending
Traceback (most recent call last):
File "/usr/local/bin/airflow", line 27, in <module>
args.func(args)
File "/usr/local/lib/python2.7/site-packages/airflow/bin/cli.py", line 392, in run
pool=args.pool,
File "/usr/local/lib/python2.7/site-packages/airflow/utils/db.py", line 50, in wrapper
result = func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/airflow/models.py", line 1492, in _run_raw_task
result = task_copy.execute(context=context)
File "/usr/local/lib/python2.7/site-packages/airflow/contrib/operators/kubernetes_pod_operator.py", line 123, in execute
raise AirflowException('Pod Launching failed: {error}'.format(error=ex))
airflow.exceptions.AirflowException: Pod Launching failed: Pod took too long to start
יכול להיות שפסק זמן של Pod יתרחש גם אם ל-Managed Airflow חסרות הרשאות ה-IAM הנדרשות לביצוע המשימה. כדי לוודא זאת, אפשר להשתמש בלוחות הבקרה של GKE כדי לבדוק את היומנים של עומס העבודה הספציפי, או להשתמש ב-Cloud Logging.
יצירת חיבור חדש נכשלה
השדרוג האוטומטי מופעל כברירת מחדל באשכולות GKE. אם מאגר הצמתים נמצא באשכול שעובר שדרוג, יכול להיות שתופיע השגיאה הבאה:
<Task(KubernetesPodOperator): gke-upgrade> Failed to establish a new
connection: [Errno 111] Connection refused
כדי לבדוק אם האשכול עובר שדרוג, במסוף Google Cloud , עוברים לדף Kubernetes clusters ומחפשים את סמל הטעינה לצד שם האשכול של הסביבה.