フィーチャー トグルをスタンドアロンで使用する
App Lifecycle Manager でデプロイまたは管理されていないアプリケーションでも、App Lifecycle Manager のフィーチャー トグルをスタンドアロン サービスとして使用して、アプリケーションの機能の可用性を管理する方法について説明します。
はじめに
このクイックスタートでは、インフラストラクチャのプロビジョニング(Terraform ブループリントを使用した VM や Cloud Run サービスのデプロイなど)に App Lifecycle Manager を使用しなくても、App Lifecycle Manager の堅牢なフィーチャー トグルと制御されたロールアウト機能を使用する方法について説明します。この方法は、アプリケーション インフラストラクチャを個別に管理しているが、安全なフィーチャー トグル管理に App Lifecycle Manager を使用 したい場合に最適です。
このスタンドアロン アプローチでは、次のことを行います。
- 軽量の App Lifecycle Manager リソースを使用してシステムをモデル化する: App Lifecycle Manager
Unitsを作成して、既存のインフラストラクチャのコンポーネント(特定のマイクロサービス デプロイ、テナント環境、単一のバイナリ インスタンスなど)を表します。これらのユニットは、フラグ構成のターゲットとしてのみ機能し、App Lifecycle Manager ブループリントを使用したインフラストラクチャのデプロイは行いません 。 - フラグを定義して配布する: App Lifecycle Manager API または Google Cloud コンソールを使用して、フィーチャー トグルを作成します。App Lifecycle Manager
Rolloutsを使用してライフサイクルを管理し、モデル化されたUnitsへの構成変更を安全かつ段階的に伝播させます。これにより、フラグのみを管理する場合でも、オペレーションの一貫性と安全性が確保されます。 - アプリケーションと統合する: アプリケーション コード(ローカル、オンプレミス 、セルフマネージド クラウドなど、任意の場所で実行)で
flagdプロバイダとともに OpenFeature SDK を使用します。App Lifecycle Manager フラグサービス(saasconfig.googleapis.com)に接続し、認証を行い、対応するUnitリソース名を使用して 自身を識別して、正しいフラグ値を取得するように構成します。
このアプローチでは、既存のデプロイ パイプラインやインフラストラクチャ管理ツールを変更することなく、マネージドで安全なフラグ配布のメリットを享受できます。
App Lifecycle Manager のフィーチャー トグルは限定公開プレビュー 版です。アクセスには許可リストへの登録が必要です。組織またはプロジェクトのアクセスをリクエストするには、こちらのフォームにご記入ください。
このクイックスタートでは、ローカルで実行される基本的な Python アプリケーションを使用して、フラグへのアクセス方法を示し、既存のアプリケーションがどのように統合されるかをシミュレートします。
目標
- 新しい Google Cloud プロジェクトを設定するか、既存のプロジェクトを使用します。
- 必要な API(App Lifecycle Manager と SaaS Config)を有効にします。
- リソースの作成とフラグの読み取りに必要な Identity and Access Management 権限を付与します。
- インフラストラクチャをデプロイせずにアプリケーション コンポーネントをモデル化するために、最小限の App Lifecycle Manager リソース(SaaS オファリング、ユニットの種類、ユニット)を作成します。
- ユニットの種類に関連付けられたフィーチャー トグルリソースを定義します。
- 配布戦略を定義するフラグ ロールアウト メカニズム(ロールアウトの種類)を作成します。
- App Lifecycle Manager のロールアウトを使用して、初期フラグ構成を配布 します。
- App Lifecycle Manager フラグサービスに接続し、モデル化されたユニットのフラグを評価するサンプル Python アプリケーションをローカルで実行します。
- フラグ値を更新し、新しいフラグリリースの作成し、変更を配布 します。
- アプリケーションが更新されたフラグ値を取得していることを確認します。
始める前に
-
ログイン Google アカウントにログインします。
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.-
Google Cloud CLI をインストールします。
-
外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。
-
gcloud CLI を初期化するには、次のコマンドを実行します:
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.-
Google Cloud CLI をインストールします。
-
外部 ID プロバイダ(IdP)を使用している場合は、まず連携 ID を使用して gcloud CLI にログインする必要があります。
-
gcloud CLI を初期化するには、次のコマンドを実行します:
gcloud init -
Python をインストールする: サンプル アプリケーションを実行するマシンに Python 3.7 以降がインストールされていることを確認します。依存関係をインストールするには、pip も必要です。
python --version
pip --version
-
アプリケーションのデフォルト認証情報(ADC)の gcloud を認証する: ローカル Python スクリプトは ADC を使用して Google Cloud サービスを認証します。ユーザー アカウントを使用してログインします。
gcloud auth application-default login
-
アプリケーション ID の権限を付与する: アプリケーションには、SaaS Config サービスからフラグ構成を読み取る権限が必要です。アプリケーションが使用する ID に `roles/saasconfig.viewer` ロールを付与します。このクイックスタートでは、ユーザー アカウントで ADC をローカルで使用するため、メールアドレスにロールを付与します。
PROJECT_ID は実際の Google Cloud プロジェクト ID に、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"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}
フィーチャー トグルを定義してロールアウトする
次に、実際のフィーチャー トグルを作成し、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 Config サービスに接続するには、ランタイムに 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"
サンプル アプリケーションを統合して実行する
モデル化されたユニット構成を使用して App Lifecycle Manager フラグサービスに接続するサンプル Python アプリケーションをローカルで実行します。
プロジェクト ディレクトリとファイルを作成する:
mkdir saas_flags_standalone_app cd saas_flags_standalone_apprequirements.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.txtapp.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 アカウントに課金されないようにするには、 次の手順を実施します。
app.pyが実行されているターミナルでCtrl+Cを押して、ローカル 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 で管理されるデプロイとどのように緊密に統合されるかを確認してください。