פיתוח InnerLoop באמצעות Cloud Workstations עם Python

1. סקירה כללית

שיעור ה-Lab הזה להדגים תכונות ויכולות שנועדו לייעל את תהליך הפיתוח עבור מהנדסי תוכנה שאחראים על פיתוח אפליקציות Python בסביבה בקונטיינרים. פיתוח אופייני של קונטיינרים מחייב את המשתמשים להבין את הפרטים של קונטיינרים ואת תהליך הפיתוח של הקונטיינרים. בנוסף, בדרך כלל מפתחים צריכים לפרוץ את התהליך ולצאת מסביבת הפיתוח המשולבת (IDE) שלהם כדי לבדוק את האפליקציות שלהם ולנפות באגים בסביבות מרוחקות. בעזרת הכלים והטכנולוגיות שמוזכרים במדריך הזה, מפתחים יכולים לעבוד ביעילות עם אפליקציות בקונטיינרים בלי לצאת מסביבת הפיתוח המשולבת (IDE).

מה תלמדו

בשיעור ה-Lab הזה תלמדו שיטות לפיתוח עם קונטיינרים ב-GCP, כולל:

  • יצירת אפליקציה חדשה של Python לתחילת פעולה
  • תסביר לי על תהליך הפיתוח
  • פיתוח שירות מנוחה פשוט מסוג CRUD
  • פריסה ב-GKE
  • ניפוי באגים במצב שגיאה
  • שימוש בנקודת עצירה (breakpoint) / ביומנים
  • שינויים בפריסה חמה בחזרה ב-GKE

58a4cdd3ed7a123a.png

2. הגדרה ודרישות

הגדרת סביבה בקצב אישי

  1. נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. אפשר לעדכן אותו בכל שלב.
  • Project ID הוא ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-Codelabs תצטרכו להפנות אל מזהה הפרויקט (בדרך כלל הוא מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניך, יש לך אפשרות ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות תבנית משלך ולבדוק אם היא זמינה. לא ניתן לשנות אותו אחרי השלב הזה, והוא יישאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי – Project Number (מספר פרויקט), שחלק מממשקי ה-API משתמשים בו. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. כדי להשבית את המשאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט כולו. משתמשים חדשים ב-Google Cloud זכאים להצטרף לתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloudshell Editor

שיעור ה-Lab הזה תוכנן ונבדק לשימוש עם Google Cloud Shell Editor. כדי לגשת לכלי העריכה:

  1. ניגשים לפרויקט Google בכתובת https://console.cloud.google.com.
  2. בפינה השמאלית העליונה, לוחצים על סמל העורך של Cloud Shell

8560cc8d45e8c112.png

  1. חלונית חדשה תיפתח בחלק התחתון של החלון
  2. לוחצים על הלחצן 'פתיחת העורך'.

9e504cb98a6a8005.png

  1. העורך ייפתח בצד שמאל עם כלי חקירה משמאל ועורך באזור המרכזי.
  2. חלונית טרמינל אמורה להיות זמינה גם בחלק התחתון של המסך
  3. אם הטרמינל לא פתוח, משתמשים בשילוב המקשים של 'Ctrl+' כדי לפתוח חלון טרמינל חדש

הגדרת סביבה

ב-Cloud Shell, מגדירים את מזהה הפרויקט ואת מספר הפרויקט. שומרים אותם כמשתנים מסוג PROJECT_ID ו-PROJECT_ID.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

הקצאת התשתית שבה נעשה שימוש בשיעור ה-Lab הזה

בשיעור ה-Lab הזה תפרסו קוד ל-GKE ותגשו לנתונים שמאוחסנים במסד הנתונים של Spanner. גם תחנות העבודה של Cloud ישמשו כסביבת הפיתוח המשולבת (IDE). סקריפט ההגדרה שבהמשך מכין את התשתית הזו עבורכם.

  1. צריך להוריד את סקריפט ההגדרה ולהפוך אותו לניתן להפעלה.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/setup_with_cw.sh
chmod +x setup_with_cw.sh
  1. פתיחת הקובץ setup_with_cw.sh ועריכה של ערכי הסיסמאות המוגדרים כרגע כ-CHANGEME
  2. תריצו את סקריפט ההגדרה כדי לעמוד באשכול GKE ובמסד הנתונים של Spanner שבו תשתמשו בשיעור ה-Lab הזה
./setup_with_cw.sh &

אשכול Cloud Workstations

  1. פותחים את Cloud Workstations במסוף Cloud. ממתינים שהאשכול יהיה בסטטוס READY.

305e1a3d63ac7ff6.png

יצירת תצורה של תחנות עבודה

  1. אם הסשן של Cloud Shell התנתק, צריך ללחוץ על Reconnect (התחברות מחדש). ואז מריצים את הפקודה cli של gcloud כדי להגדיר את מזהה הפרויקט. לפני הרצת הפקודה, צריך להחליף את מזהה הפרויקט לדוגמה שבהמשך במזהה הפרויקט ב-qwiklabs.
gcloud config set project qwiklabs-gcp-project-id
  1. כדי ליצור תצורה של Cloud Workstations, צריך להוריד בטרמינל את הסקריפט הבא ולהריץ אותו.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/python/workstation_config_setup.sh
chmod +x workstation_config_setup.sh
./workstation_config_setup.sh
  1. מאמתים את התוצאות בקטע 'הגדרות אישיות'. המעבר לסטטוס READY יימשך 2 דקות.

2e23c2e9983d1ccf.png

  1. פותחים את Cloud Workstations במסוף ויוצרים מכונה חדשה.

a53adeeac81a78c8.png

  1. שינוי השם ל-my-workstation ובחירה בהגדרה הקיימת: codeoss-python.

f052cd47701ec774.png

  1. מאמתים את התוצאות בקטע 'תחנות עבודה'.

הפעלה של תחנת העבודה

  1. מפעילים את תחנת העבודה. תחנת העבודה תתחיל לפעול תוך כמה דקות.

682f8a307032cba3.png

  1. אפשר להשתמש בקובצי Cookie של צד שלישי על ידי לחיצה על הסמל בסרגל הכתובות. 1b8923e2943f9bc4.png

fcf9405b6957b7d7.png

  1. לוחצים על "האתר לא פועל?".

36a84c0e2e3b85b.png

  1. לוחצים על "אפשר להשתמש בקובצי Cookie".

2259694328628fba.png

  1. ברגע שתושק תחנת העבודה, יופיע סביבת פיתוח משולבת (IDE) של Code OSS. לוחצים על 'סימון כ'בוצע''. בדף 'תחילת העבודה', סביבת הפיתוח המשולבת (IDE) של תחנת העבודה

94874fba9b74cc22.png

3. יצירת אפליקציה חדשה של Python לתחילת פעולה

בקטע הזה יוצרים אפליקציית Python חדשה.

  1. פותחים חלון Terminal חדש.

c31d48f2e4938c38.png

  1. יצירת ספרייה חדשה ופתיחתה כסביבת עבודה
mkdir music-service && cd music-service

code-oss-cloud-workstations -r --folder-uri="$PWD"

אם ההודעה הזו מופיעה, צריך ללחוץ על הלחצן Allow (אישור), כדי להעתיק את ההדבקה לתחנת העבודה.

58149777e5cc350a.png

  1. יוצרים קובץ בשם requirements.txt ומעתיקים אליו את התוכן הבא

789e8389170bd900.png

Flask
gunicorn
google-cloud-spanner
ptvsd==4.3.2
  1. יוצרים קובץ בשם app.py ומדביקים בו את הקוד הבא
import os
from flask import Flask, request, jsonify
from google.cloud import spanner

app = Flask(__name__)

@app.route("/")
def hello_world():
    message="Hello, World!"
    return message

if __name__ == '__main__':
    server_port = os.environ.get('PORT', '8080')
    app.run(debug=False, port=server_port, host='0.0.0.0')

  1. יוצרים קובץ בשם Dockerfile ומדביקים בו את הפרטים הבאים
FROM python:3.8
ARG FLASK_DEBUG=0
ENV FLASK_DEBUG=$FLASK_DEBUG
ENV FLASK_APP=app.py
WORKDIR /app
COPY requirements.txt .
RUN pip install --trusted-host pypi.python.org -r requirements.txt
COPY . .
ENTRYPOINT ["python3", "-m", "flask", "run", "--port=8080", "--host=0.0.0.0"]

הערה: בעזרת FLASK_DEBUG=1 אפשר לטעון מחדש באופן אוטומטי שינויי קוד באפליקציית בקבוקון Python. קובץ ה-Docker הזה מאפשר להעביר את הערך הזה כארגומנט build.

יצירת מניפסטים

בטרמינל, מריצים את הפקודה הבאה כדי ליצור ברירת מחדל של skaffold.yaml ו-Deploy.yaml

  1. אתחול Skaffold באמצעות הפקודה הבאה
skaffold init --generate-manifests

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

בוחרים אפשרות:

  • 8080 לשקע
  • y כדי לשמור את ההגדרה

עדכון ההגדרות של Skaffold

  • שינוי שם האפליקציה שמוגדר כברירת מחדל
  • פתיחה של skaffold.yaml
  • בחירת שם התמונה שמוגדר כרגע בתור dockerfile-image
  • לוחצים לחיצה ימנית ובוחרים באפשרות 'שינוי כל המופעים'
  • יש להקליד את השם החדש בתור python-app
  • ממשיכים לערוך את קטע ה-build כדי
  • הוספה של docker.buildArgs כדי לעבור את FLASK_DEBUG=1
  • צריך לסנכרן את ההגדרות כדי לטעון את השינויים בקובצי *.py מסביבת פיתוח משולבת (IDE) למאגר התגים שפועל

אחרי העריכות, קטע ה-build בקובץ skaffold.yaml יהיה:

build:
 artifacts:
 - image: python-app
   docker:
     buildArgs:
       FLASK_DEBUG: "1"
     dockerfile: Dockerfile
   sync:
     infer:
     - '**/*.py'

שינוי קובץ התצורה של Kubernetes

  1. שינוי השם שמוגדר כברירת המחדל
  • פתיחת קובץ אחד (deployment.yaml)
  • בחירת שם התמונה שמוגדר כרגע בתור dockerfile-image
  • לוחצים לחיצה ימנית ובוחרים באפשרות 'שינוי כל המופעים'
  • יש להקליד את השם החדש בתור python-app

4. להדרכה על תהליך הפיתוח

אחרי שמוסיפים את הלוגיקה העסקית, אפשר לפרוס את האפליקציה ולבדוק אותה. בקטע הבא מוסבר איך משתמשים בפלאגין של Cloud Code. בין היתר, הפלאגין הזה משתלב עם skaffold כדי לפשט את תהליך הפיתוח. כשפורסים ל-GKE בשלבים הבאים, Cloud Code ו-Skaffold ייצרו באופן אוטומטי את קובץ האימג' של הקונטיינר, העבירו אותו ל-Container Registry ולאחר מכן פורסים את האפליקציה your ב-GKE. התהליך הזה מתרחש מאחורי הקלעים מבלי לכלול את הפרטים הנדרשים בתהליך הפיתוח.

כניסה ל-Google Cloud

  1. לוחצים על הסמל של Cloud Code ובוחרים באפשרות "Sign in to Google Cloud" (כניסה ל-Google Cloud):

1769afd39be372ff.png

  1. לוחצים על 'המשך לכניסה'.

923bb1c8f63160f9.png

  1. בודקים את הפלט ב-Terminal ופותחים את הקישור:

517fdd579c34aa21.png

  1. מתחברים עם פרטי הכניסה של התלמידים ב-Qwiklabs.

db99b345f7a8e72c.png

  1. בוחרים באפשרות 'יש אישור':

a5376553c430ac84.png

  1. מעתיקים את קוד האימות וחוזרים לכרטיסייה 'תחנת עבודה'.

6719421277b92eac.png

  1. מדביקים את קוד האימות ומקישים על Enter.

e9847cfe3fa8a2ce.png

הוספת אשכול Kubernetes

  1. הוספת אשכול

62a3b97bdbb427e5.png

  1. בחירת Google Kubernetes Engine:

9577de423568bbaa.png

  1. בוחרים פרויקט.

c5202fcbeebcd41c.png

  1. בוחרים באפשרות 'אשכול python' שנוצר בהגדרה הראשונית.

719c2fc0a7f9e84f.png

  1. האשכול יופיע עכשיו ברשימת אשכולות Kubernetes בקטע Cloud Code. מכאן אפשר לנווט באשכול ולחקור אותו.

7e5f50662d4eea3c.png

הגדרת מזהה הפרויקט הנוכחי באמצעות cli של gcloud

  1. מעתיקים את מזהה הפרויקט לשיעור ה-Lab הזה מהדף qwiklabs.

fcff2d10007ec5bc.png

  1. בטרמינל, מריצים את הפקודה cli של gcloud כדי להגדיר את מזהה הפרויקט. לפני הרצת הפקודה, צריך להחליף את מזהה הפרויקט לדוגמה. צריך להחליף את מזהה הפרויקט לפני הרצת הפקודה הבאה.
gcloud config set project qwiklabs-gcp-project-id

פריסה ב-Kubernetes

  1. בחלונית שבחלק התחתון של Cloud Shell Editor, בוחרים באפשרות Cloud Code כוללת

d99a88992e15fea9.png

  1. בחלונית שמופיעה בחלק העליון, בוחרים באפשרות הפעלה ב-Kubernetes. אם מוצגת הנחיה, בוחרים באפשרות 'כן' כדי להשתמש בהקשר הנוכחי של Kubernetes.

bfd65e9df6d4a6cb.png

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

  1. בפעם הראשונה שמריצים את הפקודה, תופיע בחלק העליון של המסך הנחיה לשאול אם אתם רוצים את ההקשר הנוכחי של ה-kubernetes, צריך לבחור באפשרות 'כן'. לקבל את ההקשר הנוכחי ולהשתמש בו.
  2. בשלב הבא תוצג הודעה שמבקשת באיזה מרשם להשתמש. צריך להקיש על Enter כדי לאשר את ערך ברירת המחדל שצוין
  3. בוחרים באפשרות 'פלט'. בחלונית התחתונה כדי להציג את ההתקדמות וההתראות. באמצעות התפריט הנפתח, בוחרים באפשרות Kubernetes: Run/Debug.

9c87ccbf5d06f50a.png

  1. בוחרים באפשרות 'Kubernetes: הרצה/ניפוי באגים – פירוט'. בתפריט הנפתח של הערוץ משמאל כדי להציג פרטים נוספים ויומנים בסטרימינג בשידור חי ממאגרי התגים

804abc8833ffd571.png

בסיום ה-build והבדיקות, כתובת ה-URL http://localhost:8080 תופיע במסגרת Kubernetes: Run/Debug ביומני הכרטיסייה 'פלט'. צפייה.

  1. בטרמינל של Cloud Code, מעבירים את העכבר מעל כתובת ה-URL הראשונה בפלט (http://localhost:8080) ואז בטיפ הכלי שמופיע, בוחרים באפשרות Open Web Preview.
  2. תיפתח כרטיסייה חדשה בדפדפן שבה תוצג ההודעה Hello, World!

טעינה מחדש מתוך הזיכרון (hot Reload)

  1. פתיחת הקובץ app.py
  2. שינוי של הודעת הפתיחה לHello from Python

שימו לב שבחלון Output, בתצוגה Kubernetes: Run/Debug, המעקב מסנכרן את הקבצים המעודכנים עם הקונטיינר ב-Kubernetes.

Update initiated
Build started for artifact python-app
Build completed for artifact python-app

Deploy started
Deploy completed

Status check started
Resource pod/python-app-6f646ffcbb-tn7qd status updated to In Progress
Resource deployment/python-app status updated to In Progress
Resource deployment/python-app status completed successfully
Status check succeeded
...
  1. אם עוברים לתצוגה Kubernetes: Run/Debug - Detailed, רואים שהיא מזהה שינויים בקבצים, ואז בונה ופורס את האפליקציה מחדש
files modified: [app.py]
Syncing 1 files for gcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Copying files:map[app.py:[/app/app.py]]togcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Watching for changes...
[python-app] * Detected change in '/app/app.py', reloading
[python-app] * Restarting with stat
[python-app] * Debugger is active!
[python-app] * Debugger PIN: 744-729-662
  1. כדי לראות את התוצאות המעודכנות, צריך לרענן את הכרטיסייה בדפדפן במקום שבו ראיתם את התוצאות הקודמות.

ניפוי באגים

  1. עוברים לתצוגת ניפוי הבאגים ומפסיקים את השרשור הנוכחי 647213126d7a4c7b.png. אם מוצגת בקשה, תוכלו לפנות מקום אחרי כל הרצה.
  2. 70d6bd947d04d1e6.png
  3. לוחצים על Cloud Code בתפריט התחתון ובוחרים באפשרות Debug on Kubernetes כדי להריץ את האפליקציה במצב debug.
  • בתצוגה Kubernetes Run/Debug - Detailed של החלון Output, שימו לב ש-skaffold יפרוס את האפליקציה הזו במצב ניפוי באגים.
  1. בסיום התהליך. יופיע כלי לניפוי באגים, ובכרטיסייה 'פלט' יופיע הכיתוב: Attached debugger to container "python-app-8476f4bbc-h6dsl" successfully. וכתובת ה-URL http://localhost:8080 מופיעה.
Port forwarding pod/python-app-8bd64cf8b-cskfl in namespace default, remote port 5678 -> http://127.0.0.1:5678
  1. הצבע של שורת הסטטוס התחתונה משתנה מכחול לכתום, כדי לציין שהיא במצב ניפוי באגים.
  2. בתצוגה Kubernetes Run/Debug, ניתן לראות שהופעל מאגר תגים שניתן לניפוי באגים
**************URLs*****************
Forwarded URL from service python-app: http://localhost:8080
Debuggable container started pod/python-app-8bd64cf8b-cskfl:python-app (default)
Update succeeded
***********************************

שימוש בנקודות עצירה (breakpoint)

  1. פתיחת הקובץ app.py
  2. יש למצוא את ההצהרה שבה כתוב return message
  3. כדי להוסיף נקודת עצירה לשורה הזו, לוחצים על הרווח הריק שמימין למספר השורה. יוצג אינדיקטור אדום כדי לציין שנקודת העצירה הוגדרה
  4. בפעם הראשונה שתפעילו את הקובץ, תוצג שאלה איפה המקור נמצא בתוך הקונטיינר. הערך הזה קשור לספריות בקובץ Docker.

צריך להקיש על Enter כדי לאשר את ברירת המחדל

fccc866f32b5ed86.png

תהליך הפיתוח והפריסה של האפליקציה נמשך כמה דקות.

  1. טוענים מחדש את הדפדפן ומציינים שהכלי לניפוי באגים עוצר את התהליך בנקודת העצירה (breakpoint) ומאפשר לכם לחקור את המשתנים והמצב של האפליקציה שרצה מרחוק ב-GKE
  2. לוחצים למטה לקטע 'משתנים'
  3. לוחצים על 'מקומיים' כדי להציג את המשתנה "message".
  4. לוחצים לחיצה כפולה על שם המשתנה 'message'. בחלון הקופץ, משנים את הערך למשהו אחר, כמו "Greetings from Python"
  5. לוחצים על הלחצן 'המשך' בלוח הבקרה של ניפוי הבאגים 607c33934f8d6b39.png.
  6. בודקים את התשובה בדפדפן, שמציגה עכשיו את הערך המעודכן שהזנתם.
  7. איך מפסיקים את 'ניפוי הבאגים' במצב 'הפסקה', לוחצים שוב על לחצן העצירה 647213126d7a4c7b.png ומסירים את נקודת העצירה בלחיצה חוזרת על נקודת העצירה.

5. פיתוח שירות CRUD מסוג מנוחה פשוט

בשלב הזה האפליקציה מוגדרת במלואה לפיתוח בקונטיינרים, והסברתם על תהליך הפיתוח הבסיסי באמצעות Cloud Code. בחלקים הבאים תתרגלו את מה שלמדתם על ידי הוספת נקודות קצה של שירותי מנוחה שמתחברות למסד נתונים מנוהל ב-Google Cloud.

יצירת קוד לשירות השאר

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

  1. כדי ליצור את האפליקציה הראשית, צריך להחליף את app.py בתוכן הבא
import os
from flask import Flask, request, jsonify
from google.cloud import spanner


app = Flask(__name__)


instance_id = "music-catalog"

database_id = "musicians"

spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route('/singer', methods=['POST'])
def create():
    try:
        request_json = request.get_json()
        singer_id = request_json['singer_id']
        first_name = request_json['first_name']
        last_name = request_json['last_name']
        def insert_singers(transaction):
            row_ct = transaction.execute_update(
                f"INSERT Singers (SingerId, FirstName, LastName) VALUES" \
                f"({singer_id}, '{first_name}', '{last_name}')"
            )
            print("{} record(s) inserted.".format(row_ct))

        database.run_in_transaction(insert_singers)

        return {"Success": True}, 200
    except Exception as e:
        return e



@app.route('/singer', methods=['GET'])
def get_singer():

    try:
        singer_id = request.args.get('singer_id')
        def get_singer():
            first_name = ''
            last_name = ''
            with database.snapshot() as snapshot:
                results = snapshot.execute_sql(
                    f"SELECT SingerId, FirstName, LastName FROM Singers " \
                    f"where SingerId = {singer_id}",
                    )
                for row in results:
                    first_name = row[1]
                    last_name = row[2]
                return (first_name,last_name )
        first_name, last_name = get_singer()  
        return {"first_name": first_name, "last_name": last_name }, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['PUT'])
def update_singer_first_name():
    try:
        singer_id = request.args.get('singer_id')
        request_json = request.get_json()
        first_name = request_json['first_name']
        
        def update_singer(transaction):
            row_ct = transaction.execute_update(
                f"UPDATE Singers SET FirstName = '{first_name}' WHERE SingerId = {singer_id}"
            )

            print("{} record(s) updated.".format(row_ct))

        database.run_in_transaction(update_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e


@app.route('/singer', methods=['DELETE'])
def delete_singer():
    try:
        singer_id = request.args.get('singer')
    
        def delete_singer(transaction):
            row_ct = transaction.execute_update(
                f"DELETE FROM Singers WHERE SingerId = {singer_id}"
            )
            print("{} record(s) deleted.".format(row_ct))

        database.run_in_transaction(delete_singer)
        return {"Success": True}, 200
    except Exception as e:
        return e

port = int(os.environ.get('PORT', 8080))
if __name__ == '__main__':
    app.run(threaded=True, host='0.0.0.0', port=port)

הוספת הגדרות של מסד נתונים

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

  1. יש לעדכן את deployment.yaml. מוסיפים את הקוד הבא בסוף הקובץ (חשוב לוודא שכניסות הטאבים נשמרות בדוגמה למטה)
      serviceAccountName: python-ksa
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true" 

אחרי השינויים, קטע המפרט אמור להיראות כך

   spec:
     containers:
     - name: python-app
       image: python-app
     serviceAccountName: python-ksa
     nodeSelector:
       iam.gke.io/gke-metadata-server-enabled: "true"

פריסה ואימות של אפליקציה

  1. בחלונית שבחלק התחתון של Cloud Shell Editor, בוחרים באפשרות Cloud Code ואז בוחרים באפשרות Debug on Kubernetes בחלק העליון של המסך.
  2. בסיום ה-build והבדיקות, בכרטיסייה 'פלט' מופיע הכיתוב: Resource deployment/python-app status completed successfully, וכתובת ה-URL מופיעה: 'כתובת URL שהועברה משירות python-app: http://localhost:8080'
  3. צריך להוסיף כמה רשומות.

מ-cloudshell Terminal, מריצים את הפקודה הבאה

curl -X POST http://localhost:8080/singer -H 'Content-Type: application/json' -d '{"first_name":"Cat","last_name":"Meow", "singer_id": 6}'
  1. כדי לבדוק את בקשת ה-GET מריצים את הפקודה הבאה בטרמינל
curl -X GET http://localhost:8080/singer?singer_id=6
  1. Test Delete: עכשיו אפשר לנסות למחוק רשומה על ידי הרצת הפקודה הבאה. אם צריך, משנים את הערך של מזהה הפריט.
curl -X DELETE http://localhost:8080/singer?singer_id=6
    This throws an error message
500 Internal Server Error

זיהוי ותיקון הבעיה

  1. במצב ניפוי באגים ומוצאים את הבעיה. ריכזנו בשבילכם כמה טיפים:
  • אנחנו יודעים שמשהו השתבש ב-DELETE כי היא לא מחזירה את התוצאה הרצויה. לכן צריך להגדיר את נקודת העצירה (breakpoint) ב-app.py בשיטה delete_singer.
  • מריצים שלב אחרי שלב ועוקבים אחרי המשתנים בכל שלב כדי לתעד את הערכים של המשתנים המקומיים בחלון השמאלי.
  • כדי להבחין בערכים ספציפיים כמו singer_id ו-request.args, צריך להוסיף את המשתנים האלה לחלון הצפייה.
  1. חשוב לשים לב שהערך שהוקצה ל-singer_id הוא None. כדי לפתור את הבעיה, משנים את הקוד.

קטע הקוד הקבוע ייראה כך.

@app.route('/delete-singer', methods=['DELETE', 'GET'])
def delete_singer():
    try:
        singer_id = request.args.get('singer_id')
  1. לאחר הפעלת האפליקציה מחדש, בודקים שוב על ידי ניסיון המחיקה.
  2. כדי להפסיק את פעילות ניפוי הבאגים, לוחצים על הריבוע האדום בסרגל הכלים של ניפוי הבאגים 647213126d7a4c7b.png

6. הסרת המשאבים

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

כדי לפנות מקום אחרי שמשלימים את שיעור ה-Lab:

  1. מחיקת הקבצים ששימשו בשיעור ה-Lab
cd ~ && rm -rf ~/music-service
  1. מחיקת הפרויקט כדי להסיר את כל התשתית והמשאבים הקשורים