External Secrets Operator: התקנה והגדרה ב-Kubernetes

הנפקה ידנית של סודות באשכול כמעט תמיד מסתיימת בכשל של ריליס ובאישורים מיותרים. אנחנו מגדירים External Secrets Operator כשירות מלא: מחברים מאגר סודות ל-Kubernetes, מתארים הרשאות באמצעות מדיניות ומעבירים לצוות סכימה עובדת. הרוטציה מפסיקה להיות ידנית, והפריסה מתבצעת לפי נוהל ולא לפי הזיכרון של מישהו.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

External Secrets Operator: מדוע סודות ידניים שוברים את הריליס

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

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

ככל שיש יותר סביבות, כך לעתים קרובות יותר העבודה עם סודות באשכול אינה תואמת את מה שבאמת עובד בפרודקשן.

זה נפתר על ידי העברת מקור האמת: מאגר סודות אחיד, שממנו External Secrets Operator מושך ערכים ומפזר אותם לאובייקטים באשכול. סנכרון הסודות מתבצע לפי לוח זמנים, הרוטציה הופכת לפעולה אחת במאגר, ולא למעבר בין שירותים. העדכון מגיע לצרכנים בלי תיקונים ידניים, והריליס מפסיק להיות תלוי במי הספיק לתקן אצלו.

נפרק כיצד זה נסגר: התקנת האופרטור, חיבור למאגר, מדיניות גישה וסדר החזרות לאחור.

אפקט מדיד: פריסה, שחזור, סוג כשל

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

השינוי המדיד הראשון — זמן הכנת הריליס. כאשר External Secrets Operator בעצמו מושך ערכים מהמאגר ומעדכן אותם באשכול, השלב "תביא והנח" יוצא מהתהליך, והריליס יוצא לדרך מאותו מצב כמו הקודם.

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

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

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

מצבי אספקת סודות: השוואת גישות ומגבלות

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

אופן אספקה מתי מתאים מגבלות
סודות ב-git, מוצפנים זרימה דקלרטיבית אחידה, מעט סביבות מפתח הפענוח מופץ בנפרד, ערכים קודמים נשארים בהיסטוריה
אובייקטי Secret מובנים באשכול אשכול אחד, אפליקציות בודדות סחיפה בין סביבות, רוטציה ידנית, אין מקור אמת אחיד
סנכרון ממאגר חיצוני (External Secrets Operator) כמה אשכולות, רוטציה תכופה נדרשות הרשאות קריאה, תלות בזמינות המאגר, השהיית סנכרון
הרכבת סוד כקובץ האפליקציה קוראת את הקובץ מחדש בלי הפעלה מחדש לא מתאים לכל האפליקציות, משתני סביבה לא מתעדכנים כך

אספקת סודות לאפליקציה באף אחד מהאופנים אינה מבטלת את מודל התפקידים של האשכול: הגישה עדיין מוגבלת ברמת מרחב השמות וחשבון השירות. מגבלה נפרדת — משתני סביבה: הם נשארים בתיאור ה-Pod ונראים בדאמפ של התהליך, לכן עבור ערכים רגישים עדיף קובץ ממונט.

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

הטמעה שלב אחר שלב: ביקורת, סכימה, הגדרה, בדיקה, מסירה

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

  1. ביקורת העבודה עם סודות. עורכים מלאי של מה ומאיפה מגיע לאשכול: ערכים במניפסטים ובמאגרי קוד, משתני סביבה, קבצים ממונטים, הרשאות קריאה במאגר. התוצאה — מפה "עומס → סוד → מקור → בעלים".
  2. סכימת גישה למאגר. בוחרים מקור אמת אחיד, מודל אימות לאשכול והפרדה לפי מרחבי שמות, כך שהצוות רואה רק את הנתיבים שלו. בנפרד מתעדים כיצד רוטציה חיצונית משתקפת בעומסים.
  3. הטמעה באשכול. מתקינים External Secrets Operator במרחב שמות נפרד, מגבילים את הרשאותיו למינימום הנדרש ומפעילים סביבות אחת-אחת — תחילה סביבת בדיקה, אחר כך פרודקשן.
  4. העברת עומסים. מחליפים סודות רגילים בהצהרות ומשאירים תקופת עבודה במקביל: הדרך הישנה והחדשה מתקיימות זו לצד זו, כל עוד אין אי-התאמות.
  5. בדיקת עמידות לכשלים. מדמים אי-זמינות של המאגר, טוקן שפג תוקפו ורוטציה של ערך: בודקים אם ה-Pods שורדים הפעלה מחדש ואם התראות על חוסר סנכרון מופעלות.
  6. מסירה לתפעול. מוסרים סכימות, תצורות, הוראות לפעולות שגרתיות ונוהל רוטציה, ועוברים עם הצוות על סדר הפעולות בעת תקלה.

מה נשאר במאגר הקוד ובאשכול: תצורות ומדיניות

את הערכה מוסרים כמאגר קוד בתוספת סכימות מיוצאות: עבור כל ארטיפקט רואים מי הבעלים, כיצד הוא מתעדכן ומה יקרה בעת כשל. להלן — מה בדיוק נשאר אצל הצוות שלכם לאחר הטמעת External Secrets Operator.

  • מניפסטים של ExternalSecret ו-SecretStore/ClusterSecretStore — תצורת סנכרון: אילו מפתחות נמשכים מהמאגר, באיזו תדירות נשאל המקור, אילו שדות נכנסים ל-Secret הסופי.
  • סכימת אינטגרציה עם המאגר: נתיב למאגר הסודות החיצוני, אופן האימות באמצעות חשבון שירות, התאמה "מפתח במאגר → שם סוד באשכול".
  • מדיניות גישה: מה מותר לכל שירות לקרוא, הפרדה לפי מרחבי שמות, איסור על קריאה ישירה של ערכים מצ'ארטים ומאימג'ים.
  • נוהל רוטציה: תוקף הערכים, מי יוזם החלפה, כיצד בודקים שה-Pod קרא מחדש את הסוד המעודכן בלי הפעלה מחדש ידנית.
  • כללי טיפול בכשלים: התנהגות בעת אי-זמינות המאגר, פעולות בעת אי-התאמה עם המקור, אילו אירועים עוברים לניטור ולהתראות.
  • תיעוד סודות: מפת בעלי המפתחות, סדר הוספת ערך חדש, הוראה לתורן במקרה של תקלה.
  • תוכנית מעבר: סדר העברת סודות שכבר עובדים, חזרה לסכימת אספקה קודמת, קריטריונים שלפיהם שלב נחשב להסתיים.

מקרה בוחן: הסרנו רוטציה ידנית של סודות באשכול גדול

מה היה לפני ההטמעה

הפלטפורמה — כ-180 שירותים ב-Kubernetes, סודות למסדי נתונים, תורים ו-APIs חיצוניים ישבו במניפסטים ובמשתני סביבה של משימות בנייה. הרוטציה נותרה ידנית: מהנדס קיבל ערכים חדשים מהמאגר, עבר על מרחבי השמות, עדכן אובייקטי Secret והפעיל מחדש עומסים.

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

המחיר הופיע בשני מקומות. ראשית, תקלות: 5–7 כשלים ברבעון בגלל מפתחות שפג תוקפם וחוסר סנכרון בין סביבות בדיקה, כל אחד — עם תחקיר לילי. שנית, ריליסים: הפריסה חיכתה לחלון רוטציה, וזמן הריליס נמתח משעות ל-2–3 ימים.

מה שינו

פרסנו External Secrets Operator ותיארנו ExternalSecret לכל עומס, המקור — HashiCorp Vault. האופרטור בעצמו מושך ערכים ובונה מחדש את ה-Secret כאשר יש שינוי במאגר; רוטציה אוטומטית מתבצעת לפי לוח הזמנים של המאגר, בלי מעורבות אדם.

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

מה התוצאה

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

External Secrets מול סודות מובנים: מה ההבדל

סודות מובנים — אלו אובייקטי Secret שנמצאים ב-etcd של האשכול. הערך מקודד ב-base64, הגישה מופרדת לפי תפקידים, והרשומה עצמה חיה במקום אחד: במניפסט, ב-Helm chart או בסקריפט פריסה. כל עוד יש אשכול אחד וסודות בספירה של עשרות, זה מספיק: ה-Pod מקבל ערך ממשתנה סביבה או מקובץ ממונט.

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

סודות חיצוניים משנים את הסכימה: באשכול נשאר רק תיאור — איזה מפתח לקחת ולאן לשים — והערך נמשך על ידי האופרטור ממאגר כמו HashiCorp Vault או מנהל סודות בענן. הסנכרון מתבצע לפי לוח זמנים או לפי אירוע, והתוצאה מתממשת ל-Secret רגיל, לכן קוד האפליקציה לא נכתב מחדש.

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

המחיר — רכיב נוסף באשכול, הרשאות קריאה של האופרטור מהמאגר ונקודת כשל חדשה תחת ניטור. הבחירה נתקעת בשאלות: כמה אשכולות, מי הבעלים של הסוד, באיזו תדירות הוא משתנה, האם נדרשת ביקורת.

אשכול אחד עם רוטציה נדירה — מובנים מספיקים; סוד משותף לסביבות או אספקה ממערכת חיצונית — נדרש אופרטור.

ספקות טכניים: עמידות לכשלים, הרשאות, מיגרציה

External Secrets Operator — בקר (controller) שמחזיק את סודות האשכול מסונכרנים עם מאגר חיצוני: הערך במאגר משתנה, האובייקט ב-Kubernetes משתנה. מכאן גם הספקות העיקריים של מהנדסים — מה יקרה כשאין גישה למאגר, באילו הרשאות פועלת המערכת עצמה וכיצד לעבור אליה בלי השבתה.

מה יקרה אם המאגר אינו זמין?

סודות שכבר סונכרנו נשארים באשכול וממשיכים לעבוד — הבקר לא מוחק אותם. ערכים חדשים просто לא יימשכו עד לחידוש הקשר, האובייקט יעבור לסטטוס עם שגיאה, ואנחנו נגדיר התראה למצב הזה.

באילו הרשאות פועלת המערכת?

חשבון נפרד במאגר עם הרשאת קריאה רק לנתיבים הנדרשים. מצד האשכול — חשבון שירות עם מודל תפקידים שמוגבל למרחבי שמות מסוימים: הבקר לא יכול לקרוא סודות שאליהם אינו משויך.

כיצד מתבצעת מיגרציה מדורגת?

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

מה קורה בזמן רוטציה של סוד?

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

כיצד משתחזרים לאחר תקלה?

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

נדון במשימה: מה לשלוח וכיצד תתקדם העבודה

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

  • מפת אשכולות וסביבות: כמה יש, באיזה מעגל, מהי גרסת ה-Kubernetes העדכנית ומי מנהל אותם כעת.
  • מאגרי סודות: שירות ענן, HashiCorp Vault או פתרון עצמאי, וכיצד סודות מגיעים לאשכול היום — ידנית, דרך CI או בסקריפטים.
  • מלאי סודות: אילו קיימים, לאילו שירותים הם משויכים ואילו קריטיים עד כדי כך שדורשים תיאום עם אבטחה.
  • מודל גישה: service accounts, תפקידים, מגבלות רשת בין האשכול למאגר, קיום מעגל נפרד לבדיקות.
  • דרישות לרוטציה ולכשלים: באיזו תדירות מפתחות משתנים ומה צריך לקרות לעומס העבודה אם המאגר אינו זמין.
  • סדר הוצאה: אילו סביבות ושירותים מעבירים ראשונים, אילו חלונות מותרים לשינויים.

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