במדריך הזה מפורטות שיטות מומלצות לתכנון, להטמעה, לבדיקה ולפריסה של שירות Knative serving. טיפים נוספים זמינים במאמר העברת שירות קיים.
כתיבת שירותים יעילים
בקטע הזה מתוארות שיטות מומלצות כלליות לתכנון ולהטמעה של שירות Knative Serving.
הימנעות מפעילויות ברקע
כשעיבוד הבקשה באפליקציה שפועלת ב-Knative serving מסתיים, הגישה של מופע הקונטיינר למעבד מושבתת או מוגבלת מאוד. לכן, לא מומלץ להפעיל תהליכים או שגרות ברקע שפועלים מחוץ להיקף של מטפלי הבקשות.
הפעלת שרשורים ברקע עלולה לגרום להתנהגות בלתי צפויה, כי כל בקשה עוקבת לאותו מופע של מאגר התגים מפעילה מחדש כל פעילות ברקע שהושהתה.
פעילות ברקע היא כל מה שקורה אחרי שתגובת ה-HTTP נמסרת. צריך לבדוק את הקוד כדי לוודא שכל הפעולות האסינכרוניות מסתיימות לפני ששולחים את התגובה.
אם אתם חושדים שיש פעילות ברקע בשירות שלכם שלא ברורה, אתם יכולים לבדוק את היומנים: חפשו כל דבר שמתועד אחרי הרשומה של בקשת ה-HTTP.
מחיקת קבצים זמניים
בסביבת Cloud Run, אחסון הדיסק הוא מערכת קבצים בזיכרון. קבצים שנכתבים לדיסק צורכים זיכרון שזמין לשירות, ויכולים להישמר בין הפעלות. אם לא תמחקו את הקבצים האלה, בסופו של דבר תופיע שגיאה שמעידה על חוסר זיכרון, והמכשיר יופעל מחדש.
אופטימיזציה של הביצועים
בקטע הזה מתוארות שיטות מומלצות לאופטימיזציה של הביצועים.
הפעלה מהירה של שירותים
מכיוון שמתבצעת התאמה של מספר המופעים של הקונטיינר לפי הצורך, שיטה טיפוסית היא לאתחל את סביבת ההרצה באופן מלא. סוג כזה של אתחול נקרא "הפעלה במצב התחלתי (cold start)". אם בקשת לקוח מפעילה הפעלה מההתחלה (cold start), הפעלת מופע המאגר גורמת לזמן אחזור נוסף.
תרחיש ההפעלה כולל:
- הפעלת השירות
- הפעלת הקונטיינר
- מריצים את הפקודה entrypoint כדי להפעיל את השרת.
- בודקים אם יציאת השירות פתוחה.
אופטימיזציה של מהירות הפעלת השירות מצמצמת את זמן האחזור שגורם לעיכוב בהגשת בקשות על ידי מופע של קונטיינר.
שימוש חכם בתלות
אם אתם משתמשים בשפה דינמית עם ספריות תלויות, כמו ייבוא מודולים ב-Node.js, זמן הטעינה של המודולים האלה מוסיף חביון במהלך הפעלה במצב התחלתי (cold start). כדי לקצר את זמן האחזור של ההפעלה:
- כדי ליצור שירות יעיל, מומלץ לצמצם את מספר התלויות ואת הגודל שלהן.
- אם השפה תומכת בכך, כדאי להשתמש בטעינה מדורגת של קוד שלא נמצא בשימוש לעיתים קרובות.
- משתמשים באופטימיזציות של טעינת קוד, כמו composer autoloader optimization של PHP.
שימוש במשתנים גלובליים
ב-Knative serving, אי אפשר להניח שמצב השירות נשמר בין בקשות. עם זאת, Knative serving עושה שימוש חוזר במופעי קונטיינר בודדים כדי להציג תנועה שוטפת, כך שאפשר להצהיר על משתנה בהיקף גלובלי כדי לאפשר שימוש חוזר בערך שלו בהפעלות הבאות. אי אפשר לדעת מראש אם בקשה ספציפית תהנה מהשימוש החוזר הזה.
אפשר גם לשמור אובייקטים במטמון בזיכרון אם יקר ליצור אותם מחדש בכל בקשת שירות. העברת הפונקציה הזו מהלוגיקה של הבקשה להיקף גלובלי משפרת את הביצועים.
Node.js
Python
Go
Java
ביצוע אתחול עצלני של משתנים גלובליים
האתחול של משתנים גלובליים תמיד מתרחש במהלך ההפעלה, מה שמגדיל את זמן ההפעלה במצב התחלתי (cold start). כדאי להשתמש באתחול עצל כדי לדחות את עלות הזמן ולקצר את זמן ההפעלה במצב התחלתי (cold start) של אובייקטים שלא משתמשים בהם לעיתים קרובות.
Node.js
Python
Go
Java
אופטימיזציה של מספר הבקשות המקבילות
מופעי Knative serving יכולים לטפל בכמה בקשות בו-זמנית, עד מקסימום מקביליות שניתן להגדרה.
ההגדרה הזו שונה מפונקציות Cloud Run, שבהן נעשה שימוש ב-concurrency = 1.
כדאי להשאיר את הגדרת ברירת המחדל של מספר ההפעלות המקסימלי בו-זמנית, אלא אם בקוד יש דרישות ספציפיות לגבי מספר ההפעלות בו-זמנית.
התאמת מספר החיבורים בו-זמנית בשירות
מספר הבקשות בו-זמנית שכל מופע של קונטיינר יכול לטפל בהן יכול להיות מוגבל על ידי סטאק תוכנות והשימוש במשאבים משותפים כמו משתנים וחיבורים למסד נתונים.
כדי לבצע אופטימיזציה של השירות כך שיוכל לתמוך במספר מקסימלי של משתמשים בו-זמנית:
- אופטימיזציה של ביצועי השירות.
- מגדירים את רמת התמיכה הצפויה בריבוי משימות בו-זמנית בכל הגדרה של ריבוי משימות בו-זמנית ברמת הקוד. לא בכל מחסנית טכנולוגיות נדרשת הגדרה כזו.
- פורסים את השירות.
- מגדירים את מספר הבקשות המקבילות ב-Knative Serving לשירות כך שיהיה שווה לכל הגדרה ברמת הקוד או קטן ממנה. אם אין הגדרה ברמת הקוד, משתמשים בערך המקביל של הבו-זמניות (concurrency).
- להשתמש בכלים לבדיקת עומס שתומכים בהגדרה של מספר הבקשות המקבילות. צריך לוודא שהשירות שלכם נשאר יציב תחת העומס והבו-זמניות הצפויים.
- אם השירות לא פועל בצורה טובה, עוברים לשלב 1 כדי לשפר את השירות או לשלב 2 כדי לצמצם את הבו-זמניות. אם השירות פועל בצורה טובה, חוזרים לשלב 2 ומגדילים את מספר הבקשות המקבילות.
ממשיכים לחזור על התהליך עד שמגיעים למקסימום יציב של פעולות בו-זמניות.
התאמת הזיכרון לריבוי משימות
כל בקשה שהשירות מטפל בה דורשת כמות מסוימת של זיכרון נוסף. לכן, כשמגדילים או מקטינים את מספר הבקשות המקבילות, חשוב להגדיל או להקטין גם את מגבלת הזיכרון.
הימנעות ממצב גלובלי שניתן לשינוי
אם רוצים להשתמש במצב גלובלי שניתן לשינוי בהקשר של פעולות בו-זמניות, צריך לבצע פעולות נוספות בקוד כדי לוודא שהפעולה מתבצעת בצורה בטוחה. כדי לצמצם את התחרות על משאבים, מגבילים את השימוש במשתנים גלובליים לאתחול חד-פעמי ולשימוש חוזר, כמו שמתואר למעלה בקטע ביצועים.
אם משתמשים במשתנים גלובליים שניתנים לשינוי בשירות שמטפל בכמה בקשות בו-זמנית, חשוב להשתמש בנעילות או ב-mutex כדי למנוע מרוץ תהליכים.
Container Security
שיטות רבות לאבטחת תוכנה לשימוש כללי רלוונטיות לאפליקציות בקונטיינרים. יש כמה שיטות עבודה שספציפיות למאגרי תגים או שתואמות לפילוסופיה ולארכיטקטורה של מאגרי תגים.
כדי לשפר את אבטחת הקונטיינרים:
מומלץ להשתמש בתמונות בסיסיות מאובטחות שמתעדכנות באופן שוטף, כמו תמונות בסיסיות של Google או תמונות רשמיות של Docker Hub.
כדי להחיל עדכוני אבטחה על השירותים, צריך לבנות מחדש באופן קבוע תמונות של קונטיינרים ולפרוס מחדש את השירותים.
כוללים במאגר רק את מה שנדרש להפעלת השירות. קוד, חבילות וכלים נוספים הם נקודות חולשה פוטנציאליות באבטחה. למעלה מופיעה ההשפעה על הביצועים שקשורה לכך.
הטמעה של תהליך build דטרמיניסטי שכולל גרסאות ספציפיות של תוכנה וספריות. כך לא ייכלל קוד לא מאומת במאגר התגים.
מגדירים את מאגר התגים כך שיפעל כמשתמש אחר ולא כ-
rootבאמצעות ההצהרה DockerfileUSER. יכול להיות שחלק מתמונות המאגר כבר כוללות הגדרה של משתמש ספציפי.
אוטומציה של סריקות אבטחה
הפעלת סריקת נקודות חולשה כדי לבצע סריקת אבטחה של תמונות קונטיינרים שמאוחסנות ב-Artifact Registry.
אפשר גם להשתמש ב-Binary Authorization כדי לוודא שרק קובצי אימג' מאובטחים של קונטיינרים נפרסים.
פיתוח קובצי אימג' מינימליים של קונטיינרים
תמונות גדולות של קונטיינרים עלולות להגדיל את נקודות החולשה באבטחה, כי הן מכילות יותר ממה שהקוד צריך.
ב-Knative serving, גודל קובץ האימג' של הקונטיינר לא משפיע על זמן ההפעלה הקרה או על זמן עיבוד הבקשה, והוא לא נכלל בזיכרון הזמין של הקונטיינר.
כדי ליצור קונטיינר מינימלי, כדאי לעבוד עם קובץ אימג' בסיסי רזה כמו:
Ubuntu גדול יותר, אבל הוא קובץ אימג' בסיסי שנמצא בשימוש נפוץ עם סביבת שרת מוכנה יותר.
אם תהליך build של השירות שלכם כולל שימוש רב בכלים, כדאי להשתמש בבנייה רב-שלבית כדי שהקונטיינר יהיה קל בזמן הריצה.
במקורות המידע הבאים אפשר לקרוא מידע נוסף על יצירת תמונות קונטיינר רזות:
- שיטות מומלצות ל-Kubernetes: איך ולמה כדאי ליצור קובצי אימג' קטנים של קונטיינרים
- 7 שיטות מומלצות ליצירת קונטיינרים