שימוש בהתראות על תכונות עצמאיות
במאמר הזה מוסבר איך להשתמש בדגלי תכונות של App Lifecycle Manager כשירות עצמאי לניהול הזמינות של תכונות באפליקציות, גם אם האפליקציות האלה לא נפרסות או מנוהלות על ידי App Lifecycle Manager.
מבוא
במדריך הזה נסביר איך להשתמש ביכולות החזקות של App Lifecycle Manager לניהול תכונות והשקה מבוקרת, בלי שתצטרכו להשתמש ב-App Lifecycle Manager להקצאת משאבים (למשל, פריסת מכונות וירטואליות או שירותי Cloud Run באמצעות תוכניות Terraform). הגישה הזו מתאימה במיוחד אם אתם מנהלים את תשתית האפליקציה באופן עצמאי, אבל רוצים להשתמש ב-App Lifecycle Manager כדי לנהל את ה-feature flags בצורה בטוחה.
בגישה העצמאית הזו, תלמדו:
- יצירת מודל של המערכת באמצעות משאבי App Lifecycle Manager קלילים: יוצרים
Unitsשל App Lifecycle Manager כדי לייצג רכיבים של התשתית הקיימת (למשל, פריסה ספציפית של מיקרו-שירות, סביבת דייר, מופע בינארי יחיד). היחידות האלה משמשות רק כיעדים להגדרות של דגלים, ולא כוללות פריסה של תשתית באמצעות תוכניות בסיס של App Lifecycle Manager. - הגדרת דגלים והפצה שלהם: אפשר להשתמש ב-App Lifecycle Manager API או במסוף Google Cloud כדי ליצור דגלי תכונות. ניהול מחזור החיים שלהם באמצעות App Lifecycle Manager
Rolloutsכדי להבטיח הפצה בטוחה והדרגתית של שינויים בהגדרות אלUnitsהמעוצב. כך אפשר לשמור על עקביות ובטיחות תפעוליות גם כשמנהלים רק דגלים. - שילוב עם האפליקציה: משתמשים ב-OpenFeature SDK עם ספק
flagdבקוד האפליקציה (פועל בכל מקום – באופן מקומי, במקום, בענן בניהול עצמי). מגדירים אותו להתחבר לשירות הדגלים של App Lifecycle Manager (saasconfig.googleapis.com), לבצע אימות ולזהות את עצמו באמצעות שם המשאב התואםUnitכדי לאחזר את ערכי הדגלים הנכונים.
הגישה הזו מאפשרת לכם ליהנות מהפצה מנוהלת ובטוחה של דגלים בלי לשנות את צינורות הפריסה הקיימים או את הכלים לניהול התשתית.
הפעלת תכונות ב-App Lifecycle Manager נמצאת בגרסת טרום-השקה פרטית. כדי לקבל גישה, צריך להוסיף אתכם לרשימת ההיתרים. כדי לבקש גישה לארגון או לפרויקט, ממלאים את הטופס הזה.
במדריך למתחילים הזה נשתמש באפליקציית Python בסיסית שפועלת באופן מקומי כדי להדגים גישה לדגלים, ונדמה איך האפליקציה הקיימת שלכם תשתלב.
מטרות
- מגדירים פרויקט חדש או משתמשים בפרויקט קיים. Google Cloud
- מפעילים את ממשקי ה-API הנדרשים (App Lifecycle Manager ו-SaaS Config).
- צריך להעניק את ההרשאות הנדרשות לניהול זהויות והרשאות גישה (IAM) ליצירת משאבים ולקריאת דגלים.
- יוצרים משאבים מינימליים של App Lifecycle Manager (שירות SaaS, סוג יחידה, יחידה) כדי ליצור מודל של רכיב אפליקציה בלי לפרוס תשתית.
- מגדירים feature flag שמשויך לסוג היחידה.
- יוצרים מנגנון להפעלת תכונות (סוג ההשקה) שמגדיר את אסטרטגיית ההפצה.
- מפיצים את ההגדרה הראשונית של הדגל באמצעות השקת גרסה של App Lifecycle Manager.
- מריצים באופן מקומי אפליקציית Python לדוגמה שמתחברת לשירות הדגלים של App Lifecycle Manager ומעריכה את הדגל עבור היחידה הממוּדלת.
- מעדכנים את ערך הדגל, יוצרים גרסה חדשה של הדגל ומפיצים את השינוי.
- מוודאים שהאפליקציה מזהה את הערך המעודכן של הדגל.
לפני שמתחילים
-
נכנסים לחשבון Google.
אם עדיין אין חשבון, יוצרים חשבון חדש.
-
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the App Lifecycle Manager 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 theserviceusage.services.enablepermission. Learn how to grant roles.-
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:
gcloud init -
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the App Lifecycle Manager 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 theserviceusage.services.enablepermission. Learn how to grant roles.-
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:
gcloud init -
מתקינים את Python: מוודאים ש-Python 3.7 ואילך מותקן במחשב שבו תפעילו את אפליקציית הדוגמה. צריך גם pip כדי להתקין רכיבים תלויים.
python --version
pip --version
-
אימות gcloud ל-Application Default Credentials (ADC): סקריפט Python מקומי משתמש ב-ADC כדי לבצע אימות לשירותי Google Cloud . נכנסים באמצעות חשבון המשתמש:
gcloud auth application-default login
-
הענקת הרשאות לזהות האפליקציה: האפליקציה צריכה הרשאה לקרוא הגדרות של דגלים משירות ההגדרות של SaaS. נותנים לזהות שהאפליקציה תשתמש בה את התפקיד `roles/saasconfig.viewer`. כדי להשתמש ב-ADC באופן מקומי עם חשבון המשתמש שלכם, צריך להקצות את התפקיד לכתובת האימייל שלכם:
מחליפים את PROJECT_ID במזהה הפרויקט ואת YOUR_EMAIL_ADDRESS בכתובת האימייל שמשויכת להתחברות ל-CLI. Google Cloudgcloud projects add-iam-policy-binding PROJECT_ID \ --member="user:YOUR_EMAIL_ADDRESS" \ --role="roles/saasconfig.viewer"
יצירת משאבים מינימליים ב-App Lifecycle Manager
למרות שאנחנו לא פורסים תשתית באמצעות App Lifecycle Manager, אנחנו צריכים כמה משאבים כדי לארגן, לטרגט ולהפיץ את הדגלים שלנו בצורה בטוחה. המשאבים האלה מייצגים את רכיבי האפליקציה הקיימים ב-App Lifecycle Manager.
הגדרת משתנים: מגדירים משתני סביבה לשמות ולמיקומים של משאבים.
export PROJECT_ID="your-project-id" export SAAS_OFFERING_ID="standalone-flags-saas" export UNIT_KIND_ID="standalone-app-kind" export UNIT_ID="my-app-instance-01" export LOCATION_1="us-central1" # Example region where your app instance conceptually resides # Add more locations if your app components span multiple regions # export LOCATION_2="europe-west1"יצירת מוצר SaaS: הפעולה הזו יוצרת מאגר ברמה העליונה להגדרות השירות, כולל דגלים.
gcloud beta app-lifecycle-manager saas create ${SAAS_OFFERING_ID} \ --project=${PROJECT_ID} \ --location=global \ --locations=name=${LOCATION_1} # Add --locations=name=${LOCATION_2} if using more regions gcloud beta app-lifecycle-manager saas create ${SAAS_OFFERING_ID} \ --project=${PROJECT_ID} \ --location=${LOCATION_1} \ --locations=name=${LOCATION_1}יצירת סוג יחידה: כאן מגדירים את סוג הרכיב שמבצעים לו מודלינג. חשוב לציין שאנחנו לא מספקים תוכנית פעולה כי אנחנו לא מנהלים תשתית.
gcloud beta app-lifecycle-manager unit-kinds create ${UNIT_KIND_ID} \ --project=${PROJECT_ID} \ --location=global \ --saas=${SAAS_OFFERING_ID} gcloud beta app-lifecycle-manager unit-kinds create ${UNIT_KIND_ID} \ --project=${PROJECT_ID} \ --location=${LOCATION_1} \ --saas=${SAAS_OFFERING_ID}יצירת יחידה: מייצגת מופע ספציפי של האפליקציה.
gcloud beta app-lifecycle-manager units create ${UNIT_ID} \ --project=${PROJECT_ID} \ --unit-kind=${UNIT_KIND_ID} \ --location=${LOCATION_1}
הגדרה והשקה של feature flag
עכשיו יוצרים את דגל התכונה בפועל ומשתמשים במנגנון ההשקה של App Lifecycle Manager כדי שההגדרה שלו תהיה זמינה ליחידות שיצרתם.
הגדרת משתני דגל:
export FLAG_ID="standalone-flag-01" export FLAG_KEY="enable-beta-feature"יוצרים את משאב הדגל, את הגרסה ואת הגרסה שמופצת:
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} \ export FLAG_REVISION_ID_1="${FLAG_ID}-rev1" gcloud beta app-lifecycle-manager flags revisions create ${FLAG_REVISION_ID_1} \ --project=${PROJECT_ID} \ --flag=${FLAG_ID} \ --location=global export FLAG_RELEASE_ID_1="${FLAG_ID}-rel1" gcloud beta app-lifecycle-manager flags releases create ${FLAG_RELEASE_ID_1} \ --project=${PROJECT_ID} \ --flag-revisions=${FLAG_REVISION_ID_1} \ --unit-kind=${UNIT_KIND_ID} \ --location=globalיצירת סוג פריסה: מגדירים את האסטרטגיה להפצת שינויים בדגלים.
export ROLLOUT_KIND_ID="standalone-flags-rollout-kind" 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יצירת ההשקה: מתחילים את תהליך ההפצה.
export ROLLOUT_ID_1="${FLAG_ID}-rollout1" gcloud beta app-lifecycle-manager rollouts create ${ROLLOUT_ID_1} \ --project=${PROJECT_ID} \ --flag-release=${FLAG_RELEASE_ID_1} \ --rollout-kind=${ROLLOUT_KIND_ID} \ --location=globalמעקב אחר ההשקה: חשוב לוודא שהפריסה הצליחה לפני שממשיכים.
gcloud beta app-lifecycle-manager rollouts describe ${ROLLOUT_ID_1} \ --project=${PROJECT_ID} \ --location=global
הגדרת תשתית עצמאית
בהגדרה עצמאית, אתם מנהלים את אירוח האפליקציה (למשל, Cloud Run או GKE) ומשתמשים ב-App Lifecycle Manager רק לסנכרון ההגדרות. קוד האפליקציה נשאר סטנדרטי בכל הפריסות. כדי להתחבר לשירות ההגדרה של SaaS, צריך רק שמשתנה הסביבה FLAGD_SOURCE_PROVIDER_ID יהיה קיים בזמן הריצה.
אתם יכולים למפות את הגדרות היחידות של App Lifecycle Manager להגדרות הפריסה הרגילות של Terraform על ידי העברת הנתיב שנבנה כמשתנה סביבה.
הגדרת התשתית: ממפים את הנתיב בתבנית הפריסה (לדוגמה,
standalone.tf).variable "project_id" { type = string } variable "region" { type = string } variable "unit_id" { type = string } resource "google_cloud_run_v2_service" "standalone_app" { name = "my-standalone-service" location = var.region template { containers { image = "us-central1-docker.pkg.dev/my-project/my-repo/my-image:latest" env { name = "FLAGD_SOURCE_PROVIDER_ID" value = "projects/${var.project_id}/locations/${var.region}/featureFlagsConfigs/${var.unit_id}" } } } }מגדירים את ערכי המשתנים: מספקים את הפרמטרים של יחידת ההגדרה בקובץ משתנים משויך (למשל,
terraform.tfvars).project_id = "PROJECT_ID" region = "LOCATION_1" unit_id = "UNIT_ID"
שילוב והרצה של אפליקציית הדוגמה
מריצים באופן מקומי אפליקציית Python לדוגמה כדי להתחבר לשירות הדגלים של App Lifecycle Manager באמצעות הגדרות היחידה המעוצבות.
יוצרים קובץ וספרייה לפרויקט:
mkdir saas_flags_standalone_app cd saas_flags_standalone_appיצירה
requirements.txt: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יחסי תלות של התקנות:
pip install -r requirements.txtיוצרים את הקובץ app.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.contrib.provider.flagd import FlagdProvider from openfeature.contrib.provider.flagd.config import ResolverType app = Flask(__name__) logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') log = logging.getLogger(__name__) FLAG_KEY = os.environ.get("FLAG_KEY", "enable-beta-feature") DEFAULT_FLAG_VALUE = False # CRITICAL: Read the Unit resource name from environment variable. # This identifies the application instance to the flag service. provider_id = os.environ.get("FLAGD_SOURCE_PROVIDER_ID") if not provider_id: log.critical("FATAL: FLAGD_SOURCE_PROVIDER_ID not set.") sys.exit("FLAGD_SOURCE_PROVIDER_ID not set") log.info(f"Initializing OpenFeature provider for Unit: {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: credentials, detected_project_id = google.auth.default( scopes=["https://www.googleapis.com/auth/cloud-platform"] ) auth_req = google.auth.transport.requests.Request() configservice_credentials = grpc.composite_channel_credentials( grpc.ssl_channel_credentials(), grpc.metadata_call_credentials( google.auth.transport.grpc.AuthMetadataPlugin(credentials, auth_req) ), grpc.metadata_call_credentials( add_x_goog_request_params_header(provider_id) ) ) provider = FlagdProvider( resolver_type=ResolverType.IN_PROCESS, host="saasconfig.googleapis.com", port=443, sync_metadata_disabled=True, provider_id=provider_id, channel_credentials=configservice_credentials ) api.set_provider(provider) client = api.get_client() time.sleep(5) 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) sys.exit(f"Provider initialization failed: {e}") @app.route('/') def home(): log.info(f"Request received for endpoint '/', evaluating flag: {FLAG_KEY}") try: 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, "provider_id": provider_id }) except Exception as e: log.error(f"Error evaluating flag '{FLAG_KEY}': {e}", exc_info=True) 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 web server on host 0.0.0.0 port {port}") app.run(host='0.0.0.0', port=port)מריצים את האפליקציה:
export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}" python app.pyאימות ערך הדגל הראשוני: מריצים בדיקה מול נקודת הקצה המקומית במסוף משני.
curl http://localhost:8080
עדכון הדגל והפצת השינוי
משנים את מצב זמן הריצה של הגדרת הדגל ומפיצים את העדכון ליעדים המקושרים.
מעדכנים את משאב הדגל:
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} export FLAG_REVISION_ID_2="${FLAG_ID}-rev2" gcloud beta app-lifecycle-manager flags revisions create ${FLAG_REVISION_ID_2} \ --project=${PROJECT_ID} \ --flag=${FLAG_ID} \ --location=global export FLAG_RELEASE_ID_2="${FLAG_ID}-rel2" gcloud beta app-lifecycle-manager flags releases create ${FLAG_RELEASE_ID_2} \ --project=${PROJECT_ID} \ --flag-revisions=${FLAG_REVISION_ID_2} \ --unit-kind=${UNIT_KIND_ID} \ --location=globalיצירת פריסה חדשה לעדכון:
export ROLLOUT_ID_2="${FLAG_ID}-rollout2" gcloud beta app-lifecycle-manager rollouts create ${ROLLOUT_ID_2} \ --project=${PROJECT_ID} \ --flag-release=${FLAG_RELEASE_ID_2} \ --rollout-kind=${ROLLOUT_KIND_ID} \ --location=globalמעקב אחרי ההשקה החדשה:
gcloud beta app-lifecycle-manager rollouts describe ${ROLLOUT_ID_2} \ --project=${PROJECT_ID} \ --location=globalמאמתים את השינוי באפליקציה הפועלת:
curl http://localhost:8080
הסרת המשאבים
כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם בדף הזה, פועלים לפי השלבים הבאים:
- לוחצים על
Ctrl+Cבמסוף שבוapp.pyפועל כדי לעצור את אפליקציית Python המקומית. - מגדירים את מצב הדגל.
- כדי להסיר דגלים שהוצאו משימוש, צריך ליצור השקה חדשה.
אחרי שההשקה מסתיימת והדגלים שיצאו משימוש מוסרים, מוחקים את המשאבים של App Lifecycle Manager:
gcloud beta app-lifecycle-manager rollouts delete ${ROLLOUT_ID_1} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager rollouts delete ${ROLLOUT_ID_2} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager rollout-kinds delete ${ROLLOUT_KIND_ID} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager flags releases delete ${FLAG_RELEASE_ID_1} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager flags releases delete ${FLAG_RELEASE_ID_2} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager flags delete ${FLAG_ID} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager units delete ${UNIT_ID} --project=${PROJECT_ID} --location=${LOCATION_1} --quiet gcloud beta app-lifecycle-manager unit-kinds delete ${UNIT_KIND_ID} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager unit-kinds delete ${UNIT_KIND_ID} --project=${PROJECT_ID} --location=${LOCATION_1} --quiet gcloud beta app-lifecycle-manager saas delete ${SAAS_OFFERING_ID} --project=${PROJECT_ID} --location=global --quiet gcloud beta app-lifecycle-manager saas delete ${SAAS_OFFERING_ID} --project=${PROJECT_ID} --location=${LOCATION_1} --quietמחיקת הספרייה המקומית:
cd .. rm -rf saas_flags_standalone_app
המאמרים הבאים
- מידע נוסף על מושגים זמין במאמר סקירה כללית על דגלי התכונות של App Lifecycle Manager.
- כדי לראות איך הדגלים משתלבים בצורה חלקה עם פריסות שמנוהלות על ידי App Lifecycle Manager, אפשר לנסות את המדריך למתחילים בנושא פריסת דגלי תכונות.