כשהאתר דורש יותר ויותר משאבים בפתאומיות

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

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

  • הגדלת משאבי המכונה הוירטואלית (יותר זכרון, יותר ליבות)
  • אופטימיזציה של מערכת האתר – טיוב שאלות SQL, בניה יותר טובה של Cache, אולי מעבר ל-NGINX, שינוי PHP לעבודה כ-FPM ועוד ועוד..
  • שכפול והקמת מכונה זהה ומעל המכונות Load Balancer תוך מתן פתרון גם ל-SQL (שיטות Master/Slave, Multi Master ועוד)
  • אם אתם משתמשים בשרותי ענן כמו אמזון ושרותים כמו RDS, אולי תעברו ל-Instances יותר גדולים, אחסון יותר מהיר וכו'.

אם האתר שלכם נמצא בשרותי ענן ציבורי, בד"כ תהיה אופציה נוספת שנקראת Auto Scaling שתאפשר לכם להוסיף מכונות בהתאם לעומס (אתם יכולים לבדוק עומס על ה-CPU, עומס על הרשת, כמות זכרון פנויה וכו') ובד"כ זה פתרון טוב שעובד יפה והרבה חברות משתמשות בו. גם עניין הוספת VM לזה שקיים, ביצוע רפליקציה של SQL והוספת Load Balancer היא אפשרות טובה כשצריכים אותה.

אך לשיטות האלו יש מספר בעיות:

  • אם האתר עצמו מאוחסן ב-NFS או OCFS2 לדוגמא, תקלה בקוד או חדירה ע"י פורץ ושינוי הקוד (כמו במקרים של Defacement) – תשפיע על כל השרתים שלך. כנ"ל בעת שדרוג -אם השדרוג לא מצליח, שום אתר לא באוויר וכולם מקבלים את אותה שגיאה. בנוסף, אתם מייצרים צוואר בקבוק חדש מכיוון שכל פעם שהאתר צריך ולו את הקובץ הכי קטן – הוא צריך לבצע קריאה ל-Storage, ו-NFS לדוגמא פשוט לא מתאים לזה, אתם יוצרים צוואר בקבוק חדש.
  • מחיר – להוסיף עוד VM + Load Balancer זה לא כזה יקר (לעסק שמתפרנס [גם] מהאינטרנט לדוגמא), אבל כשאתה צריך להוסיף עוד 20 מכונות VM העסק מתחיל להיות קצת יקר וזה לא חשוב אם מדובר בספק אירוח ישראלי או בענן ציבורי.
  • תחזית: כמה הולכים להיכנס לאתר? אתה לא יודע. אתה יכול להעריך בהערכה גסה, אבל אתה לא תדע אם יכנסו פחות או יותר ואם אנשים לא עפו מהאתר או לא הצליחו להיכנס בגלל שהשרתים היו עמוסים, בגלל תקלה, ובקיצור – עניין הניחוש הזה קשה כמו לנחש כמה אנשים יגיעו לחתונה..

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

מכונות VM הם פתרון טוב, אבל יש כיום פתרון יותר טוב והוא כמובן קונטיינרים: אפשר להקים קונטיינרים שיריצו את הקוד PHP, קונטיינרים שיתנו את שרות ה-WEB עצמו, קונטיינרים ל-SQL, קונטיינרים ל-Cache וכו'. הקונטיינרים עצמם אינם דורשים משאבים גדולים – מכיוון שהקונטיינר לא צריך את כל מערכת ההפעלה מותקנת בו אלא אך ורק חלק שצריך להריץ אפליקציה ספציפית, אפשר להפעיל קונטיינרים עם כמות זכרון קטנה (נניח 512 מגהבייט זכרון) בהתאם לצרכים. בנוסף, קונטיינרים הם דבר שניתן לשכפל מאוד מהר (בניגוד ל-VM – קונטיינר משוכפל בשניות). כך בעצם ניתן "להמיר" את האתר שלך למספר קונטיינרים שישוכפלו בין מכונות VM (או Instances), תקבל Load Balancer בחינם, והמערכת תדע לגדול ולקטון בהתאם לצרכיך.

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

  • להקים מספר קונטיינרים שיתפזרו בין VM שונים, יאוחדו לקבוצות וכך המערכת תוכל "לדבר" בין החלקים
  • אם יש תקלה בקונטיינר מסוים, אפשר להרוג אותו והמערכת תקים מיד קונטיינר אחר זהה, כך שאם לדוגמא מישהו פרץ לקונטיינר מסוים, הפגיעה היא מקומית (תלוי כמובן בהגדרות היכן נמצאים הקבצים שנפגעו – בקונטיינר או על NFS/OCFS2 וכו'), ניתן להרוג את הקונטיינר ולהמשיך (כדאי כמובן לתקן את הקוד)
  • עם מערכת כמו Kubernetes ניתן לבצע תהליך הטמעה של גירסה חדשה כך שעדיין ישמרו גירסאות ישנות ולעבור לחדשות לפי קצב שיוחלט (לפי גילוי באגים ותיקונם וכו') וכך יחסך מצב של השבתת מערכת רק כי צריך להחליף גירסה.
  • אפשר להשתמש בהפצות לינוקס אחרות (או בקונטיינרים של Windows – אם אתם מריצים WIndows Server 2016) בתוך הקונטיינרים כך שאין זה משנה מה ההפצת לינוקס שמותקנת על ה-VM עצמו.
  • אין צורך בהגדרות זהות פר VM – ישנה מערכת ETCD שדואגת שההגדרות בין ה-Nodes יהיו זהות לחלוטין בין אחת לשניה באופן אוטומטי.
  • יעילות פר VM – הפצות כמו Atomic, CoreOS, RancherOS ואחרות – ניתן להתקין אותן על ה-VM ובכך לחסוך RAM שתפוס בד"כ על ידי הפצת הלינוקס ב-Node עצמו (אחרי התקנת הפצות כפי שציינתי לעיל – הזכרון התפוס נע בין 50-100 מגהבייט בלבד וה-Node גם עושה Boot מאוד מהר) ובאותו זכרון פנוי ניתן להשתמש לטובת הקונטיינרים.
  • על אותה מערכת Kubernetes ניתן גם להעלות קונטיינרים אחרים עם גרסאות שונות של האתר, לא צריך VM חדש לשם כך.
  • ויש עוד יתרונות.

במילים אחרות: מערכת Kubernetes מאפשרת לכם בעצם לעבוד בצורה יותר מאורגנת כאשר כל חלק הוא נפרד ורץ בקונטיינר משלו, כך שיותר קל לטפל בבעיות שצצות במקום "לנחש" היכן הן. בנוסף, מערכת Kubernetes כוללת כבר את כל עניין גדילה, High Availability, שרידות, Load-Balancing ללא צורך בתשלום על שרותים אלו בנפרד.

אפשר כמובן לעבוד על Kubernetes בלבד (ויש כמובן גם API – שהוא יותר "client") לשפות שונות כמו PHP, Python, דוט.נט ועוד, אולם אם בחברה יש מספר מפתחים לאתר, אני ממליץ להשתמש בכלי כמו OpenShift Origin כדי לבצע את כל הדברים ב-Kubernetes (כולל דברים ש-Kubernetes לא עושה כמו בניית קונטיינרים, עבודה כמשתמשים וקבוצות ועוד) או בכלי אוטומציה אחרים לבצע הן את הדברים דרך Kubernetes והן את ה"מסביב".

מבחינת עבודה עם Kubernetes – המערכת הזו כתובה ופועלת מעולה – כשזה נמצא על ספק ענן ציבורי כמו גוגל או אמזון. אם זה בתשתית של ספק אירוח מקומי, יש צורך לבצע "שמיניות באויר" בכדי להתחבר למכונות הללו מבחוץ כי היא פשוט בנויה לשימוש פנימי כאשר תקשורת מבחוץ מגיעה דרך תשתית ספק הענן. ב-OpenShift לעומת זאת, פתרו זאת עם HA-PROXY ועם ניתוב חכם כך שאין צורך להסתמך על שרות כמו Load Balancing של ספק ענן חכם ואפשר להשתמש בפתרון המובנה.

מבחינה טכנית, לאלו שיש כבר אתרים גדולים, אין היום שום כלי למיטב ידיעתי שיכול לעשות לאתר שלכם המרה ממצב שהוא רץ על Shared Hosting או VPS/VM או Instance למצב קונטיינר. את הדברים יש צורך לבצע ידנית ויכול להיות שיהיה צורך לבצע מספר שינויים קטנים בתהליך העבודה (שימוש ב-GIT, הפרדה בין תהליכים ועוד) וכמובן יש צורך במחשבה ובבניית תהליך כיצד להכניס את OpenShift לעבודה אצלכם (כך שלא מדובר במשהו שמבצעים בכמה שעות או ביום עבודה אחד).

לסיכום: אם יש לכם אתר שמקסימום נכנסים אליו כמה מאות בודדים של מבקרים שרק קוראים מאמרים לדוגמא, מעבר לקונטיינרים לא יסייע לכם יותר מדי. לעומת זאת אם יש לכם אתרים (או אפליקציות Web – היינו הך במקרה זה) שניגשים אליהם אלפים, עשרות אלפים ומעלה – קונטיינריזציה של המערכת תוכל לעזור הרבה הן בעמידה בעומסים, שרידות ועוד. אגב, אם אתם התחלתם להשתמש ב-Windows Server 2016 – גירסת ה-Kubernetes האחרונה תומכת גם בכם. באם אתם רוצים לבצע את כל התהליך באופן יעיל – אני ממליץ להשתמש ב-OpenShift ולא ישירות ב-Kubernetes.

גילוי נאות
מעבר לקונטיינרים הוא שרות שניתן ע"י חץ ביז

פרויקט נסיוני: קונטיינרים ו-Raspberry Pi-3

גילוי נאות / תודות
מכשירי ה-Raspberry Pi-3 ניתנו לי ע"י SuSE ישראל

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

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

כשזה מגיע לפיתוח, בין אם מדובר בפיתוח Low Level או בפיתוח בשפות אחרות, רוב הזמן המפתחים יכתבו את הקוד על ה-PC שלהם וישתמש ב-Cross Compile עם הקומפיילר החביב עליהם כדי ליצור קבצים בינאריים לציוד מבוסס ARM. אחרי הכל, לקמפל דברים על ARM זה לא כיף (זה איטי … אלא אם יש עליך איזה 500$ למערכת Jetson TX2 של nVidia ששם זה עובד יפה). הבעיה מתחילה בכל מה שקשור לבדיקות הרצה "על הברזל". פתרון של אמולציה זה לא רע (במיוחד אם האפליקציה לאנדרואיד וכתובה Native ב- ++C), אבל לפעמים צריך להריץ את האפליקציה "על הברזל" – במיוחד אם האפליקציה מתקשרת דרך ה-GPIO של הלוח (או דרך USB, יציאות סריאליות בלוח, JTAG וכו') – במקרים כאלו אמולציה לא תעזור ולחבר PC, להריץ אמולציה, למפות כתובות לתוך האמולציה בשביל להריץ את האפליקציה – זה סיבוך עם פוטנציאל להרבה נקודות כשל.

בקטע הזה – קונטיינרים על ARM יכולים להיות פתרון מעולה:

  • האפליקציות עצמם יכולות לרוץ אפליקציה פר קונטיינר על ה-Pi-3 ועוד קונטיינר יכול לשמש כ-DB קטן לדוגמא (SQLite) או אפליקציה קטנה שמקבלת תוצאות טסטים מהקונטיינר הראשון ואפשר להרחיב ולהרים קונטיינר נוסף שמקבל סדרות טסטים להריץ משרת כלשהו, כך שקונטיינר A (שמריץ את האפליקציה העיקרית) מתחבר לקונטיינר C (שמקבל משרת חיצוני את הטסטים שיש צורך להריץ), מבצע את הפעולות ומדווח את התוצאות לקונטיינר B (שמריץ DB או אפליקציה קטנה שאוספת לוגים ויוצרת סטטיסטיקות קטנות). שלושת הקונטיינרים רצים על מכשיר Pi-3 יחיד שמשמש בעצם כ-Node ומנוהל ע"י Master עם Kubernetes או OpenShift (שהם רצים על שרת רגיל).
  • לא צריך לכתוב גרסאות שונות של האפליקציה מחדש ל-eMMC, מערכת ה-Scheduling של הקונטיינר תעיף את הקונטיינר עם הגירסה הישנה ותפעיל על אותו מכשיר קונטיינר חדש. לא צריך Reboot, לא צריך להגדיר מחדש כלום. המפתח מוציא 20 גרסאות ביום עם תיקונים שונים? זמן ההקמה לבדיקה מתקצר בעשרות אחוזים.
  • לא חשוב מה המעבד ARM שיש, כל עוד יש לו גירסת לינוקס וחיבור רשת (ולא מדובר ב-MCU שעליו מבחינת חוסר משאבים לא ניתן להריץ קונטיינרים – כמו במקרים שיש לך כמה קילובייטים בודדים) – ניתן לעשות את הדברים הללו.
  • הקץ לאמולציות איטיות 🙂

ביצעתי בימים האחרונים טסט קטן שכולל 3 לוחות Raspberry Pi-3 ששימשו כ-Nodes ומכונת CentOS אחת שהריצה את OpenShift (שבתוכו יש את Kubernetes). מכיוון שהח"מ אינו חברת שמייצרת פתרונות חומרה, הקמתי מערכת שמריצה LAMP (שהתוכן מאוחסן ב-NFS) ו-2 מכונות וירטואליות שמריצות 20 קונטיינרים רזים (שמריצים ab כ"דפדפנים"). זה לא היה טסט לבדיקת ביצועים, אבל במחשבה שניה – כל Pi-3 הצליח להחזיק בערך כמה עשרות חיבורים סימולטניים. הפלתי כל פעם לוח (ניתוק חשמל) מתוך 3 לוחות ה-Pi-3 ולקח בממוצע כ-8 שניות עד שהמערכת זיהתה Node לא פעיל והזיזה את התקשורת ל-Nodes התקינים האחרים.

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