שימוש ב-Workflows לקישור שירותים

במדריך הזה מוסבר איך להשתמש ב-Workflows כדי לקשר בין סדרה של שירותים. אפשר ליצור אפליקציה גמישה ללא שרת (serverless) על ידי חיבור של שני שירותי HTTP ציבוריים באמצעות פונקציות של Cloud Run, API חיצוני בארכיטקטורת REST ושירות פרטי של Cloud Run.

מטרות

במדריך הזה נשתמש ב-Google Cloud CLI כדי ליצור תהליך עבודה יחיד, שבו נחבר שירות אחד בכל פעם:

  1. פורסים שתי פונקציות Cloud Run: הפונקציה הראשונה יוצרת מספר אקראי, ואז מעבירה את המספר הזה לפונקציה השנייה שמכפילה אותו.
  2. באמצעות Workflows, מחברים את שתי פונקציות ה-HTTP. מריצים את תהליך העבודה ומחזירים תוצאה שמועברת ל-API חיצוני.
  3. באמצעות Workflows, מחברים API חיצוני של HTTP שמחזיר את log למספר נתון. הפעלת תהליך העבודה והחזרת תוצאה שמועברת לשירות Cloud Run.
  4. פריסה של שירות Cloud Run שמאפשר גישה מאומתת בלבד. השירות מחזיר את math.floor עבור מספר נתון.
  5. באמצעות Workflows, מקשרים את שירות Cloud Run, מריצים את כל תהליך העבודה ומחזירים תוצאה סופית.

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

המחשה ויזואלית של תהליכי עבודה

עלויות

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

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

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

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

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

  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. מפעילים את ממשקי ה-API של Artifact Registry,‏ Cloud Build,‏ Cloud Run,‏ Cloud Run Functions,‏ Cloud Storage ו-Workflows:

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

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

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.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. מפעילים את ממשקי ה-API של Artifact Registry,‏ Cloud Build,‏ Cloud Run,‏ Cloud Run Functions,‏ Cloud Storage ו-Workflows:

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

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

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com
  14. מעדכנים את הרכיבים של Google Cloud CLI:
    gcloud components update
  15. אם אתם מריצים פקודות ב-Cloud Shell, אתם כבר מאומתים ב-CLI של gcloud. אחרת, אתם צריכים להיכנס באמצעות החשבון שלכם:
    gcloud auth login
  16. מגדירים את מיקום ברירת המחדל שבו משתמשים במדריך הזה:
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set functions/region ${REGION}
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}

    מחליפים את REGION במיקום של Workflows שנתמך לבחירתכם.

  17. אם אתם יוצרי הפרויקט, מוקצה לכם תפקיד הבעלים הבסיסי (roles/owner). כברירת מחדל, תפקיד ניהול הזהויות והרשאות הגישה (IAM) הזה כולל את ההרשאות שנדרשות לגישה מלאה לרוב המשאבים Google Cloud, ואפשר לדלג על השלב הזה.

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

    ההרשאות הנדרשות

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

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

    יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

  18. כשפורסים את תהליך העבודה, משייכים אותו לחשבון שירות ספציפי. יוצרים חשבון שירות לשימוש ב-Workflows:
    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}
  19. כל שירותי Cloud Run נפרסים באופן פרטי כברירת מחדל, ורק בעלי הפרויקט, עורכי הפרויקט, אדמינים של Cloud Run ומשתמשים עם הרשאה להפעלת שירותים ב-Cloud Run יכולים להפעיל אותם. כדי לאפשר לחשבון השירות לקרוא לשירות Cloud Run מאומת, צריך להקצות את התפקיד run.invoker לחשבון השירות של Workflows:
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \
        --role "roles/run.invoker"

פריסת הפונקציות הראשונות של Cloud Run

אחרי קבלת בקשת HTTP, פונקציית ה-HTTP הזו יוצרת מספר אקראי בין 1 ל-100, ואז מחזירה את המספר בפורמט JSON.

  1. יוצרים ספרייה בשם randomgen ועוברים אליה:

    mkdir ~/randomgen
    cd ~/randomgen
  2. יוצרים קובץ טקסט בשם main.py שמכיל את קוד Python הבא:

    import functions_framework
    import random
    from flask import jsonify
    
    
    @functions_framework.http
    def randomgen(request):
        randomNum = random.randint(1, 100)
        output = {"random": randomNum}
        return jsonify(output)
  3. כדי לתמוך בתלות ב-Flask לעיבוד HTTP, יוצרים קובץ טקסט עבור מנהל חבילות pip. נותנים לו את שם הקובץ requirements.txt ומוסיפים את הטקסט הבא:

    flask>=1.0.2
    functions-framework==3.0.0
  4. פורסים את הפונקציה עם טריגר HTTP ומאפשרים גישה ללא אימות:

    gcloud functions deploy randomgen-function \
        --gen2 \
        --runtime python310 \
        --entry-point=randomgen \
        --trigger-http \
        --allow-unauthenticated

    יכול להיות שיחלפו כמה דקות עד שהפונקציה תופעל. לחלופין, אפשר להשתמש בממשק של Cloud Run functions במסוף Google Cloud כדי לפרוס את הפונקציה.

  5. אחרי שפורסים את הפונקציה randomgen, אפשר לאשר את הנכס httpsTrigger.url:

    gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)"
  6. שומרים את כתובת ה-URL. תצטרכו להוסיף אותו לקובץ המקור של זרימת העבודה בתרגילים הבאים.

  7. אפשר לנסות את הפונקציה באמצעות פקודת ה-curl הבאה:

    curl $(gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)")

    מספר נוצר באופן אקראי ומוחזר.

פריסת הפונקציות השנייה של Cloud Run

אחרי קבלת בקשת HTTP, פונקציית ה-HTTP הזו מחלצת את הערך input מגוף ה-JSON, מכפילה אותו ב-2 ומחזירה את התוצאה בפורמט JSON.

  1. מנווטים חזרה לספריית הבית:

    cd ~
  2. יוצרים ספרייה בשם multiply ועוברים אליה:

    mkdir ~/multiply
    cd ~/multiply
  3. יוצרים קובץ טקסט בשם main.py שמכיל את קוד Python הבא:

    import functions_framework
    from flask import jsonify
    
    
    @functions_framework.http
    def multiply(request):
        request_json = request.get_json()
        output = {"multiplied": 2 * request_json['input']}
        return jsonify(output)
  4. כדי לתמוך בתלות ב-Flask לעיבוד HTTP, יוצרים קובץ טקסט עבור מנהל חבילות pip. נותנים לו את שם הקובץ requirements.txt ומוסיפים את הטקסט הבא:

    flask>=1.0.2
    functions-framework==3.0.0
  5. פורסים את הפונקציה עם טריגר HTTP ומאפשרים גישה ללא אימות:

    gcloud functions deploy multiply-function \
        --gen2 \
        --runtime python310 \
        --entry-point=multiply \
        --trigger-http \
        --allow-unauthenticated

    יכול להיות שיחלפו כמה דקות עד שהפונקציה תופעל. לחלופין, אפשר להשתמש בממשק של Cloud Run functions במסוף Google Cloud כדי לפרוס את הפונקציה.

  6. אחרי שפורסים את הפונקציה multiply, אפשר לאשר את הנכס httpsTrigger.url:

    gcloud functions describe multiply-function \
        --gen2\
        --format="value(serviceConfig.uri)"
  7. שומרים את כתובת ה-URL. תצטרכו להוסיף אותו לקובץ המקור של זרימת העבודה בתרגילים הבאים.

  8. אפשר לנסות את הפונקציה באמצעות פקודת ה-curl הבאה:

    curl -X POST MULTIPLY_FUNCTION_URL \
        -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
        -H "Content-Type: application/json" \
        -d '{"input": 5}'

    הפונקציה תחזיר את המספר 10.

חיבור בין שתי פונקציות Cloud Run בתהליך עבודה

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

  1. מנווטים חזרה לספריית הבית:

    cd ~
  2. יוצרים קובץ טקסט בשם workflow.yaml עם התוכן הבא:

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - return_result:
        return: ${multiply_result}
    

    קובץ המקור הזה מקשר בין שתי פונקציות HTTP ומחזיר תוצאה סופית.

  3. אחרי שיוצרים את תהליך העבודה, אפשר לפרוס אותו, וכך הוא מוכן להרצה.

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

    מחליפים את WORKFLOW_NAME בשם של זרימת העבודה.

  4. מריצים את תהליך העבודה:

    gcloud workflows run WORKFLOW_NAME

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

    אחרי הפעלת תהליך העבודה, הפלט אמור להיראות כך:

    result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\";
    ...
    startTime: '2021-05-05T14:17:39.135251700Z'
    state: SUCCEEDED
    ...
    

חיבור שירות REST ציבורי בתהליך העבודה

מעדכנים את תהליך העבודה הקיים ומקשרים API ציבורי ל-REST ‏(math.js) שיכול להעריך ביטויים מתמטיים. לדוגמה, curl https://api.mathjs.org/v4/?'expr=log(56)'.

שימו לב: אחרי שפורסים את תהליך העבודה, אפשר לערוך אותו גם דרך הדף Workflows במסוף Google Cloud .

  1. עורכים את קובץ המקור של תהליך העבודה ומחליפים אותו בתוכן הבא:

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - log_function:
        call: http.get
        args:
            url: https://api.mathjs.org/v4/
            query:
                expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
        result: log_result
    - return_result:
        return: ${log_result}
    

    הפעולה הזו מקשרת את שירות ה-REST החיצוני לפונקציות Cloud Run ומחזירה תוצאה סופית.

  2. פורסים את תהליך העבודה ששיניתם:

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

פריסת שירות Cloud Run

פריסת שירות Cloud Run, שאחרי קבלת בקשת HTTP, מחלץ את input מגוף ה-JSON, מחשב את math.floor ומחזיר את התוצאה.

  1. יוצרים ספרייה בשם floor ועוברים אליה:

    mkdir ~/floor
    cd ~/floor
  2. יוצרים קובץ טקסט בשם app.py שמכיל את קוד Python הבא:

    import json
    import logging
    import os
    import math
    
    from flask import Flask, request
    
    app = Flask(__name__)
    
    
    @app.route('/', methods=['POST'])
    def handle_post():
        content = json.loads(request.data)
        input = float(content['input'])
        return f"{math.floor(input)}", 200
    
    
    if __name__ != '__main__':
        # Redirect Flask logs to Gunicorn logs
        gunicorn_logger = logging.getLogger('gunicorn.error')
        app.logger.handlers = gunicorn_logger.handlers
        app.logger.setLevel(gunicorn_logger.level)
        app.logger.info('Service started...')
    else:
        app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

  3. באותה תיקייה, יוצרים קובץ Dockerfile עם התוכן הבא:

    # Use an official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.7-slim
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY . .
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app

  4. יוצרים מאגר רגיל ב-Artifact Registry שבו אפשר לאחסן את קובץ האימג' של קונטיינר Docker:

    gcloud artifacts repositories create REPOSITORY \
        --repository-format=docker \
        --location=${REGION}

    מחליפים את REPOSITORY בשם ייחודי למאגר.

  5. יוצרים את קובץ האימג' של הקונטיינר:

    export SERVICE_NAME=floor
    gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
  6. פורסים את קובץ האימג' של הקונטיינר ב-Cloud Run, ומוודאים שהוא מקבל רק קריאות מאומתות:

    gcloud run deploy ${SERVICE_NAME} \
        --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \
        --no-allow-unauthenticated

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

חיבור שירות Cloud Run בתהליך העבודה

מעדכנים את תהליך העבודה הקיים ומציינים את כתובת ה-URL של שירות Cloud Run.

  1. מנווטים חזרה לספריית הבית:

    cd ~
  2. עורכים את קובץ המקור של תהליך העבודה ומחליפים אותו בתוכן הבא:

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - log_function:
        call: http.get
        args:
            url: https://api.mathjs.org/v4/
            query:
                expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
        result: log_result
    - floor_function:
        call: http.post
        args:
            url: CLOUD_RUN_SERVICE_URL
            auth:
                type: OIDC
            body:
                input: ${log_result.body}
        result: floor_result
    - create_output_map:
        assign:
          - outputMap:
              randomResult: ${randomgen_result}
              multiplyResult: ${multiply_result}
              logResult: ${log_result}
              floorResult: ${floor_result}
    - return_output:
        return: ${outputMap}
    
    • מחליפים את RANDOMGEN_FUNCTION_URL בכתובת ה-URL של הפונקציה randomgen.
    • מחליפים את MULTIPLY_FUNCTION_URL בכתובת ה-URL של הפונקציה multiply.
    • מחליפים את CLOUD_RUN_SERVICE_URL בכתובת ה-URL של שירות Cloud Run.

    הפעולה הזו מחברת את שירות Cloud Run לתהליך העבודה. שימו לב שהמפתח auth מוודא שאסימון אימות מועבר בקריאה לשירות Cloud Run. מידע נוסף זמין במאמר בנושא שליחת בקשות מאומתות מתהליך עבודה.

  3. פורסים את תהליך העבודה ששיניתם:

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
  4. מריצים את תהליך העבודה הסופי:

    gcloud workflows run WORKFLOW_NAME

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

    result: '{"floorResult":{"body":"4","code":200
      ...
      "logResult":{"body":"4.02535169073515","code":200
      ...
      "multiplyResult":{"body":{"multiplied":56},"code":200
      ...
      "randomResult":{"body":{"random":28},"code":200
      ...
    startTime: '2023-11-13T21:22:56.782669001Z'
    state: SUCCEEDED
    

כל הכבוד! פרסתם והפעלתם תהליך עבודה שמקשר בין סדרה של שירותים.

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

הסרת המשאבים

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

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

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

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

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

מחיקת משאבי הדרכה

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