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

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

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

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

מטרות

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

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

כדי להפעיל את Kubernetes Engine API:
  1. נכנסים ל דף Kubernetes Engine במסוף Google Cloud .
  2. יוצרים או בוחרים פרויקט.
  3. מחכים עד שממשק ה-API והשירותים הקשורים מופעלים. הפעולה יכולה להימשך כמה דקות.
  4. Verify that billing is enabled for your Google Cloud project.

הכנת Cloud Shell

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

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

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

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

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

In the Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

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

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

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

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

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

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

  • server: שרת בסיסי עם נקודת קצה אחת 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, לוחצים על פתיחת כרטיסייה חדשה כדי לפתוח סשן נוסף.

  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 הוא קובץ טקסט שמגדיר את הפקודות שדרושות כדי להרכיב את קוד המקור של האפליקציה ואת יחסי התלות שלה בקובץ אימג' של קונטיינר. אחרי שיוצרים את קובץ האימג', מעלים אותו למאגר קונטיינרים, כמו 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. מגדירים את פרויקט ברירת המחדל Google Cloud ל-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 מופעל בGoogle Cloud פרויקט.

    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

עכשיו הגיע הזמן להוסיף את האפליקציה למאגר. קודם צריך להכניס את server hello world לקונטיינר ולהעביר את קובץ האימג' בדחיפה ל-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 במזהה הפרויקט ב- Google Cloud .

    הדגל -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. עם זאת, כדי להפעיל עומסי עבודה מהימנים בסביבת ייצור, צריך לנהל את הקונטיינרים בצורה אחידה יותר. לדוגמה, צריך לוודא שהקונטיינרים יופעלו מחדש אם הם ייכשלו, וצריך דרך להגדיל את מספר המופעים של קונטיינר ולהפעיל מופעים נוספים כדי לטפל בעלייה בתנועה.

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

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

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

    gcloud container clusters create-auto container-intro
    

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

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

     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 או במשאבים בסוף הדף הזה.

שרת

קודם, בודקים את קובץ המניפסט של 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. המפרט של ה-Pods כולל את השדה image, שהוא השם של התמונה שצריך לשלוף מ-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: מספר היציאה ששירותים אחרים באשכול משתמשים בו כששולחים בקשות.

מחולל עומסים

אובייקט הפריסה ב-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 במזהה הפרויקט ב- Google Cloud .

    • אם אתם משתמשים ב-Cloud Shell Editor, הקובץ נשמר אוטומטית. כדי לחזור לחלון הטרמינל, לוחצים על 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 במזהה הפרויקט ב- Google Cloud .

    • אם אתם משתמשים ב-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
    

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