הגדרת GCP Cloud Functions: היכן נשבר מתאר הייצור
הגדרת GCP Cloud Functions עוברת בדרך כלל חלקלק בדמו, ונשברת במתאר הייצור. הפונקציה נפרסת תחת חשבון שירות עם הרשאות רחבות מדי — כך זה מהיר יותר בהתחלה — וכעבור חודשיים איש כבר לא יגיד לאילו דליים וטבלאות יש לה גישה.
ניסיון לצמצם את ההרשאות של חשבון השירות לפני ביקורת עוצר את עיבוד ההזמנות: חלק מהקריאות עברו בדיוק דרכו.
הכשל הטיפוסי השני — סודות במשתני סביבה. מפתח לבסיס הנתונים וטוקן של שירות חיצוני שוכבים לצד ההגדרות הרגילות: הם גלויים בקונסולה, נכנסים לגיבויי קונפיגורציה וללוגים, ורוטציה דורשת בנייה מחדש ופריסה מחדש.
ולצד זה — ההתנעה הקרה של הפונקציה: כשהתעבורה דלילה הסביבה מכבה את המופע, והבקשה הראשונה אחרי ההפסקה לא נכנסת לתוך הטיימאאוט של הלקוח.
קטגוריה נפרדת — חזרות של אירועים. מטפל בלי אידמפוטנטיות, כשההודעה נמסרת שוב, מחייב פעמיים או שולח מייל שני. וטיימאאוט שקט של קריאה חיצונית נראה לעיתים קרובות כמו סיום מוצלח: הקוד מחזיר אישור בלי שהמתין לתשובה. נפרט איך סוגרים את זה — תפקידים מינימליים, סודות במאגר נפרד, חימום מופעים ומטפלים בטוחים לחזרה.
מה משתנה אחרי ההטמעה: אפקטים מדידים
פונקציה כיחידת אספקה מסירה מעלינו שכבה של עבודת תשתית: אין שרתים, עדכוני מערכת ההפעלה וטלאי אבטחה נסגרים על ידי הפלטפורמה, והצוות עוסק רק בקוד ובהתנהגות שלו. את האפקט של מעבר כזה מודדים בארבעה גדלים — זמן תגובה של הפונקציה, שיעור שגיאות ההרצה, זמן הפריסה וסוג התקלות שנמנעו. ב-Google Cloud הם נראים במטריקות של השירות כבר ביממה הראשונה אחרי העברת התעבורה.
זמן התגובה נקבע קודם כל בהרצה של מופעים חדשים תחת עומס. אנחנו מחזיקים סט מינימלי של מופעים מחוממים, מוציאים את האתחול של לקוחות לבסיסי נתונים ולשירותים חיצוניים אל מחוץ למטפל, ומגבילים את המקביליות למופע.
בעומס טיפוסי המסלול החם נכנס לעשרות מילישניות במקום שניות, והגידול במספר הבקשות לא הופך לגידול בהשהיה.
שיעור שגיאות ההרצה יורד בזכות העובדה שהסודות כבר לא חיים במשתני סביבה ובקבצים במאגר הקוד: הם מונפקים לפונקציה בזמן אמת ומתחלפים בלי בנייה מחדש. הגישה מבוססת על תפקידים ולא על מפתחות סטטיים, ולכן קונפיגורציה שגויה נתפסת בשלב הפריסה ולא בפרודקשן. שיעור ההרצות הכושלות יורד מאחוזים לעשיריות האחוז.
זמן הפריסה מצטמצם לפעולה אחת של הצינור, והגרסה החדשה מקבלת תעבורה בהדרגה — קודם חלק מהבקשות, אחר כך את השאר. אם מטריקות התגובה או השגיאות חורגות מהסף, החזרה לגרסה הקודמת אורכת פחות מדקה: התעבורה פשוט מועברת, ואין צורך לבנות את הקוד מחדש. זמן השחזור של השירות מצטמצם מעשרות דקות של פעולות ידניות לפעולה אחת.
בנפרד נעלם סוג של תקלות שקשור לדליפת פרטי זיהוי דרך ארטיפקטים של בנייה ולוגים, וגם תקלות בגלל עריכה ידנית של קונפיגורציה על השרת. רוטציה של סוד מפסיקה להיות אירוע עם עצירת שירות, והגישה של קבלנים ומהנדסים חדשים מונפקת כתפקיד על פונקציה מסוימת — ונשללת באותה דרך.
מצבי פריסה של פונקציות: השוואת גישות
מצב הפריסה קובע מי אחראי על סביבת ההרצה, איך מונפקות ההרשאות ואיך הפונקציה מקבלת סודות. מזה תלויים זמן ההתנעה הקרה, סט התלויות הזמין, ולאן להסתכל כשמנתחים תקלה.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| הרצה מנוהלת לחלוטין | מטפלים טיפוסיים: קריאות HTTP, אירועי תור, העלאת אובייקטים לאחסון | סט קבוע של גרסאות סביבת הרצה וספריות מערכת; גישה לסודות — רק דרך חשבון שירות ו-Secret Manager; מגבלת זמן לקריאה |
| תמונת פונקציה עצמאית | כשצריך חבילות מערכת או תמונה משותפת עם שירותים אחרים | את הבנייה ואת עדכון שכבת הבסיס מתחזקים בעצמכם; התמונה כבדה יותר — ההתנעה הקרה ארוכה יותר |
| היברידי עם שירותים שפועלים כל הזמן | חימום כבד, חיבורים לבסיס נתונים, ספריות משותפות; הפונקציה — שכבה דקה לפני השירות | שני מתארים לתצפית ולחזרה לאחור; קריאה ברשת מוסיפה השהיה; צריך כתובת פנימית וטוקן |
סוגי הטריגרים לא קשורים קשיחות למצב: נקודת HTTP, מנוי על תור, אירוע אחסון וקריאה לפי לוח זמנים עובדים גם בהרצה מנוהלת וגם בתמונה עצמאית. משתנה רק המקור: בסכימה היברידית הפונקציה נקראת לרוב על ידי שירות פנימי ולא על ידי לקוח חיצוני.
מעבר בין מצבים כמעט תמיד משמעותו אריזה מחדש של נקודת הכניסה, ולא כתיבה מחדש של הלוגיקה. קישורי IAM והסודות מועברים כמו שהם, אם הגישה אליהם עוברת דרך שכבת קונפיגורציה אחידה.
שלבי העבודה: מביקורת הקונפיגורציה ועד למסירה
העבודה מתנהלת בסדר קבוע — מהמיפוי ועד המסירה לצוות המתפעל. הסדר אינו מקרי: סכימת התפקידים ומדיניות הגישה מתוכננת לפני הגדרת הסודות, אחרת צריך לבנות מחדש את קישורי חשבונות השירות פעמיים. להלן שישה שלבים, ולכל אחד מהם תוצאה ניתנת לבדיקה.
- מיפוי וביקורת קונפיגורציה. אוספים את כל הפונקציות, הטריגרים, הסביבות והתלויות החיצוניות, ומסמנים היכן הרשאות ניתנו ישירות לאנשים והיכן סודות יושבים במשתני סביבה. בפלט — מפה: מה מעבירים, מה כותבים מחדש, ומה מוציאים משימוש.
- סכימת תפקידים ומדיניות גישה. לכל פונקציה — חשבון שירות נפרד עם סט מינימלי של תפקידים; קריאות בין שירותים מאומתות, ורק נקודות שבהן זו החלטה מודעת נשארות ציבוריות.
- הגדרה ורוטציה של סודות. מפתחות וטוקנים עוברים ל-Secret Manager עם ניהול גרסאות, והפונקציה ניגשת לגרסה הנדרשת לפי הרשאות החשבון שלה. הרוטציה הופכת לנוהל מתוכנן ולא להחלפה חירומית בכל הפרויקט.
- בדיקה תחת עומס. מריצים תרחישים עם התנעה קרה, קריאות מקבילות וכשל של תלות חיצונית: בודקים זמן תגובה, חזרות והתנהגות כשהמכסות נגמרות.
- תיעוד. מתעדים את סכימת הגישה, רשימת הסודות עם הבעלים, סדר הפריסה והחזרה לאחור, ומגבלות ידועות של מכסות וטיימאאוטים.
- מסירה. עוברים על הקונפיגורציה עם צוות הלקוח, מוסרים הרשאות ונהלים, ונשארים בקשר בתקופת התפעול העצמאי.
השלב נסגר לא עם הפריסה, אלא כשהצוות שלכם מוסיף פונקציה בעצמו, מנפיק לה הרשאות ומעדכן סוד בלי העזרה שלנו.
מה נשאר אצל הלקוח אחרי מסירת המתאר
מסירת המתאר היא לא הצגה של הקונסולה, אלא סט קבצים ונהלים שלפיהם הצוות שלכם, בלי אתנו, מפרסם מהדורה, מחזיר אותה לאחור ומטפל באירוע במשמרת תורנות. להלן מה שנשאר במאגר הקוד ובבסיס הידע הפנימי; כל סעיף נבדק בקבלה.
- קונפיגורציות תשתית כקוד: פונקציות, טריגרים, משתני סביבה וקישורי סודות — הסביבה מוקמת מהמאגר ולא ידנית.
- מטריצת תפקידים והרשאות: לכל חשבון שירות רואים אילו קריאות הוא יוזם, למי מותר לפרוס ולקרוא סודות; הרשאות עודפות — לשלילה.
- נוהל רוטציה של סודות: תדירות, אחראי וסדר שבו הגרסה החדשה נכנסת לפעולה לפני כיבוי הישנה — בלי השבתה ובלי עריכות בקוד.
- סכימת אינטגרציות: תורים, לוחות זמנים, קריאות חיצוניות ונקודות כשל — עם ציון איזה רכיב מדרדר ראשון ומה המשתמש רואה.
- תיעוד תשתית: פרויקטים, מכסות, מגבלות, משתני סביבה וקשרי שירותים — על עמוד אחד, שלפיו מהנדס חדש נכנס למתאר בתוך יום.
- הוראות לתורן: התראות טיפוסיות, היכן לראות לוגים ומטריקות, איך מחזירים את המהדורה האחרונה לאחור ולמי להסלים.
- תוכנית חזרה לאחור: מדיניות שמירת גרסאות קודמות וזמן חזרה למצב תקין שאומת בתרגול.
הסעיפים קשורים זה לזה: מטריצת התפקידים מפנה לנוהל הרוטציה, והוראות התורן — לסכימת האינטגרציות ולתוכנית החזרה לאחור. אם משהו לא משוחזר בלעדינו, הסעיף לא נסגר בקבלה.
מקרה בוחן: העברנו מונוליט לפונקציות בלי השבתה
הלקוח הגיע עם מונוליט על מכונות וירטואליות: פריסה אחת לשבועיים, ידנית, לפי הוראות בוויקי. זמן הפריסה — כ-40 דקות, וכל מהדורה כללה חלון אי-זמינות: חלק מהבקשות קיבלו שגיאה בזמן שהתהליכים התחממו.
הסודות ישבו במשתני סביבה משותפים והיו גלויים לכל השירותים בבת אחת — שגיאת כתיב אחת בהרשאות חשפה גישה לנתונים של אחרים.
איך העברנו
פיצלנו את המונוליט לפי דומיינים והעברנו כל אחד לפונקציה נפרדת מאחורי נתב משותף: המטפלים הישנים נשארו פעילים בזמן שהתעבורה הועברה בהדרגה — 5, 25, 50, 100%.
ההרשאות חולקו לפי חשבונות שירות: לכל פונקציה רק התפקידים שהיא צריכה כדי לעבוד, והמפתחות והטוקנים עברו ל-Secret Manager עם ניהול גרסאות ורוטציה. את התשתית פרסנו על Google Cloud ותיארנו אותה דקלרטיבית — סביבה חדשה מוקמת בפקודה אחת, בלי הגדרה ידנית.
מה קיבלנו בסוף
זמן הפריסה הצטמצם מ-40 דקות ל-4: הפרסום מתבצע אוטומטית, בלי צעדים ידניים ובלי תורנות ליד הקונסולה. שיעור השגיאות לכל מהדורה ירד מ-3.1% ל-0.4% — את רוב התקלות יצרו מפתחות משותפים ופערים בין סביבות, שנעלמו יחד עם ההגדרה הידנית.
השבתת השירות בזמן המעבר — אפס: ההעברה נעשתה לפי חלקי תעבורה, והחזרה לאחור מחזירה את הגרסה הקודמת של הפונקציה בתוך שניות.
במה נבדלות פונקציות ללא שרת משירותים קבועים?
ההבדל המרכזי הוא מתי נוצר התהליך שמטפל בבקשה. פונקציה ללא שרת נוצרת לקריאה מסוימת ומסתיימת יחד איתה: הפלטפורמה מחליטה בעצמה אם להשאיר את המופע חם או לפנות אותו לקריאה הבאה. שירות שפועל כל הזמן מחזיק תהליך ברצף — חיבורים, מטמון בזיכרון ומשימות רקע חיים בין הבקשות.
הצפיות של ההשהיות מתפצלת ראשונה. בפונקציות קריאה אחרי הפסקה עוברת התנעה קרה: אתחול הסביבה, קריאת סודות מ-Secret Manager, בדיקת הרשאות דרך IAM. רוב התשובות מהירות, אבל קריאות בודדות בולטות בפערים של פי כמה, ובאינטראקטיבי זה מורגש למשתמש. שירות קבוע מתחמם פעם אחת, ומכאן והלאה זמן התגובה נשמר במסדרון צר.
חיבורים קבועים — נקודת ההבדל השנייה. מאגר חיבורים לבסיס הנתונים, חילופי מידע דו-כיווניים עם הלקוח וזרימות נתונים ארוכות דורשים שהתהליך יחיה יותר מקריאה אחת; פונקציה לא שומרת מצב כזה, והוא מוצא אל שכבה חיצונית — עם גידול במספר הפניות זה מוסיף השהיה ונקודות כשל.
מחיר אי-הפעילות בנוי באופן מראה: פונקציות מחויבות לפי עבודה בפועל, ושירות שיושב בלי תעבורה — לפי כוח מחשוב שמור. ב-Google Cloud שני המודלים חיים באותו פרויקט, ולכן את הסכימה מרכיבים לרוב כהיברידית.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| פונקציות ללא שרת | משימות מבוססות אירועים: עיבוד קבצים, התראות ממערכות חיצוניות, פניות נדירות | התנעה קרה, אין מצב מתמשך |
| שירות שפועל כל הזמן | ממשקים אינטראקטיביים, חיבורים קבועים, תגובה יציבה | חיוב על שריון גם בלי תעבורה |
| פונקציות עם מינימום מופעים מחומם | פיקים בתעבורה כשיש דרישה קשיחה לתגובה | החימום מחויב כל הזמן |
הבחירה נעשית לא לפי העיקרון של «מה מודרני יותר», אלא לפי פרופיל העומס: באיזו תדירות מגיעות קריאות, אם יש פיקים, והאם צריך חיבורים ארוכים.
ספקות טכניים לפני העלייה למתאר הייצור
לפני העלייה למתאר הייצור הלקוח מביא רשימה של שאלות שהצטברו — מהרשאות גישה ועד להתנהגות הפלטפורמה תחת עומס. להלן חמש שהכי часто קובעות אם המהדורה תעבור בשקט, והתשובות הקצרות שלנו לכל אחת.
העיקרון הכללי אחד: הרשאות וסודות מתוארים דקלרטיבית וחיים מחוץ לקוד הפונקציה, ולכן שינוי שלהם לא מחייב לכתוב מחדש את הלוגיקה ולבנות מחדש את הארטיפקט.
יש לנו תפקידים מיושנים — צריך לכתוב אותם מחדש מאפס?
אנחנו מתחילים במיפוי: אוספים אילו הרשאות באמת בשימוש, ומעבירים חשבונות שירות לקישורים חדשים דרך קבוצות. תפקידים מיותרים מסירים בשלבים — קודם מסתכלים ביומן הפניות, אחר כך שוללים. כך ניקוי ההרשאות לא הופך לתקלה.
למה אסור להחזיק מפתחות במשתני סביבה?
משתני סביבה נכנסים לתיאור הגרסה וליומני הבנייה — כל מי שיש לו הרשאת צפייה יראה את הסוד. אנחנו מוציאים את הערכים ל-Secret Manager, ובמשתנים משאירים רק את שם הסוד ואת הגרסה שהפונקציה קוראת.
האם תהיה השבתה בעת החלפת הרשאות?
קישורי התפקידים חלים על המופעים הפעילים, ואין צורך לעצור את השירות. השבתה נוצרת במקום אחר: אם הפונקציה קוראת את הסוד פעם אחת בהתנעה ושומרת אותו במטמון, שלילת המפתח הישן לפני שהמטמון פג נותנת חלון של תקלות. אנחנו יוצרים חפיפה — הסוד החדש זמין מראש, והישן מכובה אחרי שכל המופעים קראו מחדש את הערך.
איך מתבצעת רוטציה של מפתחות בלי לפרוס גרסה חדשה?
סודות שומרים גרסאות, ולכן הרוטציה מצטמצמת להוספת גרסה חדשה ולהעברת המצביע — הקוד לא משתנה. החזרה לאחור זהה: מחזירים את המצביע לגרסה הקודמת, והפונקציה עובדת שוב עם הערך הישן בזמן שאנחנו מבררים את הסיבה.
אילו מגבלות של הפלטפורמה יבואו לידי ביטוי תחת עומס?
ישנם גבולות בזמן ההרצה של הבקשה, במספר המופעים במקביל, בגודל התמונה ובהשהיית ההתנעה הקרה. בודקים אותם בסביבת בדיקות בפרופיל עומס קרוב לזה של הייצור: אז הפגיעה במגבלה נראית מראש, וסוגרים אותה בכוונון המקביליות או בפיצול המשימה.
נדבר על המשימה: ביקורת, סכימה ותוכנית הטמעה
הערכה על סמך התכתבות כמעט תמיד נותנת טווח רחב, ולכן מתחילים בעובדות: קונפיגורציות של פונקציות, רשימת טריגרים, התפקידים שהונפקו, ואיך כיום נשמרים ומתחלפים הסודות. זה מספיק כדי לראות צווארי בקבוק — הרשאות עודפות, ערכים במשתני סביבה והיעדר הפרדה בין סביבות.
- קונפיגורציות נוכחיות של פונקציות וטריגרים — נשווה לעומס בפועל, נמצא כפילויות ומופעים נשכחים.
- רשימת חשבונות ותפקידים — נראה היכן הגישה ניתנה רחבה מהנדרש, ונצמצם אותה למינימום ההכרחי.
- סכימת אחסון ורוטציה של סודות — נבדוק שהערכים לא נכנסים ללוגים, לקוד הבנייה ולהיסטוריית השינויים.
- מגבלות הסביבה: חלונות לשינויים, דרישות לחזרה לאחור, ומי ואיך תורן ברגע הפרסום.
- ביקורת של הקונפיגורציה הנוכחית: דוח עם רשימת סיכונים, ממוינים לפי הסתברות ומחיר הטעות.
- תוכנית הטמעה: שלבים, סדר השינויים, נקודות בדיקה ומה שאפשר לפרוס בלי השבתה.
- הערכת לוחות זמנים: טווח לפי שלבים בתוספת התנאים שבהם הוא מצטמצם או, להיפך, גדל.
- העברת ידע: תיעוד, הרצות קבלה ודיון עם הצוות שלכם על הדוגמאות שלו עצמו.
אנחנו מחזירים לא דוח שיושב במגירה, אלא קונפיגורציות עובדות, סכימות תפקידים והוראות רוטציה — כדי שתוכלו לתחזק את הפתרון בהמשך בכוחות עצמכם. תארו את המשימה ואת המצב הנוכחי — נחזור עם הערכה ותוכנית.







