הגדרת openSUSE/SLES: YaST, zypper, AppArmor ואוטומציה

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

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

שאלות נפוצות

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

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

למה התקנת openSUSE על שרת פרודקשן לא הולכת לפי התוכנית

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

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

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

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

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

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

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

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

צי על ענף אחיד SUSE Linux Enterprise ו-openSUSE מפסיק להיות אוסף של מכונות "מיוחדות": אוטומציה של הגדרה מתארת את הצומת באופן דקלרטיבי — אותם מאגרים, פרופילי AppArmor וכללי גישה. צומת חדש נכנס לפעולה תוך עשרות דקות במקום צ'ק-ליסט שמהנדס עובר מהזיכרון.

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

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

חלונות תחזוקה: עדכונים לפי התוכנית

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

חזרה לאחור של עדכונים: פעולה שגרתית, לא שחזור חירום

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

נעלם סוג הכשל של מכונה "שחוצה"

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

מצבי התקנה של openSUSE: מינימלי, מלא, רשתי

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

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

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

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

סדר העבודה: מאינוונטריזציה ועד מסירה לתמיכה

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

שלבי ההטמעה

  1. סקר תשתית. אוספים רשימת צמתים, תפקידים, שירותים, אזורי רשת ותלויות חיצוניות. בפלט — מפה שבה רואים מה עובר לתבנית משותפת ומה נשאר ייחודי למכונה מסוימת.
  2. תכנון סכמת הקונפיגורציה. מפרקים את המערכת לפרופילים: תמונת בסיס, תפקיד, דריסות לצומת. מקבעים מה מתואר באופן דקלרטיבי, מה נעשה בכלים הסטנדרטיים של openSUSE ו-SLES, ואיפה נדרשות מדיניות AppArmor נפרדות.
  3. הכנת תמונת אמת ותפקידים. בונים תמונת בנייה, מאוטמטים התקנת חבילות דרך zypper, מתבנתים פרמטרים מערכתיים, מוציאים סודות מהמאגר לאחסון מאובטח.
  4. בדיקה על סביבת בדיקות. פורסים עותק של הקונטור ומריצים תרחישים: התקנה נקייה, עדכון מעל הענף הקודם, חזרה לאחור, עבודת פרופילי ההגנה. שגיאות תופסים כאן, ולא על צמתי פרודקשן.
  5. פריסה על צמתי היעד. מתקדמים בקבוצות עם נקודות בקרה ביניהן — בסטייה של מדדים הקבוצה נעצרת, והשאר לא נפגעות.
  6. מסירה לתמיכה. מוסרים תיעוד בנייה, תקנון עדכונים, נוהל חזרה לאחור ומעבירים את הידע לצוות שלכם — כדי ששינויים בתפקידים לא ידרשו אותנו בכל פעם.

קונפיגורציות, תקנונים ותיעוד: מה מוסרים

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

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

מקרה בוחן: צי של ארבעים שרתים הועבר בלי עצירת שירותים

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

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

מה שינו

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

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

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

מה עושים אם הצי כבר פרוס על הפצה אחרת

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

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

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

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

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

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

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

האם עדכונים בלי השבתה בכלל אפשריים?

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

מה יקרה אם עדכון ישבור את המערכת?

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

חבילות ממאגרים חיצוניים לא ישברו את המערכת?

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

האם סביבת בדיקות נפרדת היא חובה?

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

מה יישאר לצוות שלנו אחרי המסירה?

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

נדון במשימה ונחזור עם הערכה ותוכנית עבודה

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

מה לשלוח בהודעה הראשונה:

  • רשימת שרתים: מספר מכונות, הפצה והענף שלה (openSUSE Leap, SLES), האם ההתקנה כבר בעיצומה או רק מתוכננת;
  • תפקידי שרתים: איפה ווב, איפה מסדי נתונים, איפה וירטואליזציה — מזה תלוי סדר העדכון וסט פרופילי YaST;
  • כיצד מנוהלות חבילות וקונפיגורציות: zypper ידני, Ansible, Salt או סקריפטים משלכם — מה להשאיר, מה להחליף;
  • חלונות תחזוקה: השבתה מותרת לקבוצת שרתים, קיום גיבויים ונקודות חזרה לאחור;
  • דרישות לתיעוד יומנים והגנה: האם נדרש AppArmor, ביקורת פעולות sudo, ייצוא יומנים למערכת חיצונית;
  • הרשאות ורשת: קונטור סגור בלי יציאה החוצה, מאגר מראות משלנו, אופן מתן גישה למהנדסים;
  • סביבות בדיקות ואתרים: קונטור אחד או כמה, האם יש עותק של סביבת הפרודקשן לבדיקת מדיניות.

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