לקבל מושג ירוק על קוברנטיס (Kubernetes)

הפוסט הזה נכתב לאנשי-תוכנה מנוסים, המעוניינים להבין את Kubernetes – בהשקעת זמן קצרה.
הבאזז מסביב ל Docker ו Docker Orchestration הוא כרגע רב מאוד. דברי שבח רבים מסופרים על הטכנולוגיות הללו, מבלתי להתייחס לפרטים ועם מעט מאוד ראיה עניינית וביקורתית. כאנשי-תוכנה ותיקים אתם בוודאי מבינים שהעולם הטכנולוגיה מלא Trade-offs, וכדאי לגשת לטכנולוגיות חדשות עם מעט פחות התלהבות עיוורת – וקצת יותר הבנה.

אני הולך לספק את הידע בפוסט לא בפורמט ה “From A to Z” כפי שדיי מקובל – אבל ע”פ סדר שנראה לי יותר נכון והגיוני. אני רוצה לדלג על דיון ארוך על ההתקנה, ועוד דיון ארוך על הארכיטקטורה – עוד לפני שאנחנו מבינים מהי קוברנטיס. אני הולך לדלג על כמה פרטים – היכן שנראה לי שהדבר יתרום יותר להבנה הכללית.

בואו נתחיל.

 

אז מהי בעצם קוברנטיס?

פורמלית קוברנטיס היא Container Orchestration Framework (הנה פוסט שלי על הנושא) שהפכה בשנתיים האחרונות לסטנדרט דה-פאקטו (הנה פוסט אחר שלי שמנתח את העניין).

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

  • אנו אומרים לה מה להריץ – והיא מריצה. אנו ״מזינים״ אותה ב Containers (מסוג Docker או rkt) והגדרות – והיא ״דואגת לשאר״.
  • אנו מקצים לקוברנטיס כמה שרתים (להלן ״worker nodes״ או פשוט “nodes”) שהם השרתים שעליהם ירוצו הקונטיינרים שלנו. בנוסף יש להקצות עוד כמה שרתים (בד״כ – קטנים יותר) בכדי להריץ את ה master nodes – ה״מוח״ מאחורי ה cluster.
  • קוברנטיס תדאג ל containers שלנו:
    • היא תדאג להרים כמה containers בכדי לאפשר high availability – ולהציב אותם על worker nodes שונים.
    • אם יש עומס עבודה, היא תדאג להריץ עוד עותקים של ה containers, וכשהעומס יחלוף – לצמצם את המספר. מה שנקרא auto-scaling.
    • אם container קורס, קוברנטיס תדאג להחליף אותו ב container תקין, מה שנקרא גם auto-healing.
    • קוברנטיס מספקת כלים נוחים לעדכון ה containers לגרסה חדשה יותר, בצורה שתצמצם למינימום את הפגיעה בעבודה השוטפת – מה שנקרא deployment.
      • כפי שראינו בפוסט על Docker – פעולת restart של Container תהיה מהירה משמעותית מ VM, שזה גם אומר לרוב deployments מהירים יותר.
    • לשימוש בקוברנטיס יש יתרון בצמצום משמעותי של ה Lock-In ל Cloud Vendor [א], והיכולת להריץ את אותה תצורת ״הענן״ גם On-Premises.
      • הסתמכות על קוד פתוח, ולא קוד של ספק ספציפי – הוא גם יתרון, לאורך זמן, וכאשר הספק עשוי להיקלע לקשיים או לשנות מדיניות כלפי הלקוחות.
  • קוברנטיס גם מספקת לנו יכולות ליבה של ניהול Infrastructure as Code, היכולת להגדיר תצורה רצויה לתשתיות רשת, אבטחה בצורה הצהרתית ופשוטה – מה שמייתר כלי ניהול תצורה (Provisioning) כגון Chef, Puppet או Ansible – ויכול לחסוך עבודה משמעותית.

יעילות

 
עם כל היעילות המוגברת שהתרגלנו אליה מריצה בענן בעזרת שירותים כמו AWS EC2 או Azure Virtual Machines (להלן ״ענן של מכונות וירטואליות״) – קוברנטיס מאפשרת רמה חדשה וגבוהה יותר של יעילות בניצול משאבי-חומרה.

בתצורה קלאסית של מיקרו-שירותים, הפופולרית כיום – ייתכן ומדובר בניצולת חומרה טובה בכמה מונים. הכל תלוי בתצורה, אבל דיי טיפוסי להריץ את אותו ה workload של מיקרו-שירותים בעזרת קוברנטיס על גבי 20-50% בלבד מהחומרה שהייתה נדרשת על גבי ״ענן ציבורי של מכונות וירטואליות״.

איך זה קורה? למכונה וירטואלית יש overhead גבוה של זיכרון (הרצת מערכת ההפעלה + hypervisor) על כל VM שאנו מריצים. זה לא כ״כ משמעותי כשמריצים שרת גדול (כיום נקרא בבוז: Monolith) – אך זה מאוד משמעותי כאשר מריצים שרתים קטנים (להלן: מיקרו-שירותים).

מעבר לתקורה הישירה שעתה ציינו, יש תקורה עקיפה וגדולה יותר: כאשר אני מריץ על שרת 4 מיקרו-שירותים בעזרת VMs ומקצה לכל אחד מהמיקרו-שירותים 25% מהזיכרון וה CPU ההגבלה היא קשיחה. אם בזמן נתון שלושה מיקרו-שירותים משתמשים ב 10% ממשאבי המכונה כ״א, אבל המיקרו-שירות הרביעי זקוק ל 50% ממשאבי המכונה – הוא לא יכול לקבל אותם. ההקצאה של 25% היא קשיחה ואינה ניתנת להתגמשות, אפילו זמנית [ב].

בסביבת קוברנטיס ההגבלה היא לא קשיחה: ניתן לקבוע גבולות מינימום / מקסימום ולאפשר מצב בו 3 מיקרו-שירותים משתמשים ב 10% CPU ו/או זיכרון כ״א, והרביעי משתמש ב 50%. אפשר שגם 10 דקות אח״כ המיקרו-שירות הרביעי יהיה idle – ומיקרו-שירות אחר ישתמש ב 50% מהמשאבים.
 

 

הכרה חברתית

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

מחירים

 
כמובן שיש לכל הטוב הזה גם מחירים:
  • קוברנטיס היא טכנולוגיה חדשה שיש ללמוד – וכמות / מאמץ הלמידה הנדרש הוא לרוב גבוה ממה שאנשים מצפים לו.
    • התסריטים הפשוטים על גבי קוברנטיס נראים דיי פשוטים ואוטומטים. כאשר נכנסת לתמונה גם אבטחה, הגדרות רשת, ותעדוף בין מיקרו-שירות אחד על האחר – הדברים הופכים למורכבים יותר!
      Troubleshooting – עשוי להיות גם דבר לא פשוט, מכיוון ש”מתחת למכסה המנוע” של קוברנטיס – יש מנגנונים רבים.
    • ברוב המקרים נרצה להריץ את קוברנטיס על שירות ענן, ולכן נידרש עדיין לשמר מידה של מומחיות כפולה בשני השירותים: לשירות הענן ולקוברנטיס יש שירותים חופפים כמו Auto-Scaling, הרשאות ו Service Discovery (בד”כ: DNS). 
  • הטכנולוגיה אמנם לא ממש ״צעירה״, והיא בהחלט מוכחת ב Production – אך עדיין בסיסי הידע והקהילה התומכת עדיין לא גדולה כמו פתרונות ענן מסחריים אחרים. יש הרבה מאוד אינטגרציות, אך מעט פחות תיעוד איכותי וקל להבנה.
  • כמו פעמים רבות בשימוש ב Open Source – אין תמיכה מוסדרת. יש קהילה משמעותית ופעילה – אבל עדיין הדרך לפתרון בעיות עשויה להיות קשה יותר מהתבססות על פתרון מסחרי.
    • גם בשימוש ב״קוברנטיס מנוהל״ (EKS, AKS, ו GKE), החלק המנוהל הוא החלק הקטן, והשאר – באחריותנו.
    • האם החיסכון הצפוי מניהול משאבים יעיל יותר, יצדיק במקרה שלכם שימוש בסביבה שדורשת מכם יותר תפעול והבנה?
      • במקרה של ניהול מאות או אלפי שרתים – קרוב לוודאי שזה ישתלם.
      • שימוש בקוברנטיס עשוי לפשט את סביבת התפעול, וה Deployment Pipeline. ההשקעה הנדרשת היא מיידית – בעוד התשואה עשויה להגיע רק לאחר זמן ניכר, כאשר היישום הספציפי באמת הגיע לבגרות.
      • במקרים לא מעטים, ארגונים נקלעים לשרשרת של החלטות שנגזרות מצו האופנה ובניגוד לאינטרס הישיר שלהם: עוברים למיקרו-שירותים כי ״כך כולם עושים״ / ״סיפורי הצלחה״ שנשמעים, משם נגררים לקוברנטיס – כי יש להם הרבה מאוד שרתים לנהל, שכבר נהיה דיי יקר.
        לו היינו עושים שיקולי עלות/תועלת מול המצב הסופי – כנראה שהרבה פעמים היה נכון לחלק את המערכת למודולים פשוטים, או להשתמש במיקרו-שירותים גדולים (“midi-services”) – וכך לשלוט טוב יותר בעלויות והמורכבויות האחרות.
 

 

 
 

קוברנטיס בפועל

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

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

 
לצורך הדיון, נניח שאנו עובדים על AWS ו EKS ואמזון מנהלים עבורנו את ה Masters nodes. ה Worker nodes שלנו נמצאים ב Auto-Scaling Group – מה שאומר שאמזון תנהל עבורנו את ה nodes מבחינת עומס (תוסיף ותוריד מכונות ע״פ הצורך) והחלפת שרתים שכשלו. זה חשוב!
 
אנחנו גם משתמשים ב ECR (קרי Container Registry מנוהל) , ואנו משתמשים בכל האינטגרציות האפשריות של קוברנטיס לענן של אמזון (VPC, IAM, ELB, וכו׳). התצורה מקונפגת ועובדת היטב – ונותר רק להשתמש בה.
 
אנחנו רק רוצים ״לזרוק״ קונטיינרים של השירותים שלנו – ולתת ל״קסם״ לפעול מעצמו. רק לומר בפשטות מה אנחנו רוצים – ולתת לקוברנטיס לדאוג לכל השאר!
 

יצירת Pod

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

אני מניח שאנחנו מבינים מהו Container (אם לא – שווה לחזור צעד אחורה, ולהבין. למשל: הפוסט שלי בנושא), ויש לנו כבר Image שאנו רוצים להריץ ב ECR.

בכדי להריץ Container, עלינו לעדכן את קוברנטיס ב manifest file המתאר Pod חדש מצביע ל container image. קוברנטיס ירשום את ה Pod ויתזמן אותו לרוץ על אחד מה nodes שזמינים לו.

כאשר ה node מקבל הוראה להריץ Pod עליו להוריד את ה container image – אם אין לו אותו כבר. כל node מחזיק עותקים עצמאיים של ה container images משיקולים של high availability.

הנה קובץ ה manifest שהרכבנו:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
env: dev
version: v1
spec:
containers:
- name: hello-world-ctr
image: hello-world:latest
ports:
- containerPort: 8080
protocol: TCP

קובץ ה manifest בקוברנטיס מורכב מ 4 חלקים סטנדרטיים:

  1. גרסת ה API
    1. הפורמט הוא לרוב / אבל כמה הפקודות הבסיסיות ביותר בקוברנטיס נמצאות תחת API Group שנקרא core – ולא צריך לציין אותו.
    2. ה API של קוברנטיס נמצא (בעת כתיבת הפוסט) בגרסה 1.13 – אז למה גרסה 1?
      ניהול הגרסאות בקוברנטיס הוא ברזולוציה של משאב. הקריאה לייצור pod היא עדיין בגרסה 1 (כמו כמעט כל ה APIs. בעת כתיבת הפוסט אין עדיין גרסת v2 לשום API, מלבד v2alpha או v2beta – כלומר גרסאות v2 שעדיין אינן GA).
  2. סוג (kind) – הצהרה על סוג האובייקט המדובר. במקרה שלנו: Pod.
  3. metadata – הכולל שם ו labels שיעזרו לנו לזהות את ה pod שיצרנו.
    1. ה labels הם פשוט זוגות key/value שאנחנו בוחרים. הם חשובים מאוד לצורך ניהול Cattle של אובייקטים, והם בלב העבודה בקוברנטיס.
  4. spec – החלק המכיל הגדרות ספציפיות של המשאב שהוגדר כ “Type”.
    1. name – השם שניתן ל container בתוך ה Pod, וצריך להיות ייחודי. במקרה של container יחיד בתוך ה pod – אין בעיה כזו. 
    2. image – כמו בפקודת docker run…
    3. ports – ה port שיהיה published.
      TCP הוא ערך ברירת-המחדל, אך הוספתי אותו בכדי לעשות את ה Yaml לקריא יותר.

תזכורת קצרה על Yaml:

פה ייתכן וצריך לעצור שנייה ולחדד כמה מחוקי-הפורמט של Yaml.
ייתכן ונדמה לכם ש Yaml הוא פורמט פשוט יותר מ JSON – אבל זה ממש לא נכון. זה פורמט “נקי לעין” – אבל מעט מורכב.

רשימה ב Yaml נראית כך:

mylist:
- 100
- 200

“mylist” הוא ה key, והערך שלו הוא רשימה של הערכים 100 ו 200.
כל האיברים שלפניהם הסימן ” – ” ובעלי עימוד זהה – הם חברים ברשימה.
סימן ה Tab ברוב ה Editors מתתרגם ל 2 או 4 רווחים. ב Yaml הוא שקול לרווח אחד, ולכן שימוש בו הוא מקור לבעיות ובלבולים. הימנעו משימוש ב Tab בתוך קבצי Yaml!

המבנה הבא, שגם מופיע ב manifest (ועשוי לבלבל) הוא בעצם רשימה של Maps:

channels:
- name: '#mychannel'
password: ''
- name: '#myprivatechannel'
password: 'mypassword'

“channel” הוא המפתח הראשי, הכולל רשימה.
כאשר יש “מפתח: ערך” מתחת ל”מפתח: ערך” באותו העימוד – משמע שמדובר ב Map.
כלומר, המפתח “channel” מחזיק ברשימה של שני איברים, כל אחד מהם הוא מפה הכוללת שני מפתחות “name” ו “password”.

אם נחזור לדוגמה של הגדרת ה container ב manifest למעלה, בעצם מדובר במפתח “containers” המכיל רשימה של איבר אחד.
בתוך הרשימה יש מפה עם 3 מפתחות (“image”, “name”, ו “ports”) כאשר המפתח האחרון “ports” מכיל רשימה עם ערך יחיד, ובה מפה בעלת 2 entries.

הנה מדריך המתאר את ה artifacts הבסיסיים ב Yaml ממנו לקחתי את הדוגמאות.
חשוב להזכיר שיש עוד כמה וכמה artifacts ב Yaml – אם כי כנראה שלא נזדקק להם בזמן הקרוב.

 

עכשיו כשיש לנו manifest, אנחנו יכולים להריץ את ה Pod:

$ kubectl apply -f my-manifest-file.yml
 

kubectl הוא כלי ה command line של קוברנטיס. פקודות מסוימות בו יזכירו לכם את ה command line של docker.
במקרה הזה אנו במקרה הזה אנו מורים לקוברנטיס להחיל קונפיגורציה. הפרמטר f- מציין שאנו מספקים שם של קובץ.

תוך כמה עשרות שניות, לכל היות, ה pod שהגדרנו אמור כבר לרוץ על אחד ה nodes של ה cluster של קוברנטיס.

אנו יכולים לבדוק אלו Pods רצים בעזרת הפקודה הבאה:

$ kubectl get pods

עמודה חשובה שמוצגת כתוצאה, היא עמודת הסטטוס – המציגה את הסטטוס הנוכחי של ה pod. אמנם יש רשימה סגורה של מצבים בו עשוי להיות pod, אולי עדיין הסטטוס המדווח יכול להיות שונה.
למשל: הסטטוס ContainerCreating יופיע בזמן שה docker image יורד ל node. זה מצב נפוץ – אך לא מתועד היטב. את הסטטוס ניתן למצוא בעיקר… בקוד המקור של קוברנטיס.

הפקודה הבאה (וריאציות), בדומה לפקודת ה Docker המקבילה – תציג את הלוגים של ה Container ב Pod :

$ kubectl logs my-pod 
אם ב Pod יש יותר מ-2 containers (מצב שלא אכסה בפוסט), הפקודה תציג לוגים של ה container הראשון שהוגדר ב manifest. אפשר לציין את שם ה container כפי שצוין ב manifest – וכך להגיע ל container נתון בתוך Pod-מרובה containers.
 
עבור תקלות יותר בסיסיות (למשל: ה pod תקוע על מצב ContainerCreating וכנראה שה node לא מצליח להוריד את container image) – כדאי להשתמש בפקודה:
$ kubectl describe pods my-pod
התוצאה תהיה ססטוס מפורט שיכיל את הפרטים העיקריים מתוך ה manifest, רשימה של conditions של ה pod, ורשימת כל אירועי-המערכת שעברו על ה pod מרגע שהורנו על יצירתו. הנה דוגמה להפעלה הפקודה (מקור):
 
 
Name:  nginx-deployment-1006230814-6winp
Node: kubernetes-node-wul5/10.240.0.9
Start Time: Thu, 24 Mar 2016 01:39:49 +0000
...
Status: Running
IP: 10.244.0.6
Controllers: ReplicaSet/nginx-deployment-1006230814
Containers:
nginx:
Container ID: docker://90315cc9f513c750f244a355eb1149
Image: nginx
Image ID: docker://6f623fa05180298c351cce53963707
Port: 80/TCP
Limits:
cpu: 500m
memory: 128Mi
State: Running
Started: Thu, 24 Mar 2016 01:39:51 +0000
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-5kdvl (ro)
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-4bcbi:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4bcbi
Optional: false
...
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
54s 54s 1 {default-scheduler } Normal Scheduled Successfully assigned nginx-deployment-1006230814-6winp to kubernetes-node-wul5
54s 54s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Pulling pulling image "nginx"
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Pulled Successfully pulled image "nginx"
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Created Created container with docker id 90315cc9f513
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Started Started container with docker id 90315cc9f513
 
ניתן גם, בדומה ל Docker, לגשת ישירות ל console של ה container שרץ ב pod שלנו בעזרת הפקודה:
$ kubectl exec my-pod -c hello-world-ctr -it -- bash
במקרה הזה ציינתי את שם ה container, אם כי לא הייתי חייב.

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

$ kubectl delete -f my-manifest-file.yml

הפעולה הזו עלולה להיראות מוזרה ברגע ראשון. הסרנו את הקונפיגורציה – ולכן גם ה Pod ייסגר?

לשימוש בקוברנטיס יש שתי גישות עיקריות:

  • גישה אימפרטיבית – בה מורים לקוברנטיס איזה שינוי לבצע: להוסיף משאב, לשנות משאב, או להוריד משאב.
    • פקודות כגון kube ctl create או kubectl replace הן בבסיס הגישה האימפרטיבית.
  • גישה דקלרטיבית – בה מורים לקוברנטיס מה המצב הרצוי – והוא יגיע עליו בעצמו.
    • פקודת kubectl apply – היא בבסיס הגישה הדקלרטיבית. אפשר להגדיר כמעט הכל, רק באמצעותה.
    • החלת patch על גבי קונפיגורציה קיימת הוא משהו באמצע: זו פקודה דקלרטיבית, אך מעט חורגת מה lifecycle המסודר של הגישה הדקלרטיבית הקלאסית. סוג של תרגיל נינג’ה.
כמובן שהגישה הדקלרטיבית נחשבת קלה יותר לשימוש ולתחזוקה לאורך זמן – והיא הגישה הנפוצה והשלטת.

מכיוון שאין לנו הגדרה אלו Pods קיימים סה”כ במערכת – לא יכולנו לעדכן את המערכת בהגדרה הכוללת – ולכן הסרנו את המניפסט.

סיכום

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

לא פעם קראתי מאמרים שמתארים את קוברנטיס כמעבר מהובלת מסע על גבי פרד – לנסיעה ברכב שטח יעיל!
אני חושב שההנחה הסמויה ברוב התיאורים הללו היא שהקוראים עדיין עובדים על גבי מערכות On-Premises ללא טכנולוגיות ענן. מעבר משם לקוברנטיס – היא באמת התקדמות אדירה.

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

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

חשוב לציין שה Pod שהגדרנו הוא עצמאי ו”חסר גיבוי” – מה שנקרא “naked pod”.
אם naked pod כשל מסיבה כלשהי (הקוד שהוא מריץ קרס, או ה node שעליו הוא רץ קרס/נסגר) – הוא לא יתוזמן לרוץ מחדש. מנגנון ה auto-healing של קוברנטיס שייך לאובייקט / אבסטרקציה גבוהה יותר בשם ReplicaSet. אבסטרקציה מעט יותר גבוהה, שבה בדרך כלל משתמשים – נקראת Deployment.

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

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

—-

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

רפרנס של פקודות ה kubectl

—-

 
[א] אל דאגה! לספקי הענן יש אינטרס עליון לגרום לנו ל Lock-In גם על סביבת קוברנטיס. לאחר שהניסיונות להציע חלופות ״מקומיות״ לקוברנטיס כשלו – רק טבעי שהם יתמקדו בלהציע יכולות שיפשטו את השימוש בקוברנטיס, אך גם יוסיפו סוגים חדשים של Lock-In. בכל מקרה, ברוב הפעמים אנו כבר תלויים בתשתיות כמו RDS, Athena, S3 ועוד – ולכן כבר יש Lock-In מסוים גם בלי קשר לקוברנטיס.
“Cloud Agnostic Architecture״ הוא בסה״כ מיתוס, השאלה היא רק מידת התלות.
 
[ב] שווה לציין שזה המצב בענן ציבורי. כששכן שלנו למכונה ב AWS רוצה יותר CPU – למה שנסכים לתת לו? אנחנו משלמים על ה ״slice״ שלנו במכונה – שהוגדר בתנאי השירות.
בפתרונות של ענן פרטי (כמו VMWare) ישנן יכולות ״ללמוד״ על brusts של שימוש בקרב VM ולהתאים את המשאבים בצורה יעילה יותר. כלומר: המערכת רואה ש VM מספר 4 דורש יותר CPU אז היא משנה, בצורה מנוהלת, את ההגדרות הקשיחות כך שלזמן מסוים – הוא יקבל יותר CPU מה VMs האחרים הרצים על אותה המכונה. טכנולוגית ה VM עדיין מקצה משאבים בצורה קשיחה – אך תכנון דינמי יכול להגביר יעילות השימוש בהם. זה יכול לעבוד רק כאשר כל ה VMs על המכונה שייכים לאותו הארגון / יש ביניהם הסכמה.
T3/T2 instances ב EC2 הם VMs שעובדים על עיקרון דומה: ב״חוזה״ שלנו רשום שה instance יכול לעבוד ב burst ולקבל יותר משאבים – אך עדיין יש פה עבודה לפי חוזה, ולא אופטימיזציה גלובלית של המשאבים על המכונה (מכיוון שה VMs שייכים לארגונים שונים).  

קוברנטיס (Kubernetes) עומד להיות הענן-בתוך-הענן של רובנו

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

מדוע אני כותב את הפוסט דווקא עכשיו? שום דבר לא קרה בשבוע האחרון. רק יצא יום כיפור (אין קשר), אמנם הכריזו על ליין חדש של אייפונס, ויש גם את ארכיטקטורת Turing החדשה של nvidia – אבל לא באמת היה השבוע משהו גדול ורועש בגזרת ה Containers ו/או Container Orchestration Framework (בקיצור עבור הפוסט: COF).
בכל זאת, לפני כשנה כתבתי פוסט שעסק ב COFs והשווה קצת בין מזוס, ECS, קוברנטיס, Swarm ו Nomad – ובאותה עת נראה היה שהתחרות בין כמה מה COFs שהוזכרו עדיין פתוחה.
כשאני מסתכל על ההתרחשויות של השנה האחרונה – נראה שהעניין נסגר. אם “קולות החיילים” לא יבצעו מהפך של הרגע האחרון – Kubernetes הוכרזה בחודשים האחרונים כ COF שתכתיב את הטון בעתיד הנראה לעין.
תזכורת קצרה:
  • קוברנטיס (לעתים נכתב בקיצור K8s) היא פריימוורק ששוחרר כפרויקט קוד פתוח ע״י גוגל באמצע שנת 2014 לניהול Orchestrations של Containers. בסה”כ בת ארבע שנים.
    • לגוגל היה ניסיון קודם בפרויקטים פנימיים דומים: הראשון בשם Borg והמחליף שלו – Omegaֿ, להרצת קונטיינרים. הם לא הריצו Docker או Rkt – אלא קונטיינרים פרי פיתוח מוקדם של גוגל. הניסיון הזה הוכיח את עצמו.
  • קוברנטיס (בדומה ל COFs אחרים) מספקת יכולות Load Balancing, Discovery ו Auto-Scaling ובעצם מהווה סוג של ״מיני-ענן״ בו יחידת ה compute היא Container. האיום הזה לא נחבא מעיניהם של ספקי-הענן הגדולים, והם ניסו לפתח COFs מקבילים שישמרו את ה Lock-In לענן שלהם.
  • אמזון יצאה עם ECS, ומייקרוסופט עם ACS (שתי החברות שאולי היה להן הכי הרבה להפסיד) – פתרון הרצת ו Orchestrations של Containers שתפור לענן שלהן. והן הטילו את כובד משקלן בכדי לשכנע שזו אלטרנטיבה ראויה (וטובה יותר) לקוברנטיס – אלטרנטיבה שרק צריכה עוד זמן להבשיל.
  • השוק לא הגיב יפה להצעות הללו – ופנה ל manual installation של קוברנטיס על גבי EC2.
  • מייקורוסופט הוציאה את AKS (קרי Azure Kubernetes Service) ואמזון את EKS (קרי Elastic Kubernetes Service) כ Kubernetes מנוהל. בהתחלה נראה היה ש EKS ו AKS הולכים להיות offering משני על מנת לשמר לקוחות ולא להישאר יותר מדי מאחור, אבל מהר מאוד התברר שהשירותים הללו תופסים את תשומת-לב הלקוחות, ומשם השתנו הדברים והם התחילו לקבל גם את מירב ההשקעה מצד ספקי הענן. ECS/ACS הופכים להיות פתרונות נישה, בעיקר עבור לקוחות שכבר נרתמו לחזון שהוצג ב 2015, והשקיעו בו, או אולי יצליחו לשלב אותם גם בעולם של קוברנטיס (עבור ה worker nodes – על זה בהמשך).
  • גם פתרונות ענן כגון Pivotal Container Service ו Cloud Foundary – הגיעו למסקנה דומה, ופנו לכיוון קוברנטיס.
  • אפילו החברה מאחורי Docker שניסתה להציג חזון משלה בדמות Swarm (לאחר שהבינה שב COFs יש פוטנציאל עסקי גדול יותר מתמיכה ב Docker בלבד) הכריזה לפני כשנה על תמיכה ״גם״ בקוברנטיס – מה שבפועל ״הוציא את העוקץ״ מ Swarm שמותג כ”פתרון הרשמי של דוקר”.
  • Mesosphere DC/OS – הגרסה המסחרית של Mesos, מציעה גם היא תמיכה בקוברנטיס.
בקיצור: מלחמת ה COFs הסתיימה. Long live Kubernetes!
חשוב לציין שלמרות שקוברנטיס הוא ה COF שהפך לברירת-המחדל, יש עדיין תהליכים שלא ברור כיצד יסתיימו:
  • מייקרוסופט שחררה את ACI (קרי Azure Container Instances) ואמזון את AWS Fargate כשירותים בהם ניתן להריץ container on-demand ולשלם ע״פ השימוש הנקודתי. השירותים מזכירים מאוד את AWS Lambda או Azure functions כאשר הרזולוציה היא Container ולא פונקציה, על אף שמנסים לשווק אותם כ”תחליף ל EC2″.
    • השימוש העיקרי הוא בהפעלה של containers המבצעים batch של עבודה – ולא בהרכבה של containers מסוגים שונים המתקשרים זה עם זה. האלמנט של Orchestration לא ממש קיים בשירותים הללו.
    • גם קוברנטיס תומכת בהפעלת containers באופן on-demand, מה שעשוי לרמז שהלקוחות העיקריים של ACI ו Fargate הם לקוחות שלא מריצים קובנרטיס או כאלו שיש להם Workload מאסיבי שאינם רוצים להפעיל על ה Kubernetes cluster הרגיל שלהם (למשל: משימות AI כבדות).
  • קוברנטיס עצמה נפתחה לספקי הענן, למשל: החל מגרסה 1.9 קוברנטיס תומכת באופן טבעי ב AWS NLB (קרי Network Load Balancer). מיותר לציין שיש הרבה Kubernetes-plugins שמסייעים לבצע את החיבורים לעננים ספציפיים בצורה טבעית יותר.
  • ישנה השקעה בהרצה של Kubernetes בכדי להפעיל VMs ולא רק Containers. המוטיבציה היא לשלב גם שרתים שאינם לינוקס (למשל Windows או אפליקציות Unikernel) ו/או בידוד גבוה יותר – בעיקר משיקולי אבטחה.
  • קוברנטיס מאפשרת יכולות ניהול משאבים טובות ברמת התשתית, אבל ניהול של מאות מיקרו-שירותים הוא עדיין דבר קשה מאוד בקוברנטיס. יש פרויקטים (למשל: lstio הנתמך ע״י Lyft, IBM וגוגל) המנסים לספק שכבת ניהול ברמה יותר ״אפליקטיבית״ שתקל על ניהול שכזה. פרויקטים כאלו יכולים להשתלב עם קוברנטיס כ plug-in ו/או להחליף כמה מיכולות הליבה שלה (למשל: Service Discovery או Load Balancing).

Managed Kubernetes

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

  • יש שורה של בחירות שיש לבצע בהתקנה של קוברנטיס. האם אתם מעדיפים א או ב, ג או ד? דוגמה טובה היא תקשורת בין Containers: האם Kubenet (ברירת-המחדל) מספיק לכם? אולי אתם צריכים scale, ביצועים, ו/או יכולות שליטה מתקדמות יותר ברמת הרשת וכדאי להשתמש ב Weave? אולי בעצם ב Calico? ואם אתם בוחרים ב Calico – אתם מעדיפים אותו עם Flannel (כלומר: Canal) או בלעדיו?
  • קוברנטיס מטפל בשורה של מקרי-קצה מורכבים להבנה, שללא ניסיון ניכר – קשה להבין אותם ולוודא שהם עובדים בצורה תקינה.
    • High Availability – איך להבטיח ש pods ימשיכו לתפקד ככל האפשר. לדוגמה: האם ה masters הם באמת highly available? האם אתם יכולים ליצור master חדש עם קונפיגורציה שלמה בצורה אוטומטית?
    • אבטחה – האם אתם מודעים כיצד להקשיח התקנה של קוברנטיס, ויש לכם את המנגנון להתקין עדכונים בכל השכבות?
  • חיבור של קוברנטיס לספק הענן הספציפי היא עוד משוכה שיש לעבור. למשל: על EC2 לא תוכלו ליצור cluster גדול מ 50 nodes ללא החלפה של ה CNI Network plugin. כנראה שתרצו כמה מה nodes שירוצו על spots. כדאי מאוד להתחבר ל IAM בצורה נכונה, לקנפג את Route53 כך שה master ימצא את כל הרכיבים שלו ואם יש כמה clusters – הם יהיו זקוקים ל subdomains, וכו׳.
הפתרון הטבעי, בדומה מאוד לבחירה בספק ענן (ולא הפעלה של Data Center של החברה) – הוא שימוש ב Managed Kubernetes. זו הבחירה הטבעית עבור הרוב הגדול של משתמשי Kubernetes, במיוחד אלו שלא הולכים להריץ אלפי שרתים ב Cluster של קוברנטיס (ולכן סביר יותר שיהיה לכם את האינטרנס והמשאבים לעבוד עם קונפיגורציה מאוד ספציפית (“לא מקובלת”) לצרכים שלכם).

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

  • גוגל – בתור היוצרים של Kubernetes והמאמצים הראשונים שלו כשירות Managed בענן, אין הפתעה בכך ש GKE (להלן Google Kubernetes Engine) הוא המוצר הבשל ביותר.
    • האינטגרציה הטובה ביותר, UI מלוטש לניהול, והפעלה מהירה של Cluster מאשר של המתחרות.
    • הבעיה היחידה: רוב החברות (בכלל, אך בישראל בפרט) לא פועלות על הענן של גוגל, והם לא יעבירו אותן לשם בשביל “Managed Kubernetes טוב יותר”. זה עשוי להשתנות בעתיד – אבל כרגע לא נראה שזה המצב.
    • בניגוד ל BigQuery שהוא שירות שלקוח של AWS עשוי להשתמש בו על אף שהוא שוכן בענן אחר – קוברנטיס מריצה את לב המערכת שלנו. להשתמש בקוברנטיס בענן אחר, משמע להתחיל לעבור לענן אחר.
  • אמזון מציעה את EKS, שהיה עד לא מזמן plan B – שהתממש.
    • EKS תנהל עבורכם את ה Control plane מבחינת scalability ו high-availability על גבי AZs שונים. לא תהיה לכם גישה ברמת Admin אליו (בדומה ל RDS), אבל אתם ממשיכים לעבוד עם kubectl כרגיל.
    • לEKS יש אינטגרציה עם שירותי אמזון בראשם IAM, אבל גם ELB, VPC ו CloudTrail.
    • את ה Worker nodes עדיין עליכם לנהל לבד – ויש עוד קונפיגורציה ועבודה שעליכם לעשות על גבי EKS. יש תוכניות לבצע אינטגרציה בין EKS ל ECS כך ש ECS ינהל את ה worker nodes. מכיוון שהוא לא נבנה מלכתחילה לצורת העבודה הזו – צריך לראות כמה טוב זה יעבוד. רעיון דומה מתוכנן לאינטגרציה בין EKS ל Fargate להרצה של Containers שהם task-oriented.
    • לאחרונה שוחררה גרסאת eks.2 של EKS – ויהיו עוד רבות. כרגע ל EKS יש סיכוי טוב להיות פתרון ה Managed Kubernetes הפופולארי ביותר (גם אם לא בהכרח יהיה המתקדם ביותר).
  • מייקורוספט מציעה על גבי Azure את שירות AKS המנוהל, שדומה ביכולות ל EKS.
    • אולי בגלל קהילה קטנה יותר ופעילה פחות, AKS נראה כשירות קצת פחות פופולארי. אפשר לנחש שהלקוחות הקלאסיים של מייקרוסופט הם ברובם לא early adapters של טכנולוגיות חדשות.
  • גם OpenShift ויבמ BlueMix – מציעות פתרונות Kubernetes שנחשבים מפותחים, אך הם מתאימים בפועל בעיקר למי שכבר פעיל על תשתיות הענן הללו.
  • Stackpoint מציעה פתרון של managed control plane על ידה, כאשר את ה worker nodes תתקינו על ענן לבחירתכם. הפתרון אטרקטיבי בעיקר למי שמריץ את ה workload בענן שבו אין offering סביר של managed kubernetes.
השוואה שנעשתה בין שלושת פתרונות ה Managed Kubernetes הנפוצים. מקור

גם מי שמתקין קוברנטיס לבד (על הענן או On-Premises) לרוב לא עושה זה בדרך הארוכה והקשה.
kubernetes-the-hard-way הוא שם של מדריך פופולארי ונחשב להתקנת קוברנטיס מ scratch, שבעיקר משמש בכדי ללמוד את הפרטים השונים שקיימים בהתקנת קוברנטיס, ואת השיקולים שנלקחים בכזו התקנה.

בפועל, מי שמתקין קוברנטיס, יעשה זאת כמעט תמיד עם “installer” המיועד לכך:

  • Kops הוא המקובל ביותר. הוא חלק מפרויקט קוברנטיס והיה במשך תקופה כלי להתקנת קוברנטיס על גבי AWS בלבד. הוא יודע לייצר קבצי Terraform, יודע לבנות תצורות high-availability (כמובן), ותומך ב-7 אפשרויות שונות ל CNI (כלומר: plugin לתקשורת פנימית. אחת הבחירות עם הווריאציות המגוונות יותר בהתקנת קוברנטיס).
  • Kubespray (לשעבר Kargo), תת-פרויקט של קוברנטיס הוא כלי להתקנת קוברנטיס בהתבסס על Ansible, כלי ה configuration management שנחשב לפופולארי ולמתקדם – עד להופעת ה COFs שהולכים ומייתרים אותו. Kubespray נחשב יותר גמיש מ Kops ומציע מגוון רחב יותר של אפשרויות התקנה. יש לו גם תמיכה ספציפית ב AWS, Azure, Google Cloud, Digital Ocean ו Open Stack.
  • TK8 הוא עוד כלי פופולרי, שהדגש שלו הוא עבודה צמודה עם Terraform והוא זוכה לכמה נקודות פופולריות בזכות זה שהוא כתוב ב Go (אזהרת באזז). TK8 כולל גם אפשרות התקנה של כמה אפליקציות פופולריות בהמשך ל Kubernetes Cluster כמו Zipkin+Jagger, Prometheus ועוד.
  • עוד שמות שאפשר לציין הם RKE (להתקנה של ה Cluster בלבד, לאחר שהכנתם את המכונות באופן מסוים), מודול שקיים ומתוחזק ב Puppet להתקנה של Kubernetes, או Kubeinformation שהוא כלי online שעוזר לייצר templates של קונפיגורציות ע”פ סט בחירות שתתנו לו. Kubeinformation עשוי להיות מקור מעניין להתרשם בזריזות מתהליך ההתקנה, אבל בעת כתיבת פוסט זה הוא עדיין לא תומך ב EKS (זו הפריט הבא ב roadmap שלו).

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

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

סיכום

העולם הטכנולוגי מתקדם בחזית רחבה לכיוון קוברנטיס (גם בצורה עיוורת לפעמים – סממן חזק להפיכתו ל”באזז”). קוברנטיס היא תשתית מרשימה, אבל גם לא-פשוטה לניהול. התסריט הסביר ביותר הוא שפתרונות של Managed Kubernetes ישמשו את רוב השחקנים בשוק, בעיקר הקטנים והבינוניים (תמיד יכולה להיות שחקנית שתדמה ל Netflix ע”ג AWS, כלומר: שתחליט להריץ גם מאות-אלפי worker nodes על גבי פתרון Managed).

Enterprises שרצים On-Premises, או מריצים ענן משלהם, או סתם חברות שמריצות Workload גדול במיוחד – כנראה ימשיכו לנהל את ה Kubernetes Cluster מא’ עד ת’ – אבל זו התמחות שהן יכולות להרשות לעצמן לפתח ולתחזק.

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

EKS נראה כרגע כאופציה בעלת נקודת הפתיחה הטובה ביותר להיות הפופולרית ביותר (פופולריות שנגזרת באופן ישיר מ AWS ומגוון השירותים הטובים שהיא מציעה) – אבל הכל עוד יכול לקרות. למשל: אם הקוברנטיס יהפוך לחשוב יותר משאר שירותי הענן – אזי ל GKE (קרי Google Kubernetes Engine) יש את היתרון הברור.

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

  • להתקין קוברנטיס לבד – על בסיס Installers כמובן, ולא בדרך הקשה והארוכה. יש לפניכם השקעה משמעותית בלמידה והתמחות של Infrastructure חדש ונוסף.
  • להשתמש בפתרון Managed Kubernetes, תוך שאתם משלמים “מחיר התבגרות” בשנה-שנתיים הבאות עד שהפתרון שבחרתם יתבגר.
  • לדחות בשנה-שנתיים את אימוץ קוברנטיס עד שהוא יהיה קל מאוד לצריכה בצורה Managed.
    • אם אתם לא יודעים לומר מה Kubernetes יתרום לכם ברגע זה – זו הבחירה הנבונה (אם כי לא הכי-מגניבה)
  • להחליט שאתם בוחרים לא להשתמש בקוברנטיס כעיקרון, מה שיכול לזרוק אתכם לאחת משתי נקודות קיצון חברתיות בעולם התוכנה: “סופר מיושנים” או “סופר מגניבים וחתרניים”.
  • להחליט שאתם מתחילים עם קוברנטיס היום, לדבר על זה הרבה, להשקיע ב POCs ולמידה – אבל בעצם להתברבר עם זה עוד שנה-שנתיים עד שנקודה שבה אימוץ Kubernetes יהיה דבר קל – מה שבעצם שם אתכם עם ה Majority של התעשייה.

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

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

השוואה בין GKE, EKS וAKS (מקור: Kubdex)

Amazon Virtual Private Cloud

VPC (קיצור של Virtual Private Cloud) היא רשת מבודדת לוגית ב Data Center של AWS. היא באה לדמות Data Center פרטי של ארגון (כלומר: ב On-Premises), בו תעבורת הרשת, והגישה לשרתים מוגבלת למי שנמצא בתוך ה Data Center.

  • מבחינה טכנית, ניתן לחשוב עליה כתת-רשת (subnet) בתוך אמזון שמוקצה רק לכם.
  • מבחינת אבטחה, ניתן לחשוב עליה כ VLAN [א] – רשת משותפת שהתשתית יודעת להפריד בין packets של תתי-רשתות נפרדות – הפרדה מוחלטת.
VPC הוא לא שירות פרימיום. הוא כמעט חינם, ואם אתם פועלים ב AWS ולא משתמשים בו – כדאי להכיר.בניגוד לניהול רשת “קלאסי” בו צריך להכיר את הראטורים השונים ולתכנת אותם, העבודה ב VPC היא ברמת התוכנה ובממשק אחיד של אמזון – סוג של Software Defined Networking (קונספט שגם תופס תאוצה ברשתות On-Premises).

למרות שה VPC מבודד אותנו משאר העולם, ניתן לבצע קשרים מאובטחים עם רשתות אחרות:

  • VPN שיחבר בין רשת אחרת של הארגון (למשל – המשרד) ל VPC בו נמצאים השרתים.
  • VPC Peering – חיבור (שניתן להגדיר את מידת החופש שלו) בין שני VPCs, למשל: VPC של ספק שירות או לקוח, או אולי VPC אחר של הארגון שלכם (כי לעתים נכון ליצור בענן כמה VPCs לאותו הארגון).

אם אתם רוצים אבטחה אפילו גבוהה יותר, אז VPC תומך במצב של הפרדה מוגברת – מה שנקרא “dedicated tenant”.
כל ה EC2 instances שנוצרים בתוך VPC שהוא dedicated tenant הם dedicated instances (כלומר: השרת הפיסי רק משרת אתכם – אין לכם “שכנים”), וגם חלק מתשתיות הרשת יהיו מופרדות בצורה טובה יותר – עבורכם.
השירות הזה, באופן טבעי – מגדיל את העלויות בצורה משמעותית.

מה החשיבות של VPC, ומדוע לא כדאי לעבוד באמזון בלעדיו?

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

אמנם גם ללא VPC ניתן להגן בעזרת “Firewall” על השרתים שלכם: ניתן לאגד שרתים דומים בקבוצה הנקראת “קבוצת אבטחה” (Security Group), ואז להגדיר:

  • תקשורת נכנסת – כתובות IP, פורטים, ופרוטוקולים (tcp, HTTP, וכו’) ספציפיים שיכולים לגשת למשאבים בקבוצת האבטחה.
  • תקשורת יוצאת – כתובות IP, פורטים, ופרוטוקולים אליהם יכולים המשאבים בקבוצת האבטחה לפנות.

הגישה הזו היא מוגבלת:

  • ניתן להגדיר רק הרשאות (whitelist) ולא חסימות (blacklist).
  • אם אתם רוצים לבודד בין קבוצות שרתים שלכם (“ניתן לגשת לבסיסי הנתונים רק מתוך ה Application Servers”) היא הגדרה כמעט בלתי אפשרית ללא VPC: כתובות ה IP משתנות כל הזמן, ויהיה עליכם לעקוב אחר השינוי ולעדכן את ה Security Groups. נתקן: אפשרי – אך לא סימפטי לתחזוקה.
VPC מאפשר הרבה מאוד גמישות להגביל את התעבורה בין כל קבוצת משאבים שלכם – לכל קבוצה אחרת, ובצורה שניתנת לניהול.
עוד צורך חשוב ש VPC פותר הוא בידוד הרמטי יותר בין חלקים במערכת, למשל: משאבים המשרתים מחלקות שונות, בין dev ל production, וכו’. הפתרון שהיה מקובל קודם ל VPC הוא לנהל חשבונות (account) שונים ב Amazon – מה שהקשה מאוד על כמה פעולות אחרות (למשל: העברת נתונים בצורה מאובטחת בין החשבונות).עוד כמה שימושים ל VPC:

  • Compliance – אם יש תקן שמחייב אתכם להגביל ו/או לעשות Audit לכל מי שניגש לקבוצה מסוימת של משאבים – VPC יהפוך את המלאכה לקלה יותר.
  • הפרדה בין dev/test ל production – לצורך הגנה בפני טעויות אנוש.
  • הפרדה דומה בין יחידות שונות בארגון, למשל: ארגון ה BI רוצה אחריות משלו על החשבון, והפרדה מכל מה שמתרחש ב R&D.

“The “Default VPC

החל מ 2014 [ב] כל חשבון חדש שנוצר באמזון, נוצר ב Default VPC – שזו בעצם תשתית התקשורת המשופרת של אמזון שמאפשרת הגדרה של VPCs. אם אתם נמצאים “ב Default VPC” – אין הכוונה שבאמת אתם משתמשים ב VPC, אלא שאתם נמצאים על התשתית החדישה יותר של אמזון, ברשת משותפת… ביחד עם עוד כמה אלפי ארגונים.

תשתית הרשת הישנה יותר של AWS נקראת “EC2 Classic”. היא מוגבלת יותר:

  • לא מאפשרת יצירה של VPC.
  • פחות גמישות ב Security Groups: לא ניתן להגביל outbound traffic, לא ניתן להחליף באופן דינאמי Security Group למשאב).
  • פחות גמישות בהגדרות רשת בסיסיות: לא ניתן לתת למשאב יותר מכתובת IP אחת, קשה יותר לשלוט בהגדרות ה DHCP, DNS, ו NTS של המשאבים.
  • לא ניתן להשתמש ב Enhanced Networking (משלמים יותר, מקבלים רשת יותר “יציבה” ומהירה).
  • וכו’.
אם אתם נמצאים על EC2-Classic – אז כדאי לעבור “Default VPC” גם אם אתם לא מתכננים לנהל VPC משלכם. יבוא היום ואמזון תכריח אתכם לעבור. בכל מקרה, מעבר שכזה הוא תהליך מורכב – אם אתם לא מוכנים לספוג downtime. כלי שיכול להקל בכזה מעבר הוא AWS ClassicLink.

ב Default VPC, כל מכונה חדשה שתוסיפו תקבל אוטומטית כתובת IP ציבורית באינטרנט – בכדי לתאום לאחור להתנהגות של EC2 Classic. זה לא יקרה ב VPC שהוגדר על ידכם.

כמו כן, ב Default VPC כל שרת שלכם יוכל לגשת לאינטרנט – כי הוגדר לו Internet Gateway כברירת מחדל.
ב VPC משלכם, ברירת המחדל היא ששרתים לא יכולים לגשת לאינטרנט – אלא אם חיברתם אותם בעצמכם ל Internet Gateway.
מדוע זה חשוב? כי אם יש לכם שרת שלא אמור מתוקף תפקידו לגשת לאינטרנט (למשל Database Server) – גישה לרשת יכולה לרמז על תוכנה עוינת שרצה על המחשב ושולחת מידע לתוקף. תוכלו למנוע זאת ע”י בקרה ושליטה בתקשורת היוצאת מהרשת שלכם.

יוצאים לדרך!

יצירה של VPC היא פעולה דיי פשוטה, והיא נראית כך:

1. אנו יוצרים את ה VPC ומגדירים לו טווח כתובות (cidr-block) של בטווח הכתובות השמורות לרשתיות פרטיות, בכדי לא להתנגש עם כתובות באינטרנט.

CIDR (קיצור של Classless Inter-Domain Routing) היא שיטה להגדרת תתי-רשתות (subnets) שיכולה לנצל את טווח הכתובת של IPv4 בצורה יעילה יותר, ואולי מעט יותר קלה להגדרה מהשיטה של subnet-masks.

התחביר של CIDR נראה כך:

a.b.c.d/x

כאשר כתובת ה IP הבסיסית היא כתובת בת 4 מספרים בני 8 ביט (0-255) – סה”כ 32 ביט, וה Suffix הוא מספר בין 0 ל 32 – המתאר כמה ביטים בכתובת הבסיס הם “קבועים” ומתארים בעצם את טווח תת-הרשת.

למשל:
127.0.0.0/24 – היא צורה לתאר תת-רשת עם טווח הכתובות 127.0.0.0 עד 127.0.0.255.
24 ביט הם שלשה מספרים, ולכן 127.0.0 הוא החלק ה”קבוע” בטווח הכתובת.

עוד דוגמה:
30.0.0.0/8 היא צורה לתאר תת-רשת שטווח הכתובת שלה הוא 30.0.0.0 עד 30.255.255.255.
8 ביט הם מספר אחד, ולכן רק 30 הוא החלק ה”קבוע” בטווח הכתובות.

ניתן להשתמש ב CIDR בכתיבה מקוצרת, ולהשמיט מכתובת הבסיס אפסים שאינם קבועים. למשל הדוגמה הראשונה יכולה להיכתב כ 127.0.0/24 והדוגמה השניה יכולה להיכתב כ 30/8. ניתן למצוא עוד מגוון דוגמאות בערך בוויקיפדיה.

בדוגמה שלנו הגדרנו את 10.0.0/16 – הטווח בין 10.0.0.0 ל 10.0.255.255 – טווח אפשרי של 65K כתובות (המקסימום של VPC מאפשר). אנו כמובן משתמשים באחד הטווחים של פרוטוקול ה IP לרשתות פרטיות – לא נרצה התנגשות עם כתובות של שירותים ברחבי האינטרנט. התוצאה של הפעולה מחזירה לנו id של ה VPC שרק נוצר, במקרה שלנו: vpc-a01106c2.

2. בתוך ה VPC עלינו להגדיר subnet לכל Availability Zone. ה VPC, כקונספט לוגי שמכיל הגדרות, יכול להתפרס על גבי Region של אמזון, אבל ה subnet הספציפי יכול לחיות רק ב Availability Zone – שהרי זהו Data Center פיסי.

ה Subnet יהיה בטווח קטן יותר של כתובות IP – כ 256 כתובות, בכדי לא “לשתות” את כל הכתובות של ה VPC, ואנו נייצר אותו ב AZ בסימון a של אירלנד (eu-west1).

3. הנה אנו מגדירים subnet נוסף ב AZ בסימון b, ובאופן דומה. שימו לב שמרחב הכתובות של ה subnet הזה הוא שונה.

התוצאה היא המבנה הבא:

לכל subnet יהיה id, למשל “subnet-d38d91dd” וברגע שנבקש להקים EC2 instance – יהיה עלינו לציין באיזה subnet ליצור אותם.

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

1. אנו יוצרים Internet Gateway, רכיב של AWS שמאפשר גישה לאינטרנט. בהפעלת הפעולה – נקבל id (למשל “igw-c0a643a9”)

2. אנו מוסיפים route ל “router הווירטואלי שלנו”, שאומר שכל כתובת בעולם (0.0.0.0/0), אם לא נמצאה בתוך ה subnet – הולכת ל internet gateway שלנו.

ה VPC מחזיק טבלת ניתוב (routing table) לכל ה subnets, אך ניתן להגדיר טבלאות ניתוב שונות – ולקשר כל subnet לטבלת ניתוב שונה.

“למה שארצה להגדיר טבלאות ניתוב, פחחחח?” – יכול מישהו לשאול.
ברור שזו התעסקות נוספת, קצת יותר low level מרוב העבודה עם אמזון. הדרך לאבטחה טובה, היא לתכנן ולשלוט בניתובי הרשת.

לשמחתנו ניתן לבצע את כל הפעולות עם ה aws console – ממשק אחיד לו ניתן לכתוב סקריפטים (ניתן גם דרך ה UI של אמזון – למי שמעדיף). לא צריך להתחבר ל router החומרה ולעשות את זה מולו ישירות – כמו פעם.

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

אז איך מתכננים VPC?

“VPC ניתן להגדיר ב-2 אופנים: VPC יחיד, או ריבוי VPCs – אך יש אלפי תצורות שונות בהן ניתן להגדיר את שני האופנים” — יועץ AWS זקן וחכם.

בתור התחלה, בואו נחלק את המשאבים שלנו באמזון לכמה מחלקות ארגוניות שונות:

  • VPCs בניהול ה R&D:
    • Production
    • Dev/Test – ההפרדה נעשתה כדי למצמצם טעויות אנוש שישפיעו על production.
      יש גם ארגונים שלא מאפשרים למפתחים בכלל לגשת ל production – וזו דרך פשוטה לנהל זאת.
  • VPC עבור ה IT:
    • מערכות ה Active Directory, מערכת ניהול הכספים, נוכחות משתמשים ומערכת ה HR – לא צריכות להשפיע על production, ואף מפתח לא זקוק לגישה אליהן. לכולם יותר נוח שרק לאנשי ה-IT תהיה גישה לרשת זו.
  • VPC עבור ה Data Science
    • צוות ה Data Science זקוק להרשאות Admin ל AWS כי הם מרימים ומורידים מכונות (למשל EMR) בכמויות סיטונאיות, וחס וחלילה לא נרצה שיפגעו בפרודקשיין. “אופס סגרתי לכם 100 מכונות בפרודקשיין, לא שמתי לב בגלל המספר הקטן” – הוא לא מה שאתם רוצים לשמוע…

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

כמו כן, ברוב הפעמים המערכת שלנו תהיה מפוזרת בכמה Regions של אמזון. לצורך הפוסט אני מפשט את התמונה ומניח שאנו פעילים רק ב Region יחיד – ה Region (העתידי) של IL-Center-1 😉 .

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

  1. בתוך ה VPC, יש לנו 2 (בד”כ 3 או 4 – לא היה לי כח לצייר) AZs זהים. בגלל שכל AZ הוא Data Center מבודד פיסית (ואנו רוצים את היתירות הזו) – יהיה עלינו להרכיב subnets סימטרים ב AZs השונים, שיבדלו ע”י טווח כתובות שונה (כלומר: ה CIDR שלהם). כמובן שעדיף לעשות זאת בעזרת כלים אוטומטיים (למשל: Cloud Formation) ולא בצורה ידנית.
    לצורך פשוט התרשים, פירטתי רק את המבנה של AZ סימן a – אנא הניחו ש AZ סימן b הוא סימטרי לחלוטין, גם בתוכן וגם בחיבוריות פנימה והחוצה.
  2. ה Traffic שמגיע מבחוץ (משתמשים באינרטנט, למשל) עובר דרך ה DNS של אמזון (קרי: route 53). ה DNS מספק Load Balancing ראשוני בין ה AZs השונים. משם ה Traffic עובר ל Router של אמזון שמנתב אותו כל פעם ל AZ שנבחר.
  3. הכניסה הראשונית היא ל subnet “ציבורי” אליו ניתן לגשת מכל מקום באינטרנט, ושם אנו מבצעים את הסינון הראשוני של התעבורה. אמזון מספקת לנו שירות, המגיע כ AMI שעלינו להתקין, שנקרא VPN NAT Gateway – שהוא בעצם Reverse Proxy. רוב הסיכויים שנרצה סינון קצת יותר רציני של Traffic, למשל – WAF (קיצור של Web Application Firewall). לאמזון יש גם שירות שכזה – אך הוא עדיין מאוד בסיסי.
    1. אם הרעיון של ה public subnet מזכיר לכם DMZ ברשתות On-Premises זה לא במקרה – זה בדיוק אותו התפקיד, ואותו הרעיון של Layered Security.
  4. ה Subnets הפנימיים (נקראים “פרטיים” כי אנו מגבילים את הגישה אליהם) מכילים את חלקי המערכת שלנו. למשל, ה Subnet הראשון אליו מגיעים מכיל את ה Web Server ואנו יוצרים כלל שמאפשר רק לתקשורת שמקורה ב public subnet – להגיע ל subnet הזה.
    1. באופן דומה, שירות X יסכים לקבל תקשורת רק מה Web Server או כל Subnet שנגדיר לו.
    2. הגדרת הכללים היא קלה: אנו יודעים מה ה CIDR (טווח הכתובות הקבוע) של כל subnet, כך שב Security Group של שירות X אנו נאפשר את ה Subnets (אחד לכל AZs) של ה Web Servers.
      אם מתווספים שרתי ווב חדשים – הם עדיין יהיו בטווח הכתובות של ה subnets, ולכן הכללים שהגדרנו – עדיין יהיו תקפים.
    3. אנו יודעים איזה חלק של המערכת אמור לתקשר עם איזה חלק אחר – וכך אנו חוצצים את השירותים שלנו למספר subnets, ע”פ פרופיל התקשורת שלהם: הנכנסת והיוצאת.
      יש ארגונים שיחלקו את הרשת שלהם ל 3-4 פרופילים שכאלו, ויש כאלו שיחלקו ל 50. הכל תלוי במידת האבטחה שאתם רוצים להשיג ועד כמה אתה מוכנים לטרוח בכדי להשיג אותה.
  5. כפי שציינתי, גם התקשורת היוצאת היא פרופיל שכדאי לשלוט בו. יהיו מעט התקפות יעילות על הרשת שלכם – שלא יידרשו סוג של קשר עם המתקיף.
    1. באופן דומה, נהוג גם את התקשורת היוצאת לסנן בעזרת IDS, WAF, או לפחות NAT פשוט. לאחר הסינון התקשורת תגיע ל Internet Gateway שזה שירות של אמזון (highly available, fully elastic) – שמאפשר את תקשורת הנתונים החוצה.
  6. סביר שתרצו לאפשר גם לעובדים במשרד לגשת לחלקים מהמערכת, ולכך יש שירותי VPN. אם אתם רוצים לאפשר גישה מה VPN ל Web Server, יהיה עליכם להגדיר כלל נוסף שמאפשר ל subnet של ה Web Server לקבל תקשורת מה VPC Gateway.
  7. הזכרנו שהמוטיבציה העיקרית ל VPC היא אבטחה. עוד שירות חשוב של אמזון הוא ה VPC Flow Logs.
    זהו שירות המאפשר לקבל לוגים על כל התעבורה אל ומחוץ ל VPC.
    ישנם שירותי צד-שלישי (כמו Observe Networks, Dome9, SumoLogic, ועוד) שישמחו לאסוף עבורכם את הלוגים הללו, לנתח אותם, להציג ב Dashboard יפה – ואף לנסות ולאתר אנומליות.

עוד כמה פרטים אחרונים

VPN

ניתן לאפשר ערוץ תעבורה בין המשרד, או כל רשת אחרת ל VPC שלכם על גבי VPN. הרכיב באמזון שמאפשר זאת הוא ה VPN Gateway (בקיצור: VGW, נקרא גם Virtual Private Gateway) היודע לעבוד עם פרוטוקול IPSec VPN.

כל חיבור VPN כולל 2 IPSec Tunnels (ערוצים מוצפנים), כך שאם ערוץ אחד כשל, פרוטוקול ה BGP (קיצור של Border Gateway Protocol) ינתב את התעבורה דרך הערוץ השני. ניתן כמובן להגדיר יותר מ VPN Gateway  – וכך לאפשר יתירות של ארבעה Tunnels ויותר.

AWS Direct Connect

AWS Direct Connect הוא שירות של אמזון לחיבור רשת משופר (קווים שאמזון שוכרת לצורך זה, ככל הנראה) בין VPCs ב Regions שונים לרשת של הארגון שלכם. אם יש יש לכם תעבורה משמעותית בין הרשתות – השירות הזה עשוי להפחית עלויות, לשפר latency ולשפר את האבטחה.

התקשורת ב AWS Direct Connect מבודדת ע”י פרוטוקול VLAN – כך שהיא לא תערבב עם תקשורת של VPCs אחרים.

גם בשימוש ב Direct Connect, ניתן להגדיר Tunnels של VPN כ fallback, במידה וה Direct Connect כושל (בעזרת פרוטוקול BGP).

VPC Peering

זוהי היכולת המאפשרת לחבר בין שני VPCs, בהסכמה הדדית, ובצורה קלה ויעילה. את התעבורה שמגיעה מ VPC אחר ניתן עדיין להעביר דרך Firewall או WAF – במידת הצורך.
ניתן בפועל להשתמש גם ב VPN על מנת לתקשר בין 2 VPCs, אם כי VPC Peering עושה זאת בצורה פשוטה הרבה יותר – ובטוחה באותה המידה.

VPC Endpoint

מאפשר להגדיר ערוץ תקשורת פרטי בין ה VPC לשירות של אמזון (ולא דרך הרשת הכללית של ה Data Center).
כרגע השירות היחידי שתומך ביכולת זו הוא S3 – אך עוד שירותים יתווספו בעתיד.

בכדי להשלים את התמונה, ב S3 Bucket ניתן להגדיר (בעזרת Policy) שיסכים לקבל קריאות רק מתוך VPC endpoint מסוים (ע”פ id) – וכך גם לוודא שלא בטעות פניתם ל Bucket שלא דרך הערוץ המאובטח.

סיכום

Virtual Private Cloud היא במידה מסוימת יכולת “לא סקסית” של AWS – אך חשובה מאוד.
לפני כמה שנים דובר כמה ארגונים חוששים, משיקולי אבטחה, לעבור לענן. ראיתי תצורות רשת של כמה חברות גדולות. רובן היו פרימיטיביות יותר ממה שניתן להשיג בעזרת VPC במאמץ סביר. למשל: לחלק כל שירות ל subnet ולהגביל את סוג התקשורת הנכנסת + היוצאת? מבחינת אבטחה – זה נהדר!  בד”כ ארגונים מספקים רמת שליטה שכזו רק על כל ה Data Center או רק בסיסי הנתונים (כולם, כמקשה אחת).

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

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

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

AWS re:Invent 2015 | (ARC403) From One to Many: Evolving VPC Design

SDD422) Amazon VPC Deep Dive)

25 טיפים להגדרת VPC

[א] מהו VLAN – אפשר לקרוא הסבר קצר בפוסט שפירסמתי על OpenStack.

[ב] 4 בדצמבר 2013, לדקדקנים שביננו.

על DevOps וה DevOps toolkit

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

  • מפתחים אחראים לכתוב קוד
  • איש ה UX אחראי לעצב את חווית השימוש
  • ה DBA מתמחה ב Database Systems
  • ה QA בודק את המערכת
  • איש ה Operations אחראי להתקין את התוכנה ולנטר אותה
  • וכו’…

באופן טבעי, הושתת ניגוד-אינטרסים מובנה בין חלק מבעלי התפקידים:
  • איש ה 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 של משתשמש (שאנחנו סיפקנו) בכדי לנסות ולאתר מדוע שימוש מסוים גורר בעיות – וכו’.

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 במגוון קטגוריות

AWS: “השירותים הפשוטים” של אמזון – חלק ב’, וארכיטקטורה מונחית-אירועים

בפוסט הקודם כיסינו שני “שירותים אפליקטיביים” בסיסיים של AWS: שירות ההודעות SNS, ושירות התורים SQS.
בפוסט הזה נמשיך את הסקירה ונכסה את שירות ה Workflows שנקרא SWF – שירות שימושי, אך קצת פחות מוכר.

Simple WorkFlow Service (בקיצור SWF)

SWF בא לפתור לנו כמה בעיות שלא נפתרות ב SQS או SNS. למשל:

  • נניח שיש לי סדרה של הודעות בין שירותים הקריטיות לביזנס, שעלינו לוודא שכולן טופלו בהצלחה + לדעת מתי כולן הסתיימו.
    כיצד מתמודדים עם משהו שכזה בעזרת SQS? מחזיקים הודעות אימות ואז סורקים אותן כל כמה זמן?! – לא יעיל.
  • נניח שיש לי מקביליות-חלקית ברצף של הודעות שבהן ארצה לטפל: חלק מההודעות עלי לשלוח בזו אחר זו, אבל חלק ניתן לשלוח במקביל – ולקצר את התהליך.
    כאשר אני שולח הודעות ב SNS או SQS  אין לי שליטה מה קורה איתן, ובטח שאינני יכול לתזמן את הטיפול בין הודעות שונות….
הפתרון הפשוט לבעיה זו הוא לנהל רצפי-הודעות שכאלה בצורה ריכוזית של תקשורת “הודעה-תשובה” בקוד של שירות כלשהו. למשל שירות ‘A’:

  • שירות A שולח את הודעה 1 לטיפול ומחכה שתסתיים.
  • שירות A שולח את הודעות 2, 3, ו 4 לטיפול במקביל (משיקולי ביצועים). הוא מממש Pattern של Monitor – שנותן אות ברגע שהטיפול בשלושת ההודעות הסתיים.
  • שירות A שולח את הודעה 4 לטיפול – והנה כאן ה”טיפול המיוחד” מסתיים.

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

לצורך כך צמחו שירותים נוסח SWF או IronWorker, שמספקים תשתית אמינה, יעילה, ובדוקה היטב לטפל בקלות ברצפים כאלו של הודעות, מה שנקרא גם “Workflows”.

רגע של תיאוריה

ישנו סגנון ארכיטקטוני שנקרא Event-Driven Architecture (ארכיטקטורה מונחית-אירועים, להלן EDA).

לכאורה, כל פתרון בו יש הודעות א-סינכרוניות – יכול להיחשב “סוג של EDA”: כל אפליקציית UI או קוד ג’אווהסקריפט
בפועל, החכמה ב EDA היא לא עצם השימוש בהודעות / תקשורת א-סינכרונית, אלא בארגון שלהן.

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

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

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

  • Broker – מתווך ביניים שיוצר decoupling בין שולח ההודעה, ובין המקבל שלה, אך עושה זאת בתצורה של “הודעה-תשובה”.
  • Message Broker – שהוא כמו Broker, אבל עובד בתצורה של “שגר ושכח”
  • Publisher-Subscriber, תצורה של Message Broker עם Fan Out, כלומר: שליחת הודעה אחת וקבלה שלה ע”י כמה נמענים (נוסח SNS של אמזון).
  • Message Queue – נוסח SQS של אמזון.
  • ועוד ועוד…
מכיוון שיש הרבה סוגי אינטראקציה אפשריים, ועל כל אחד ניתן לעשות כמה וריאציות, ההמלצה היא קודם כל לחשוב ב “טופולוגיות” ורק אז לבחור את סוגי האינטרציה. קיימות 2 טופלוגיות מרכזיות:
  • Broker Topology – שליחה וטיפול בהודעות בודדות ובלתי-תלויות.
    כל הודעה עומדת בפני עצמה, והמערכת שלנו היא כמו “כוורת דבורים” של שליחת הודעות וטיפול בהודעות – ש”זורמות מעצמן”, ללא ניהול מרכזי.
  • Mediator Topology – ההודעות, או לפחות חלק מהן, אינן זורמות באופן עצמאי – אלא מנוהלות במסגרת מקומית מסוימת.
    למשל: יש לנו בכוורת כמה “דבורים סמליות (sergeant)” שמנהלות בצורה אקטיבית כמה תהליכים שהוגדרו כמורכבים או קריטיים במיוחד. ה Mediator הוא בעצם סוג של Workflow Engine. הנה דוגמה:
טופולוגיה של Broker. מקור – Mark Richards
בתרשים למעלה מתוארת טופולוגית Mediator. בתחתית התרשים אנו יכולים לראות שירותים שונים (Processors) שיודעים לטפל בהודעות. הם יכולים לעבוד בכמה תצורות שונות, למשל: בתצורה בה שולחים הודעה ומספקים כתובת (queue אחר, בד”כ) לשלוח אליו את ההודעות שטופלו (במידה וזקוקים לתשובה).
ה Mediator מנהל עשרות תורים קטנים (בשם Channels, למעלה), כאשר כל תור מתאר instance של Workflow בהרצה. ה Mediator מחזיק State Machine המאתר את ה Workflow. בכל שלב הוא שולח הודעות א-סינכרוניות (בד”כ) ל Processors הנכונים (בתרשים למטה לכל processor יש תור), וברגע שטיפול בהודעה הסתיים, הוא עובר שלב ב State machine, וכך יודע מה ההודעה הבאה שעליו לשלוח – עד סיום ה Workflow.
—את ה Mediator (= דפוס עיצוב) ניתן לממש לבד בקוד. שירות SWF הוא מעין “תשתית” שמאפשרת ליישם Mediator בצורה קלה ואמינה יותר.

הערה: SWF הוא לא חדשני. יש הרבה Frameworks לניהול Workflows (שמות נרדפים הם Process Integration, EAI, וכו’), ותיקים ומשוכללים בהרבה. כמו ששמו מעיד עליו: הוא שירות פשוט ובסיסי למדי, אבל שיכול לספק אמינות גבוהה ואינטגרציה טובה לסביבת אמזון.

ניתן לתאר את עיקר התכונות של SWF באופן הבא:

  • שירות מבוזר, אמין, highly scalable, המנוהל כשירות.
  • השירות מספק בעיקר כלי ניהול והרצה של ה workflow – קרי Mediator.
    את ה activities – יהיה עליכם לממש לבד (בג’אווה, רובי, וכו’) ולעשות deploy של הקוד על מכונות EC2 שבבעלותכם או אפילו מכונה מרוחקת (לא על AWS). מה ש SWF עושה הוא לקרוא לקוד שלכם ברגעים הנכונים, אבל הלוגיקה – היא בבעלותכם.
  • ניתן לשלב בצעדי ה Workflow קריאה לשירותים שלא רצות בענן (למשל: אפליקציות on-premises) או פעולות אנושיות (למשל: אישור או דחיה של בקשה).
  • ה workflow יכול לחיות עד כשנה (ניתן להגדיר retention period משלכם לכל workflow), לאחר מכן – אמזון תמחק אותו.
  • את ה workflow מנהלים בתוך domains, שלרוב נקצה אחד כזה לכל אפליקציה (לצורך ארגון והפרדה).
    • כל domain יכול להכיל מספר workflows.
    • workflow מדומיין A מנוע מלתקשר עם workflow מדומיין B.
  • ה state של ה Workflow execution, נשמר במקום אמין במיוחד (S3?) שמבטיח שלא סביר [א] שהוא יאבד.

השחקנים העקריים ב Workflow של SWF הם:

  • Activity Worker – הוא מי שמבצע את ה Activity. לפעמים זה יהיה חישוב פשוט, ולעתים – delegation של העבודה לחלק אחר של תוכנה, או לאדם שייקח החלטה.
  • Decider – לוקח החלטה מה לעשות ברגע ש Activity יחיד ב Workflow הסתיים – כלומר, מה השלב הבא ב workflow. המימוש הוא לרוב סט חוקים פשוט או State Machine.
הקוד שמפעיל את ה workflow נקרא Workflow Starter.
דוגמה ל workflow פשוט של עיבוד תמונה: מתאימים לה את הגודל, מוסיפים כיתוב (watermark) ושולחים הודעה שהתמונה מוכנה.

הערה קטנה של מינוחים:

start_to_close_timeout – הוא פרמטר של workflow או activity, שלאוזן ישראלית ממוצעת עלול להישמע כמו “מתי מתחילים לסגור את העניינים” 🙂
בפועל מדברים על timeout נוקשה, שיעצור את ה activity/worfklow אם מרגע התחלת הפעולה (start) עד סופה (close) – היא לא הסתיימה.

באופן דומה יש timeout שנקרא schedule_to_start, שמגביל את הזמן בו workflow יכול להמתין לפני שהוא מתחיל להיות בכלל מטופל (כלומר: להמתין ב Queue לתחילת טיפול).

בתיעוד של אמזון, ניתן למצוא תיעוד ברור על קונספטים מתקדמים יותר של שירות ה SWF, כגון: markers, signals, tags ו child workflows.

בקיצור רב (רק בכדי לקבל מושג):

  • Signals מאפשרים לעדכן את ה workflow בשינוי state מעניין שהתרחש – מאז שה workflow החל לפעול.
  • tags – מאפשרים לתייג, לצורך חיפוש עתידי ב workflow history , אחר מצבים מיוחדים שה workflow הגיע אליהם.
  • Markers – מידע (או state) נוסף שה Deciders יכולים לשמור על ה workflow – לצורך ביצוע החלטות עתידיות.
  • Child Workflow – צעד בודד ב workflow, פותח workflow משל עצמו. הצעד ב workflow מסתיים כאשר ה child workflow הסתיים. הגיוני.
שיהיה בהצלחה!

—-

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

Webinar: Introduction to Amazon SWF

AWS in Plain English – הצעה לשמות טובים יותר לשירותים של AWS + הסבר קצר על כל שירות. אהבתי (!) אם כי דווקא ההסבר על SWF הוא לא כ”כ מוצלח לטעמי (הייתי פשוט קורא לו “Workflow Service”).

[א] “לא סביר” הוא עדיין אפשרי, כמובן.
“חוק מרפי-בענן” גורס: “כל מה שעלול להיכשל – אכן ייכשל: בסוף השבוע, בחצות, ובשיא העומס”.