2016-05-28

משינה אויסלערן - או בקיצור: Machine Learning

Machine Learning הוא תחום שאמנם קיים בערך משנות ה-60, אך שהתפתח בעיקר ב 10-15 השנים האחרונות.

מנקודת מבט אחת, Machine Learning (בקיצור: ML) הוא כלי שמאפשר לפתור בעיות תוכנה, שלא ניתן לפתור בדרך הרגילה - קרי: בעזרת משפטי if ולולאות for.
ארתור סמואל, החלוץ בתחום תיאר זאת כ "give computers the ability to learn without being explicitly programmed".

כמובן שיש בשכבות הנמוכות של פתרונות ה ML הרבה משפטי if ולולאות for, אך ML מספק שיטה מתמטית/סטטיסטית המאפשרת לחשוב בפרדיגמה שונה של "תכנות" על הבעיות האלה.

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


בפוסט הבא אנסה לתת סקירה לא משוחדת של עולם ה Machine Learning, ומשמעויותיו.






היכרות בסיסית עם ML


לא כל בעיה ניתן לפתור בעזרת ML - להיפך. הבעיות העיקריות שניתן לפתור בעזרת ML מחולקות לקטגוריות הבאות:
  • Regression - חיזוי של ערך, על בסיס נתונים. למשל: שערוך ערך של דירה על סמך הנתונים שלה (שטח, גיל, וכו') או הערכה מה יהיה סכום העסקאות של לקוח בחודש הקרוב - על סמך עסקאות עבר, גיל, ומדדים של הרגלי קנייה.
  • Classification - סיווג של entities למספר סגור של קבוצות מוגדרות, למשל: שביעות רצון של לקוח (3 ערכים אפשריים: נאמן, רגיל, נוטה לעזוב), האם עסקה היא לגיטימית או הונאה (2 ערכים אפשריים), וכו'.
  • Clustering - גיבוש קבוצות של פריטים מסוימים. למשל: ברוסיה יש 10,500 ערים - צור קבוצות של ערים דומות (ע"פ סדרה של נתונים על הערים, קרי: מספר תושבים, הכנסה ממוצעת, שטח, שנות קיום, וכו').
  • Recommender Systems - חיזוי פריטים דומים שמישהו עשוי להתעניין בהם, למשל: אם אהבת דיסק של כנסיית השכל - אולי תאהב את הדיסק החדש של שלמה ארצי (לא!!!!!!)
    • Collaborative Filtering - "מי שאהב X אהב גם Y" - המלצת תוכן או מוצר למשתמש, ע"פ סיווג של משתמשים "דומים", ותיאור הפריטים שקבוצת ה"משתמשים הדומים" נוטה לאהוב.


מקור: https://dataaspirant.com



את עולם ה ML מחלקים בדרך ל-2 קטגוריות:


Supervised Learning

כאשר יש לנו מאגר של נתונים ותשובות (= target value), שהושגו בצורה כזו או אחרת (מדידה, עבודה של מומחים, וכו') - ואנו רוצים שהמחשב ינסה לחקות את התשובות.

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

בעזרת ML אנו יכולים לפעול באופן הבא:
  • להשתמש ב Domain Knowledge (בקיצור DK) על מנת למצוא, או לפחות לנחש את ה features (תכונות) שמסבירות את מחיר הדירה. מיקום, ושטח במ"ר הם features חזקים מאוד, קומה וגיל הבנין הם features בינוניים וצבע הקירות או גודל המטבח יחסית לגודל חדר האמבטיה - הם features זניחים או אפילו מטעים.
  • בשלב הבא אנו נבחר אלגוריתם למידה (מתוך מבחר אלגוריתמים בתחום) ונפעיל אותו על 80% מהנתונים שלנו (למשל).
  • האלגוריתם ירכיב מודל חיזוי, ע"פ כל מיני שיטות מתמטיות / סטטיסטיות - שניתן להריץ: לשלוח לו פרטים של דירה - ולקבל תשובה = מחיר משוערך.
  • נשתמש ב 20% הנתונים הנותרים שלא השתמשנו בהם ללמידה - לצורך ביקורת: עד כמה טוב המודל שנוצר? מה התפלגות התשובות שלו?
  • כך אפשר לחזור כמה מחזורים עד שאנו מוצאים אלגוריתם ו tuning שמספקים תוצאות שאנו מרוצים מהן.
  • שלב זה יש לנו תוכנה שיכולה לשערך בדיוק כזה או אחר (בשאיפה: דיוק דיי טוב) את העלות הצפויה של דירה ע"פ נתונים גולמיים.
  • כמובן שניתן לשפר את המודל עם הכנסה של Domain Knowledge נוסף: למשל אנו יכולים להעריך שיש הבדל בהתנהגות בין המרכז לפריפריה. אולי הרכבה של 2 מודלים שונים: אחד למרכז ואחד לפריפריה - תשיג תוצאה טובה יותר.
    • יש עוד כלים רבים לשיפור מודל החיזוי - מדובר בד"כ בתהליך איטרטיבי ומשמעותי של שיפורים.


Unsupervised Learning


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

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

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

---

שתי הקטגוריות של ML, "למידה מפוקחת" ו"למידה לא מפוקחת" - מייצרות מודלים שאינם מושלמים:
בבעיות Binary Classification (כאשר התשובה היא X או Y) הצלחות של 80% ואפילו 70% נחשבות להצלחה.
להזכיר: בכזו בעיה נקודת האפס היא 50% - השקולה להטלת מטבע, או התפלגות ידועה אחרת (קרי: ההסתברות האפריורית של האירוע).

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

המוטיב המרכזי לשימוש ב ML הוא לפתור בעיות שאין לנו פתרון טוב יותר עבורן:

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

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







תהליך העבודה (Workflow) של ML


תהליך העבודה של ML, הוא מעט יותר מורכב ממה שתיארתי. מכיוון שעיקר העבודה על ML היא התהליך ולא כתיבת קוד - אפרט מעט יותר על התהליך.
אני אתמקד בתהליך שמתאים ל Supervised Learning, כמו בעיית רגרסיה (ניבוי ערך של נכס נדל"ן).

השלבים בתהליך הם:


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

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

מי יכול לדעת ששישה חודשי עבודה על ניסיונות המלצה שונים הולכים לרדת לטמיון?
דרוש כאן בעיקר Domain Knowledge עמוק ואיכותי ו/או מתודולוגיה שתזהה כישלון בשלב מוקדם.


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

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

שלב זה בעיה משולבת של Domain Knowledge, תכנות, והבנה ארגונית טובה - ברוב הפעמים לא תוכלו להשיג את הנתונים לבד.

".More data beats clever algorithms, but better data beats more data" -- פיטר נורוויג (המחבר-שותף של הספר הנודע "AI: A Modern Approach" ומנהל מחקר בגוגל).



קרצוף הנתונים (Scrubbing Data)
גם ברגע שיש נתונים "נכונים "- לרוב יהיו להם בעיות איכות (Data Quality):
  • להשלים ערכים חסרים (או להסיר אותם, אם תיקון לא אפשרי). באג בפרודקשיין עשוי לגרור לאחוז כזה או אחר של נתונים שגויים או חסרים - לאורך תקופה.
  • לתקן אי התאמות. למשל שמי הופיע פעם בספריית הוידאו גם כ "ליאור בר און" וגם כ "ליאור בר-און" - הייתי מיוצג כשני אנשים, למרות שאני אדם אחד - מה שיגרום להטיה בניתוח הנתונים.
    • יש טכניקות שונות (חלקן מבוססות ML) בכדי להתאים ולזהות שבעצם מדובר באותו האדם (בסבירות כזו או אחרת)
  • נורמליזציה של הנתונים, למשל: כל התאריכים באותו ה format כך שניתן יהיה לעשות השוואות. המרה של מיילים לקילומטרים, סדר נתונים כזה לסדר אחר, וכו'. ישנו כלל של ML שטוען: "הנתונים שתקבלו תמיד יהיו בפורמט הלא-נכון"
שלב השגת הנתונים + "הקרצוף" נחשבים בד"כ לכ 50-80% מכלל העבודה ב ML Workflow - החלק הארי.
שלב זה דורש יכולות תכנות, קצת הבנה סטטיסטית (עבור תיקונים וקירובים), ומעט Domain Knowledge - על מנת להבין את הנתונים טוב יותר.
כמעט תמיד ניתן להשקיע עוד עבודה בכדי לשפר עוד יותר את איכות הנתונים - וחשוב לדעת גם מתי "לעצור".


בחירת האלגוריתם

ישנם עשרות אלגוריתמים של ML, וכמה שרלוונטיים לכל סוג של בעיה. עליכם להבין את הנתונים ואת האלגוריתם - על מנת (לנסות ו)להתאים את האלגוריתם הטוב ביותר.

למשל: בעיה של Binary Classification ניתן לפתור בעזרת Naive Bayes (מודל סטטיסטי שלא דורש כמויות גדולות של נתונים ורץ מהר), בעזרת Logistic Regression (המבצע רגרסיה בין features ע"פ משקולות נתונות), או עץ החלטה (שמנסה לשערך הסתברות של כל feature בנפרד - ואז לסכם את סך ההסתברויות).

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

שלב זה הוא Pure Machine Learning Knowledge


בתרשים זה ניתן לראות כיצד בחירה של אלגוריתם משפיעה על אחוז הטעות של האלגוריתם. תמיד קיים tradeoff בין טעות מסוג I וטעות מסוג II, אבל ניתן לראות שאלגוריתם ה Random Forest עליון במקרה זה על האלגוריתמים האחרים. מקור: wise.io




אימון המודל

זהו השלב בו מזרימים את הנתונים לאלגוריתם, ובד"כ בונים תהליך אוטומטי שיעשה זאת.

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

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

שלב זה דורש הבנה סטטיסטית, מעט תכנות, ויכולות תפעול.


בחינת המודל

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

--

השלב הבא הוא לא GA (כלומר: General Availability).
בד"כ יהיו השגות חדשות על איכות הנתונים / סוג הנתונים הנדרש / התאמת האלגוריתם וכו'.
מכאן חוזרים לכמה איטרציות נוספות של שיפורים - עד שמגיעים לרמה הרצויה.

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


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



סיכום


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

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

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

התחום הזה הוא לא פשוט בכלל: זה לא כמו ללמוד עוד שפת תכנות או עוד Framework.
ספקי ענן כאלו אחרים יספרו לכם שיש להם "Machine Learning as a Service" ושהיום הכל יותר פשוט: לא צריך דוקטורט, אלא רק חשבון ב <שם ספק ענן מוכר> - ואפשר להתחיל להריץ ML.
זה נכון - התהליך הופך לנגיש יותר ויותר מבחינת התפעול, אך אין עדיין (למיטב ידיעתי) - התקדמות משמעותית בניסיון לייתר את המומחיות בתחום.


שיהיה בהצלחה!



---


לינקים רלוונטיים:

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


https://charlesmartin14.wordpress.com - בלוג שמנסה להסביר לעומק קונספטים שונים ב ML



2016-05-21

על DevOps וה DevOps toolkit

יש כמה הבדלים מהותיים בין פיתוח תוכנה של המתכנת הבודד ("לבד בבית") לקבוצה גדולה יותר של אנשים שמפתחת את הפרויקט ביחד. המעבר לקבוצת פיתוח מכתיב צרכים של תיאום וסנכרון, ובסיס הקוד הגדול והמורכב יותר (שהוא פועל יוצא של יותר ידיים עובדות) - דורש תהליכים של "ניהול תצורה", Deployment, וניהול הקוד ב Production.   בכדי להתמודד עם האתגרים הללו, קבוצות הפיתוח השתמשו בשני כלי-עוצמה ניהוליים: התמחויות ואחריות, וכך נוצרו התפקידים הבאים:
  • מפתחים אחראים לכתוב קוד
  • איש ה UX אחראי לעצב את חווית השימוש
  • ה DBA מתמחה ב Database Systems
  • ה QA בודק את המערכת
  • איש ה Operations אחראי להתקין את התוכנה ולנטר אותה
  • וכו'...

מקור: http://nealford.com/abstracts.html#cd

באופן טבעי, הושתת ניגוד-אינטרסים מובנה בין חלק מבעלי התפקידים:
  • איש ה UX רוצה להשיג את חווית השימוש הטובה ביותר - והמפתח רוצה לשחרר פיצ'רים מהר.
  • איש ה QA רוצה שלמות במוצר - והמפתח רוצה לשחרר פיצ'רים מהר.
  • איש ה Operations רוצה יציבות - והמפתח רוצה לשחרר פיצ'רים מהר.

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

שינוי #1: הגבולות בין אנשי ה QA והמפתחים החלו להיטשטש

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


שינוי #2: המעבר לענן ואוטומציה של התפעול

המעבר לענן הסיר מאנשי ה Operations בארגון כמה עיסוקים הרחוקים מאוד מהמפתחים: טיפול בחומרה ורשתות תקשורת - עולם שלם בפני עצמו. את החומרה והרשת מנהלים בצורה אוטומטית בעזרת תוכנה (להלן Virtualization ו Software Defined Networks) וכך התקרב העולם של אנשי ה Operations לעולם המתכנתים - עולם של כתיבת סקריפטים ~= קוד.    

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

היכולת של ה Operations להתמודד עם אתגרים אלו כקבוצה חיצונית לפיתוח - הפכה מורכבת יותר ויותר. חילופי ההאשמות והמתח בין הקבוצות רק הלך וגבר (להלן blaming culture).

שינוי שאנו נמצאים במהלכו כיום נקרא The DevOps Movement - ההכרה שהדרך הטובה ביותר להתמודד עם סביבות המחשוב המורכבות שנוצרו - הוא בשיתוף פעולה אמיתי בין Operations ל Developers.


מקור: ThoughtWorks Radar - מארס 2012
 
כמובן שארגונים רבים לא מכירים בעומק הרעיונות שמאחורי תנועה זו, ופשוט משנים את ה title של אנשי ה Operations ל "DevOps" - שם פופולארי יותר.

מקור: ThoughtWorks Radar - נוב' 2015
 

עבודת ה Dev-Ops בארגון


בשלב הזה אני לסקור את העבודה שיש בפני ה Operations וה Dev (וגם קצת IT וגם קצת QA) בארגון. אני יכול להתחיל בהצהרות ברמה גבוהה "לדאוג ליציבות המערכת". הצהרות אלו הן נכונות - הן אם לא תמיד כ"כ מוחשיות. מה כן מוחשי? כלים ותהליכים. אספתי את סוגי הכלים והתהליכים הקיימים בעולם Dev-Ops לכדי רשימה, ואני הולך לפרט לגבי כל קטגוריה בנפרד. אני אציג תמונה (/ "סיפור") מציאותית - אך כמובן לא יחידה: ניתן לתאר את התהליכים הללו בצורות שונות, ולאנשים שונים וארגונים שונים יש תפיסות שונות לגבי גבולות הגזרה בין התהליכים / הכלים / ותחומי-האחריות השונים. אני לוקח כמה הנחות בסט הכלים שאראה:
  • אני מניח שמדובר ב Deployment בענן, ולא ב On-Premises (קרי: אין ניהול של חומרה ורשת פיסיים) - ואני מתמקד ב AWS (עננים אחרים הם דיי דומים בהיבט זה).
  • אני מניח שמדובר באפליקציית ווב.
  • אני מניח ש Docker (או פתרון אחר של Linux Containers) אינו מעורב - אחרת התמונה תשנה במידת-מה.
אם יצאתם זה עתה מהאוניברסיטה, או אי בודד - פוסט זה יכול לספק תמונה לא רעה על תהליכי פיתוח בקבוצות-תוכנה בתעשיה.
אם אתם כבר בתעשיה - אני מקווה שתמונה זו תוכל להשלים "חורים" שאולי חסרים לכם.

       
המורכבות של Stack מודרני, מול Stack בן עשור. מקור: https://goo.gl/9yCLtp

לרבים מההיבטים שאתאר (למשל: Logging, Version Control, וכו') יש היבטים ברורים מאוד של פיתוח: קביעת conventions לעבודה, למשל -  בד בבד עם היבטים של תפעול (התקנה ותחזוק של השרתים, גיבויים וכו').
להזכיר: השאלה החשובה היא לא "מי צריך לתפעל מה" אלא: כיצד ביחד, יכולים Operations ופיתוח - להגיע לתוצאות טובות יותר. תזכורת אחרונה: אני בעצם מנסה לתאר את הצרכים דרך הכלים - אך חשוב לזכור את הפער. כלי הוא לא צורך.  



כלים "פנימיים"


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

דוגמאות לכמה כלים בכל קטגוריה


Issue Tracking

היכן מנהלים ומשתפים את רשימת המשימות שיש לבצע? פן אחד הוא ניהול רשימת משימות והעברת משימות בין צוותים, פן אחר הוא גזירת תמונת-מצב על כלל הפרויקט.
יש כאן ניגוד אינטרסים קטן: מי שמביט על כלל הפרויקט (מנהל פרויקטים, מנהל פיתוח) מעוניין לאסוף כמה שיותר פרטים על כל משימה - עבור יכולות הניתוח, בעוד מי שעובד עם המערכת (מתכנתים) מעדיף להתעסק עם הכלי כמה שפחות - כי בסוף העיסוק ב Issue Tracking לא מייצר Value ללקוחות.
Jira (ויש מתכנתים האומרים: ״Jifa״) הוא כנראה הכלי הנפוץ ביותר, שמכסה גם היבטים של ניהול פרויקטים ובאגים - אך יש גם כלים אחרים.


Version Control

בסטארט-אפים מקובל בעיקר לעבוד עם Github.com - ולקבל משם שירותים מנוהלים של ניהול קוד.
ארגונים גדולים, יותר מקובל לעבוד עם Git ישירות או עם GitHub Enterprise (או החלופות שלו) - תוכנה שיש להתקין ולנהל לבד, עם היכולת לאבטח בצורה יותר טובה.

מלבד ניהול השרת של ה Version Control, יש עניין של ניהול התוכנה עצמה: ניהול ה Repositories, וההרשאות (האם אתם בודקים כל תקופה שעובדים שעזבו הוסרו מהמערכת?), הכשרה לעובדים (לא כולם מכירים את Git), ופתרון בעיות ("אופס... עשיתי force-- למשהו שגוי....").


Build

את הקוד צריך לקמפל (במקרה של Java, Go, #C, וכו') - או שלא (במקרה של רובי, Python, או ג'אווהסקריפט).
לרוב יהיו לנו בדיקות (יחידה, אינטגרציה, ביצועים, אבטחה) אוטומטיות - שירוצו כחלק מתהליך ה Build.
תוצרי הקוד (תמונות, קבצי JavaScript, קבצים בינאריים) לעתים קרובות עוברים עיבוד נוסף: דחיסה / אופטימיזציה - לתמונות, minification / obfuscation ו unification לקבצי ג'אווהסקריפט, או bundling לקבצים בינאריים (למשל: אריזת קבצי jar. כקובץ war. או ear. - בעולם הג'אווה).

את תהליך ה Build לרוב מריצים על כל submit / push של קוד ל Version Control - על מנת לאתר תקלות בשלב מוקדם ככל האפשר. באופן זה העלות לתקן את הבעיות - פחותה.

בטעות, יש כאלו שקוראים לתהליך ה Build בשם "Continuous Integration", ולשרת ה Build - כ "CI Server". זה שימוש שגוי בטרמינולוגיה: Continuous Integration הוא תהליך בו מגבירים את תדירות האינטגרציה בין המפתחים השונים. למשל: כל מפתח מבצע merge של הקוד שלו חזרה ל master / trunk - כל יום!

ו Git Flow? - הוא כבר לא כ"כ באופנה. זו בערך הגישה ההפוכה לגישה של Continuous Integration.
בעולם ה Build יש כלים ברמות שונות: Jenkins או TravisCI הם Build Servers שמנהלים את ה Build Pipeline.
כלים כמו Maven, SBT, Ant, או Gradle (כולם מעולם הג'אווה) - הם כלים להגדרת המיקרו של ה build (וניהול תלויות). דומים יותר ל Make או Rake.
בעולם הג'אווהסקריפט משימות מסוימות מבוצעות עם כלים כמו Grunt, Gulp, או npm - ואת משימת האריזה עם כלים כמו webpack או Browserify.


Artifact Management (בקיצור AM)

תוכנת AM היא כזו שעוזרת לנהל תוצרי תהליך ה-build (למשל: קבצים בינאריים, Gem Files, או Images של VM) בצורה: מסודרת, מאובטחת, Highly Available, ו Durable (כלומר: יש גיבויים).

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

AM יכולים לנהל תוצרים פנימיים שנוצרו ע"י הארגון, או Caching לתוצרים חיצוניים כמו ספריות Open Source (בכדי לקצר זמני הורדה שלהם ברשת). הרבה פעמים יהיו בארגון כמה כלי AMs שונים (למשל: תוצרי ג'אווה או רובי, תוצרי AWS, ותוצרי Linux).


Development Environment Management 

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

היבט אחר של "סביבת הפיתוח" הוא המחשב האישי של המתכנת (או QA וכו'). כמה זמן לוקח להתקין מחשב חדש ומפורמט - עד שיש סביבת עבודה מלאה? לעתים זה יכול אפילו כמה ימים מלאים של עבודה.
כנראה שהייתם רוצים שיהיה דף וויקי (במינימום), תמיד מעודכן, שמסביר את סדרת התהליכים הידניים שיש לעבור על להתקנה מלאה של הסביבה, ועדיף - שיהיה כלי אוטומטי שמבצע את כל תהליך ההתקנה בלחיצת כפתור (ובזמן סביר).


Collaboration

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

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



כלי "Production"


את הכלים הללו לרוב מפעיל צוות שנקרא בארגונים גדולים בשם ״Web Operations״. זו נחשבת התמחות שונה מצווות ה IT Operations.

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

כשעבדתי ב SAP למשל, צוות ה IT Operations ישב איתנו ונקרא "DevOps". הם ניהלו את כל הכלים הפנימיים, הדריכו ותמכו במפתחים וממש עזרו להם. הצוות הזה הכיר Git, Jira, ו Maven - יותר טוב מכולם.
צוות ה Web Operations נקרא "Hosting", ישב בגרמניה והיה מאוד מרוחק מאיתנו - פיסית ומנטלית. אם השתקפה בעיה ב Monitoring - מישהו היה מתקשר, אבל מעבר לזה הקשר ביננו היה חלש, ולא היה הרבה מה לעשות בנידון. זה היה תת-ארגון אחר. לכלי ה Monitoring למשל, לא הייתה לנו גישה. אפילו לא לצפייה. ממש לא DevOps Culture...


דוגמאות לכמה כלים בכל קטגוריה

 Web/HTTP

בקטגוריה זו יש לרוב יהיה שימוש ב 2 או 3 מתוך תתי הקטגוריות הבאות:
  1. HTTP Server - עבור הגשת Static Content ו/או ניהול התעבורה עבור Technology Stack שאינו multi-threaded מטבעו. כלומר: PHP, Ruby, Python. הכלים הנפוצים בקטגוריה זו היא Nginx ו Apache httpd.
  2. Application Server - סביבת ריצה לאפליקציות ווב. בעולם הרובי Applications Servers נפוצים הם Puma, Unicorn, ו Raptor. בעולם הג'אווה הם יכולים להיות Tomcat, Jetty, או Glassfish.
  3. Content Delivery Network (בקיצר CDN) - שהיא יעילה אף יותר מ HTTP Server בהגשת Static Content, אך יש לעתים סיבות להשתמש בשניהם.
כלים אלו משפיעים במידה ניכרת על ה Traffic / התנהגות המערכת. כנראה שתרצו מישהו בארגון שמבין בהם, יידע לקנפג אותם, לנטר אותם, ולאתר תקלות בצורה מהירה - ולא תמיד אלו יהיו המפתחים.


Configuration Management

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


Packaging

ה Packaging מטפל באריזת ה VM Image שממנו ניצור instances של מכונות בענן.
אם אתם עובדים בענן כלשהו (אמזון, Azure, או אפילו VMWare) - סביבת הענן תאפשר לכם לייצר Image ממכונה.

כלים כמו boxfuse או packer מאפשרים לכם לייצר מאותה המכונה Images מסוגים שונים (למשל: אחד ל Azure ואחד ל AWS במקביל), וגם ליצור Images קטנים ויעילים יותר (ע"י זיהוי התלויות הנדרשות ובניית "סביבת מערכת הפעלה" מספיקה לצרכים הספציפיים).
Image מוקטן שכזה מתאים ל Immutable Deployments (להלן הפוסט על כלי ניהול תצורה), ומגיע על חשבון החופש להתקין בקלות עוד כלים על המכונה במהלך הדרך.

למרות שאני מציג את ה Packaging כקטגוריה בלתי-תלויה בכלי ניהול תצורה - לרוב משלבים בתהליך ה Packaging כלי ניהול תצורה, שילוב שלרוב הוא מובנה בכלי ה Packaging.


Deployment

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

התיאור הזה הוא נכון לשרת בודד שאנו מרימים מהתחלה. הקושי מתחיל כאשר מדובר בהעלאת גרסה חדשה של התוכנה לשרתים קיימים, וללא downtime. אז עולות בעיות כגון:
  • כיצד להתקין שרתים חדשים מבלי לפגוע ב Traffic הקיים? לא Downtime ולא שיהוק.
  • אם אנו עושים זאת בהדרגה, כיצד מתמודדים עם מצב הביניים בו יש כמה שרתים בגרסה n, וכמה שרתים בגרסה n-1 החיים זה לצד זה?
  • מכיוון שמדובר ב cluster, כיצד עושים זאת עם כל הגדרות ה Load Balances, רשת, אבטחה - ומבלי להתבלבל. ה UI הרגיל של אמזון כבר לא כ"כ טוב לבעיה הזו.
  • מה עושים במצב של כשל? מתי מזהים אותו וכיצד - ואיך עושים Rollbacl? (לא נחכה לתיקון קוד עם בעיה חמורה בפרודקשיין, ולא משנה עד כמה המתכנתים שלנו זריזים).

בגדול, יש שתי "אסטרטגיות: עיקריות לביצוע Deployment:
  • Rolling Deployment -
    • התהליך (נניח שהשרת שלנו רץ על m nodes):
      • ניקח node אחד ואז:
        • ננתק אותו מה LB 
        • נוודא שכל ה requests שבתהליך סיימו להיות מטופלים
        • נתקין את הגרסה החדשה
        • נחבר אותו בחזרה ל LB וננטר אותו לזמן קצר לראות שהכל בסדר.
      • נחזור על כל התהליך הזה עוד כ m-1 פעמים.
    • ל Rolling Deployments יש ייתרון של חסכון במשאבים (צריך עוד שרת אחד, אפילו אם יש לנו 100 nodes), אבל הוא יכול להיות תהליך ארוך - ו rollback הוא קשה וארוך גם כן.
  • Blue/Green Deployment
    • התהליך (נניח שהשרת שלנו רץ על m nodes - "ה cluster הכחול"):
      • ניצור cluster חדש ("ירוק") זהה בחומרה ל cluster המקורי - ונתקין עליו את הגרסה החדשה.
      • ננתב חלק קטן מה traffic ל cluster החדש וננטר לזמן קצר. הכל בסדר? נחליף ברגע אחד את ה cluster הירוק להיות ה cluster הפעיל.
        • ניתוב ה Traffic יכול להיעשות באסטרטגיה של DNS cutover, באמזון - זמינה גם אסטרטגיה בשם swap auto-scaling groups, ויש גם אסטרטגיות אחרות.
      • ה cluster הכחול ימשיך לחיות עוד זמן מה (החיוב באמזון למכונות הוא ע"פ שעה עגולה של שימוש). אם נגלה בעיות בגרסה החדשה נוכל לחזור ל cluster הכחול - ברגע.
    • Blue/Green Deployment דורש יותר משאבים - אך הוא בטוח יותר, ומאפשר Rollback מהיר.
האם אתם רוצים לבצע בשטח את אסטרטגיית ה Deployment בצורה ידנית? קרוב לוודאי שלא, שתעדיפו לעשות את התהליך בעזרת כלי שיצמצם משמעותית את טעויות האנוש ויקצר את התהליך.

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


הערה: Jenkins הוא לא כלי מוצלח לניהול Deployment. נכון: גרסה 2.0 שלו הציגה קונספט של "Pipeline as code", אך קונספט זה ממשיך לעקוב אחר המודל הקיים והסבוך של pipelines של Jenkins והגמישות בו מבוססת על Plugins.
Jenkins הוא סבבה כנראה ל build pipeline, כך בכל הקשור ל deployment - מומלץ להיצמד לכלים ייעודיים.


כדאי להכיר: אלו סט הכלים של HashiCorp - ארגון מוערך מאוד שהוציא כמה כלים מאוד מעניינים (דגש על Vagrant ו Consul) בתחום. חשוב גם להיזהר מהנטייה האישית "לאסוף סריות": לא כל כלי של HashiCorp הוא בהכרח מתאים לכם. בוודאי שלא!

RDBMS Migration

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

להזכיר: בזמן ה Deployments (אם רוצים zero downtime) יהיו שלבים בהם ירוץ קוד חדש וישן זה לצד זה - ושניהם מול בסיס נתונים אחד (זה לא ריאלי בד"כ לרפלק את בסיס הנתונים לצורך deployment. יותר מדי סיכונים והשקעה).
ניתן לבחור ב-2 גישות: 
  • קוד תואם לאחר שיתמוך ב-2 הסכמות (השקעה גדולה). את המיגרציה ניתן לעשות לאחר עדכון הקוד (סיכון).
  • סכמה תואמת לאחור - כלומר רק תוספות ולא מחיקות או שינויים (הגישה הנפוצה). את המיגרציה יש לעשות לפני עדכון הקוד, בשלב מוקדם של ה deployment.
עבור migrations יש כלים רבים. חלקים מגיעים כחלק מה Framework (כמו ב !Ruby On Rails, Play, או Django). ישנם כלים כמו Flyway או Liquibase שאינם תלויים בשפת תכנות או Framework ספציפי.

ה Migration עצמו הוא סכנה ליציבות המערכת: תקלה בו יכולה להיות בעיה קשה.


סיכון נוסף הוא שינוי של טבלאות גדולות במיוחד (עשרות או מאות מיליוני רשומות?) או פעילות במיוחד (הרבה locking). פעולות migration שכזו עשויה להתארך לאורך שעות - ולפגוע לאורך כל הזמן הזה בביצועי המערכת.

כלים כמו LHM או Table_migrator מצמצמים סיכונים ע"י העתקת הטבלה הצידה, ביצוע ה migration, ואז החלפתה (rename) - קונספט דומה ל Blue/Green Deployment - רק שצריך לנהל delta של השינויים שלא נכנסו לטבלאת העותק בזמן ה migration - ולעדכן אותם מאוחר יותר.


Monitoring

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

כלי ה Monitoring הם אלמנט חשוב לתפעול, ולרוב יהיה לנו Monitoring בכמה רמות שונות (מערכת, אפליקציה, Proactive Monitoring, וכו'.) - ייתכן וכל רמה בכלי שונה.

כתבתי כבר בעבר פוסט על New Relic - הכלי האהוב עלי בתחום: על Performance Monitoring ו New Relic.
כתבתי גם פוסט בשם Monitoring: מבוא ל Graphite ושימוש ב Time-Series - המתאר כלים ל custom monitoring (בהיבט של time series).

תת-קטגוריה אחת ששווה להזכיר היא נושא ה Alerting - שליחת אימייל / SMS / או טלפון (עם הודעה קולית) לאנשים הרלוונטיים (ע"פ תורניות), ועל סמך הצטברות מדדים כאלו או אחרים ממערכות ה Monitoring. כלי כזה לדוגמה הוא PagerDuty.

תת-קטגוריה קרובה אחרת היא הנושא של Event Management: בהינתן מדדים כאלו ואחרים - הפעל response שנקבע מראש (ונבדק). למשל: restart ל service, הריגת טרנזקציה מסוימת ב DB, הגדלת מספר השרתים, וכו'.


Logging

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

מה קורה עם הלוגים אח"כ?
מה קורה בענן ו/או ובארכיטקטורה של מיקרו-שירותים? אם לא נאסוף את הלוגים הללו למקום מרכזי - הם יעלמו לנו.
אם לא נאנדקס אותם - לא נוכל לחפש בהם בצורה יעילה.
אם לא נמחק אותם (מהמכונות, ומהאינדקסים של ה repository המרכזי) - ייגרם נזק לשרתים או ליכולת שלנו לחפש בהם ביעילות.

הכלים הנפוצים לניהול לוגים הם ה ELK Stack (קיצור של ElasticSearch, LogStash, ו Kibana) או לחלופין Splunk או SumoLogic (שלא כוללים את איסוף הלוגים - LogStash או מוצרים חלופיים).

יש גם תת קטגוריה של Error Tracking - שהם כלים ייחודיים לניתוח תקלות משמעותיות במערכת (מול לוגים - שכוללים את כל המידע וגם info, traces, וכו'). כלים מוכרים בקטגוריה זו הם Airbrake, Sentry, ו Raygun.

יכולות ייחודיות לכלים אלו הם סנכרון עם עדכוני קונפיגורציה / תוכנה - וניתוח ה impacts שלהם מבחינת צפיפות ה errors, חיתוך ע"פ id של משתשמש (שאנחנו סיפקנו) בכדי לנסות ולאתר מדוע שימוש מסוים גורר בעיות - וכו'.




מקור: Sounil Yu
 

Security

כלי אבטחה הוא עולם בפני עצמו. אני יכול בקלות לזרוק רשימה ארוכה של כלים רלוונטיים:
  • מתחילים עם Firewall - שבדרך כלל ספק הענן יספק.
  • אם המערכת שלכם עובדת על גבי HTTP, קרוב לוודאי Web Application Firewall (בקיצור WAF) - כמו Cloudflare, אינקפסולה, או BigIP (של F5).
  • דרך כלים ל Authentication ו/או Federated Identity Management (בקיצור FIM) כמו PingIdentity, OKTA, או Auth0.
  • כלי Intrusion Detection System (בקיצור: IDS) - כמו Snort, או Trend Micro's Deep Security.
  • כלים ל audit בגישה ל Production כמו ObserveIt או CyberArk.
  • כלי SIEM - כלי לניהול לוגים בהיבט האבטחה, כלים כמו ArcSight, QRadar, או Splunk (שהוא גם "חזק" בעולם ה Security).
  • כלים ל Security Static Code Analysis המחברים לתהליך ה build כגון Checkmarx או Fortify.
  • ועוד...

בארגונים יותר גדולים, כל הנושא של כלי ה Security מופקד ביחיד צוות Operations מיוחד, שמתמחה בנושא.
בארגונים קטנים יותר - זה היה צוות ה Web Operations או אפילו המפתחים.

לכאורה, ניתן לכתוב פוסט מקביל לזה - רק בהיבט האבטחה.  



סיכום


עוד פוסט שחששתי שלא יהיה לי מה לכתוב בו - אך התארך מעבר הצפוי :)
נושא ה Operations וה Production הוא עולם בלתי נגמר.

תנועת ה DevOps שמשפיעה על כלל התעשיה (שלב א': שינוי ה Title של אנשי ה Operations - אך יש גם את השלבים הבאים) - משנה את העולם.

עוד כוח שמשנה את התמונה הוא טכנולוגיית ה Linux Containers (ובחזיתה: Docker), גישה החותרת ל Fully Immutable Deployment - גישה שעשויה לשנות כמה מהתהליכים ויחסי-הכוחות בעולם זה.
תוצר לוואי של גישת ה Containers היא החתירה ליצירת כלי Infrastructure Management חדשים (כמו Mesos, Tectonic, או Atlas), שלא מבוססים על ספקי הענן  - מה שעלול לגרום לעוד כמה תזוזות.


שיהיה בהצלחה!



---

לינקים רלוונטיים

DevOps Awesome Links - כמה קישורים מעניינים!

DevOps From the ground up Deep Dive into Blue/Green Deployments on AWS - על אסטרטגיות Deployment.

ההבדל בין Packer ל Vagrant מאמר + דברים של מיטשל האשימוטו (Hashi)  

Cybersecurity Market Review - סוקר הרבה כלי Security במגוון קטגוריות



2016-05-07

על כלי ניהול תצורה / Provisioning - מבראשית ועד ימי ה Docker

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

ישנם מגוון כלים לניהול תצורה (Configuration Management בקיצור CM), המאפשרים לנהל מספר גדול של שרתים (מאות, אולי אלפים) בצורה אוטומטית ומסודרת. כלים אלו לרוב מספקים את היכולות הבאות:

  • Change Management - ניהול הגדרות ה"מצב הרצוי" בתצורת השרתים, בצורה מסודרת וניתנת לשליטה. למשל: שינוי הגדרות של nginx בשרתים מסוג x או הוספת תיקיה חדשה במערכת הקבצים של שרתים מסוג y.
    • חשוב שיהיה קל להבין ולהגדיר מהם "שרתים מסוג x". לעתים אגב, אלו יכולים להיות שרתים עם מערכות הפעלה שונות, ושמריצים תוכנות שונות.
  • Provisioning - זהו בעצם התהליך של העברת שרת ממצב נתון כלשהו - למצב הרצוי. 
    • זה יכול להיות התקנה של שרת מאפס, או בדיקת המצב בשרת קיים - וביצוע השינויים הנדרשים על מנת להגיע למצב הרצוי.
    • לרוב שינוי ההגדרה יכלול ביצוע שינוי בשרתים שכבר "באוויר", וגם הכללת השינוי החדש בשרתים הבאים שיקומו.
    • כאשר מבצעים שינויים, ישנן תקלות (פעולות רצויות שנכשלו) - תקלות שיש לנהל.
  • Orchestration - תיאום הפעולות בין כמה שרתים. למשל:
    • ביצוע שינוי מסוים באותו הזמן על מספר שרתים. אולי כדאי קודם לבצע בדיקה שמאשרת (כמיטב היכולת) שאכן כל השרתים מסוגלים לעבור את השינוי.
    • אם אחוז גבוה מהשרתים לא מצליח לעבור שינוי - אולי כדאי לעצור את השינוי המתגלגל, ולהתחיל פעולה של rollback (חזרה למצב הקודם)?
    • יש שינויים שצריכים להיעשות בצורה מדורגת כלשהי: קודם ביצוע שינוי בשרתי x ורק אח"כ אפשר לבצע את השינוי בשרתי y.
הכל כמובן - בצורה אוטומטית.


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







"דור ראשון"


CFEngine

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

CFEngine ממומש בשפת C, והוא ידוע במהירות הגבוהה שלו. מצד שני - הוא דורש ידע מלא בתכנות בשפת C על מנת לתפעל אותו, מה שמגביל מאוד את קהל היעד.

כלי זה, כמו הכלים הבאים אחריו עובדים ע"פ עקרון דומה:
  • שרת מרכזי מחזיק את התצורה הרצויה לסוגי השרתים השונים (ע"פ ארגון של קבוצות או כללים).
  • על כל שרת מותקן Agent שמתשאל מדי פעם את השרת המרכזי, וברגע שהוא מבין שיש לבצע שינוי תצורה (קרי: עדכון תוכנה, שינוי הגדרות, וכו') - הוא מבצע אותו.
    • כששרת מופעל בפעם הראשונה (לפעמים הוא כולל מערכת הפעלה ו Agent בלבד) - הוא יבצע את כל שינויי התצורה לפני שיתחבר ל Load Balancer (קרי: יהיה זמין לשאר ה Landscape).


איך CFEngine עובד. מקור: CFEngine.com


"דור שני"


Puppet

הכלי הבא שהופיע והשאיר חותם הוא Puppet, עם המטפורה המפורסמת של ה "Puppet Master" - השרת המרכזי שלו שהוא כמו "מפעיל בובות". גם Puppet החל בשנת 2005 כ Open Source ורק מאוחר יותר הופיעה גרסה מסחרית (Enterprise).
החידוש המשמעותי של Puppet היה שהוא לא דרש ידע מעמיק בתכנות, אלא כתיבת DSL (כלומר: Domain Specific Language) המבוססת על שפת רובי - דבר שצוות ה Operations של הארגון היה מסוגל לתפעל בצורה מלאה.

קוד Puppet לדוגמה

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

השפה של Puppet (או כלי CM אחרים) היא DSL שמותאמת לצרכים המאוד ספציפיים של ניהול תצורה, ועוזרת לשרת את קריאות הקוד (הקוד הרבה יותר נוח לקריאה מ bash) ולצמצם טעויות אפשריות. עוד ייתרון הוא היכולת להגדיר תצורה שתפעל על מערכות הפעלה שונות (דיסטרוס שונים של לינוקס, או אפילו לינוקס ו"חלונות").

השפה של Puppet מספקת שורה של פרמיטיבים (File, User, Package, Service, וכו') שניתן להרכיב למודולים (הניתנים לשימוש חוזר) או פשוט להוריד מוכנים מ PuppetForge[א]. היכולת לשתף מודולים ברמת הקהילה מסייעת לקיצור זמני-פיתוח והגברת אמינות ניהול התצורה - כל עוד מדובר במודולים איכותיים. יש לציין שלא כולם כאלו, וחשוב מאוד לברור את מקור המודולים בהם אתם משתמשים.

בזכות קלות השימוש - Puppet לקח מ CFEngine את הבכורה.


Chef

לא הרבה מאוחר יותר, בשנת 2008, הופיע כלי חשוב נוסף בשם Chef. גם הוא, אגב, כלל סדרת מטפורות בלתי-נשכחות ("Knife", "Kitchen", "Cookbook", ו "Recipe", וכו'). Chef שיפר כמה מהדברים שהציקו ב Puppet וזכה לפופולריות גדולה בעצמו. גם הוא - מבוסס על שפת רובי.
בשלב הזה Chef ו Puppet החלו בתחרות "ראש בראש", כאשר הם משלימים כל הזמן את הפיצ'רים החדשים אחד של השני. במהלך התחרות הזו נוספו לכל אחד מהם יכולות וכלים, מה שגרם להם בעצם להפוך מכלים פשוטים יחסית - לכלים מורכבים לשימוש, הדורשים מהמשתמשים למידה משמעותית.

בגדול, Chef נחשב יותר "ידידותי למפתח" (כזה שרגיל לכתוב בדיקות יחידה, ו/או לעבוד בכלי פיתוח)  בעוד Puppet מעט יותר ידידותי לאיש ה Operations (שאינו מתכנת).
יש אומרים ש Puppet נוח יותר לניהול תחנות עבודה של משתמשים, וש Chef - נוח יותר לניהול חוות שרתים (אולי בגלל ה output המפורט שלו שמסייע לאתר הבעיה - כאשר יש תקלות). בסופו של דבר, שני הכלים קרובים זה לזה ביכולות, ובבגרות. ל Puppet יש קהילה גדולה יותר, וב Chef מורכב יותר להתמקצע.

לא לזכותם של הכלים הללו ניתן לומר שהם כיום מורכבים למדי לשימוש, עבור רוב המשימות הנפוצות, וה Learning Curve שלהם הוא תלול ממה שארגונים רבים היו רוצים.

עוד נקודה מעניינת היא ששלושת הכלים שהזכרתי עד רגע זה (Chef, Puppet, ו CFEngine) תוכננו ונבנו בתקופה בה התפיסה הייתה לעדכן שרתים קיימים, ולאורך זמן.

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

גישת ה Convergence אפשרה לבצע עדכונים תכופים בתצורת השרתים, מבלי לגזול זמן רב / לשלם ב downtime.
המחיר של גישה זו היא שניהול deltas לאורך זמן הוא מסוכן ולא יציב - ודברים יכולים (ואכן) נוטים להשתבש. למשל: מפתח התחבר ב SSH לשרת ושינה הרשאה של איזו תיקיה. עדכון נכשל והשאיר אחריו מצב בלתי רצוי שאינו מתוקן ע"י הגדרות התצורה של הכלי, וכו'.
הפתרון היה להחזיר שרת ל "baseline" - ברגע שדברים מסתבכים. לשלם את המחיר ההתקנה מחדש - בכדי לחזור למצב של סדר ושליטה.
הבעיה: בזמן שחלף עד שהבנו שהשרת הוא בתצורה בעייתית - התצורה הבעייתית יוצרת "רעש", ועוד רעש בפרודקשיין!

התפיסה השלטת היום היא תפיסה של Immutable Servers (או "כמעט Immutable Servers"), כאשר כל שינוי תצורה (או: כמעט כל שינוי תצורה) - משמעו ליצור Image חדש, נקי ומסודר של שרת, ולעדכן את המכונות הרצויות.
היכולת הזו מתאפשרת בעקבות טכנולוגיות הוירטואליזציה והענן שהפכו לנפוצות כ"כ, ומתקדמות צעד אחד נוסף קדימה בעקבות טכנולוגיה כמו Containers.

כלומר: כל פעם שאנו רוצים לבצע שינוי בשרתים (נניח להוסיף לשרת agent של logstash) - ניצור Image חדש ונקי, ונריץ את כלי שלבי ה provisioning מאפס עד לקבלת שרת בתצורה הרצויה (כולל השלב החדש של התקנת ה logstash agent). כעת נייצר מהשרת הזה Image ואת ה Image הזה - נתקין על המכונות הפיסיות בפרודקשיין.

גישת ה Immutable Server נחשבת אמינה ופשוטה יותר לשליטה - ולכן עדיפה. החיסרון: שינויים קטנים עדיין דורשים בנייה של Image - תהליך שיכול לארוך זמן רב (עשרות דקות עד שעות).
אם כל השינוי הנדרש בשרת הוא העתקה של קובץ בודד, שינוי הרשאות על תיקיה, או שינוי הגדרה - רבים מאיתנו יעדיפו שיהיה על השרת גם כלי CM בעזרתו יוכלו לבצע את השינוי בזריזות. הזריזות הזו חשובה מאוד כאשר יש להגיב לתקלות בפרודקשיין. במקביל, ניתן לבצע את השינוי בצורה מסודרת על ה Image ו"ליישר קו" ב deployment הבא.
גישה זו, היא גישת ה "כמעט Immutable Servers" - המשלבת בעצם בין שתי הגישות.


שינוי הגישה מניהול תצורה בעזרת deltas שמתמשכים למשך חודשים, לצורה של "Immutable Servers" או "כמעט Immutable Servers" (לא ידוע לי על מונח מוסכם) פתח הזדמנות לכלים פשוטים משמעותית, שלא צריכים להתמודד עם המורכבות הרבה של ניהול deltas בתצורת השרת - להצטרף לזירה.

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



מקור: google trends



"דור שלישי"



Ansible

בשנת 2012, הופיעו כלי CM חדש בשם Ansible ששינה הרבה מצורת העבודה של Chef ו Puppet:
  • ניהול העדכונים: במקום שיהיה שרת מרכזי (או כמה לצרכי HA ו Scale) אליו כל ה Agent פונים ב pull, הגישה היא לבצע push: אתם פונים לשרתים השונים ואומרים להם לבצע את השינוי.
    • יתרונות: הסרת שרת הקונפיגורציה מה landscape. הבדיקות של תצורות חדשות נעשות ב cycles קצרים יותר, ב push העדכונים מגיעים לשרתים מהר יותר. קל לשימוש בסביבת פיתוח, בה ניתן לפתוח laptop ולעדכן שרת - בלי להתקין ולתחזק "שרת מרכזי".
    • חסרונות: כאשר מדובר ב scale גדול (מאות ואלפי שרתים) - עדכון השרתים ב push ייקח יותר זמן. אם בדיוק עלה שרת חדש לפני שיש image מעודכן - הוא עשוי לפספס את העדכון.
  • שפת התכנות: במקום DSL ומיומנויות של semi-תכנות, ההגדרה של התצורה נעשית בעזרת קובץ yaml פשוט.
    • יתרונות: הרבה פחות "קוד" לכתוב. זמן למידה קצר בהרבה של הכלי. אין צורך ברקע בתכנות בכלל על מנת ליצור הגדרות תצורה.
    • במקום שפת תכנות שיוצרת הפשטה מעל כל סוג של מערכת הפעלה, שכבת ההפשטה היא רזה. יש מודול לפקודות apt (נניח אובונטו) ומודול לפקודות yum (נניח Red Hat). ההפשטה הרזה לא מאפשרת "לכתוב סקריפט אחד שמתאים לכל מערכת הפעלה", אך מפשטת מאוד את הלמידה (כי אתם יודעים כיצד apt או yum עובדים, ומקלה להבין מה קורה בפועל.
    • חסרונות: פחות גמישות: בעיות CM מורכבות יידרשו כתיבת סקריפט מיוחד (בעיקר: שימוש ב Jinja2 - שפת templates בה ניתן לכתוב מעט קוד פייטון או להפעיל קוד bash).
    • הערה: Ansible הושפעה מפייטון (השפה בה היא כתובה) בגישת ה "Batteries included". המודולים הטובים שנכתבו / אושרו ע"י Ansible הם חלק מהכלי, ולא צריך להוריד אותם מ repository מרכזי כמו Chef או Puppet.
  • אין Agnets: אין צורך להתקין Agent (להלן Chef-Client או Puppet-Agent): על גבי השרתים. Ansible משתמש ב SSH סטנדרטי (ליתר דיוק: OpenSSH) בכדי לגשת לשרתים ולבצע בהם שינויים. עבור Windows - משתמשים ב PowerShell remoting.
    • יתרונות: אין צורך בהתקנה, עדכון, וניטור של Agents על גבי השרתים. רק צריך שרת עם SSH ו Python 2.5.
    • חסרונות: SSH הוא אטי יותר (פחות מתאים לעדכון אלפי שרתים),


Salt (מבית SaltSlack)

מעט לפני Ansible הופיעה ספרייה בשם Salt.

בכמה מובנים, Slat דומה למדי ל Ansible: הגדרות התצורה מוגדרות ב Yaml ולא בשפת תכנות, והוא פשוט בסדר גודל מ Chef או Puppet.
Salt ו Ansible שניהם כתובים בפייטון (Chef וגם Puppet כתובים בשפת רובי).

בכל זאת, הגישה של Salt להעברת העדכונים לשרתים - היא דיי דומה לזו של Chef ו Puppet.

המוטיבציה המוצהרת ליצירת Slat הייתה עדכון תצורה מהיר של קנה מידה גדול של שרתים. נראה שיצירת סביבת עבודה פשוטה יותר מ Chef/Puppet הייתה מהלך טבעי, אך משני - בתכנון של Salt.
  • השרת (הקרוי Slat Master) מבצע עדכונים ב push לתור של ZeroMQ. על השרתים מותקנים Minions (סוג של agents) שמאזינים לעדכונים על ה Queue ומבצעים מייד את העדכון. זו גישה משולבת בין ה Push של Ansible וה Pull של Chef/Puppet, שמבטיחה בד"כ זמני תגובה מהירים יותר מ Chef/Puppet (כי יש Push), ו scalability גבוה - היכולת לעדכן אלפי שרתים במקביל.
  • ניתן להגדיר ה Salt Master בהיררכיה כך שיש Centralized Master אחד שמגדיר מה לעשות, אך כמה Masters תחתיו שמפיצים את הבשורה לשרתים שונים. גישה זו יכולה לספק Scale גבוה אף יותר (נאמר: עשרות אלפי שרתים?)
בשנת 2014 Salt הציג Queue ייעודי משלו בשם RAET שהוא Scalable ואמין יותר מ ZeroMQ - לצורך הספציפי.



מקור: Google Trends


עידן ה Docker - "דור רביעי?"


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

Docker הוא כלי שמנבאים שיחולל מהפיכה לא רק בסביבת ה Production - אלא גם בעולם הגדרות התצורה.
מכיוון ש Docker "מפרק" את סביבת השרת להרבה Containers קטנים, הוא גם הופך את בעיית ניהול התצורה לסט בעיות קטנות יותר: תצורת ה Application Server ב Container A, תצורת ה Nginx ב Container B, ותצורת ה Monitoring Deamon ב Container C. על אחד מהן עשויה להיות בלתי תלויה, ופשוטה הרבה יותר מתצורה כוללת.

ה dockerfile, אם כן, הוא בערך כמו קובץ ה Yaml של Ansible או Salt, המאתר כיצד להתקין תהליך ואת התלויות שלו. טעינה מחדש של container היא כ"כ מהירה (עשרות שניות) - שניתן (אולי?) להסתפק בגישה טהורה של "Immutable Servers".

מצד שני, לנהל אלפי containers (הנחה: על כל שרת יש 5-10 containers) - זו משימה קשה בהחלט! זו בעצם בעיית ה Orchestration ש Docker איננו מכסה. למשימה זו, נבנים כיום כלים ייעודיים, שהמוכרים ביניהם הם:
  • Kubernetes - כלי מבית גוגל, המשתמש בניסיון הקיים של גוגל בעבודה עם Linux Containers וניסיון שהצטבר עם כלי פנימי של גוגל בשם borg - האחראי על ה provisioning של השרתים הרבים מאוד ב Data Centers של גוגל. בעצם, גוגל כבר עושה היום משהו דומה.
    הניסיון הזה מתבטא למשל, בכל ש Kubernetes פתרה בעיות של Docker עצמו שהיו קיימות בגרסאות מוקדמות.
    Kubernetes מציע פתרון שלם יחסית, עם etcd ל container discovery, עם flannel לניהול הרשת בין ה containers (עניין מסובך ומתיש), ועוד.
    לסביבה העשירה הזו יש מחיר: יש לכלי CLI משלו, API משלו, וקבצי YAML משלו להגדרות התצורה - וזו סביבה שיש ללמוד להשתמש בה, בנוסף ל Docker.
  • Docker Swarm - הוא כלי אשר נוקט בגישה כמעט הפוכה: הוא תומך ב API הקיים של Docker, ובסביבת ה CLI - מה שאומר שקל מאוד להשתמש ב Docker Swarm עם ה toolchain הקיים של Docker (למשל: Docker Machine (לשעבר Krane) או Compose, וכו').
    Docker Swarm מתוחזק ע"י קהילת ה Docker, והוא חלק מ"פתרון כולל" שנבנה בתוך קהילה זו לניהול תצורה.
    האם זו בהחלט הגישה המועדפת? קשה לומר. התאימות ל Docker API מגבילה את הכלי למגבלות של Docker עצמו ומקשה עליו לבצע חלק מהדברים שניתן יהיה לעשות ב Kubernetes.

זה לא כ"כ משנה איזה עוד כלים קיימים או ייווצרו בקהילה של Docker.
אם וכאשר Docker יהפוך לסביבת ה Deployment המקובלת ב Production - הוא עתיד לבצע Disruption גם בעולם ה CM ולשנות אותו משמעותית ממה שאנו מכירים אותו היום.



סיכום


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

הכלי הנכון ביותר לשימוש - משתנה עם הזמן, מכיוון שבחברות הצרכים משתנים: פעם יש רק לינוקס (נניח RedHat) ואז יש גם OpenSuse ו Windows. פעם ה deploy הוא תהליך חודשי - ולאחר מכן כבר מדברים על Continuous Deployment. פעם זה על שרתים של הארגון, ומעט אחרי זה - בענן. פעם על VMs וקצת אחרי זה על Containers.
הצרכים הארגוניים משתנים ככל כנראה מהר יותר ממה שניתן להסתגל לכלים השונים, ומכאן ניתן להסיק שאחוז גבוה מהארגונים משתמש בכל רגע נתון בכלי CM שאינו אופטימלי לצרכים שלו.

ישנה תקווה אמיתית שכלים חדשים ופשוטים יותר (Ansible או Swarm, למשל) יאפשרו לארגונים לבצע שינויים תכופים יותר בצורת העבודה - ולהתאים בצורה טובה יותר את מערכת ה CM לצרכים המשתנים של הארגון.


שיהיה בהצלחה!



-----


קישורים רלוונטיים


Chef vs. Ansible vs. Puppet vs. Salt בהקשר של OpenStack - אך עדיין מעניין ורלוונטי.

http://martinfowler.com/bliki/ImmutableServer.html - פוסט של מרטין פאוולר על Immutable Servers.

http://techblog.netflix.com/2013/03/ami-creation-with-aminator.html - פוסט מהבלוג של Netflix שמתאר את תהליך ה Provisioning שלהם

על Convergence מול Immutable Deployment


-----

[א] רמז לכך ש puppet נבנה בימים בהם הכלי המקובל לניהול קוד פתוח היה SourceForge? היום בוודאי היו קוראים לו PuppetHub...