פיתוח Ansible Playbooks לאוטומציה של תשתיות

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

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

שאלות נפוצות

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

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

פיתוח Ansible playbooks: איפה הגדרה ידנית נשברת

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

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

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

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

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

מה נותנת קונפיגורציה מנוהלת במקום תיקונים ידניים

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

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

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

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

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

דרכים לתיאור תשתית: השוואת גישות

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

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

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

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

שלבי הטמעה: מביקורת ועד מסירת נהלים

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

רצף השלבים

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

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

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

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

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

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

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

ארטיפקטים בפלט: תפקידים, סכמות, נהלים

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

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

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

מקרה בוחן: איך הסרנו פערים בין סביבות

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

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

מה שינינו

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

מה השתנה

פעולות ידניות לשחרור ירדו מ-40–60 לאפס: המהנדס מריץ את אותה קבוצת תפקידים בכל המתחמים. פריסה נמשכת 12–15 דקות במקום 2–4 שעות, הקמת סביבה מאפס — כחצי שעה, שחזור צומת — 8 דקות מול חמש שעות. אחידות הסביבות נבדקת כעת בקוד, ולא באירוע תקלה.

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

במה נבדלים תפקידים מתרחישים ב-Ansible

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

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

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

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

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

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

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

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

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

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

היכן נשמרים סיסמאות ומפתחות גישה?

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

האם בטוח להריץ את הסט שוב?

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

מה נשאר למהנדסים שלכם אחרי המסירה?

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

נדון במשימה: מה דרוש להתחלה נכונה

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

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

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