חדש: קונטיינרים

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

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

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

מטרות

  1. אפליקציית "hello world" פשוטה עם כמה שירותים.
  2. מריצים את האפליקציה מקוד המקור.
  3. העברת האפליקציה לקונטיינר.
  4. יוצרים אשכול Kubernetes.
  5. פורסים את הקונטיינרים באשכול.

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

כדי להפעיל את Kubernetes Engine API:
  1. נכנסים לדף Kubernetes Engine במסוף Cloud de Confiance .
  2. יוצרים או בוחרים פרויקט.
  3. מחכים עד שממשק ה-API והשירותים הקשורים יופעלו. הפעולה עשויה להימשך כמה דקות.
  4. מוודאים שהחיוב מופעל בפרויקט ב- Cloud de Confiance .

הכנת Cloud Shell

במדריך הזה משתמשים ב-Cloud Shell, שמקצה מכונה וירטואלית (VM) מסוג g1-small Compute Engine שמריצה מערכת הפעלה מבוססת-Debian Linux.

אלה היתרונות של שימוש ב-Cloud Shell:

  • סביבת פיתוח של Python 3 (כולל virtualenv) מוגדרת במלואה.
  • כלי שורת הפקודה gcloud,‏ docker,‏ git ו-kubectl שמשמשים במדריך הזה כבר מותקנים.
  • אתם יכולים לבחור מבין כלי עריכת הטקסט המובנים:

    • Cloud Shell Editor, שאליו נכנסים בלחיצה על Open Editor בחלק העליון של החלון של Cloud Shell.

    • ‫Emacs,‏ Vim או Nano, שאליהם ניגשים משורת הפקודה ב-Cloud Shell.

מפעילים את Cloud Shell במסוף Cloud de Confiance .

הפעלת Cloud Shell

בחלק התחתון של מסוף Cloud de Confiance יתחיל סשן של Cloud Shell ותופיע הודעה של שורת הפקודה. Cloud Shell היא סביבת מעטפת שבה ה-CLI של Google Cloud מותקן ומוגדרים ערכים לפרויקט הקיים. הסשן יופעל תוך כמה שניות.

הורדת הקוד לדוגמה

  1. מורידים את קוד המקור של helloserver:

    git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
    
  2. עוברים לספרייה של הקוד לדוגמה:

    cd anthos-service-mesh-samples/docs/helloserver
    

הכרת האפליקציה עם כמה שירותים

אפליקציית הדוגמה כתובה ב-Python. הוא כולל את הרכיבים הבאים, שמתקשרים באמצעות REST:

  • ‫server: שרת בסיסי עם נקודת קצה (endpoint) אחת של GET, ‏/ , שמדפיס את הטקסט "hello world" בחלון הטרמינל.
  • ‫loadgen: סקריפט ששולח תנועה אל server, עם מספר בקשות לשנייה (RPS) שאפשר להגדיר.

אפליקציה לדוגמה

הפעלת האפליקציה מקוד המקור

כדי להכיר את האפליקציה לדוגמה, מריצים אותה ב-Cloud Shell:

  1. מהספרייה sample-apps/helloserver, מריצים את server:

    python3 server/server.py
    

    בזמן ההפעלה, ב-server מוצגים הנתונים הבאים:

    INFO:root:Starting server...
    
  2. פותחים חלון טרמינל נוסף כדי לשלוח בקשות אל server. כדי לעשות את זה ב-Cloud Shell, לוחצים על Open a new tab כדי לפתוח סשן נוסף.

  3. בחלון הטרמינל החדש, שולחים בקשה אל server:

    curl http://localhost:8080
    

    הפלט של server הוא:

    Hello World!
    
  4. באותה כרטיסייה, עוברים לספרייה שמכילה את הסקריפט loadgen:

    cd anthos-service-mesh-samples/docs/helloserver/loadgen
  5. יוצרים את משתני הסביבה הבאים:

    export SERVER_ADDR=http://localhost:8080
    export REQUESTS_PER_SECOND=5
    
  6. התחלה של virtualenv:

    virtualenv --python python3 env
    
  7. מפעילים את הסביבה הווירטואלית:

    source env/bin/activate
    
  8. מתקינים את הדרישות של loadgen:

    pip3 install -r requirements.txt
    
  9. מריצים את האפליקציה loadgen כדי ליצור תנועה עבור server:

    python3 loadgen.py
    

    בזמן ההפעלה, הפלט של loadgen אמור להיראות כך:

    Starting loadgen: 2024-10-11 09:49:51.798028
    5 request(s) complete to http://localhost:8080
    
  10. פותחים את חלון הטרמינל שבו פועל server. אמורה להופיע הודעה דומה לזו:

    127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
    INFO:root:GET request,
    Path: /
    Headers:
    Host: localhost:8080
    User-Agent: python-requests/2.32.3
    Accept-Encoding: gzip, deflate
    Accept: */*
    Connection: keep-alive
    

    מבחינת הרשת, כל האפליקציה פועלת עכשיו באותו מארח, מה שמאפשר להשתמש ב-localhost כדי לשלוח בקשות אל server.

  11. כדי להפסיק את loadgen ואת server, לוחצים על Ctrl-c בכל חלון של מסוף.

  12. בחלון הטרמינל של loadgen, משביתים את הסביבה הווירטואלית:

    deactivate
    

העברת האפליקציה לקונטיינר

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

כדי להכיל את האפליקציה בקונטיינר באמצעות Docker, צריך Dockerfile. Dockerfile הוא קובץ טקסט שמגדיר את הפקודות שדרושות כדי להרכיב את קוד המקור של האפליקציה ואת יחסי התלות שלה בקובץ אימג' של קונטיינר. אחרי שיוצרים את קובץ האימג', מעלים אותו ל-Container Registry, כמו Artifact Registry.

קוד המקור של המדריך הזה כולל Dockerfile גם ל-server וגם ל-loadgen, עם כל הפקודות שנדרשות כדי ליצור את קובצי האימג'. זהו ה-Dockerfile של ה-server:

FROM python:3.14-slim as base
FROM base as builder
RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        g++ \
    && rm -rf /var/lib/apt/lists/*

# Enable unbuffered logging
FROM base as final
ENV PYTHONUNBUFFERED=1

RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        wget

WORKDIR /helloserver

# Grab packages from builder
COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/

# Add the application
COPY . .

EXPOSE 8080
ENTRYPOINT [ "python", "server.py" ]

בקובץ הזה אפשר לראות את הפרטים הבאים:

  • ההוראה FROM python:3-slim as base אומרת ל-Docker להשתמש בתמונה העדכנית של Python 3 כתמונת הבסיס.
  • ההוראה COPY . . מעתיקה את קובצי המקור מספריית העבודה הנוכחית (במקרה הזה, server.py) למערכת הקבצים של הקונטיינר.
  • התג ENTRYPOINT מגדיר את ההוראה שמשמשת להפעלת הקונטיינר. בדוגמה הזו, ההוראה דומה לזו שבה השתמשתם כדי להריץ את server.py מקוד המקור.
  • ההוראה EXPOSE מציינת ש-server מאזין ליציאה 8080. ההוראה הזו לא חושפת יציאות, אלא משמשת כתיעוד לכך שצריך לפתוח את היציאה 8080 כשמריצים את הקונטיינר.

הכנה להעברת האפליקציה לקונטיינר

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

  1. מגדירים את פרויקט ברירת המחדל Cloud de Confiance ל-Google Cloud CLI.

    gcloud config set project PROJECT_ID
  2. מגדירים את האזור שמוגדר כברירת מחדל ב-Google Cloud CLI.

    gcloud config set compute/region us-central1
    

יצירת המאגר

כדי ליצור מאגר חדש לקובצי אימג' של קונטיינרים של Docker ב-Artifact Registry:

  1. מוודאים שהשירות Artifact Registry מופעל בפרויקט ב-Cloud de Confiance .

    gcloud services enable artifactregistry.googleapis.com
    
    
  2. יוצרים את המאגר ב-Artifact Registry:

    gcloud artifacts repositories create container-intro --repository-format=docker \
        --location=us-central1 \
        --description="My new Docker repository"
    
  3. מגדירים אימות מ-Docker ל-Artifact Registry באמצעות Google Cloud CLI:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

הכנסת server לקונטיינר

עכשיו הגיע הזמן להכיל את האפליקציה בקונטיינר. קודם צריך להכניס את התוכנה hello world server לקונטיינר ולהעביר את קובץ האימג' בדחיפה אל Artifact Registry:

  1. עוברים לספרייה שבה נמצאת הדוגמה server:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. יוצרים את קובץ האימג' באמצעות Dockerfile:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
    
    • מחליפים את PROJECT_ID במזהה הפרויקט ב- Cloud de Confiance by S3NS .

    הדגל -t מייצג את התג של Docker. זה השם של קובץ האימג' שבו משתמשים כשפורסים את הקונטיינר.

  3. מעבירים את קובץ האימג' ל-Artifact Registry:

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

הכנסת loadgen לקונטיינר

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

  1. עוברים לספרייה שבה נמצאת הדוגמה של loadgen:

    cd ../loadgen
    
  2. יצירת התמונה:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
    
  3. מעבירים את קובץ האימג' ל-Artifact Registry:

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

רשימת התמונות

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

gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro

הפלט צריך לכלול את שמות התמונות שדחפתם, בדומה לזה:

NAME
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen

יצירת אשכול GKE

בשלב הזה, אפשר פשוט להריץ את הקונטיינרים במכונה הווירטואלית של Cloud Shell באמצעות הפקודה docker run. עם זאת, כדי להריץ עומסי עבודה מהימנים בסביבת הייצור, צריך לנהל את הקונטיינרים בצורה אחידה יותר. לדוגמה, צריך לוודא שהקונטיינרים מופעלים מחדש אם הם נכשלים, וצריך דרך להרחיב אנכית בהתאם לעומס (scale up) ולהפעיל מכונות נוספות של קונטיינר כדי לטפל בעלייה בתנועה.

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

כדי להריץ את הקונטיינרים ב-GKE, קודם צריך ליצור אשכול ואז להתחבר אליו:

  1. יוצרים את האשכול:

    gcloud container clusters create-auto container-intro
    

    הפקודה gcloud יוצרת אשכול בפרויקט ובאזור שמוגדרים כברירת מחדל Cloud de Confiance .

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

     NAME: container-intro
     LOCATION: us-central1
     MASTER_VERSION: 1.30.4-gke.1348000
     MASTER_IP: 34.44.14.166
     MACHINE_TYPE: e2-small
     NODE_VERSION: 1.30.4-gke.1348000
     NUM_NODES: 3
     STATUS: RUNNING
    
  2. כדי להשתמש בכלי שורת הפקודה kubectl לניהול האשכול, צריך לספק לו את פרטי הכניסה:

    gcloud container clusters get-credentials container-intro
    

בדיקת מניפסטים של Kubernetes

כשמריצים את האפליקציה מקוד המקור, משתמשים בפקודה אימפרטיבית: python3 server.py

ציווי פירושו פועל: "עשה זאת".

לעומת זאת, Kubernetes פועל לפי מודל הצהרתי. כלומר, במקום להורות ל-Kubernetes בדיוק מה לעשות, אתם מספקים ל-Kubernetes את המצב הרצוי. לדוגמה, Kubernetes מפעיל ומפסיק Pods לפי הצורך, כדי שמצב המערכת בפועל יתאים למצב הרצוי.

אתם מציינים את המצב הרצוי בקובץ שנקרא מניפסט. קובצי מניפסט נכתבים בשפות כמו YAML או JSON, והם מכילים את המפרט של אובייקט Kubernetes אחד או יותר.

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

בתרשים הבא מוצגת האפליקציה שפועלת ב-GKE:

אפליקציה בקונטיינר שפועלת ב-GKE

מידע נוסף על Pods,‏ Deployments ו-Services זמין במאמר תחילת הלמידה על Kubernetes או במקורות המידע שבסוף הדף הזה.

שרת

קודם כול, בודקים את קובץ המניפסט של Hello World server:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloserver
  template:
    metadata:
      labels:
        app: helloserver
    spec:
      containers:
      - image: gcr.io/google-samples/istio/helloserver:v0.0.1
        imagePullPolicy: Always
        name: main
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

המניפסט הזה מכיל את השדות הבאים:

  • ‫kind מציין את סוג האובייקט.
  • ‫metadata.name מציין את שם הפריסה.
  • השדה הראשון spec מכיל תיאור של המצב הרצוי.
  • ‫spec.replicas מציין את מספר ה-Pods הרצוי.
  • בקטע spec.template מוגדרת תבנית של Pod. השדה image כלול במפרט של ה-Pods, והוא השם של התמונה שצריך לשלוף מ-Artifact Registry. בשלב הבא, תעדכנו את התמונה לתמונה החדשה שיצרתם.

השירות hellosvc מוגדר באופן הבא:

apiVersion: v1
kind: Service
metadata:
  name: hellosvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: helloserver
  type: LoadBalancer
  • ‫LoadBalancer: לקוחות שולחים בקשות לכתובת ה-IP של מאזן עומסי רשת, שיש לו כתובת IP יציבה וניתן להגיע אליו מחוץ לאשכול.
  • ‫targetPort: זכרו שהפקודה EXPOSE 8080 ב-Dockerfile לא באמת חושפת יציאות. אתם חושפים את יציאה 8080 כדי שתוכלו להגיע למאגר server מחוץ לאשכול. במקרה הזה, hellosvc.default.cluster.local:80 (שם מקוצר: hellosvc) ממפה ליציאה 8080 של כתובת ה-IP של Pod helloserver.
  • ‫port: זהו מספר היציאה שבו משתמשים שירותים אחרים באשכול כששולחים בקשות.

מחולל עומסים

האובייקט Deployment ב-loadgen.yaml דומה ל-server.yaml. הבדל בולט הוא שמפרט ה-Pod של פריסת loadgen כולל שדה בשם env. בקטע הזה מוגדרים משתני הסביבה שנדרשים ל-loadgen, שהגדרתם קודם כשהפעלתם את האפליקציה מהמקור.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: loadgenerator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: loadgenerator
  template:
    metadata:
      labels:
        app: loadgenerator
    spec:
      containers:
      - env:
        - name: SERVER_ADDR
          value: http://hellosvc:80/
        - name: REQUESTS_PER_SECOND
          value: '10'
        image: gcr.io/google-samples/istio/loadgen:v0.0.1
        imagePullPolicy: Always
        name: main
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 300m
            memory: 256Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

מכיוון שה-loadgen לא מקבל בקשות נכנסות, השדה type מוגדר ל-ClusterIP. סוג השירות הזה מספק כתובת IP יציבה שישויות באשכול יכולות להשתמש בה, אבל כתובת ה-IP לא חשופה ללקוחות חיצוניים.

apiVersion: v1
kind: Service
metadata:
  name: loadgensvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: loadgenerator
  type: ClusterIP

פריסת הקונטיינרים ב-GKE

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

פריסת server

  1. עוברים לספרייה שבה נמצאת הדוגמה של server:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. פותחים את הקובץ server.yaml ב-Cloud Shell Editor (או בכלי לעריכת טקסט שאתם מעדיפים).

  3. מחליפים את השם בשדה image בשם של קובץ אימג' של Docker.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

    מחליפים את PROJECT_ID במזהה הפרויקט ב- Cloud de Confiance .

    • אם אתם משתמשים בעורך של Cloud Shell, הקובץ נשמר באופן אוטומטי. כדי לחזור לחלון הטרמינל, לוחצים על Open terminal (פתיחת הטרמינל).
    • אם משתמשים בכלי לעריכת טקסט ב-Cloud Shell, שומרים וסוגרים את server.yaml.
  4. פורסים את המניפסט ב-Kubernetes:

    kubectl apply -f server.yaml
    

    הפלט אמור להיראות כך:

    deployment.apps/helloserver created
    service/hellosvc created
    

פריסת loadgen

  1. עוברים לספרייה שבה נמצא loadgen.

    cd ../loadgen
    
  2. פותחים את loadgen.yaml בכלי לעריכת טקסט, כמו קודם.

  3. שוב, מחליפים את השם בשדה image בשם של קובץ אימג' של Docker.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

    מחליפים את PROJECT_ID במזהה הפרויקט ב- Cloud de Confiance .

    • אם אתם משתמשים ב-Cloud Shell Editor, הקובץ נשמר אוטומטית. כדי לחזור לחלון הטרמינל, לוחצים על Open terminal (פתיחת הטרמינל).
    • אם משתמשים בכלי לעריכת טקסט ב-Cloud Shell, שומרים וסוגרים את loadgen.yaml.
  4. פורסים את המניפסט באשכול:

    kubectl apply -f loadgen.yaml
    

    אם הפקודה מסתיימת ללא שגיאות, התגובה תהיה:

    deployment.apps/loadgenerator created
    service/loadgensvc created
    

אימות הפריסה

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

  1. בודקים את הסטטוס של ה-Pods באשכול:

    kubectl get pods
    

    התגובה של הפקודה תכלול את הסטטוס, כמו בדוגמה הבאה:

    NAME                             READY   STATUS    RESTARTS   AGE
    helloserver-69b9576d96-mwtcj     1/1     Running   0          58s
    loadgenerator-774dbc46fb-gpbrz   1/1     Running   0          57s
    
  2. מקבלים את יומני האפליקציה מ-Pod‏ loadgen. מחליפים את POD_ID במזהה של ה-Pod של מחולל העומסים מהפלט הקודם.

    kubectl logs POD_ID
    
  3. מקבלים את כתובות ה-IP החיצוניות של hellosvc:

    kubectl get service hellosvc
    

    הפלט אמור להיראות כך:

    NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
    
  4. שליחת בקשה אל hellosvc. מחליפים את EXTERNAL_IP בכתובת ה-IP החיצונית של hellosvc.

    curl http://EXTERNAL_IP
    

    ההודעה "Hello World!‎" אמורה להופיע מהשרת.

הסרת המשאבים

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

אם לא רוצים למחוק את הפרויקט כולו:

  • מוחקים את אשכול ה-GKE. כשמוחקים את האשכול, נמחקים כל המשאבים שמרכיבים אותו, כמו מכונות Compute Engine, דיסקים ומשאבי רשת.

     gcloud container clusters delete container-intro
    
  • מוחקים את המאגר ב-Artifact Registry:

     gcloud artifacts repositories delete container-intro --location=us-central1
    

המאמרים הבאים