פריסת מתגי feature flag

במדריך למתחילים הזה נסביר איך ליצור, להשיק ולהשתמש בדגלי תכונות באמצעות App Lifecycle Manager.

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

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

  1. נכנסים לחשבון Google.

    אם עדיין אין חשבון, יוצרים חשבון חדש.

  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the App Lifecycle Manager, Artifact Registry, Infrastructure Manager, Developer Connect, Cloud Build, Cloud Storage, Cloud Run and SaaS Config APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. Create a service account:

    1. Ensure that you have the Create Service Accounts IAM role (roles/iam.serviceAccountCreator) and the Project IAM Admin role (roles/resourcemanager.projectIamAdmin). Learn how to grant roles.
    2. In the Google Cloud console, go to the Create service account page.

      Go to Create service account
    3. Select your project.
    4. In the Service account name field, enter a name. The Google Cloud console fills in the Service account ID field based on this name.

      In the Service account description field, enter a description. For example, Service account for quickstart.

    5. Click Create and continue.
    6. Grant the Project > Owner role to the service account.

      To grant the role, find the Select a role list, then select Project > Owner.

    7. Click Continue.
    8. Click Done to finish creating the service account.

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

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

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

    gcloud init
  9. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  10. Verify that billing is enabled for your Google Cloud project.

  11. Enable the App Lifecycle Manager, Artifact Registry, Infrastructure Manager, Developer Connect, Cloud Build, Cloud Storage, Cloud Run and SaaS Config APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  12. Create a service account:

    1. Ensure that you have the Create Service Accounts IAM role (roles/iam.serviceAccountCreator) and the Project IAM Admin role (roles/resourcemanager.projectIamAdmin). Learn how to grant roles.
    2. In the Google Cloud console, go to the Create service account page.

      Go to Create service account
    3. Select your project.
    4. In the Service account name field, enter a name. The Google Cloud console fills in the Service account ID field based on this name.

      In the Service account description field, enter a description. For example, Service account for quickstart.

    5. Click Create and continue.
    6. Grant the Project > Owner role to the service account.

      To grant the role, find the Select a role list, then select Project > Owner.

    7. Click Continue.
    8. Click Done to finish creating the service account.

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

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

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

    gcloud init
  16. יצירת מוצר SaaS. כדי להשלים את המדריך למתחילים הזה, אתם צריכים פתרון SaaS. מידע נוסף על יצירת מוצר SaaS זמין במאמר יצירת מוצר SaaS.

מתן הרשאות לחשבון השירות של App Lifecycle Manager

כשמפעילים את App Lifecycle Manager API, ‏ App Lifecycle Manager יוצר חשבון שירות. חשבון השירות הזה נקרא service-PROJECT-NUMBER@gcp-sa-saasservicemgmt.iam.gserviceaccount.com, כאשר PROJECT-NUMBER הוא מספר הפרויקט.

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

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-saasservicemgmt.iam.gserviceaccount.com" \
    --role="roles/saasservicemgmt.serviceAgent"

מחליפים את:

  • PROJECT_ID: מזהה מחרוזת שמייצג את מזהה הפרויקט.
  • PROJECT_NUMBER: מספר הפרויקט.

איפה אפשר למצוא מאמרי עזרה

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

יצירת מאגר ב-Artifact Registry

כדי להשתמש ב-App Lifecycle Manager, צריך מאגר ב-Artifact Registry. כדי ליצור את המאגר הזה, מריצים את הפקודה הבאה בטרמינל:

gcloud artifacts repositories create flags-quickstart \
    --repository-format=docker \
    --location=us-central1

המאגר הזה יכיל תוכנית (קובצי Terraform ארוזים) שמתארת איך להקצות את היחידות.

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

יוצרים סקריפט Python שקורא את feature flag ומשתמש בו כדי ליצור קובץ אימג' של Docker ולהעביר אותו בדחיפה:

  1. יוצרים ספרייה בשם alm_docker בשביל הקשר של בניית Docker.

  2. בספרייה alm_docker, יוצרים את הקובץ flags.py עם קטע הקוד הזה:

    import google.auth.transport.grpc
    import google.auth.transport.requests
    import grpc
    import logging
    import time
    import os
    import sys
    from flask import Flask, jsonify
    
    from openfeature import api
    from openfeature.provider import ProviderEvent, ProviderStatus
    from openfeature.contrib.provider.flagd import FlagdProvider
    from openfeature.contrib.provider.flagd.config import ResolverType
    
    # --- Flask App Setup ---
    app = Flask(__name__)
    
    # --- Logging Setup ---
    logging.basicConfig(stream=sys.stdout) # Log to stdout for Cloud Run
    log = logging.getLogger(__name__)
    log.setLevel(logging.INFO) # Use INFO or DEBUG as needed
    
    # --- OpenFeature/Flagd Setup ---
    FLAG_KEY = "quickstart-flag"
    DEFAULT_FLAG_VALUE = False
    
    # Check for necessary environment variable
    provider_id = os.environ.get("FLAGD_SOURCE_PROVIDER_ID")
    if not provider_id:
      log.critical("FATAL: FLAGD_SOURCE_PROVIDER_ID environment variable not set.")
      sys.exit("FLAGD_SOURCE_PROVIDER_ID not set") # Exit if critical config is missing
    
    log.info(f"Initializing OpenFeature provider for ID: {provider_id}")
    
    def add_x_goog_request_params_header(config_name):
      return lambda context, callback: callback([("x-goog-request-params", f'name={config_name}')], None)
    
    try:
      # Configure gRPC credentials for Google Cloud service
      configservice_credentials = grpc.composite_channel_credentials(
          grpc.ssl_channel_credentials(),
          grpc.metadata_call_credentials(
              google.auth.transport.grpc.AuthMetadataPlugin(
                  google.auth.default()[0], # Get just the credentials from the tuple
                  google.auth.transport.requests.Request()
              )
          ),
          grpc.metadata_call_credentials(
              add_x_goog_request_params_header(provider_id)
          )
      )
    
      # Set up the Flagd provider to connect to SaaS Config service
      # Using IN_PROCESS resolver type as recommended for direct gRPC connection
      provider = FlagdProvider(
          resolver_type=ResolverType.IN_PROCESS,
          host="saasconfig.googleapis.com",
          port=443,
          sync_metadata_disabled=True, # Important when using IN_PROCESS with direct service
          provider_id=provider_id,
          channel_credentials=configservice_credentials
      )
      api.set_provider(provider)
      client = api.get_client()
    
      initial_flag_value = client.get_boolean_value(FLAG_KEY, DEFAULT_FLAG_VALUE)
      log.info(f"***** STARTUP FLAG CHECK ***** Flag '{FLAG_KEY}' evaluated to: {initial_flag_value}")
    
    except Exception as e:
      log.critical(f"FATAL: Failed to initialize OpenFeature provider: {e}", exc_info=True)
      # Depending on the desired behavior, you might exit or let Flask start
      # but log the critical failure. Exiting might be safer in production.
      sys.exit(f"Provider initialization failed: {e}")
    
    # --- Flask Routes ---
    @app.route('/')
    def home():
      """Endpoint to check the feature flag's value."""
      log.info(f"Request received for flag: {FLAG_KEY}")
      try:
          # Get the flag value. Use the client initialized earlier.
          # The default value (DEFAULT_FLAG_VALUE) is returned if the flag isn't found
          # or if the provider isn't ready/errors occur during evaluation.
          flag_value = client.get_boolean_value(FLAG_KEY, DEFAULT_FLAG_VALUE)
          log.info(f"Evaluated flag '{FLAG_KEY}': {flag_value}")
          return jsonify({
              "flag_key": FLAG_KEY,
              "value": flag_value,
          })
      except Exception as e:
          log.error(f"Error evaluating flag '{FLAG_KEY}': {e}", exc_info=True)
          # Return an error response but keep the server running
          return jsonify({
              "error": f"Failed to evaluate flag {FLAG_KEY}",
              "details": str(e),
          }), 500
    
    if __name__ == '__main__':
      port = int(os.environ.get('PORT', 8080))
      log.info(f"Starting Flask server on port {port}")
      app.run(host='0.0.0.0', port=port)
    

    סקריפט Python הזה מדגים איך לגשת לדגלים של תכונות באפליקציה שפועלת כקובץ אימג' של Docker ביחידה של App Lifecycle Manager. הוא משתמש בעקרונות סטנדרטיים של OpenFeature כדי להשתלב עם שירות ההגדרות של דגלי התכונות של App Lifecycle Manager‏ (saasconfig.googleapis.com).

  3. יוצרים קובץ טקסט בשם requirements.txt בספרייה alm_docker שמכילה את קטע הקוד הזה:

    google-auth
    grpcio>=1.49.1,<2.0.0dev
    openfeature-sdk==0.8.0
    openfeature-provider-flagd==0.2.2
    requests 
    typing_extensions
    Flask>=2.0
    
  4. מוסיפים את Dockerfile בספרייה alm_docker באמצעות:

    FROM python:3.11-slim
    
    WORKDIR /app
    
    COPY requirements.txt .
    
    RUN pip install --no-cache-dir -r requirements.txt
    COPY flags.py .
    CMD ["python", "flags.py"]
    
  5. מריצים את הפקודה הזו בסביבה המקומית כדי ליצור את קובץ האימג' של Docker ולהעביר אותו בדחיפה:

    export DOCKER_REGISTRY="us-central1-docker.pkg.dev/PROJECT_ID/flags-quickstart"
    export FULL_IMAGE_PATH="${DOCKER_REGISTRY}/flags-quickstart:latest"
    docker build -t "${FULL_IMAGE_PATH}" .
    docker push "${FULL_IMAGE_PATH}"
    

    מחליפים את:

    • PROJECT_ID: מזהה מחרוזת שמייצג את מזהה הפרויקט.
  6. בסביבת Docker, יוצרים ספרייה בשם alm_terraform.

  7. ב-alm_terraform, יוצרים את הקבצים הבאים:

    main.tf

    locals {
      config_path = "projects/${var.system_unit_project}/locations/${var.system_unit_location}/featureFlagsConfigs/${var.system_unit_name}"
      docker_image_path = "${var.system_unit_location}-docker.pkg.dev/${var.system_unit_project}/${var.docker_repo_name}/${var.docker_tag}"
    }
    
    provider "google" {
      project = var.system_unit_project
      region  = var.system_unit_location
    }
    
    resource "google_cloud_run_service" "flags_quickstart_service" {
      name     = var.cloud_run_service_name
      location = var.system_unit_location
      project  = var.system_unit_project
    
      template {
        spec {
          containers {
            image = local.docker_image_path 
    
            env {
              name  = "FLAGD_SOURCE_PROVIDER_ID"
              value = local.config_path
            }
          }
          service_account_name = var.actuation_sa
        }
      }
    }
    

    variables.tf

    variable "actuation_sa" {
      description = "Actuation SA"
      type        = string
    }
    
    variable "system_unit_project" {
      description = "Project id - variable set by App Lifecycle Manager"
      type        = string
    }
    
    variable "system_unit_location" {
      description = "Location - variable set by App Lifecycle Manager"
      type        = string
    }
    
    variable "system_unit_name" {
      description = "Unit name- variable set by App Lifecycle Manager"
      type = string
    }
    
    variable "docker_repo_name" {
      description = "The name of the Artifact Registry repository where the Docker image is stored."
      type        = string
      default     = "flags-quickstart"
    }
    
    variable "docker_tag" {
      description = "The tag of the Docker image to deploy."
      type        = string
      default     = "flags-quickstart:latest"
    }
    
    variable "cloud_run_service_name" {
      description = "Name for the Cloud Run service to be created."
      type        = string
      default     = "saas-flags-quickstart-svc"
    }
    
  8. בספרייה alm_terraform, מריצים את הפקודה הבאה כדי לארוז את קובצי התוכנית של Terraform:

    zip terraform-files.zip main.tf variables.tf
    

שימוש בתוכנית האפליקציה ליצירת יחידה

אחרי שיוצרים תוכנית של אפליקציה שמשתמשת בדגלי תכונות, צריך ליצור סוג של יחידה של App Lifecycle Manager ‏ (flags-unit-kind), ואז ליצור יחידה מהסוג הזה (flags-quickstart-unit).

מידע נוסף על יחידות וסוגי יחידות זמין במאמר יחידות של מודלים וחבילות בפריסה.

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

  1. כדי לארוז את ההגדרות של Terraform כתבנית OCI, יוצרים קובץ בשם Dockerfile בספרייה של Terraform:

    # syntax=docker/dockerfile:1-labs
    FROM scratch
    COPY --exclude=Dockerfile --exclude=.git --exclude=.gitignore . /
    
  2. יוצרים את Dockerfile ומעבירים אותו בדחיפה למאגר Artifact Registry:

    IMAGE_NAME="us-central1-docker.pkg.dev/PROJECT_ID/flags-quickstart/flags-quickstart-blueprint:latest"
    ENGINE_TYPE=inframanager
    ENGINE_VERSION=1.5.7
    
    docker buildx build -t $IMAGE_NAME \
      --push \
      --annotation "com.easysaas.engine.type=$ENGINE_TYPE" \
      --annotation "com.easysaas.engine.version=$ENGINE_VERSION" \
      --provenance=false .
    

    מחליפים את:

    • PROJECT_ID: מזהה מחרוזת שמייצג את מזהה הפרויקט.
  3. יצירת משאב flags-unit-kind ומשאב flags-release:

    # Create unit kind
    gcloud beta app-lifecycle-manager unit-kinds create flags-unit-kind \
      --project=PROJECT_ID \
      --location=global \
      --saas=flags-quickstart-saas-offering
    
    # Create release referencing the Blueprint image
    gcloud beta app-lifecycle-manager releases create flags-release \
      --project=PROJECT_ID \
      --location=global \
      --unit-kind=flags-unit-kind \
      --blueprint-package=$IMAGE_NAME
    

    מחליפים את:

    • PROJECT_ID: מזהה מחרוזת שמייצג את מזהה הפרויקט.
  4. יוצרים את היחידה flags-quickstart-unit:

    gcloud beta app-lifecycle-manager units create flags-quickstart-unit \
      --project=PROJECT_ID \
      --location=us-central1 \
      --unit-kind=flags-unit-kind \
      --management-mode=user
    

    מחליפים את:

    • PROJECT_ID: מזהה מחרוזת שמייצג את מזהה הפרויקט.

יצירה והקצאה של feature flag

כדי להשתמש ב-feature flag של App Lifecycle Manager ביחידה שהוקצתה לכם, צריך ליצור את משאב ה-feature flag ולהתחיל בהשקה כדי להפיץ את ההגדרה ליחידה.

מריצים את הפקודות כדי ליצור ולהקצות משאבים ל-feature flag quickstart-flag:

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

    export FLAG_ID="quickstart-flag"
    export FLAG_KEY="quickstart-flag"
    export SAAS_OFFERING_ID="flags-quickstart-saas-offering"
    export UNIT_KIND_ID="flags-unit-kind"
    export UNIT_ID="flags-quickstart-unit"
    export ROLLOUT_KIND_ID="flags-quickstart-rollout-kind"
    export ROLLOUT_ID="flags-quickstart-rollout"
    
  2. יוצרים את משאב ה-feature flag:

    gcloud beta app-lifecycle-manager flags create ${FLAG_ID} \
      --project=${PROJECT_ID} \
      --key=${FLAG_KEY} \
      --flag-value-type=BOOL \
      --location=global \
      --unit-kind=${UNIT_KIND_ID}
    
  3. יצירת גרסה:

    export FLAG_REVISION_ID="${FLAG_ID}-rev1"
    gcloud beta app-lifecycle-manager flags revisions create ${FLAG_REVISION_ID} \
      --project=${PROJECT_ID} \
      --flag=${FLAG_ID} \
      --location=global
    
  4. יצירת גרסה:

    export FLAG_RELEASE_ID="${FLAG_ID}-rel1"
    gcloud beta app-lifecycle-manager flags releases create ${FLAG_RELEASE_ID} \
      --project=${PROJECT_ID} \
      --flag-revisions=${FLAG_REVISION_ID} \
      --unit-kind=${UNIT_KIND_ID} \
      --location=global
    
  5. יוצרים סוג השקה:

    gcloud beta app-lifecycle-manager rollout-kinds create ${ROLLOUT_KIND_ID} \
      --project=${PROJECT_ID} \
      --unit-kind=${UNIT_KIND_ID} \
      --rollout-orchestration-strategy=Google.Cloud.Simple.AllAtOnce \
      --location=global
    
  6. יוצרים את ההשקה:

    gcloud beta app-lifecycle-manager rollouts create ${ROLLOUT_ID} \
      --project=${PROJECT_ID} \
      --flag-release=${FLAG_RELEASE_ID} \
      --rollout-kind=${ROLLOUT_KIND_ID} \
      --location=global
    

אפשר לעקוב אחרי סטטוס ההשקה באמצעות:

gcloud beta app-lifecycle-manager rollouts describe ${ROLLOUT_ID} --project=${PROJECT_ID} --location=global

הצגת ערך הדגל בשירות הפועל

אחרי שיחידת App Lifecycle Manager תספק בהצלחה את שירות Cloud Run, תוכלו לוודא שהאפליקציה פועלת ומעריכה נכון את feature flag:

  1. במסוף Google Cloud , עוברים אל Cloud Run:

    כניסה ל-Cloud Run

  2. מאתרים את השירות בשם saas-flags-quickstart-svc באזור us-central1. סימן וי לצד saas-flags-quickstart-svc מציין שהיא פועלת בהצלחה.

  3. לוחצים על saas-flags-quickstart-svc כדי לראות את הפרטים שלו.

    עוברים אל saas-flags-quickstart-svc.

  4. לוחצים על הכרטיסייה יומנים.

    1. ברשומות ביומן, מחפשים הודעה שדומה להודעה הבאה:

      INFO:__main__:***** STARTUP FLAG CHECK ***** Flag 'quickstart-flag' evaluated to: false
      

      כך מאשרים שהאפליקציה הופעלה, שהיא התחברה לשירות SaaS Config ושהיא העריכה את quickstart-flag.

  5. כדי לגשת לנקודת הקצה הציבורית, לוחצים על הכרטיסייה Networking.

    1. מאתרים את כתובת ה-URL הציבורית שמופיעה בקטע נקודות קצה.
    2. לוחצים על כתובת ה-URL כדי לפתוח אותה בדפדפן, או משתמשים בכלי כמו curl כדי לגשת אליה מהטרמינל (לדוגמה, curl YOUR_SERVICE_URL).
    3. בכל פעם שתיגשו לכתובת ה-URL, השירות יבדוק את דגל התכונה ויחזיר את הערך הנוכחי שלו בפורמט JSON. לדוגמה:

      {
        "flag_key": "quickstart-flag",
        "value": false
      }
      

הצלחתם לפרוס שירות Google Cloud שקורא feature flag שמנוהל על ידי App Lifecycle Manager. אתם יכולים להתנסות בשינוי הערך של הדגל וליצור השקה חדשה כדי לראות את השינוי באפליקציה.

הסרת המשאבים

כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם בדף הזה, פועלים לפי השלבים הבאים:

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

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

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

    כניסה לדף Manage resources

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

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