יצירת אפליקציית אינטרנט מרובת רמות באמצעות Redis ו-PHP

במדריך הזה נדגים איך ליצור אפליקציית אינטרנט רב-שכבתית באמצעות Google Kubernetes Engine ‏ (GKE).

במדריך הזה תלמדו:

בדוגמה מתוארים המושגים הבאים ב-Kubernetes:

  • הגדרה הצהרתית באמצעות קובצי מניפסט של YAML
  • פריסות, שהן משאב ב-Kubernetes שקובע את ההגדרה של קבוצה של Pods משוכפלים
  • שירותים ליצירת מאזני עומסים פנימיים וחיצוניים לקבוצה של Pods

מטרות

כדי לפרוס את האפליקציה ולהריץ אותה ב-GKE:

  1. הגדרת ה-leader של Redis
  2. הגדרת שני עוקבים של Redis
  3. הגדרת הקצה הקדמי של האתר
  4. כניסה לאתר
  5. הרחבה אנכית של הקצה הקדמי של האתר

בתרשים הבא מוצגת סקירה כללית של ארכיטקטורת האשכול שתיצרו כשתשלימו את היעדים האלה:

ארכיטקטורת אשכול GKE

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

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

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

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

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

ב-Cloud Shell מותקנת מראש התוכנה שדרושה למדריך הזה, כולל kubectl ו-ה-CLI של gcloud. אם אתם לא משתמשים ב-Cloud Shell, אתם צריכים להתקין את ה-CLI של gcloud.

  1. התקינו את ה-CLI של Google Cloud.

  2. הגדירו שה-CLI של gcloud ישתמש בזהות המאוחדת שלכם.

    איך נכנסים ל-CLI של gcloud באמצעות הזהות המאוחדת?

  3. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  4. יוצרים או בוחרים Google Cloud פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Google Cloud פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Google Cloud שיוצרים.

    • בוחרים את הפרויקט שיצרתם ב- Google Cloud :

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Google Cloud .

  5. מוודאים שהחיוב מופעל בפרויקט ב- Google Cloud .

  6. מפעילים את GKE API, אם הוא עדיין לא מופעל:

    התפקידים שנדרשים כדי להפעיל ממשקי API

    כדי להפעיל ממשקי API, צריך את ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com

הכנת הסביבה

כדי להגדיר את הסביבה:

  1. מגדירים את משתני הסביבה:

    export PROJECT_ID=PROJECT_ID
    export COMPUTE_LOCATION=COMPUTE_LOCATION
    

    מחליפים את מה שכתוב בשדות הבאים:

  2. משכפלים את המאגר ב-GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. עוברים לספריית העבודה:

    cd kubernetes-engine-samples/quickstarts/guestbook/
    

יצירת אשכול GKE

יוצרים אשכול GKE במצב Autopilot או Standard:

Autopilot

gcloud container clusters create-auto guestbook \
    --location=${COMPUTE_LOCATION} \

רגילה

gcloud container clusters create guestbook \
    --location=${COMPUTE_LOCATION} \
    --num-nodes=4

התחברות לאשכול

מגדירים את kubectl לתקשורת עם האשכול:

gcloud container clusters get-credentials guestbook \
    --location=${COMPUTE_LOCATION}

הגדרת ה-leader של Redis

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

  1. המניפסט הבא מתאר פריסת Kubernetes שמריצה Pod אחד של מנהיג Redis:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: leader
            tier: backend
        spec:
          containers:
          - name: leader
            image: "docker.io/redis:6.0.5"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379

    מחילים את המניפסט על האשכול:

    kubectl apply -f redis-leader-deployment.yaml
    
  2. מוודאים שפוד ה-Redis הראשי פועל:

    kubectl get pods
    

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

    NAME                           READY     STATUS    RESTARTS   AGE
    redis-leader-343230949-qfvrq   1/1       Running   0          43s
    

    יכול להיות שיחלפו כמה דקות עד שהסטטוס של STATUS ישתנה מPending לRunning.

יצירת שירות Redis leader

אפליקציית האינטרנט צריכה לתקשר עם ה-leader של Redis כדי לכתוב את הנתונים שלה. אתם יכולים ליצור שירות כדי להעביר את התנועה ל-Pod הראשי של Redis.

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

  1. במניפסט הבא מתואר שירות למנהל Redis:

    apiVersion: v1
    kind: Service
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      ports:
      - port: 6379
        targetPort: 6379
      selector:
        app: redis
        role: leader
        tier: backend

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

    הקטע ports במניפסט מצהיר על מיפוי יציאה יחיד. השירות מעביר את התנועה ב-port: 6379 אל targetPort: 6379 של מאגרי התגים שתואמים לתוויות selector שצוינו. ה-containerPort שמשמש לפריסה צריך להיות זהה ל-targetPort כדי להפנות תנועה לפריסה.

    מחילים את המניפסט על האשכול:

    kubectl apply -f redis-leader-service.yaml
    
  2. מוודאים ש-GKE יצר את השירות:

    kubectl get service
    

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

    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    42s
    redis-leader   10.51.242.233   <none>        6379/TCP   12s
    

הגדרת עוקבים ב-Redis

למרות ש-Redis leader הוא פוד יחיד, אפשר להוסיף כמה Redis followers, או רפליקות, כדי להפוך אותו לזמין מאוד ולעמוד בדרישות התנועה.

  1. קובץ המניפסט הבא מתאר פריסה של פודים של Redis follower:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-follower
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: follower
            tier: backend
        spec:
          containers:
          - name: follower
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379
  2. מחילים את המניפסט על האשכול:

    kubectl apply -f redis-follower-deployment.yaml
    
  3. מוודאים ששני העותקים המשוכפלים של Redis פועלים:

    kubectl get pods
    

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

    NAME                              READY   STATUS    RESTARTS   AGE
    redis-follower-76588f55b7-bnsq6   1/1     Running   0          27s
    redis-follower-76588f55b7-qvtws   1/1     Running   0          27s
    redis-leader-dd446dc55-kl7nl      1/1     Running   0          119s
    

    יכול להיות שיחלפו כמה דקות עד שהסטטוס של STATUS ישתנה מPending לRunning.

יצירת שירות Redis follower

אפליקציית האינטרנט צריכה לתקשר עם העותקים המשניים של Redis כדי לקרוא נתונים. כדי שניתן יהיה לגלות את ה-Redis followers, צריך להגדיר שירות.

  1. המאניפסט הבא מתאר שירות עבור העוקבים של Redis:

    apiVersion: v1
    kind: Service
    metadata:
      name: redis-follower
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      ports:
        # the port that this service should serve on
      - port: 6379
      selector:
        app: redis
        role: follower
        tier: backend

    קובץ המניפסט הזה מציין שהשירות פועל ביציאה 6379. השדה selector של השירות תואם לקבוצות ה-Pod של Redis follower שנוצרו בשלב הקודם.

    מחילים את המניפסט על האשכול:

    kubectl apply -f redis-follower-service.yaml
    
  2. מוודאים ש-GKE יצר את השירות:

    kubectl get service
    

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

    NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes     10.51.240.1     <none>        443/TCP    1m
    redis-leader   10.51.242.233   <none>        6379/TCP   49s
    redis-follower 10.51.247.238   <none>        6379/TCP   3s
    

הגדרת הקצה הקדמי של האפליקציה באינטרנט

עכשיו, אחרי שיש לכם אחסון Redis לאפליקציה, אפשר להפעיל את שרתי האינטרנט. בדומה ל-Redis followers, הקצה הקדמי נפרס באמצעות Kubernetes Deployment.

אפליקציית האינטרנט משתמשת בחלק הקדמי של PHP, שמוגדר לתקשורת עם שירותי העוקב או המוביל של Redis, בהתאם לשאלה אם הבקשה היא קריאה או כתיבה. החלק הקדמי של האפליקציה חושף ממשק JSON ומציג ממשק משתמש מבוסס-jQuery Ajax.

  1. המניפסט הבא מתאר פריסה של שרת האינטרנט:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
    spec:
      replicas: 3
      selector:
        matchLabels:
            app: guestbook
            tier: frontend
      template:
        metadata:
          labels:
            app: guestbook
            tier: frontend
        spec:
          containers:
          - name: php-redis
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
            env:
            - name: GET_HOSTS_FROM
              value: "dns"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 80

    קובץ המניפסט מציין את משתנה הסביבה GET_HOSTS_FROM=dns. כשמספקים את ההגדרה לאפליקציית הקצה הקדמי באינטרנט, אפליקציית הקצה הקדמי משתמשת בשמות המארחים redis-follower ו-redis-leader כדי לבצע חיפוש DNS. חיפוש ה-DNS מוצא את כתובות ה-IP של השירותים שיצרתם בשלבים הקודמים. המושג הזה נקרא זיהוי שירותים ב-DNS.

    מחילים את המניפסט על האשכול:

    kubectl apply -f frontend-deployment.yaml
    
  2. מוודאים שהרפליקות פועלות:

    kubectl get pods -l app=guestbook -l tier=frontend
    

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

    NAME                        READY   STATUS    RESTARTS   AGE
    frontend-7b78458576-8kp8s   1/1     Running   0          37s
    frontend-7b78458576-gg86q   1/1     Running   0          37s
    frontend-7b78458576-hz87g   1/1     Running   0          37s
    

חשיפת חזית האתר בכתובת IP חיצונית

בהגדרה הנוכחית, אפשר לגשת לשירותים redis-follower ו-redis-leader שיצרתם בשלבים הקודמים רק בתוך אשכול GKE, כי סוג ברירת המחדל של שירות הוא ClusterIP.

שירות ClusterIP מספק כתובת IP אחת לקבוצת ה-Pods שאליהם השירות מפנה. כתובת ה-IP הזו נגישה רק בתוך האשכול.

כדי להפוך את ממשק המשתמש של שירות האינטרנט לנגיש חיצונית, אפשר לציין type: LoadBalancer או type: NodePort בהגדרת השירות, בהתאם לדרישות.

המניפסט הבא מתאר שירות מסוג LoadBalancer:

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  type: LoadBalancer
  ports:
    # the port that this service should serve on
  - port: 80
  selector:
    app: guestbook
    tier: frontend

הצהרת היציאה בקטע ports מציינת את port: 80, ו-targetPort לא מצוין. אם לא מציינים את המאפיין targetPort, ערך ברירת המחדל שלו הוא הערך של השדה port. במקרה הזה, השירות הזה מעביר תנועה חיצונית ביציאה 80 ליציאה 80 של הקונטיינרים בפריסת frontend.

מחילים את המניפסט על האשכול:

kubectl apply -f frontend-service.yaml

כשיוצרים את שירות frontend, ‏ GKE יוצר מאזן עומסים וכתובת IP חיצונית. המשאבים האלה מחויבים.

כניסה לאתר של האפליקציה

כדי לגשת לאתר של האפליקציה, צריך לקבל את כתובת ה-IP החיצונית של השירות frontend:

kubectl get service frontend

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

NAME       CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   10.51.242.136   109.197.92.229     80:32372/TCP   1m

יכול להיות שבעמודה EXTERNAL-IP יוצג הערך <pending> בזמן שמאזן העומסים נוצר. הפעולה עשויה להימשך כמה דקות. אם מופיעות שגיאות כמו Does not have minimum availability, צריך לחכות כמה דקות. השגיאה הזמנית הזו מתרחשת כי GKE יוצר מחדש את הצמתים כדי לבצע את השינויים.

מעתיקים את כתובת ה-IP ופותחים את הדף בדפדפן:

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

כדי להוסיף רשומות, כותבים הודעה ולוחצים על שליחה. ההודעה שהקלדתם מופיעה בממשק הקצה. ההודעה הזו מציינת שהנתונים נוספו בהצלחה ל-Redis דרך השירותים שיצרתם.

הגדלת קנה המידה של הקצה הקדמי של האתר

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

  1. מגדילים את מספר הפודים של frontend:

    kubectl scale deployment frontend --replicas=5
    

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

    deployment.extensions/frontend scaled
    
  2. בודקים את מספר הרפליקות שפועלות:

    kubectl get pods
    

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

    NAME                             READY     STATUS    RESTARTS   AGE
    frontend-88237173-3s3sc          1/1       Running   0          1s
    frontend-88237173-twgvn          1/1       Running   0          1s
    frontend-88237173-5p257          1/1       Running   0          23m
    frontend-88237173-84036          1/1       Running   0          23m
    frontend-88237173-j3rvr          1/1       Running   0          23m
    redis-leader-343230949-qfvrq     1/1       Running   0          54m
    redis-follower-132015689-dp23k   1/1       Running   0          37m
    redis-follower-132015689-xq9v0   1/1       Running   0          37m
    

    כדי להקטין את מספר ה-Pods של frontend, משתמשים באותה פקודה ומחליפים את 5 ב-1.

הסרת המשאבים

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

מחיקת הפרויקט

    כדי למחוק Google Cloud פרויקט:

    gcloud projects delete PROJECT_ID

מחיקת המשאבים הנפרדים

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

  1. מחיקת השירות frontend:

    kubectl delete service frontend
    
  2. מוחקים את אשכול GKE:

    gcloud container clusters delete guestbook
    

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