העברת אפליקציית קונטיינר לענן - חלק א׳ (App Runner)

Published
העברת אפליקציית קונטיינר לענן - חלק א׳ (App Runner)

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

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

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

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

אנו נתחיל עם App Runner.

תרחיש השימוש

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

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

דמו

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

  1. אפליקציית האקספרס עצמה שנמצאת ב-index.mjs.

  2. טמפלייט ליצירת ECR שנמצא ב-template.yaml, האפליקציה שלנו מבוססת קונטיינר. אנו נעלה את הקונטיינר ל-ECR שאנו מייצרים. ECR הוא פתרון זהה ל-Docker Hub ומשמש לאותה מטרה בדיוק - Docker image registry.

  3. הגדרת הקונטיינר עצמו ב-Dockerfile.

התקנת הדמו

  1. צרו את ה-ECR באצעות הרצת הטמפלייט הזה.

  2. גשו לספריה legacy-app. והריצו מקומית את npm run aws:deploy , הפקודה מבצעת שלוש פעולות מאחורי הקלעים:

    1. בניית הקונטיינר מקומית על המכונה באמצעות docker build.

    2. , ביצוע אוטנטיקציה מול ה-ECR כדי שדוקר יוכל לדחוף את הקונטיינר ל-ECR.

    3. דחיפת הקונטיינר באמצעות docker push.

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

ניטור

אני מאמין מאוד גדול בניטור מערכות שרצות בענן ומראש צריך לאפות מנגנון ניטור בכל אפליקציה שאנו בונים. אנו משתמשים ב-Open Telemtry באפליקציית הדמו ומציגים את הטרייסים ואת הלוגים באמצעות CloudWatch Logs ו - Xray.

הוספתי Auto instrumention באמצעות @aws/aws-distro-opentelemetry-node-autoinstrumentation, כל מה שהיה צריך לעשות זה להוסיף את החבילה הנ״ל ולהוסיף פרמטר ריצה שיטען את החבילה לפני שהאפליקציה שלנו רצה, לדוגמא

1node --require @aws/aws-distro-opentelemetry-node-autoinstrumentation/register index.mjs

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

הדמו מוכן, כעת הגיע הזמן להבין מהו App Runner ולמה הוא משמש.

ברוך הבא App Runner

השירות App Runner מאפשר לקחת אפליקציית ווב סטנדרטית, כלומר שרת HTTP שמאזין על פורט מקומי, ובמספר צעדים פשוטים, לעלות אותו לענן של AWS ולהחצין אותו לעולם. App Runner הוא סוג של container orchestrator, כלומר הוא מנהל עבורכם את משך החיים של הקונטיינר, יודע מתי להרים, מתי להוריד, הוא גירסה פשוטה של ECS או EKS. בסופו של דבר יש ל-App Runner מספר יתרונות מרכזיים אשר מקלים על השימוש בו יחסית לפתרונות הנוספים של AWS:

  1. Continuous delivery אוטומטי - ניתן להגדיר שבשינוי קוד בגיט או שינוי הקונטיינר ב-ECR, השירות ידחף את השינוי לסביבת האפליקציה.

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

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

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

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

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

דגשים לשימוש

סקיילינג

מנגנון הסקיילינג של App Runner בנוי משלוש קונפיגורציות:

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

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

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

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

עלות

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

מעבד

זיכרון

0.25 vCPU

0.5 GB

0.25 vCPU

1 GB

0.5 vCPU

1 GB

1 vCPU

2 GB

1 vCPU

3 GB

1 vCPU

4 GB

2 vCPU

4 GB

2 vCPU

6 GB

4 vCPU

8 GB

4 vCPU

10 GB

4 vCPU

12 GB

עלות השימוש היא $0.064 לשעה לכל vCPU ו-$0.007 לשעה לכל ג׳גה זיכרון.

אז השימוש הכי זול של השירות הוא רבע vCPU וחצי ג׳גה שעולים $0.0195 לשעה או $0.468 ליום שלם. אבל ל-App Runner יש טריק שיכול להוזיל את העלויות משמעותית והוא תשלום חלקי על קונטיינרים שהם לא בשימוש.

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

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

הרשאות

השירות דורש שני roles שונים על מנת לתפקד:

  1. Access Role - הרשאות אשר מאפשרות לשירות עצמו לגשת להגדרת הדוקר ב-ECR.

  2. Instance Role - ההרשאות אשר ניתנות לקוד עצמו שכתבתם, לדוגמא במקרה שלנו, ניתן הרשאות לגשת לשירות הלמדה.

בחלק הבא אנחנו נרים את השירות שבנינו באמצעות App Runner.

הרצת הדמו באמצעות App Runner

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

הגדרת ההרשאות

1AppRunnerServiceRole:
2 Type: AWS::IAM::Role
3 Properties:
4 AssumeRolePolicyDocument:
5 Version: '2012-10-17'
6 Statement:
7 - Effect: Allow
8 Principal:
9 Service: build.apprunner.amazonaws.com
10 Action: 'sts:AssumeRole'
11 ManagedPolicyArns:
12 - 'arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess'
13
14 AppRunnerTaskRole:
15 Type: AWS::IAM::Role
16 Properties:
17 RoleName: AppRunnerLambdaListRole
18 AssumeRolePolicyDocument:
19 Version: '2012-10-17'
20 Statement:
21 - Effect: Allow
22 Principal:
23 Service: tasks.apprunner.amazonaws.com
24 Action: sts:AssumeRole
25 ManagedPolicyArns:
26 - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
27 Policies:
28 - PolicyName: LambdaListPolicy
29 PolicyDocument:
30 Version: '2012-10-17'
31 Statement:
32 - Effect: Allow
33 Action:
34 - lambda:ListFunctions
35 Resource: '*'
  • שורות 1-12: הגדרת ההרשאה שמשמשת למשיכת האימג׳ של הקונטיינר. שימו לב שזו הרשאה שניתנת לסרוויס של ה-App Runner, לא לאפליקציה שלכם

  • שורה 12 - ההרשאה הספיציפית.

  • שורות 14 - 35: הגדרת ההרשאות שניתנות לאפליקציה שלכם.

  • שורה 34 - ניתנת הרשאה בודדת לביצוע פעולת list על למדות.

הגדרת סקיילניג

1ListAppScaleConf:
2 Type: AWS::AppRunner::AutoScalingConfiguration
3 Properties:
4 AutoScalingConfigurationName: ListAppScaleConf
5 MaxConcurrency: 100
6 MaxSize: 10
7 MinSize: 1
8 Tags:
9 - Key: Name
10 Value: ListAppScaleConf

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

  • שורה 5 - הגדרת הסף, מעליו נוסיף עוד קונטיינר. הערך כאן הוא 100.

  • שורה 6 - מקסימום קונטיינרים שירוצו לכל היותר

  • שורה 7 - מינימום קונטיינרים שירוצו

תצורת ניטור

1ListAppObservabilityConf:
2 Type: AWS::AppRunner::ObservabilityConfiguration
3 Properties:
4 ObservabilityConfigurationName: ListAppObservabilityConf
5 TraceConfiguration:
6 Vendor: AWSXRAY

AWS תריץ deamon פנימי של xray במידה ונדליק את האופציה הזאת. שימו לב לשורה 6, הערך היחיד שמתקבל כאן הוא xray.

הגדרת השירות

1AppRunnerService:
2 Type: AWS::AppRunner::Service
3 Properties:
4 ServiceName: ListLambdas
5 SourceConfiguration:
6 AuthenticationConfiguration:
7 AccessRoleArn: !GetAtt AppRunnerServiceRole.Arn
8 AutoDeploymentsEnabled: true
9 ImageRepository:
10 ImageRepositoryType: ECR
11 ImageIdentifier:
12 Fn::Join:
13 - ':'
14 - - Fn::ImportValue:
15 Fn::Sub: '${ECRStackName}-RepositoryURI'
16 - 'latest'
17 ImageConfiguration:
18 Port: 3000
19
20 HealthCheckConfiguration:
21 Path: /health-check
22 Protocol: HTTP
23 HealthyThreshold: 3
24 UnhealthyThreshold: 3
25 Interval: 10
26 Timeout: 5
27 AutoScalingConfigurationArn: !GetAtt ListAppScaleConf.AutoScalingConfigurationArn
28 ObservabilityConfiguration:
29 ObservabilityEnabled: true
30 ObservabilityConfigurationArn: !GetAtt ListAppObservabilityConf.ObservabilityConfigurationArn
31 InstanceConfiguration:
32 Cpu: '0.25 vCPU'
33 Memory: '0.5 GB'
34 InstanceRoleArn: !GetAtt AppRunnerTaskRole.Arn

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

  • שורות 5 - 17 - מהיכן נלקח האימג׳ שמרכיב את השירות.

  • שורה 8 - יכולות ה-continues delivery, ברגע שהאימג׳ מתעדכן, App Runner יתפוס את השינוי וידחוף את השינוי לפרודקשן.

  • שורה 17 - מייחצת את פורט 3000 לעולם החיצון. כלומר כל בקשה שתגיע לשירות תופנה פנימית לפורט 3000. שימו לב שזה פורט שיוחצן כחלק מ-Dockerfile.

  • שורות 20 - 26 - שירות ה-App Runner מבצע בדיקות תקינות (health checks) ודוגם את השירות שלך כל פרק זמן מסוים. ישנן שתי סוגי בדיקות, מסוג http ומסוג tcp, במקרה של tcp הוא פשוט מבצע ping, במקרה של http הוא מבצע קריאת GET ומצפה לקבל 200. במידה והגדרתם בדיקה מסוג http, אחריותכם לנקודת קצה באפליקציה שאכן תחזיר תשובה.

  • שורות 31 - 33 - הגדרות של מעבד וזיכרון שמשמפיעות על העלות ועל חוזק המכונה.


על מנת להתקין את ה-CloudFormation אצלכם לחצו על הקישור הבא.

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

שם הסטאק של ה-ECR
שם הסטאק של ה-ECR

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

הקונסול

חפשו בשורת החיפוש App Runner ולחצו על האפשרות הראשונה. אמורה להופיע לכם רשימה של כל הסרוויסים שרצים באמצעות השירות. תחת העמודה Default domain תופיע הכתובת הפומבית של השירות, לחצו עליה והוסיפו לכתובת את המחרוזת /lambdas וראו את הפלא, אתם מקבלים חזרה את רשימת כל הלמדות שלכם.

כתובת השירות
כתובת השירות

ניטור

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

אחת הלשוניות היא לשונית הלוגים. ישנם שני סוגי לוגים:

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

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

לוגים אפליקטיביים
לוגים אפליקטיביים

ישנה לשונית נוספת את מציגה את המטריקות של השירות:

  1. מספר בקשות.

  2. כמות קונטיינרים רצים.

  3. ניצולת זכרון

  4. ועוד.

ולשונית נוספת אשר מפנה לטריסיים שנוצרו ב-xray.

קונפיגורציות נוספות

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

מחיקת הסרוויס

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

מחיקת הסטאק
מחיקת הסטאק

סיכום

בפוסט זה סקרנו את AWS App Runner, פתרון מצוין להעברת מערכות מבוססות קונטיינרים לענן בצורה פשוטה ומהירה. התמקדנו בהדגמה מעשית של הרצת אפליקציית Express פשוטה, הגדרת הרשאות, קונפיגורציות סקיילינג, ויכולות ניטור. ראינו את היתרונות המרכזיים של continuous delivery אוטומטי, חיבור פשוט לעולם החיצון, סקיילינג אוטומטי והאפשרות ליצור שירות פנימי בתוך ה-VPC. לסיכום, App Runner מהווה פתרון אידיאלי להרצת POC או שירותים קלים בענן, עם יחס עלות-תועלת מצוין עבור מערכות שאינן דורשות ארכיטקטורה מורכבת.

ביבליאוגרפיה

ניוזלטר

תגובות