Utiliser des flags de fonctionnalité autonomes

Découvrez comment utiliser les flags de fonctionnalité App Lifecycle Manager en tant que service autonome pour gérer la disponibilité des fonctionnalités dans vos applications, même si elles ne sont pas déployées ni gérées par App Lifecycle Manager.

Introduction

Ce guide de démarrage rapide explique comment utiliser les fonctionnalités robustes de gestion des flags de fonctionnalité et de déploiement contrôlé d'App Lifecycle Manager sans avoir à utiliser App Lifecycle Manager pour le provisionnement de l'infrastructure (comme le déploiement de VM ou de services Cloud Run à l'aide de plans Terraform). Cette approche est idéale si vous gérez votre infrastructure d'application de manière indépendante, mais que vous souhaitez utiliser App Lifecycle Manager pour une gestion sécurisée des flags de fonctionnalité.

Dans cette approche autonome, vous allez :

  1. Modéliser votre système avec des ressources App Lifecycle Manager légères : créez des Units App Lifecycle Manager pour représenter les composants de votre infrastructure existante (par exemple, un déploiement de microservice spécifique, un environnement locataire, une instance binaire unique). Ces unités agissent uniquement comme cibles pour les configurations de flag et n'impliquent pas le déploiement d'une infrastructure à l'aide de plans App Lifecycle Manager.
  2. Définir et distribuer des flags : utilisez l'API App Lifecycle Manager ou la Google Cloud console pour créer des flags de fonctionnalité. Gérez leur cycle de vie à l'aide des Rollouts App Lifecycle Manager pour assurer une propagation progressive et sécurisée des modifications de configuration à vos Units modélisées. Cela garantit la cohérence et la sécurité opérationnelles, même lorsque vous ne gérez que des flags.
  3. Intégrer à votre application : utilisez le SDK OpenFeature avec le fournisseur flagd dans le code de votre application (exécuté n'importe où : localement, sur site, dans un cloud autogéré). Configurez-le pour qu'il se connecte au service de flag App Lifecycle Manager (saasconfig.googleapis.com), s'authentifie et s'identifie à l'aide du nom de ressource Unit correspondant afin de récupérer les valeurs de flag correctes.

Cette approche vous permet de bénéficier d'une distribution de flag gérée et sécurisée sans modifier vos pipelines de déploiement ni vos outils de gestion d'infrastructure existants.

Les flags de fonctionnalité App Lifecycle Manager sont en preview privée. L'accès nécessite une liste d'autorisation. Pour demander l'accès pour votre organisation ou votre projet, remplissez ce formulaire.

Ce guide de démarrage rapide utilise une application Python de base exécutée localement pour montrer comment accéder aux flags, en simulant l'intégration de votre application existante.

Objectifs

  • Configurer un nouveau Google Cloud projet ou en utiliser un existant.
  • Activer les API requises (App Lifecycle Manager et SaaS Config).
  • Accorder les autorisations Identity and Access Management nécessaires pour la création de ressources et la lecture de flags.
  • Créer des ressources App Lifecycle Manager minimales (offre d'application, type d'unité, unité) pour modéliser un composant d'application sans déployer d'infrastructure.
  • Définir une ressource de flag de fonctionnalité associée au type d'unité.
  • Créer un mécanisme de déploiement de flag (type de déploiement) définissant la stratégie de distribution.
  • Distribuer la configuration de flag initiale à l'aide d'un déploiement App Lifecycle Manager.
  • Exécuter localement un exemple d'application Python qui se connecte au service de flag App Lifecycle Manager et évalue le flag pour l'unité modélisée.
  • Mettre à jour la valeur du flag, créer une version de flag et distribuer la modification.
  • Vérifier que l'application récupère la valeur de flag mise à jour.

Avant de commencer

  1. Connectez-vous à votre compte Google.

    Si vous n'en possédez pas déjà un, vous devez en créer un.

  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 and SaaS Config APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. 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.

    Enable the APIs

  5. Install the Google Cloud CLI.

  6. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  7. To initialize the gcloud CLI, run the following command:

    gcloud init
  8. 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

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

  10. 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.enable permission. 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.

    Enable the APIs

  11. Install the Google Cloud CLI.

  12. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  13. To initialize the gcloud CLI, run the following command:

    gcloud init
  14. Installer Python : assurez-vous que Python 3.7 ou une version ultérieure est installé sur la machine sur laquelle vous exécuterez l'exemple d'application. Vous avez également besoin de pip pour installer les dépendances.
    python --version
    pip --version
  15. Authentifier gcloud pour les identifiants par défaut de l'application (ADC) : le script Python local utilise les ADC pour s'authentifier auprès des Google Cloud services. Connectez-vous à l'aide de votre compte utilisateur :
    gcloud auth application-default login
  16. Accorder des autorisations d'identité d'application : votre application a besoin d'une autorisation pour lire les configurations de flag à partir du service SaaS Config. Accordez le rôle `roles/saasconfig.viewer` à l'identité que l'application utilisera. Pour ce guide de démarrage rapide qui utilise les ADC localement avec votre compte utilisateur, accordez le rôle à votre adresse e-mail :
        gcloud projects add-iam-policy-binding PROJECT_ID \
            --member="user:YOUR_EMAIL_ADDRESS" \
            --role="roles/saasconfig.viewer"
    Remplacez PROJECT_ID par l'ID de votre Google Cloud projet et YOUR_EMAIL_ADDRESS par l'adresse e-mail associée à votre identifiant de connexion à la CLI.

Créer des ressources App Lifecycle Manager minimales

Même si nous ne déployons pas d'infrastructure avec App Lifecycle Manager, nous avons besoin de quelques ressources pour organiser, cibler et distribuer nos flags en toute sécurité. Ces ressources représentent vos composants d'application existants dans App Lifecycle Manager.

  1. Définir des variables : définissez des variables d'environnement pour les noms et les emplacements des ressources.

    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"
    
  2. Créer une offre d'application : elle sert de conteneur de premier niveau pour la configuration de votre service, y compris les flags.

    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} 
    
  3. Créer un type d'unité : il définit le type de composant que vous modélisez. Il est essentiel de ne pas fournir de plan, car nous ne gérons pas l'infrastructure.

    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}
    
  4. Créer une unité : elle représente une instance spécifique de votre application.

    gcloud beta app-lifecycle-manager units create ${UNIT_ID} \
      --project=${PROJECT_ID} \
      --unit-kind=${UNIT_KIND_ID} \
      --location=${LOCATION_1} 
    

Définir et déployer le flag de fonctionnalité

Créez maintenant le flag de fonctionnalité et utilisez le mécanisme de déploiement App Lifecycle Manager pour rendre sa configuration disponible pour les unités que vous avez créées.

  1. Définir des variables de flag :

    export FLAG_ID="standalone-flag-01"
    export FLAG_KEY="enable-beta-feature" 
    
  2. Créer la ressource, la révision et la version du 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
    
  3. Créer un type de déploiement : définissez la stratégie de distribution des modifications de flag.

    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
    
  4. Créer le déploiement : lancez le processus de distribution.

    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
    
  5. Surveiller le déploiement : assurez-vous que le déploiement réussit avant de continuer.

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

Configurer une infrastructure autonome

Dans une configuration autonome, vous gérez votre propre hébergement d'application (par exemple, Cloud Run ou GKE) et utilisez App Lifecycle Manager uniquement pour Config Sync. Le code de l'application reste standard dans tous les déploiements. Il nécessite uniquement que la variable d'environnement FLAGD_SOURCE_PROVIDER_ID soit présente au moment de l'exécution pour se connecter au service SaaS Config.

Vous pouvez mapper vos définitions d'unité App Lifecycle Manager dans vos définitions de déploiement Terraform standards en transmettant le chemin construit en tant que variable d'environnement.

  1. Définir votre infrastructure : mappez le chemin dans votre modèle de déploiement (par exemple, 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}"
          }
        }
      }
    }
    
  2. Définir les valeurs de vos variables : fournissez les paramètres de l'unité de configuration dans un fichier de variables associé (par exemple, terraform.tfvars).

    project_id = "PROJECT_ID"
    region     = "LOCATION_1"
    unit_id    = "UNIT_ID"
    

Intégrer et exécuter l'exemple d'application

Exécutez un exemple d'application Python localement pour vous connecter au service de flag App Lifecycle Manager à l'aide des configurations d'unité modélisées.

  1. Créer un répertoire et des fichiers de projet :

    mkdir saas_flags_standalone_app
    cd saas_flags_standalone_app
    

    Créez 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
    

    Installez les dépendances :

    pip install -r requirements.txt
    
  2. Créez 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)
    
  3. Exécutez l'application :

    export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"
    python app.py
    
  4. Vérifiez la valeur de flag initiale : exécutez une vérification par rapport au point de terminaison local dans un terminal secondaire.

    curl http://localhost:8080
    

Mettre à jour le flag et distribuer la modification

Modifiez l'état d'exécution de la définition de flag et distribuez la mise à jour aux cibles connectées.

  1. Mettre à jour la ressource de 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_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
    
  2. Créer un déploiement pour la mise à jour :

    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
    
  3. Surveiller le nouveau déploiement :

    gcloud beta app-lifecycle-manager rollouts describe ${ROLLOUT_ID_2} \
      --project=${PROJECT_ID} \
      --location=global 
    
  4. Vérifier la modification dans l'application en cours d'exécution :

    curl http://localhost:8080
    

Effectuer un nettoyage

Pour éviter que les ressources utilisées dans cette démonstration soient facturées sur votre Google Cloud compte pour les ressources utilisées sur cette page, procédez comme suit :

  1. Appuyez sur Ctrl+C dans le terminal où app.py est en cours d'exécution pour arrêter l'application Python locale.
  2. Définissez l'état du flag.
  3. Créez un déploiement pour supprimer les flags obsolètes.
  4. Une fois le déploiement terminé et les flags obsolètes supprimés, supprimez les ressources 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 
    
  5. Supprimez le répertoire local :

    cd ..
    rm -rf saas_flags_standalone_app
    

Étape suivante