Step 8: Install hybrid runtime

Apply the configuration to the cluster

Use the following steps to install Apigee hybrid into your cluster:

  1. Be sure that you are in the hybrid-base-directory/hybrid-files directory.
    cd $HYBRID_FILES
  2. Verify that kubectl is set to the correct context using the following command. The current context should be set to the cluster to which you are deploying Apigee hybrid.
    kubectl config current-context

    The result should include the name of the cluster you are deploying Apigee hybrid in. For example, on GKE, the context name is usually in the form gke_project-id_cluster-location_cluster-name, as in:

    gke_my-project_us-central1_my-cluster

    If the name cluster name in the context does not match, the following command will get the gcloud credentials of the cluster and set the kubectl context:

    Regional clusters

    gcloud container clusters get-credentials $CLUSTER_NAME \
    --region $CLUSTER_LOCATION \
    --project $PROJECT_ID

    Zonal clusters

    gcloud container clusters get-credentials $CLUSTER_NAME \
    --zone $CLUSTER_LOCATION \
    --project $PROJECT_ID
  3. For Anthos on bare metal, AWS on GKE, EKS, and GKE on prem platforms only, Verify that the KUBECONFIG variable is set using the following command:
    echo ${KUBECONFIG}
  4. Do a dry run initialization. Doing a dry run lets you check for any errors before any changes are made to the cluster. Execute the init command with the --dry-run flag as follows:
    ${APIGEECTL_HOME}/apigeectl init -f overrides/overrides.yaml --dry-run=client
  5. If there are no errors, execute the init command as follows:
    ${APIGEECTL_HOME}/apigeectl init -f overrides/overrides.yaml

    The init command installs the Apigee deployment services Apigee Deployment Controller and Apigee Admission Webhook.

  6. To check the status of the deployment, you can use the following commands:
    ${APIGEECTL_HOME}/apigeectl check-ready -f overrides/overrides.yaml
    kubectl get pods -n apigee-system
    kubectl get pods -n apigee

    When the pods are ready, go to the next step.

  7. Do a dry run install. Execute the apply command with the --dry-run flag.
    ${APIGEECTL_HOME}/apigeectl apply -f overrides/overrides.yaml --dry-run=client
  8. If there are no errors, you can apply the Apigee-specific runtime components to the cluster with the following command:
    ${APIGEECTL_HOME}/apigeectl apply -f overrides/overrides.yaml
  9. To check the status of the deployment, run the following command:
    ${APIGEECTL_HOME}/apigeectl check-ready -f overrides/overrides.yaml

    Repeat this step until the pods are all ready. The pods may take several minutes to start up.

GKE with Workload Identity

If you are using Workload Identity on GKE, follow these instructions to associate the Kubernetes service accounts created by apigeectl with the Google service accounts you created in Step 4: Create service accounts and credentials.

These procedures make use of the following environment variables. Either set these in your command shell or replace them in the code samples with the actual values:

  • APIGEECTL_HOME: The directory where you have installed apigeectl.
  • CLUSTER_LOCATION: The region or zone of your cluster, for example: us-west1.
  • CLUSTER_LOCATION: The name of your cluster.
  • ENV_NAME: Then name of the Apigee environment.
  • NAMESPACE: your Apigee namespace. By default, apigee.
  • HYBRID_FILES: Your hybrid files directory, for example hybrid-base-directory/hybrid-files.
  • ORG_NAME: The name of your Apigee organization.
  • PROJECT_ID: The ID of your Google Cloud project.

Verify the environment variables:

echo $APIGEECTL_HOME
echo $CLUSTER_LOCATION
echo $ENV_NAME
echo $HYBRID_FILES
echo $NAMESPACE
echo $ORG_NAME
echo $PROJECT_ID

Initialize any of the variables you need:

export APIGEECTL_HOME=hybrid-base-directory/apigeectl
export CLUSTER_LOCATION=my-cluster-location
export ENV_NAME=my-environment-name
export HYBRID_FILES=hybrid-base-directory/hybrid-files
export NAMESPACE=apigee
export ORG_NAME=$PROJECT_ID
export PROJECT_ID=my-project-id
  1. Optional: Delete the service account key files.

    When running Apigee hybrid on GKE, the standard practice is to create and download private keys (.json files) for each of the service accounts. When using Workload Identity, you do not need to download service account private keys and add them to GKE clusters.

    You can delete the key files with the following command:

    rm $HYBRID_FILES/service-accounts/*.json
  2. Check that the current gcloud configuration to your Google Cloud project ID with the following command:
    gcloud config get project
  3. If needed, set the current gcloud configuration:

    gcloud config set project $PROJECT_ID
  4. Create the apigee-cassandra-restore Kubernetes service account.

    When you applied your configuration by running apigeectl apply, the command created most of the Kubernetes service accounts needed for workload identity.

    To create the apigee-cassandra-restore Kubernetes service account, run apigeectl apply with the --restore flag:

    $APIGEECTL_HOME/apigeectl apply -f $HYBRID_FILES/overrides/overrides.yaml --restore
  5. Verify that Workload Identity is enabled for your GKE Cluster. When you created the cluster in Step 1: Create a cluster, step 6 was to Enable Workload Identity. You can confirm if Workload Identity is enabled by running the following command:

    Regional clusters

    gcloud container clusters describe $CLUSTER_NAME \
      --region $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten 'workloadIdentityConfig'

    Zonal clusters

    gcloud container clusters describe $CLUSTER_NAME \
      --zone $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten 'workloadIdentityConfig'

    If Workload identity is enabled for the cluster, the output should look like the following:

      ---
      workloadPool: PROJECT_ID.svc.id.goog

    If you see null instead in your results, run the following command to enable Workload identity for your cluster:

    Regional clusters

    gcloud container clusters update $CLUSTER_NAME \
      --workload-pool=$PROJECT_ID.svc.id.goog \
      --project $PROJECT_ID \
      --region $CLUSTER_LOCATION

    Zonal clusters

    gcloud container clusters update  $CLUSTER_NAME \
      --workload-pool=$PROJECT_ID.svc.id.goog \
      --zone $CLUSTER_LOCATION \
      --project $PROJECT_ID
  6. Verify that Workload identity is enabled on your node pools with the following commands:

    Regional clusters

    gcloud container node-pools describe apigee-data \
      --cluster $CLUSTER_NAME \
      --region $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten "config:"
    gcloud container node-pools describe apigee-runtime \
      --cluster $CLUSTER_NAME \
      --region $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten "config:"

    Zonal clusters

    gcloud container node-pools describe apigee-data \
      --cluster $CLUSTER_NAME \
      --zone $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten "config:"
    gcloud container node-pools describe apigee-runtime \
      --cluster $CLUSTER_NAME \
      --zone $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --flatten "config:"

    Your output should look something like:

    ---
    diskSizeGb: 100
    diskType: pd-standard
    ...
    workloadMetadataConfig:
      mode: GKE_METADATA
        

    If your output does not contain a line for workloadMetadataConfig:, enable Workload identity for each node pool with the following commands. This operation can take up to 30 minutes:

    Regional clusters

    gcloud container node-pools update NODE_POOL_NAME \
      --cluster=$CLUSTER_NAME \
      --region $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --workload-metadata=GKE_METADATA

    Zonal clusters

    gcloud container node-pools update NODE_POOL_NAME \
      --cluster=$CLUSTER_NAME \
      --zone $CLUSTER_LOCATION \
      --project $PROJECT_ID \
      --workload-metadata=GKE_METADATA

    Where NODE_POOL_NAME is the name of each node pool. In most Apigee hybrid installations, the two default node pools are named apigee-data and apigee-runtime.

  7. Check the names of the Google service accounts for your project with the following command:
    gcloud iam service-accounts list --project $PROJECT_ID

    Your output should look something like:

    Non-prod

    For non-production environments:

    DISPLAY NAME         EMAIL                                                      DISABLED
    apigee-non-prod      apigee-non-prod@my_project_id.iam.gserviceaccount.com      False
    

    Prod

    For non-production environments:

    DISPLAY NAME         EMAIL                                                      DISABLED
    apigee-cassandra     apigee-cassandra@my_project_id.iam.gserviceaccount.com     False
    apigee-logger        apigee-logger@my_project_id.iam.gserviceaccount.com        False
    apigee-mart          apigee-mart@my_project_id.iam.gserviceaccount.com          False
    apigee-metrics       apigee-metrics@my_project_id.iam.gserviceaccount.com       False
    apigee-runtime       apigee-runtime@my_project_id.iam.gserviceaccount.com       False
    apigee-synchronizer  apigee-synchronizer@my_project_id.iam.gserviceaccount.com  False
    apigee-udca          apigee-udca@my_project_id.iam.gserviceaccount.com          False
    apigee-watcher       apigee-watcher@my_project_id.iam.gserviceaccount.com       False
    
  8. Verify the service accounts with the following command:
    kubectl get sa -n $NAMESPACE

    Your output should look something like the following. The Kubernetes service accounts in bold are the ones you will need to annotate with your Google service accounts:

    NAME                                                         SECRETS   AGE
    apigee-cassandra-backup                                      1         11m
    apigee-cassandra-restore                                     1         11m
    apigee-cassandra-schema-setup-my-project-id-123abcd-sa       1         11m
    apigee-cassandra-schema-val-my-project-id-123abcd            1         11m
    apigee-cassandra-user-setup-my-project-id-123abcd-sa         1         11m
    apigee-connect-agent-my-project-id-123abcd-sa                1         11m
    apigee-datastore-default-sa                                  1         11m
    apigee-ingressgateway                                        1         11m
    apigee-ingressgateway-my-project-id-123abcd                  1         11m
    apigee-ingressgateway-manager                                1         11m
    apigee-init                                                  1         11m
    apigee-mart-my-project-id-123abcd-sa                         1         11m
    apigee-metrics-sa                                            1         11m
    apigee-mint-task-scheduler-my-project-id-123abcd-sa          1         11m
    apigee-redis-default-sa                                      1         11m
    apigee-redis-envoy-default-sa                                1         11m
    apigee-runtime-my-project-id-env-name-234bcde-sa             1         11m
    apigee-synchronizer-my-project-id-env-name-234bcde-sa        1         11m
    apigee-udca-my-project-id-123abcd-sa                         1         11m
    apigee-udca-my-project-id-env-name-234bcde-sa                1         11m
    apigee-watcher-my-project-id-123abcd-sa                      1         11m
    default                                                      1         11m
        
  9. For each Apigee component annotate the corresponding Kubernetes service accounts with the Google service account for the component.

    The following steps use two environment variables. You will reset the values of these variables before each set of commands:

    • GSA_NAME: The name of a Google service account. These are the service accounts you created with the create-service-account tool in Step 4: Create service accounts.
    • KSA_NAME: The name of a Kubernetes service account. These are the accounts you listed above with the kubectl get sa -n $NAMESPACE command, for example: apigee-cassandra-schema-setup-hybrid-example-project-123abcd-sa.
    • Cassandra

      The Cassandra component has six associated Kubernetes service accounts:

      • apigee-cassandra-backup
      • apigee-cassandra-restore
      • apigee-cassandra-schema-setup
      • apigee-cassandra-schema-val (val = validation)
      • apigee-cassandra-user-setup
      • apigee-datastore-default

      Non-prod

      The following steps use two environment variables. You will reset the values of these variables before each set of commands:

      • GSA_NAME: The name of a Google service account. These are the service accounts you created with the create-service-account tool in Step 4: Create service accounts.
      • KSA_NAME: The name of a Kubernetes service account. These are the accounts you listed above with the kubectl get sa -n $NAMESPACE command.

      apigee-cassandra-backup Kubernetes service account

      1. Define the KSA_NAME and GSA_NAME environment variables:
        GSA_NAME="apigee-non-prod"
        KSA_NAME="apigee-cassandra-backup"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

        Your output should have a line describing the annotation, similar to:

        Annotations:         iam.gke.io/gcp-service-account: apigee-non-prod@my-project-id.iam.gserviceaccount.com

      apigee-cassandra-restore Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-restore"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-schema-setup Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-schema-setup-service-account-name-sa"
        for example: apigee-cassandra-schema-setup-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-schema-val Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-schema-val-service-account-name"
        for example: apigee-cassandra-schema-val-hybrid-example-project-123abcd.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-user-setup Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-user-setup-service-account-name-sa"
        for example: apigee-cassandra-user-setup-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-datastore-default-sa Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-datastore-default-sa"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      apigee-cassandra-backup Kubernetes service account

      1. Define the KSA_NAME and GSA_NAME environment variables:
        GSA_NAME="apigee-cassandra"
        KSA_NAME="apigee-cassandra-backup"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
      5. Your output should have a line describing the annotation, similar to:

        Annotations:         iam.gke.io/gcp-service-account: apigee-cassandra@my-project-id.iam.gserviceaccount.com
      6. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-restore Kubernetes service account

      1. Redefine the KSA_NAME environment variable:

        KSA_NAME="apigee-cassandra-restore"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com

      apigee-cassandra-schema-setup Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-schema-setup-service-account-name-sa"
        for example: apigee-cassandra-schema-setup-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:

        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-schema-val Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-schema-val-service-account-name"
        for example: apigee-cassandra-schema-val-hybrid-example-project-123abcd.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-cassandra-user-setup Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-cassandra-user-setup-service-account-name-sa"
        for example: apigee-cassandra-user-setup-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      apigee-datastore-default-sa Kubernetes service account

      1. Redefine the KSA_NAMEenvironment variable:

        KSA_NAME="apigee-datastore-default-sa"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • Apigee Connect

      Non-prod

      1. Define the KSA_NAME environment variable:

        KSA_NAME="apigee-connect-agent-service-account-name-sa"
        for example: apigee-connect-agent-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:
        GSA_NAME="apigee-mart"
        KSA_NAME="apigee-connect-agent-service-account-name-sa"
        for example: apigee-connect-agent-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • MART

      Non-prod

      1. Define the KSA_NAME environment variable:

        KSA_NAME="apigee-mart-service-account-name-sa"
        for example: apigee-mart-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-mart"
        KSA_NAME="apigee-mart-service-account-name-sa"
        for example: apigee-mart-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • Apigee metrics

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-metrics-sa"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-metrics"
        KSA_NAME="apigee-metrics-sa"
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
        $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
        --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
        --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • UDCA (org-level)

      UDCA is implemented in both organization-level and environment-level scopes. Therefore, there are two separate Kubernetes service accounts for UDCA, one for each scope. You can tell them apart by the name of the account. The env-scope account includes the environment name in the service account name. For example:

      • Org-level: apigee-udca-my-project-id-123abcd-sa where my-project-id is the name project ID.
      • Env-level: apigee-udca-my-project-id-my-env-234bcde-sa where my-env is the name of the environment.

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-udca-service-account-name-sa"
        for example: apigee-udca-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
          gcloud iam service-accounts add-iam-policy-binding \
            --role roles/iam.workloadIdentityUser \
            --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
            $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
            --project $PROJECT_ID
      3. Annotate the service account:
          kubectl annotate serviceaccount \
            --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-udca"
        KSA_NAME="apigee-udca-service-account-name-sa"
        for example: apigee-udca-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • Apigee Watcher

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-watcher-service-account-name-sa"
        for example: apigee-watcher-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-watcher"
        KSA_NAME="apigee-watcher-service-account-name-sa"
        for example: apigee-watcher-hybrid-example-project-123abcd-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • Runtime

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-runtime-env-level-service-account-name-sa"
        for example: apigee-runtime-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-runtime"
        KSA_NAME="apigee-runtime-env-level-service-account-name-sa"
        for example: apigee-runtime-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • Synchronizer

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-synchronizer-env-level-service-account-name-sa"
        for example: apigee-synchronizer-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-synchronizer"
        KSA_NAME="apigee-synchronizer-env-level-service-account-name-sa"
        for example: apigee-synchronizer-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
    • UDCA (env-level)

      Non-prod

      1. Define the KSA_NAMEenvironment variables:

        KSA_NAME="apigee-udca-env-level-service-account-name-sa"
        for example: apigee-udca-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME

      Prod

      1. Define the KSA_NAME and GSA_NAME environment variables:

        GSA_NAME="apigee-udca"
        KSA_NAME="apigee-udca-env-level-service-account-name-sa"
        for example: apigee-udca-hybrid-example-project-example-env-234bcde-sa.
      2. Bind the IAM role:
        gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \
          $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
          --project $PROJECT_ID
      3. Annotate the service account:
        kubectl annotate serviceaccount \
          --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
      4. Verify the annotation:
        kubectl describe serviceaccount \
          --namespace $NAMESPACE $KSA_NAME
  10. (Optional) You can see the status of your Kubernetes service accounts in the Kubernetes: Workloads Overview page in the Google Cloud Console.

    Go to Workloads

  11. To check the status of the deployment again with apigeectl check-ready:
    ${APIGEECTL_HOME}/apigeectl check-ready -f ${HYBRID_FILES}/overrides/overrides.yaml
1 2 3 4 5 6 7 8 (NEXT) Step 9: Expose Apigee ingress 10