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

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

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

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

  • הגדרת הצהרה באמצעות קובצי מניפסט של YAML
  • פריסות, שהן משאבי Kubernetes שקובעים את ההגדרה של קבוצה של קבוצות Pod משוכפלות
  • Services כדי ליצור מאזני עומסים פנימיים וחיצוניים לקבוצה של 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. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. התקינו את ה-CLI של Google Cloud.

  3. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

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

    gcloud init
  5. יוצרים או בוחרים 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 .

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

  7. מפעילים את GKE API:

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

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable container.googleapis.com
  8. התקינו את ה-CLI של Google Cloud.

  9. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

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

    gcloud init
  11. יוצרים או בוחרים 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 .

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

  13. מפעילים את GKE API:

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

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    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. מוודאים ש-Pod של Redis leader פועל:

    kubectl get pods
    

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

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

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

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

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

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

  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 follower או leader, בהתאם לסוג הבקשה (קריאה או כתיבה). החלק של ה-frontend חושף ממשק 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. הגדלת מספר ה-Pods של 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
    

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