הרצת אפליקציית קונטיינר בסביבות שונות
במעבדה זו ניתן לרכוש את הידע ולהתאמן בנושאים הבאים:
1. עבודה עם Docker ויצירת קונטיינר.
2. Artifact Registry.
3. Cloud Run.
4. GKE ו-Kubernetes.
הקדמה:
מעבדה זו מהווה המשך למעבדה הקודמת, שבה הודגם כיצד לכתוב תכנית פייתון ולהפוך אותה לאפליקציית Web. כאן כהמשך, נלמד להעביר את האפליקציה לקונטיינר ולעבוד איתה במגוון סביבות ענן.
עבודה עם קונטיינרים מהווה הליך חשוב בתכנון, שדרוג, בניה מחדש, הגירה ושגרת עבודה עדכנית ויעילה של אפליקציות ושירותים.
העבודה באמצעות קונטיינרים מאפשרת חסכון ויעילות בניצול משאבים, ניידות רבה וקלה בין סביבות, אמצעים וספקים שונים, והליכי CI\CD קלים וזריזים.
במעבדה זו השתדלתי לתת גישה ראשונית לסביבות מבוססות קונטיינרים, ולהדגים כיצד אפליקציה שנעטפה לקונטיינר, יכולה לרוץ בסביבות שונות.
רובו של המדריך מלמד כיצד לנהל את הסביבות השונות. כי ברגע שהסביבה קיימת ומנוהלת והקונטיינר בנוי נכון, להריץ אותו על הסביבה זה עניין פשוט יחסית.
עבודה עם Docker:
קודם נרצה סביבה שבה נוכל לבנות קונטיינר וגם לנסות שהוא עובד. ב-Cloud Shell כבר מותקנים הכלים שאנחנו צריכים כמו Docker ו-Git. אבל יהיה לנו קצת קשה לבחון את האפליקציה בסביבה הזו. אז נקים לנו שרת Ununtu בגודל מיקרו בשם docker-test, כאשר עם ההקמה נסמן בסעיף של Firewall – Allow HTTP traffic.
בנוסף, תחת Identity and API access יש את Access scopes, שם נבחר Allow full access to all Cloud APIs. נצטרך את זה בהמשך. כל השאר כברירת מחדל.
לאחר שהשרת עלה ומוכן, נתחבר אליו באמצעות לחצן SSH ושם נתקין את הכלים.
התקנת דוקר:
לאחר ההתחברות לשרת, נריץ בתוכו את הפקודות הבאות:
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# Install Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
יצירת קונטיינר:
ניצור שם את התיקיה app-files ואז נכנס אליה באמצעות הפקודה:
mkdir app-files && cd app-files
ואז נעתיק אליה את קבצי המשחק (הפניה למעבדה הקודמת) מתוך GitHub:
git clone https://github.com/yoson7/Linkedin-Articles.git .
הנקודה בסוף אומרת שאנחנו מורידים את התוכן מתוך ה-Repository למיקום בו אנו נמצאים.
כעת שהקבצים איתנו, ניצור Dockerfile. זהו קובץ שאומר ל-Docker כיצד לבנות Container Image.
Dockerfile:
עם הפקודה – nano Dockerfile, יפתח עורך הטקסט ושם נדביק את התוכן הבא:
FROM nginx
ADD BreakBricks/works/build /usr/share/nginx/html
RUN sed -i 's\root /usr/share/nginx/html;\root /usr/share/nginx/html/web;\g' /etc/nginx/conf.d/default.conf
EXPOSE 80
לשמור ולסגור.
הסבר על התוכן:
כל השורות הבאות בונות Image מתוך בסיס מסוים. על אותו הבסיס נרצה להוסיף דברים, לשנות, למחוק חלק ולערוך חלק. לפעמים לא נכיר את מבנה עץ התיקיות של ה-Image שעליו נרצה לעבוד. כדי לדעת מה ואיפה לשנות, נמשוך את ה-Image ונריץ אותו כקונטיינר. כשאנחנו מתחברים פנימה, נוכל לבחון את עץ התיקיות. כך נדע לאן צריך להעתיק קבצים ואיזה הגדרות צריך לערוך.
נגיד שנרצה פשוט להריץ את ה-Image הבסיסי של nginx. אז נתחבר פנימה כדי לבחון את עץ התיקיות ואת הגדרות ה-nginx בפנים. נשתמש בפקודה הבאה:
docker run -it nginx bash
כאשר בפקודה זו אנחנו אומרים ל-Docker להריץ קונטיינר. ב-Flags של -it אנחנו אומרים לו שאנחנו רוצים להתחבר פנימה. אז נותנים לו את השם של ה-Image להפעיל, ולבסוף איזו פקודה להפעיל. היות ואנחנו מתחברים פנימה, נצטרך Command Line Shell. לכן הפקודה היא – bash.
הפקודות בקובץ:
· FROM – הפקודה הזו פותחת את ה-Dockerfile ואומרת ל-Docker מאיפה לטעון בסיס ל-Image שאנחנו רוצים לבנות.
לפעמים כשנגדיר FROM זה לא יהיה כדי להגדיר image בסיס, אלא כדי לקבוע מקור להעתקה של קבצים וספריות. כי פעמים רבות התוצר הסופי מורכב מרכיבים שהושגו מכמה image שונים.
יש המון Image מוכנים של כל מיני דברים שאפשר להוריד סתם, או למשוך בתצורה הזו ב-Dockerfile. כאשר סתם מציינים שם של מקור, Docker מושך אותה מתוך מאגר ה-Image שלו – Docker Hub. אבל יש גם מאגרים לגוגל – GCR, למיקרוסופט – MCR וכו'. כשרוצים למשוך משם קונטיינר, פשוט שמים במקום את השם, את הכתובת של אותו Image באותו מאגר.
· ADD – מעתיק תוכן של תיקיה בסביבת ה-Build אל תוך הקונטיינר שנבנה. במקרה שלנו הסביבה זה השרת docker-test, ואנחנו נותנים לו נתיב בתוך הקונטיינר שאליו התוכן יועתק. כאן אנחנו מעתיקים את קבצי האפליקציה שהורדנו מ-Git לתוך הקונטיינר שנבנה.
· RUN – מריץ פקודת לינוקס בסביבת ה-Build. במקרה שלנו זו פקודה שמחליפה מחרוזת בתוך קובץ. הקובץ הוא קובץ ההגדרות של דף ברירת המחדל של nginx בקונטיינר. אנחנו מחליפים את נתיב ברירת המחדל, לנתיב שיתאים לאפליקציה שהעלינו לשם בשלב הקודם.
· EXPOSE – פקודה זו מורה לקונטיינר להאזין בפורט מסוים. היות והקונטיינר מפעיל שירות nginx, הוא יאזין בפורט 80.
בניית הקונטיינר:
כדי לבנות את הקונטיינר על סמך התצורה שנכתבה ב-Dockerfile, נריץ את הפקודה הבאה:
docker build -t nginx-test .
לאחר שתהליך הבנייה יסתיים נריץ את הפקודה:
docker images
אפשר לראות Image בשם nginx-test. כדי להריץ את הקונטיינר ולבדוק שהכל תקין, נזין את הפקודה הבאה:
docker run -p 80:80 -d test
הסבר:
p ממפה את הפורט במכונה לפורט של הקונטיינר. הפורט משמאל זה של המכונה, והימני זה של הקונטיינר.
d משמעותו detach. כלומר, במקום להפעיל את הקונטיינר ולהכניס אותנו לאיזה Shell, Docker מפעיל את הקונטיינר כדי שירוץ ברקע כשירות.
כעת נפנה לכתובת IP החיצונית של השרת docker-test בפורט 80. אנחנו אמורים להגיע לאפליקציה כפי שהגענו אליה בשרת ה-nginx שהוקם במעבדה הקודמת. זה בגלל שקישרנו את הפורט הפעיל בקונטיינר לפורט 80 של השרת.
Artifact Registry:
זהו שירות המהווה ספרייה לחבילות מוכנות.
קודם דיברנו על ספריות הקונטיינרים של דוקר, של מיקרוסופט ושל גוגל. משם אפשר למשוך ולהפעיל Image של קונטיינרים מוכנים, או להתאים וליצור Image משלנו. את ה-Image שנוצר נאחסן ב-Artifact Registry. בכל פעם שנרצה להשתמש בו בכל שירות שמריץ קונטיינרים, השירות ישתמש ב-Image כדי להפעיל קונטיינרים ולבצע את העבודה.
אפשר להשתמש בשירות גם כדי לאחסן חבילות תוכנה ומערכות הפעלה, אבל לא נעסוק בזה.
הקמת ספריה:
נקים לנו ספריה ונאחסן בה את ה-Image שלנו.
בתפריט הכללי של לוח הניהול של GCP צריך ללחוץ למטה על Mor Products, ואז לגלול למטה עד לקטגוריה של CI/CD. אפשר במקום פשוט לכתוב בחיפוש שבראש הלוח – Artifact Registry.
בפעם הראשונה שמתחברים, צריך להפעיל את ה-API של השירות באותו הפרויקט. לאחר מכן נעבור לדף של השירות, ונוכל ללחוץ על CREATE REPOSITORY.
- שם – breakbricks.
- מתחת צריך לסמן פורמט. כמו שאמרנו, אפשר לאחסן שם גם חבילות תוכנה ודברים אחרים. אבל אנחנו צריכים לאחסן שם Docker Container, אז זה מה שצריך להיות מסומן.
- לבחור Region – me-west1.
- תחת Cleanup policies, לסמן Delete artifacts, ואז ללחוץ ADD CLEANUP POLICY.
- ניתן ל-Policy שם – last-3. ובהתאם לשם – נסמן מתחת Keep most recent versions.
- אז יפתח שדה ובו כתוב Keep count, שבו צריך לציין כמה גרסאות נשמור. נשים את הספרה 3.
- ללחוץ CREATE.
עכשיו נוצרה הספריה ונרצה לראות איך נוכל לשלוח אליה קונטיינר.
העלאת קונטיינר לספריה (push):
1. ללחוץ על השם של הספריה כדי להכנס.
2. ללחוץ למעלה על Setup instructions.
3. בחלונית שתקפוץ מימין, להעתיק את הפקודה שיש שם.
4. להתחבר ב-SSH לשרת docker-test שבו יצרנו קודם את הקונטיינר. להפעיל משם את הפקודה. אז תופיע בקשת אישור לכתיבת ההגדרות על קובץ בשרת – ללחוץ y.
5. נחזור לספריה ב-Artifact Registry ונראה שלמעלה יש לנו נתיב. הנתיב מורכב מ-Hostname של השירות ב-Region שבחרנו, אחריו הפרויקט שבו אנחנו עובדים ובסוף הספריה שפתחנו. לידו יש לחצן העתקה. להעתיק את הנתיב. במקרה שלי זה – me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks
6. בשרת docker-test נבנה שוב את הקונטיינר לפי אותו Dockerfile. רק שעכשיו במקום לקרוא לו test, נקרא לו בשם שמכיל את כל הנתיב שהעתקנו, ולבסוף שם הקונטיינר עצמו. למשל – me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks/breabricks נכנס לתיקיה המכילה את ה-Dockerfile
כך תראה הפקודה:
docker build -t me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks/breabricks .
7. לאחר תום הליך יצירת הקונטיינר (Build), נזין את הפקודה docker images ונראה את ה-Image החדש שם.
8. לפני שנעלה את ה-Image לספריה, נצטרך הרשאות. אז או שנצמיד לשרת docker-test את החשבון שלנו, שהוא ה-Owner של הפרויקט – באמצעות הפקודה gcloud auth login, או שניתן הרשאות לחשבון של המכונה. ניתן הרשאות לחשבון של המכונה, שכרגע הוא חשבון ברירת המחדל של הפרויקט. הפקודה gcloud auth list תציג לנו אותו, ונוכל להעתיק אותו מחלון ה-SSH.
9. בחלון של Artifact Registry ללחוץ למעלה (בנתיב) על שם הפרויקט, או משמאל בתפריט על Repositories. כעת בתצוגת הספריות (כאן בסביבת מעבדה יש רק אחת) נסמן את תיבת הסימון ליד breakbricks, ויקפוץ לנו מימין חלון לניהול הרשאות.
10. לוחצים ADD PRINCIPAL, בחלונית שנפתחת מדביקים את חשבון השרת docker-test בשורה של New principals.
11. לוחצים על התפריט ב-Select a role, ובוחרים משמאל ב-Artifact Registry, ואז מימין ב-Role של Artifact Registry Create-on-push Writer.
12. לוחצים SAVE.
13. עכשיו פקודת push פשוטה תעביר אותו לספריה. היות וכבר הכנסנו לשם שלו את הנתיב, הפקודה כבר יודעת לאן להעביר אותו.
כך תראה הפקודה:
docker push me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks/breabricks
14. נכנסים לספריה ורואים שם Image בשם breakbricks. אפשר לראות שבפנים מנוהלות הגרסאות, אם כי כרגע ישנה רק גרסה אחת.
15. ללחוץ על הגרסה כדי לקבל מבט על הנתונים. מה שמעניין אותנו זו הלשונית Pull. שם באמצע העמוד תחת Pull by tag ישנה פקודה למשיכת הקונטיינר. היא פחות מעניינת. מה שמעניין זה המחרוזת ובה הכתובת המלאה של הקונטיינר יחד עם התגית latest. שימוש במחרוזת הזו יתן לנו תמיד את הגרסה האחרונה של אותו image. להעתיק ולשמור בצד לשלב הבא.
חשוב לזכור:
– בגלל שאנחנו עובדים עם חשבון ברירת המחדל של VM בפרויקט, אם בשלב הקמת השרת docker-test לא היינו פותחים גישה לכל ה-Cloud API, לא היינו מצליחים לבצע קריאה ל-API של Artifact Registry, למרות שיש לחשבון הרשאה על הספריה שפתחנו שם.
– Best Practice זה לעבוד עם חשבון שירות שאנחנו פתחנו עם הרשאות מותאמות לצורך העבודה. החשבון רשאי לקרוא לכל API, אבל אז אותו API יבדוק את הרשאות שלו המנוהלות באמצעות IAM.
Cloud Run:
אם נרצה להפעיל קונטיינר בודד, כשירות שפעיל כל הזמן או לצורך פעולה מתוזמנת, נוכל להשתמש בשירות Cloud Run. זהו שירות מנוהל לגמרי להפעלת קונטיינרים. כך משלמים רק על זמן הריצה ועל משאבי המחשוב של הקונטיינר עצמו. בנוסף, לא צריך לנהל ולתחזק שרתים ומערכת תקשורת שמפעילים את סביבת הקונטיינרים. הכל מנוהל. אבל בשביל זה, צריך קונטיינר זמין בסביבת הענן, או תהליך של Build שיבנה קונטיינר כשצריך.
היות ובשלב הקודם כבר העלינו את הקונטיינר שלנו לסביבת הענן, נוכל להציב אותו כשירות Web.
יצירת שירות:
1. בתפריט הכללי משמאל לוחצים למטה על MORE PRODUCTS ואז בקטגוריה של SERVERLESS לוחצים על Cloud Run – או שכותבים בשורת החיפוש למעלה.
2. מנבלים את הפה – כלומר – Enable API.
3. בדף Cloud Run שנפתח, לוחצים למעלה על CREATE SERVICE.
4. לסמן Deploy one revision from an existing container image.
5. בשדה Container image URL להדביק את המחרוזת של נתיב ה-Image עם התגית latest שהעתקנו קודם. זה נראה ככה:
me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks/breakbricks:latest
6. לבחור region – me-west1.
7. Authentication – לבחור Allow unauthenticated invocation בגלל שאנחנו פותחים שירות Web ציבורי.
8. כעת אנחנו מגיעים לאפשרות של Auto Scaling. אפשרות זו נועדה להריץ במקביל עוד קונטיינרים אם יש עומס, ולכבות אותם כשהעומס פוחת. כך משלמים רק על מה שצריך לאותו זמן. לכן נשאיר את הסימון על CPU is only allocated during request processing, ונבחר מספר מופעים של 0-2.
9. תחת Ingress control לבחור All – שוב, כי אנחנו מפרסמים אתר ציבורי.
10. כעת יש כל מיני הגדרות שברובן לא נרצה לגעת כרגע, ובחלקן ניגע במעבדה מתקדמת בהמשך. רק להגדיר פורט ומשאבי מחשוב: פורט 80, memory 128MIB, CPU נבחר ב- 1>. כשיפתח לנו שדה נוסף כדי לדעת איזה חלקיק ליבה של CPU נרצה לצרוך, נסמן שמינית – 0.125.
11. בגלל שבחרנו כאלה משאבים מצומצמים, תחת השדה של Requests נהיה חייבים לסמן ש-Maximum concurrent requests per instance זה 1. אבל אנחנו לא צריכים יותר.
12. ללחוץ למטה על CREATE.
כעת השירות יפרוש את הקונטיינר מתוך ה-Image עם כל ההגדרות שהגדרנו לו, זה יקח כמה דקות.
בסיומן, נקבל בראש העמוד קישור URL לשירות שהעלינו. כאן זו סביבת מעבדה וזה מספיק. במציאות נרצה להצמיד לשירות כתובת DNS ברורה תחת הדומיין שלנו, בתור CNAME.
עבודה עם GKE:
GKE הוא שירות Kubernetes בסביבת הענן של גוגל – Google Kubernetes Engine. תחת השירות המנוהל הזה ניתן להקים ולהגדיר אשכולות Kubernetes, המקושרים לרשתות, למערכת ההרשאות (IAM) ולשירותים אחרים בסביבת הענן של גוגל.
שירות GKE מנוהל בדרגות שונות. כלומר – בתצורות מסוימות צריך/ניתן להגדיר פחות דברים, והכל מתנהל מאחורי הקלעים. זה גם אומר מרחב תמרון מוגבל יותר עבור מנהל המערכת, שיכול לבחור תצורה שבה יש לו יכולת הגדרה גבוהה יותר.
במעבדות קודמות התייחסנו לכל מיני פקודות gcloud, וכל מי שנכנס לדפי ה-Docs של הפקודות ראה את כמות האפשרויות והערכים (Flags) שניתן או צריך להוסיף לפקודות. לצורך השוואה ניתן להכנס לדף של הפקודה הבאה:
gcloud container clusters create
שם אפשר לראות את הכמות העצומה של הערכים שניתן להצמיד לפקודה הזו. ללמדך כמה אפשר להרחיב ולהעמיק ולפרט בהגדרות אשכול GKE.
ולכן, למרות שאפשר ליצור אשכול GKE בפקודה אחת קצרה של CLI, כאן נבצע את היצירה בתהליך מורכב ומרובה הגדרות. כל זה נועד לתת הבנה של האשכול ושל המבנה שלו.
הכנה:
אשכול GKE נועד להפעיל תוכנות מורכבות או פשוטות, בתצורה מבוזרת. המטרה היא לפרק את התוכנה לשירותים קטנים שכל אחד מבצע חלק קטן. כך אם ישנה בעיה בתהליך ניתן להבין די מהר באיזה חלק הבעיה ואיפה צריך לתקן. כך גם ניתן לשדרג ולעדכן בקלות ובמהירות יחסית.
כל חלק כזה פועל ביחידה שנקראת Pod. יחידה כזו יכולה לכלול קונטיינר פעיל אחד או יותר, שיחד מבצעים את העבודה הנדרשת מאותו שירות. כמעט תמיד נפרוש שירות בתצורה של יתירות, ומספר העותקים של אותו Pod שפועלים במקביל, יגדל ככל שגדל העומס על השירות. לכן הביטוי Service – בשפה של GKE משמש גם לתיאור שער שהוא גם Load Balancer, כתובת IP המקבלת תעבורה בפורט מסוים עבור השירות בכללותו. אותו Load Balancer יודע להעביר את הפניות ל-Pods השונים.
לכן נצטרך טווח כתובות עבור כל ה-Pods השונים שירוצו תחת האשכול, ונצטרך עוד טווח כתובות עבור אותם Services – אותם LB שיקבלו את התעבורה מבחוץ או משירותים אחרים באשכול, ויעבירו ל-Pods.
מטבע הדברים, טווח הכתובות של ה-Pods יצטרך לכלול הרבה יותר כתובות, כי כל שירות צורך כתובת אחת עבור LB וכמה כתובות עבור Pods.
אז ניצור לנו רשת שבה יפעל האשכול, וניתן לה את הטווחים הנדרשים.
רשתות וטווחים:
– במעבדות הקודמות הוסבר הליך הקמת רשתות בסביבת GCP.
1. להקים VPC בשם app, עם MTU של 1500, Custom subnets.
2. Subnet עיקרי בשם main, Region – me-west1, טווח עיקרי – 10.0.1.0/24.
3. ליצור Subnet משני בשם services, טווח – 10.0.2.0/24.
4. ליצור Subnet משני בשם Pods, טווח – 10.0.4.0/22.
5. לאפשר Private Google Access וליצור את הרשת.
– לשים לב לטווח של ה-Pods. טווח בקידומת 22 מאפשר כאלף כתובות. כל Pod דורש שתי כתובות לצרכי תחלופה ותחזוקה. לכן אם מחשבים שנצטרך אשכול בן 4 מכונות שבכל אחת יפרשו 30 Pods, יספיק לנו טווח כתובות בקידומת 24. תמיד צריך לחשב את הטווחים הזמינים ולהקצות בהתאם לדרוש, כדי שלא לבזבז טווחים לחינם. אבל היות ואנחנו בסביבת מעבדה, וברוב הפעמים אשכולות Kubernetes מכילים הרבה יותר Pods, נקצה טווח גדול יותר.
חשבון שירות:
– במעבדות הקודמות הוסבר הליך הקמת חשבון שירות.
להקים חשבון שירות בשם apps-gke ולתת לו את ה-Roles הבאים:
1. Kubernetes Engine Service Agent
2. Monitoring Viewer
3. Monitoring Metric Writer
4. Logs Viewer
5. Logs Writer
6. Service Account User
יצירת אשכול GKE:
בתפריט הראשי לוחצים על Kubernetes Engine, מאפשרים את ה-API ונכנסים לדף של Clusters. שם לוחצים למעלה על Create כדי לפתוח בתהליך.
ברירת המחדל היא יצירת Auto Pilot Cluster, שזה אומר גרסה יותר מנוהלת של שירות Kubernetes מצד אחד, ומצד שני פחות אפשרות לתמרון ומשחק בהגדרות. לכן אנחנו נלך לפינה הימנית העליונה של המסך ונלחץ על SWITCH TO STANDARD CLUSTER. בחלון שיקפוץ ללחוץ שוב.
כעת נפתח דף הגדרות מרובה שלבים. ניתן לשים לב כי בצד ישנו תפריט בן עשרה שלבים. נתחיל.
Cluster basics:
1. שם – apps
2. מיקום – Regional, me-west1.
אין עוד מה להגדיר שם. נמשיך לשלב אחר. לא ללחוץ על CREATE!
default-pool:
1. Size – נשנה למכונה אחת בכל zone. בהמשך נשנה עוד. המטרה היא כמה שפחות מכונות שעובדות סתם.
2. מתחת נסמן את Enable cluster autoscaler.
3. כתוצאה מכך נשנה מעט למטה משם את Size limits type ל-Total limits.
להמשיך לשלב הבא.
Nodes:
לגלול מעט למטה ואז לבחור במכונה מסוג e2-standard-4. מכונה זו מספיק גדולה בשביל להריץ Control-Plan (שזו מערכת הניהול של האשכול) ועוד כמה קונטיינרים קטנים. ורק אם יגדל העומס, האשכול יציב מכונות נוספות.
Networking:
תחת Maximum Pods per node נסמן 32. מכונה בגודל כזה לא יכולה להפעיל כמות כזו של Pods ולכן אין טעם לבזבז יותר כתובות.
Security:
1. לבחור את חשבון השירות שיצרנו קודם עבור האשכול.
2. לסמן Enable secure boot.
להמשיך ל-CLUSTER.
Automation:
1. תחת Maintenance Policy לסמן Enable Maintenance Window.
2. נסמן לו יומיים בשבוע חלון תחזוקה לשש שעות. נגיד – שישי ושבת בין 12 בלילה ל-6 בבוקר. זה אומר לבחור את 12AM כשעת התחלה, ולסמן אורך של 6 שעות.
Networking:
1. ב-Network לבחור את רשת app שיצרנו קודם.
2. Node subnet זה main – ה-Subnet הראשי שיצרנו לאותה הרשת.
3. תחת IPV4 network access, נסמן Private Cluster.
4. לבטל את הסימון של Access control plane using its external IP address.
5. לתת טווח קטן בקידומת 28 עבור כתובות של Control Plan. אלה כלי הניהול של האשכול, והם לא צריכים הרבה. לכן טווח כמו 172.16.1.0/28 אמור להספיק.
6. לבטל את הסימון של Automatically create secondary ranges.
7. לטווח המשני עבור Pods לבחור ב-pods subnet שיצרנו קודם.
8. לסמן מקסימום 32 Pods למכונה.
9. לטווח המשני עבור Services לבחור ב-services subnet שיצרנו קודם.
10. לסמן Enable Dataplane V2.
11. תחת Authorized networks ללחוץ ADD AN AUTHORIZED NETWORK. שם לבחור את טווחי הכתובות שמהן ניתן להתחבר לניהול האשכול בכלי Kubectl.
12. ניתן לטווח את השם App וניתן לו את הטווח 10.0.1.0/24, שזה הטווח של Subnet main ברשת שבה יושב האשכול.
– תמיד עדיף לנהל את האשכול בצורה פרטית ופנימית לגמרי. אם יש שירות שנרצה לחשוף לעולם, אפשר לעשות את זה דרך Load Balancer עם כתובת חיצונית. עדיף גם לשים עליו Cloud Armor שנותן הגנות רשת וסוג של WAF. בהמשך נלמד דרכים מורכבות ומוגנות יותר לפרסם שירותים.
– כדאי לצמצם ככל האפשר את הגישה לניהול האשכול. בהמשך נראה עוד כיצד לעשות את זה.
Security:
לשים לב לאפשרויות שיש כאן. כרגע לא נסמן שום דבר שלא מסומן, בהמשך נערוך את האשכול ונוסיף אפשרויות.
ללחוץ CREATE.
כעת ירוץ מאחורי הקלעים תהליך שיבנה את האשכול בהתאם להגדרות שהכנסנו. זה יכול לקחת 5-20 דקות. כבר עם התהליך אנחנו עוברים לדף של Clusters ורואים את האשכול הראשון שלנו ברשימה, בהווצרות.
לאחר שהתהליך מסתיים, האשכול ברשימה מקבל סימון ירוק ואנחנו יכולים להתחיל לעבוד.
Auto Scaling:
אחד העקרונות שעומדים מאחורי שירותי קונטיינר, זה לצרוך את המשאבים שמשתמשים בהם, ולא הרבה יותר מזה. כדי לנצל את התכונה הזו, צריך להגדיר כמו שצריך את ה-Auto Scale. כך כל אפליקציה/שירות או כמות המכונות באשכול, יגדלו ויתכווצו בהתאם לעומס העבודה, וכך משלמים רק על מה שצורכים.
1. לחיצה על שם האשכול בדף Clusters כדי להכנס להגדרות שלו.
2. נראה שיש לנו למעלה כמה לשוניות. אנחנו רוצים לעבור ל-Nodes.
3. מי שיחכה כמה דקות לאחר שהאשכול נוצר, יראה שכרגע יש רק מכונה אחת שרצה. האשכול ראה שאין עומס, וכיבה שתים משלושת המכונות שהוקמו עם האשכול.
4. ללחוץ על default-pool תחת node Pools.
5. פה נראה את כל ההגדרות שקשורות למכונות. איזה גודל הן, מה חשבון השירות שלהן, כמה מכונות בסך הכל באשכול, וכמה לכל zone וכו'.
6. לשים לב להגדרות של Size. את כל אלה הגדרנו כבר בשעת ההקמה. אבל מי שמאכלס את האשכול שלו באפליקציות, יראה בהמשך שהצריכה הולכת וגדלה בהתאם לשימוש, ואז האשכול יציב כבר שלוש מכונות, ופתאום צריך להגדיל. כדאי להיות עם אצבע על הדופק ולאפשר בהגדרה של Maximum number of all nodes מרחב בטחון שמאפשר לאשכול לגדול מעבר לצריכה הנורמלית שלו.
7. מצד שני צריך להזהר לא לאפשר עכשיו מקסימום 100 מכונות, ולסמוך על זה שה-Auto Scaler ישאיר אותנו על מכונה אחת. כמעט תמיד זה באמת מה שיקרה. אבל כבר קרו מקרים של תקלה או מתקפה שגרמו לשירות לצרוך עוד ועוד ועוד משאבים, ובמצב כזה האשכול יגדל ויתפח עד לגבול שאפשרו לו. ועל כל מכונה משלמים. אז לאפשר לו מרחב גדילה בגבולות הסביר, ולא יותר.
8. ללחוץ למטה CANCEL ולצאת מדף העריכה.
הצבת אפליקציה באשכול:
1. בתפריט של Kubernetes Engine משמאל ללחוץ על Workloads.
2. בדף שנפתח, ללחוץ על CREATE DEPLOYMENT ולעבור לדף שבו מגדירים את האפליקציה.
3. נראה שיש לנו כרטיס שבו מגדירים את הקונטיינר. כרגע הוא מצביע על Image של Nginx עם תגית של הגרסה האחרונה. נמחק את זה ונדביק שם את המחרוזת ובה הכתובת של הקונטיינר עם התגית latest:
me-west1-docker.pkg.dev/mobile-app-yosi/breakbricks/breakbricks:latest
4. ללחוץ CONTINUE.
5. כרגע מגדירים Deployment, שזה השם לחבילת ההגדרות שתחתיה רצה האפליקציה.
6. ניתן את השם – breakbricks.
7. Namespace מחלק לקטגוריות את כל מה שמריצים על האשכול. כך ניתן להפריד או לרכז שיוך של חשבונות שירות, אמצעי אחסון, משתנים סביבתיים ועוד. ניתן לו את ה-namespace – breakbricks.
8. Labels יכול לעזור בהמשך, כשממיינים שירותים ומשאבים לפי תוויות. כרגע זה לא כל כך מעניין. אפשר למחוק, אבל אנחנו רק נשנה את התווית מ-nginx-1 ל-breakbricks.
9. מתחת לזה יש לחצן VIEW YAML. ללחוץ ולהתבונן. ככה נראות ההגדרות של הפצה. בהמשך נראה איך להתעסק עם זה. לסגור את ה-YAML וללחוץ CONTINUE.
10. לסמן את התיבה של Expose deployment as a new service.
11. מיד יפתחו עוד אפשרויות להגדיר. אין צורך לשנות כלום, כי נפנה לשירות בפורט 80, וגם הקונטיינר מקבל פורט 80. אם הקונטיינר היה מקבל פורט שונה מהפורט שאליו אנחנו פונים מבחוץ, היה צריך לציין גם Target port. כמו כן הפרסום של השירות הוא כ- Load Balancer. הוא צריך להחצין כתובת שנוכל לפנות אליה מחוץ לאשכול, כדי להגיע לאפליקציה.
12. ללחוץ DEPLOY.
והנה נפתח לנו דף של ה-Deployment. החבילה נפרשה בשלושה Pods, ולמטה רואים את הכתובת החיצונית של אותו LB שהגדרנו ב-Expose.
אם נלחץ על הכתובת שם או נכניס את הכתובת בדפדפן בפרוטוקול http, נקבל גישה למשחק שובר הלבנים שלנו – הפעם מתוך GKE.
Autoscale:
ההבדל בין Horizontal ל-Vertical בהקשר של Autoscaling, הוא של גדילה (או צמצום) של הקצאה. גדילה אנכית מתייחסת לכמות המשאבים שמקצים לאותה יחידה. אם היחידה זה VM או Container. גדילה אופקית מתייחסת לכמות היחידות שפורשים באותה קבוצה כדי לספק את הדרישה לשירות.
יש מקרים שבהם נדרשת גדילה אנכית, אבל ברוב המקרים היום מעדיפים גדילה אופקית. גדילה אופקית מייצרת חלוקת עומסים טובה יותר, מנגנון מבוזר שעמיד בפני כשלים. כי אם חלק אחד נופל, יש עוד כמה זמינים לתת שירות עד שהכשל יתוקן.
כל זה נכון במיוחד לטכנולוגיה מבוססת קונטיינרים. קונטיינר נועד להיות יחידה קטנה ומצומצמת, שאם היא ממצה את יכולות המחשוב שלה, מעלים קונטיינר נוסף. אם יש כשל ביחידה אחת, עולה במהירות קונטיינר נוסף והתקול כבה.
בראש העמוד נלחץ:
ACTIONS >> Autoscale >> Horizontal pod autoscaling.
נראה שמוגדרת לאפליקציה שלנו טווח של 1-5 עותקים. כמו כן נראה שמוגדרת לנו אמת מידה לכמות העותקים שרצים – אם העותק הקיים מגיע ל-80% CPU, האשכול יציב עותק נוסף.
אפשר לסגור.
נסתכל על הדף ונראה בלוח את מד צריכת ה-CPU. כרגע הצריכה אפסית. אבל אם נסתכל למטה יותר, נראה שעדיין רצים במקביל 3 עותקים.
למה?
ישנו מקום נוסף שאפשר להגדיר בו Horizontal pod autoscaling, וזה בשורות שבין הלוחות של צריכת המשאבים לבין רשימת העותקים שרצים. נראה שיש שם שורה של Horizontal pod autoscaling, ומצד ימין יש עפרון לעריכה. ונשים לב לעוד משהו – בצד הכותרת של Horizontal pod autoscaling יש סימון כתום להתרעה – האשכול לא מצליח לפענח את ההגדרה של Autoscaling לפי צריכת משאבי עיבוד.
כדי להבין למה זה, ניגש לחלק החשוב ביותר בהפעלת מערכת Kubernetes, וזה קבצי YAML.
YAML Manifests:
המשאבים באשכול Kubernetes מוגדרים באמצעות קבצי YAML שמכילים שדות מסוימים. כתיבה של הפירוט בצורה הנכונה והעלאה שלו לאשכול, יעדכנו את המערכת מה אנחנו רוצים שיפעל, איך, בכמה עותקים וכו'.
עדיין באותו דף, נשים לב שקרוב לראש העמוד יש שורה של לשוניות, כשאנחנו בלשונית OVERVIEW. נעבור ללשונית YAML.
כל הסעיפים האלה שאנחנו רואים, מכילים הגדרות או אפשרויות בהפצה של האפליקציה. אין צורך להבהל מהבלאגן, ככל שנתעסק יותר ב-Kubernetes נכיר יותר את הסעיפים, והבלאגן יהפוך למשהו מוכר שבו נדע איפה שמים ואיפה מוצאים כל דבר.
כמו כל קובץ YAML, יש פה היררכיה מדורגת לפי קטגוריות וסעיפי משנה. אם נגלול למטה עד הסוף נראה שהקטגוריה האחרונה היא הסטטוס של ההפצה, ומעליה קטגוריה של spec. Spec זה שם שמופיע המון בתור הכללה לקבוצת הגדרות (specification) של רכיבים.
ניתן לראות שבתוך הקטגוריה של spec יש עוד תת-קטגוריה בעלת אותו שם. שם יש את הגדרת הקונטיינר שמציבים ב-Pod. ושם יש את ההגדרה resources, והיא ריקה.
כל עוד שלא הגדרנו כמה משאבים להקצות לכל קונטיינר, ה-Autoscaler לא ידע מתי הצריכה גבוהה או נמוכה מ-80%, ולא ידע מה לעשות. ולכן עכשיו הוא הלך על הכמות הממוצעת שבין 1 ל-5 והציב שלושה עותקים.
לכן נלחץ בראש העמוד על EDIT, נמחק את הסוגריים המסולסלים של resources ונשנה את הערך שיראה כמו בצילום ונלחץ על SAVE.
נחזור לדף של OVERVIEW ואולי נרענן אותו, אבל מהר מאוד נראה שכמות העותקים הצטמצמה וכעת רץ Pod אחד בלבד. ניתן גם לראות שסימן האזהרה ליד Horizontal pod autoscaling הפך לסימון ירוק של תקינות.
Kubectl:
עד עכשיו יצרנו וניהלנו את האשכול לגמרי מתוך לוח הניהול. חלק חשוב מאוד בידע, זה לדעת לתפעל את שורת הפקודה. כמו תמיד, יש המון דברים שאפשר לעשות טוב יותר, או אפילו רק דרך שורת הפקודה.
לכלי הניהול הזה של Kubernetes קוראים kubectl. כעת נתקין אותו ונלמד להכיר את העבודה איתו.
– צריך לזכור שבאופן עקרוני אפשר לעבוד עם Kubectl מתוך Cloud Shell, אבל בגלל שהגבלנו את הגישה ל-Control Plan, נפעיל אותו מתוך שרת באותה הרשת שהגדרנו כ-Authorized Network.
הכנה:
עדיין בדף של Kubernetes Engine, בתפריט בצד ללחוץ על Clusters, ושם להכנס לאשכול שלנו – app.
שם בראש העמוד נלחץ על CONNECT, נעתיק את הפקודה שמופיעה שם ונדביק בצד.
נלך ל- IAM & ADMIN >> Service Accounts ונקים חשבון שירות בשם kub-mgmt, וניתן לו את ההרשאות הבאות:
· Compute Viewer
· Kubernetes Engine Service Agent
אז נלך ל-Compute Engine וניצור לנו שרת Ubuntu בגודל micro. נקרא לו kub-managment ונציב אותו ב-Region בישראל. נחבר אותו לרשת app ב-Subnet main, וניתן לו את הכתובת 10.0.1.50 ולא ניגע בהגדרה של הכתובת החיצונית. נצטרך אותה עבור כמה התקנות, ולאחר מכן נוריד אותה.
להצמיד לשרת את חשבון השירות שיצרנו הרגע.
– לפעמים לוקח זמן עד שהמערכת מתעדכנת בפרטי החשבון החדש. אז אם הוא עדיין לא מופיע ברשימת חשבונות השירות הזמינים עבור השרת, לחכות עוד ולפתוח את הדף מעט מאוחר יותר ולנסות שוב.
– לפני שמתחברים ב-SSH לאותו השרת, לוודא שנפתח חוק בפיירוואל לאפשר תעבורה מטווח הכתובות 35.235.240.0/20, כמו שלמדנו במעבדות הראשונות.
מתחברים ב-SSH ובודקים מה מצבנו עם הפקודה:
gcloud components list
הכלים שאנחנו צריכים הם kubectl וגם gke-gcloud-auth-plugin ואלה אינם מותקנים כברירת מחדל.
בזמן שהכל פועל כפי שאמור לפעול, הפקודה
gcloud components install kubectl
אמורה להתקין את הכלי, אבל בזמן כתיבת שורות אלה זה פשוט לא עובד, וצריך להתקין מחדש את כל החבילה של gcloud, ולאחר מכן בנפרד את שתי החבילות האחרות.
אז עד שיתקנו את זה, נתקין מחדש את הכלים.
פקודות התקנה:
# gcloud
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates gnupg curl sudo -y
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get update && sudo apt-get install google-cloud-cli -y
# kubctl & gke-gcloud-auth-plugin
sudo apt install kubectl -y
sudo apt install google-cloud-cli-gke-gcloud-auth-plugin -y
ולאחר שהכל הותקן, אפשר להסיר את הכתובת החיצונית מהשרת ולהתחבר לאשכול GKE.
עבודה עם שורת הפקודה:
ראשית, צריך להגדיר מול איזה אשכול אנחנו עובדים, ולאן נשלחות פקודות kubectl שאנחנו מפעילים. לכן צריך להדביק את הפקודה שהעתקנו קודם מדף CONNECT של האשכול. במקרה שלי זה נראה ככה:
gcloud container clusters get-credentials app --region me-west1 --project mobile-app-yosi
ועכשיו אפשר לעבוד.
פקודות kubectl עובדות בתצורה מוכרת ואפשר ליישם שם עקרונות שמכירים מעבודה מול docker או דברים אחרים. המבנה הוא:
Kubectl <command> <resource> <flags and options>
אז לדוגמה, אחרי kubectl שקורא לכלי, ניתן להציב פקודות כמו get, describe, create, delete וכו'.
ה-resource שעליו חלה הפקודה, יכול להיות deployment, pod, service, namespace, serviceaccount וכו'.
פקודות בסיסיות:
נזרוק כמה פקודות כדי לקבל מידע על מה שיש לנו באשכול נכון לעכשיו:
kubectl get namespaces
– נקבל רשימה של ה-namespace שיש לנו באשכול. נראה את default, כמה שה-Control-Plan משתמש בהם, ואת breakbricks שיצרנו ובו הצבנו את המשחק שלנו.
kubectl describe namespace breakbricks
– נראה שיש לנו pod אחד ו-service אחד שרצים שם.
kubectl get pods --namespace breakbricks
– יראה לנו את ה-Pods שרצים. משם נוכל לקחת את שם ה-pod שרץ, ולהפעיל עליו פקודות כמו describe כדי לקבל מידע, delete כדי למחוק, להתחבר אליו ועוד.
kubectl logs breakbricks-6759c5bf8-x4jgv --namespace breakbricks
– לקחתי את שם ה-pod מהפקודה הקודמת, והשתמשתי בו כדי להריץ פקודה שמריצה על המסך את הלוגים שלו.
עדכון הגדרות:
עד עכשיו השתמשנו בפקודות לקריאה בלבד. עכשיו נלמד איך לעדכן הגדרות וליצור תכונות באשכול באמצעות kubectl.
ראשית, לפני כל עריכה, צעד טוב וזהיר הוא לעבור שוב על הפרטים של הפריט:
kubectl get deployments --namespace breakbricks
kubectl describe deployment -n breakbricks
ואז מבט על ה-YAML של ההפצה:
kubectl get deployment breakbricks -n breakbricks -o yaml
קודם ראינו איך לעדכן את ההגדרות ישירות דרך לוח הניהול, או דרך ה-YAML בלוח הניהול.
דרך kubectl אנחנו יכולים לשנות תכונות באופן ישיר, כגון פקודת kubectl set שיכולה לקבוע מספר מועט של הגדרות (ניתן להזין kubectl set -h כדי לראות איזה הגדרות), או פקודות שנועדו לשנות תכונה אחת בלבד. כמו kubectl scale שקובעת מספר קשיח של עותקים, או kubectl autoscale שקובעת טווח, ומדד שלפיו נקבע מספר העותקים על פני הטווח. לדוגמה:
kubectl scale deployment/breakbricks --replicas=10
kubectl autoscale scale deployment/breakbricks --min=1 --max=5 --cpu-percent=80
אבל הדרך הכי מתקדמת שנותנת גישה לעריכת כל האפשרויות, זו עריכת YAML.
בכך ניתן להשתמש בפקודה kubectl edit, וכך עורכים את ה-YAML דרך עורך הטקסט של השרת. מי שלא אוהב להשתמש ב-vi ומעדיף את nano, יקבע קודם את המשתנה המקומי:
export KUBE_EDITOR=nano
ואז:
kubectl edit deployment breakbricks -n breakbricks
נרד עד לשם הקונטיינר, ונשנה אותו מ- breakbrick-1 ל-test. נצא ונשמור כמו כל שמירה של nano. אם הקפדנו לשמור על הפורמט הנכון של YAML ולהזין ערכים תקינים, נקבל הודעה שה-deployment נערך.
נבדוק:
kubectl get pods -n breakbricks
– נותן לי שם של pod. ואז:
kubectl describe pod breakbricks-59bffc84bd-mtq4j -n breakbricks
– והנה אני מסתכל תחת Containers ואני רואה שנמצא שם הקונטיינר test.
בדרך זו ניתן לערוך את כל ההגדרות שרוצים.
יצירה באמצעות YAML:
באמצעות YAML ופקודת kubectl apply ניתן לערוך הגדרות או ליצור פריטים חדשים.
כל מה שצריך זה להפנות לקובץ YAML, ואז לבצע פקודה דומה:
kubectl apply -f Config-File.yaml
צריך לשים לב שבכל YAML כזה יש בראש הקובץ סעיף שאומר איזה סוג פריט זה – מסוג של deployment או pod או service.
במקרה בו ההגדרות מצביעות על פריט קיים – לדוגמה: הקובץ אומר שמדובר בהגדרות מסוג deployment, והסעיפים שקובעים את שם ה-deployment וה-namespace מתאימים ל-deployment שכבר קיים באותו namespace, מה שיקרה זה שאותו deployment יתעדכן לפעול לפי ההגדרות החדשות.
אם עדיין לא קיים פריט כזה, האשכול יצור אותו בדיוק לפי ההגדרות בקובץ. כמובן, בהנחה שהפורמט והערכים בקובץ נכתבו בצורה תקינה.