פרויקט DevOps: התוכנית

בפרויקט הזה בונים delivery pipeline ל‑web API קטן:

  • CRUD API ב‑Python, ב‑GitHub repository משלו;
  • pipeline של GitHub Actions:
    • push ל‑branch שלכם מריץ את ה‑tests המהירים;
    • pull request מריץ יותר: integration tests, וכלי אבטחה ובחינת קוד;
    • pull request מחכה למאשר לפני שאפשר לעשות לו merge;
    • merge ל‑main בונה container image ומעלה אותו;
  • deployment ב‑AWS: EKS cluster, או קבוצת EC2 instances.

ה‑pipeline המוגמר בפעולה, אירוע אחר אירוע: The Pipeline, Step by Step (באנגלית).

המסלולים

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

ה‑framework של ה‑API

  • Flask: המסלול הבסיסי.
    • כל request מריץ function רגילה, מההתחלה ועד הסוף, ב‑worker משלו.
    • מספיק Python רגיל.
  • FastAPI: המסלול המתקדם.
    • הוא בודק כל request מול types מוצהרים, ומייצר מהם דף OpenAPI.
    • הוא בנוי על asyncio: route יכול להיות async def, שרץ על ה‑event loop היחיד של השרת.
      • await מעביר את ה‑loop ל‑request אחר בזמן שה‑request הזה מחכה.
      • קריאה חוסמת בתוך async def (‏time.sleep, או driver סינכרוני ל‑database) עוצרת את כל ה‑requests.
    • בחרו בו אם אתם מכירים async/await ואת ה‑event loop, או רוצים ללמוד אותם בדרך.

היעד של ה‑deployment

  • EKS: המסלול הראשי.
    • Kubernetes cluster: ה‑deployment הוא Deployment ו‑Service, כמו שרוב הצוותים מעלים containers.
    • הוא עולה כסף מהרגע שהוא קיים, בין אם האפליקציה רצה ובין אם לא.
    • אם יוצרים אותו בתחילת כל מפגש עבודה ומוחקים בסופו, הוא עולה בערך $13–$37 בסך הכול ל‑20–30 שעות בחודש, לאורך 2–4 חודשים: החישוב נמצא במשימה 5.
    • אם משאירים אותו רץ, הוא עולה בערך $200 בחודש.
  • EC2: קבוצת instances שמריצים את ה‑container, למי שמוצא את EKS קשה מדי.
    • פחות חלקים ללמוד, ומשלמים רק על ה‑instances ועל ה‑load balancer.
    • ה‑deploy הוא script שלכם, במקום ה‑rollouts וה‑health checks ש‑EKS נותן.

בשני היעדים האפליקציה רצה ב‑container.

עבודה לבד או בזוג

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

  • בשני המקרים, הדרך שבה שינויים מגיעים ל‑main משתנה במשימה 3:
    • משימות 1–2: עושים push ישר ל‑main. שום דבר עוד לא מגן עליו, וכך הכי קל לראות את ה‑pipeline הריק.
    • ממשימה 3 והלאה: main מוגן. כל שינוי נעשה ב‑branch משלו, דרך pull request, ועובר merge רק אחרי שה‑checks שלו עוברים והוא מאושר.
  • ההבדל הוא מי מאשר.
  • בכל מקרה, כל branch נקרא לפי שיטת שמות אחת: ראו Topic branches.
לבד
  • כל issue משויך אליכם, וכל branch הוא שלכם.
  • המאשר הוא pr-reviewer, ה‑GitHub App: הוא ממלא את מקומו של האדם השני.
    • הוא מאשר אחרי סבב אחד של בקשת שינויים, ולעולם לא קורא את הקוד.
    • ה‑review הוא פורמליות; ה‑checks הם מה שעוצר שינוי שבור.
  • AWS: החשבון שלכם.
בזוג
  • repository אחד: סטודנט אחד יוצר אותו, ומוסיף את השני כ‑collaborator עם הרשאת write.
  • כל משימה ביחד, ושני המסלולים משותפים: בוחרים Flask או FastAPI, ו‑EKS או EC2, פעם אחת לזוג.
  • כל issue משויך לאחד מכם: מי שהוא משויך אליו הוא בעל ה‑branch שלו, כך ששניכם יודעים של מי כל branch.
  • הסטודנט השני מאשר: GitHub לא מאפשר לכותב של pull request לאשר אותו.
    • קראו את השינוי לפני שאתם מאשרים: זה ה‑review ש‑pr-reviewer רק מחקה.
    • התחלפו: אחד כותב את השינוי של משימה, השני עושה לו review, ובמשימה הבאה מתחלפים.
    • pr-reviewer מותקן גם כאן במשימה 3, כך שה‑pipeline זהה לעבודה לבד; כל אחד מהאישורים מספיק ל‑merge.
  • אחרי משימה 3, לעולם לא עושים push ישר ל‑main, גם לא כדי לתקן טעות של השני: פותחים pull request.
  • חשבון AWS אחד, של בעל ה‑repository. ה‑pipeline עושה deploy עם ה‑role שלו, כך שהסטודנט השני צריך גישה ל‑console רק כדי להסתכל: TODO: IAM user עם הרשאת קריאה בלבד, או IAM Identity Center.
  • מתחלקים בעלות של AWS: השעות של ה‑cluster הן השעות של הזוג, כך ש‑cluster אחד לא עולה יותר מאשר לבד.

Topic branches

כל שינוי מתחיל כ‑issue ב‑GitHub, וה‑branch שלו נקרא <type>/<issue>-<what>.

חלקמה הוא מכילדוגמה
type‏feature להתנהגות חדשה של ה‑API, ‏fix ל‑bug, ‏ci ל‑pipeline: ה‑workflows, ה‑Dockerfile, התשתיתfeature
issueהמספר של ה‑issue12
whatכמה מילים, באותיות קטנות, מחוברות במקפיםsearch-books
1$ git switch -c feature/12-search-books
2$ git push -u origin feature/12-search-books
  • המספר מקשר את הכול: ה‑branch נושא את מספר ה‑issue, בתיאור של ה‑pull request כתוב Closes #12, וה‑merge סוגר את ה‑issue.
  • ה‑type מקבץ את ה‑branches: רשימת ה‑branches של GitHub, והפילטר branches: של workflow, יכולים לבחור fix/**.
  • המילים אומרות מה זה בלי לפתוח את ה‑issue.
  • issue אחד, branch אחד, pull request אחד; ה‑branch נמחק אחרי ה‑merge.

ה‑pipeline המוגמר

The Pipeline, Step by Step מציג את כולו, אירוע אחר אירוע: push ל‑topic branch, pull request דרך ה‑checks וה‑review שלו, ה‑merge וה‑delivery, ו‑push ל‑main שנדחה.

אירועJobs
push ל‑branch שלכםlint, unit tests
pull request ל‑mainlint, unit tests, integration tests, אבטחה ובחינת קוד, בניית image; ואחריהם ה‑review של המאשר
merge ל‑mainבניית image ו‑push, deploy, smoke test

סדר המשימות

המשימות בונות קודם את כל ה‑pipeline, ואז ממלאות אותו.

  • משימות 1–3: ה‑pipeline, ריק.
    • כל job קיים ממשימה 2, כ‑placeholder שמדפיס מה הוא יעשה.
    • רואים כל אירוע מריץ את ה‑jobs שלו, ואת המאשר עוצר את ה‑merge, לפני שאיזשהו job עושה עבודה אמיתית.
  • משימות 4–6: הפתרון השלם הראשון.
    • ה‑placeholders של ה‑image ושל ה‑deployment נעשים אמיתיים.
    • merge ל‑main מעלה את האפליקציה ל‑AWS.
  • משימות 7–10: הפרטים.
    • כל משימה מחליפה עוד placeholders, או מחמירה job שכבר עובד.
משימהפוסט
1האפליקציה וה‑repository שלה
2ה‑pipeline, ריק
3pull requests והמאשר
4ה‑container image
5התשתית ב‑AWS
6ה‑deployment הראשון
7tests בכל push
8ה‑checks של ה‑pull request
9אבטחה ובחינת קוד
10ה‑delivery לפרטיו
11ניקוי

לפני שמתחילים

  • חשבון GitHub.
  • חשבון AWS, ממשימה 5. התשתית עולה כסף כל זמן שהיא רצה; משימה 11 מסירה אותה.
  • חשבון Docker Hub, ממשימה 4.
  • Python 3.12 ומעלה, Docker ו‑git על המחשב שלכם.

החומרים האחרים באתר שמשמשים בדרך (באנגלית):

Translations: