שימוש במתגי feature flag עצמאיים
איך משתמשים ב-feature flags של App Lifecycle Manager כשירות נפרד כדי לנהל את הזמינות של תכונות באפליקציות, גם אם האפליקציות האלה לא נפרסו או מנוהלות על ידי App Lifecycle Manager.
מבוא
במדריך למתחילים הזה נסביר איך להשתמש ביכולות המתקדמות של App Lifecycle Manager לניהול של feature flags והשקות מבוקרות, בלי להשתמש ב-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בקוד האפליקציה (שפועל בכל מקום – באופן מקומי, on-premises, בענן בניהול עצמי). מגדירים את האפליקציה כך שתתחבר לשירות הדגלים של App Lifecycle Manager (saasconfig.googleapis.com), תבצע אימות ותזהה את עצמה באמצעות שם המשאב התואם שלUnitכדי לאחזר את ערכי הדגלים הנכונים.
הגישה הזו מאפשרת לכם ליהנות מהפצה מנוהלת ובטוחה של דגלים בלי לשנות את צינורות עיבוד הנתונים לפריסה או את הכלים לניהול התשתית.
ה-feature flags של App Lifecycle Manager נמצאים בגרסת טרום-השקה פרטית. כדי לקבל גישה, צריך להוסיף את המשתמש לרשימת ההיתרים. כדי לבקש גישה לארגון או לפרויקט, מלאו את הטופס הזה.
במדריך למתחילים הזה נשתמש באפליקציית Python בסיסית שפועלת באופן מקומי כדי להדגים את הגישה לדגלים, ולדמות את אופן השילוב של האפליקציה הקיימת שלכם.
מטרות
- מגדירים פרויקט חדש ב- Google Cloud או משתמשים בפרויקט קיים.
- מפעילים את ממשקי ה-API הנדרשים (App Lifecycle Manager ו-SaaS Config).
- לתת את ההרשאות הנדרשות לניהול זהויות והרשאות גישה (IAM) כדי ליצור משאבים ולקרוא דגלים.
- יוצרים משאבים מינימליים של App Lifecycle Manager (הצעת אפליקציה, סוג יחידה, יחידה) כדי ליצור מודל של רכיב באפליקציה בלי לפרוס תשתית.
- מגדירים משאב של feature flag שמשויך לסוג היחידה.
- יוצרים מנגנון השקה של דגל (סוג השקה) שמגדיר את אסטרטגיית ההפצה.
- מפיצים את ההגדרה הראשונית של הדגל באמצעות השקה של App Lifecycle Manager.
- מריצים באופן מקומי אפליקציית Python לדוגמה שמתחברת לשירות הדגלים של App Lifecycle Manager ומעריכה את הדגל של היחידה המעוצבת.
- מעדכנים את ערך הדגל, יוצרים גרסה חדשה של הדגל ומפיצים את השינוי.
- מוודאים שהאפליקציה משתמשת בערך המעודכן של הדגל.
לפני שמתחילים
-
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, if any are not already enabled.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.-
Install the Google Cloud CLI.
-
Configure the gcloud CLI to use your federated identity.
For more information, see Sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init -
התקנת Python: ודאו שמותקנת גרסה 3.7 ומעלה של Python במכונה שבה תפעילו את האפליקציה לדוגמה. צריך גם את pip כדי להתקין יחסי תלות.
python --version
pip --version
-
אימות של gcloud ל-Application Default Credentials (ADC): סקריפט Python המקומי משתמש ב-ADC כדי לאמת את שירותי Google Cloud . נכנסים באמצעות חשבון המשתמש:
gcloud auth application-default login
-
מתן הרשאות לזהות האפליקציה: האפליקציה צריכה הרשאה לקרוא את הגדרות הדגלים משירות SaaS Config. מקצים את התפקיד `roles/saasconfig.viewer` לזהות שבה האפליקציה תשתמש. במדריך למתחילים הזה, שבו משתמשים ב-ADC באופן מקומי עם חשבון המשתמש, מקצים את התפקיד לכתובת האימייל שלכם:
מחליפים את PROJECT_ID במזהה הפרויקט ב- Google Cloud ואת YOUR_EMAIL_ADDRESS בכתובת האימייל שמשויכת להתחברות ל-CLI.gcloud 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"יצירת חבילת אפליקציה: החבילה הזו משמשת כמאגר ברמה העליונה להגדרות של השירות, כולל דגלים.
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
עכשיו, יוצרים את ה-feature flag בפועל ומשתמשים במנגנון ההשקה של App Lifecycle Manager כדי להפוך את ההגדרות שלו לזמינות ביחידות שיצרתם.
הגדרת משתני דגל:
export FLAG_ID="standalone-flag-01" export FLAG_KEY="enable-beta-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} \ 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 רק לסנכרון ההגדרות האישיות. קוד האפליקציה נשאר סטנדרטי בכל הפריסות. צריך רק שמשתנה הסביבה FLAGD_SOURCE_PROVIDER_ID יהיה קיים בזמן הריצה כדי להתחבר ל-SaaS Config Service.
כדי למפות את הגדרות היחידות של 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 על המשאבים שבהם השתמשתם בדף הזה, מבצעים את הפעולות הבאות.
- כדי לעצור את אפליקציית Python המקומית, מקישים על
Ctrl+Cבטרמינל שבו פועלapp.py. - מגדירים את מצב הדגל.
- כדי להסיר סימונים מיושנים, צריך ליצור השקה חדשה.
אחרי שההשקה מסתיימת והדגלים המיושנים הוסרו, מוחקים את המשאבים של 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
המאמרים הבאים
- מידע נוסף זמין במאמר סקירה כללית על ה-feature flags של App Lifecycle Manager.
- כדי לראות איך feature flags משתלבים בצורה הדוקה עם פריסות שמנוהלות על ידי App Lifecycle Manager, נסו את המדריך למתחילים בנושא פריסת feature flags.