watcher: serviceAccountRef: my-watcher-k8s-secret
See:
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:
PROJECT_ID
: The ID of your Google Cloud project.ORG_NAME
: The name of your Apigee organization.ENV_NAME
: The name of the Apigee environment.NAMESPACE
: The name of your Apigee namespace. This is usually apigee
.CLUSTER_NAME
: The name of your cluster.CLUSTER_LOCATION
: The region or zone of your cluster, for example: us-west1
.APIGEECTL_HOME
: The directory where you have installed apigeectl
.HYBRID_FILES
: Your hybrid files directory, for example hybrid-base-directory/hybrid-files
.Verify the environment variables:
echo $PROJECT_IDecho $ORG_NAME
echo $ENV_NAME
echo $NAMESPACE
echo $CLUSTER_NAME
echo $CLUSTER_LOCATION
echo $APIGEECTL_HOME
echo $HYBRID_FILES
Initialize any of the variables you need:
export PROJECT_ID=my-project-idexport ORG_NAME=$PROJECT_ID
export ENV_NAME=my-environment-name
export NAMESPACE=apigee
export CLUSTER_NAME=my-cluster-name
export CLUSTER_LOCATION=my-cluster-location
export APIGEECTL_HOME=hybrid-base-directory/apigeectl
export HYBRID_FILES=hybrid-base-directory/hybrid-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.
If you have downloaded service account key files as part of your Apigee hybrid installation, you can delete them after enabling Workload Identity. In most installations, they reside in the hybrid-base-directory/hybrid-files/service-accounts/
directory.
To begin, follow the instructions in Prepare to enable Workload Identity to update node pools and initialize variables prior to enabling Workload Identity.
Then, follow the instructions in Set workloadIdentityEnabled: true
and create service accounts to enable Workload Identity on your Apigee hybrid installation.
Before starting the install process, follow the steps in this section.
gcloud config set project $PROJECT_ID
gcloud
credentials of the cluster on which you are enabling Workload Identity with the following command: gcloud container clusters get-credentials ${CLUSTER_NAME} \ --region ${CLUSTER_LOCATION} \ --project ${PROJECT_ID}
gcloud container clusters describe $CLUSTER_NAME --region $CLUSTER_LOCATION --project $PROJECT_ID
The output should include something like the following:
……status:RUNNINGsubnetwork:defaultworkloadIdentityConfig:workloadPool:my-project-id.svc.id.goog
If needed, enable workload identity on the cluster. This operation can take up to 30 minutes:
gcloud container clusters update $CLUSTER_NAME \ --workload-pool=$PROJECT_ID.svc.id.goog \ --project $PROJECT_ID \ --region $CLUSTER_LOCATION
For more information, see Enable Workload Identity.
gcloud container node-pools list \ --cluster $CLUSTER_NAME \ --region $CLUSTER_LOCATION \ --project $PROJECT_ID
Your output should look something like:
NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION apigee-runtime e2-standard-4 100 1.23.12-gke.100 apigee-data e2-standard-4 100 1.23.12-gke.100
gcloud container node-pools update NODE_POOL_NAME \ --cluster=$CLUSTER_NAME \ --region $CLUSTER_LOCATION \ --project $PROJECT_ID \ --workload-metadata=GKE_METADATA
Where NODE_POOL_NAME is the name of each node pool.
Google service accounts are created for many Apigee hybrid components during installation. Use this procedure to verify the Google service accounts and create any that are needed.
gcloud iam service-accounts list --project $PROJECT_ID
Your output should look something like:
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
For non-production environments:
DISPLAY NAME EMAIL DISABLED apigee-non-prod apigee-non-prod@my_project_id.iam.gserviceaccount.com False
If you need to create the Google service accounts for your project, there are two methods you can use:
create-service-account
tool included with apigee in the apigeectl/tools/
directory. This tool can create all the service accounts with a single command or let you create them individually. gcloud iam service-accounts create
command to create the service accounts one at a time and the gcloud projects add-iam-policy-binding
command to assign the appropriate roles to each service account. This method requires you to create each service account individually, but lets you avoid downloading the key files. create-service-account
For non-production environments:
$APIGEECTL_HOME/tools/create-service-account --env prod --dir $APIGEECTL_HOME/../service-accounts
This command will create the following service accounts:
apigee-cassandra
apigee-logger
apigee-mart
apigee-metrics
apigee-runtime
apigee-synchronizer
apigee-udca
apigee-watcher
For non-production environments:
$APIGEECTL_HOME/tools/create-service-account --env non-prod --dir $APIGEECTL_HOME/../service-accounts
This command will create a single service accounts, apigee-non-prod
, with all the roles assigned needed to manage all Apigee components.
gcloud
Create the following service accounts and assign roles to them.
apigee-cassandra
, role: roles/storage.objectAdmin
Create the account:
gcloud iam service-accounts create apigee-cassandra \ --display-name="apigee-cassandra" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-cassandra@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin"
apigee-logger
, role: roles/logging.logWriter
Create the account:
gcloud iam service-accounts create apigee-logger \ --display-name="apigee-logger" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-logger@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/logging.logWriter"
apigee-mart
, role: roles/apigeeconnect.Agent
Create the account:
gcloud iam service-accounts create apigee-mart \ --display-name="apigee-mart" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-mart@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigeeconnect.Agent"
apigee-metrics
, role: roles/monitoring.metricWriter
Create the account:
gcloud iam service-accounts create apigee-metrics \ --display-name="apigee-metrics" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-metrics@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/monitoring.metricWriter"
apigee-runtime
, role: No role assigned.Create the account:
gcloud iam service-accounts create apigee-runtime \ --display-name="apigee-runtime" \ --project $PROJECT_ID
apigee-synchronizer
, role: roles/apigee.synchronizerManager
Create the account:
gcloud iam service-accounts create apigee-synchronizer \ --display-name="apigee-synchronizer" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-synchronizer@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.synchronizerManager"
apigee-udca
, role: roles/apigee.analyticsAgent
Create the account:
gcloud iam service-accounts create apigee-udca \ --display-name="apigee-udca" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-udca@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.analyticsAgent"
apigee-watcher
, role: roles/apigee.runtimeAgent
Create the account:
gcloud iam service-accounts create apigee-watcher \ --display-name="apigee-watcher" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-watcher@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.runtimeAgent"
workloadIdentityEnabled: true
and create service accounts apigeectl
creates Kubernetes service accounts for each Apigee hybrid component when you set workloadIdentityEnabled: true
in your overrides file and apply the changes.
overrides.yaml
file under the gcp
stanza. This enables Workload Identity for your installation and triggers apigeectl
to create the Kubernetes service accounts when you apply the configuration: gcp: projectID: "my-project-id" name: "my-project-id" region: "analytics-region" workloadIdentityEnabled: true
overrides.yaml
file under the cassandra
stanza. This triggers the creation of the apigee-cassandra-backup
Kubernetes service account: cassandra: ... backup: enabled: true
apigeectl
with the --restore
flag: $APIGEECTL_HOME/apigeectl apply -f overrides/overrides.yaml --restore
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
For each Apigee component annotate the corresponding Kubernetes service accounts with the Google service account for the component.
You will have only one instance of each Kubernetes service account for your Apigee org.
Component | Kubernetes Service Account | Google Service Account |
---|---|---|
Cassandra | apigee-cassandra-backup | apigee-cassandra |
apigee-cassandra-restore | apigee-cassandra | |
apigee-cassandra-schema-setup-my-project-id-num-id1-sa | apigee-cassandra | |
apigee-cassandra-schema-val-my-project-id-num-id1 | apigee-cassandra | |
apigee-cassandra-user-setup-my-project-id-num-id1-sa | apigee-cassandra | |
apigee-datastore-default-sa | apigee-cassandra | |
Apigee Connect | apigee-connect-agent-my-project-id-num-id1-sa | apigee-mart |
MART | apigee-mart-my-project-id-num-id1-sa | apigee-mart |
Metrics | apigee-metrics-sa | apigee-metrics | UDCA (org-level) | apigee-udca-my-project-id-num-id1-sa | apigee-udca |
Watcher | apigee-watcher-my-project-id-num-id1-sa | apigee-watcher |
You will have one instance of each Kubernetes service account for each Apigee environment.
Component | Kubernetes Service Account | Google Service Account |
---|---|---|
Apigee Runtime | apigee-runtime-my-project-id-env-name-num-id2-sa | apigee-runtime |
Synchronizer | apigee-synchronizer-my-project-id-env-name-num-id2-sa | apigee-synchronizer |
UDCA (env-level) | apigee-udca-my-project-id-env-name-num-id2-sa | apigee-udca |
In the following commands use the Kubernetes service account names returned by the kubectl get sa -n $NAMESPACE
command, for example: apigee-cassandra-schema-val-hybrid-example-project-123abcd
.
In this procedure, for each Kubernetes service account, you will:
roles/iam.workloadIdentityUser
IAM role. Annotate Kubernetes service accounts for the org-level components. You will need to do this once for each component in your Apigee organization.
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
apigee-cassandra-backup
KSA_NAME
and GSA_NAME
environment variables: GSA_NAME="apigee-cassandra" KSA_NAME="apigee-cassandra-backup
"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-restore
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-restore"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-setup-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-schema-setup-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-val-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-schema-val-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-user-setup-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-user-setup-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-datastore-default-sa
KSA_NAME
environment variable:KSA_NAME="apigee-datastore-default-sa"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-backup
KSA_NAME
and GSA_NAME
environment variables: GSA_NAME="apigee-non-prod" KSA_NAME="apigee-connect-agent-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-restore
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-restore"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-setup-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-schema-setup-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-val-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-schema-val-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-user-setup-service-account-name
KSA_NAME
environment variable:KSA_NAME="apigee-cassandra-user-setup-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-datastore-default-sa
KSA_NAME
environment variable:KSA_NAME="apigee-datastore-default-sa"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables: GSA_NAME="apigee-mart" KSA_NAME="apigee-connect-agent-service-account-name
"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-connect-agent-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-mart" KSA_NAME="apigee-mart-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-mart-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-metrics" KSA_NAME="apigee-metrics-sa"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-metrics-sa"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-udca" KSA_NAME="apigee-udca-org-level-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variables:KSA_NAME="apigee-udca-org-level-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-watcher" KSA_NAME="apigee-watcher-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-watcher-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
For each environment:
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-runtime" KSA_NAME="apigee-runtime-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-runtime-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-synchronizer" KSA_NAME="apigee-synchronizer-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-synchronizer-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
and GSA_NAME
environment variables:GSA_NAME="apigee-udca" KSA_NAME="apigee-udca-env-level-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
KSA_NAME
environment variable:KSA_NAME="apigee-udca-env-level-service-account-name"
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
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
gcloud config set project $PROJECT_ID
Select a kubernetes service account to test, for example: apigee-cassandra-backup
.
KSA_NAME="kubernetes-service-account-name"
kubectl run --rm -it --image google/cloud-sdk:slim \ --namespace $NAMESPACE workload-identity-test\ -- gcloud auth list
If you don't see a command prompt, try pressing Enter.
If the steps were correctly run, you should see a response like the following:
Credentialed Accounts ACTIVE ACCOUNT * GSA@PROJECT_ID.iam.gserviceaccount.com
kubectl delete secrets -n $NAMESPACE $(k get secrets -n $NAMESPACE | grep svc-account | awk '{print $1}')
kubectl logs -n $NAMESPACE -l app=apigee=synchronizer,env=$ENV_NAME,org=$ORG_NAME apigee-synchronizer
Follow these instructions to add Workload Identity to an existing hybrid installation.
Here is a sample showing Google Service Accounts (GSA) created for Apigee:
gcloud iam service-accounts list --filter "apigee"
DISPLAY NAME EMAIL DISABLED apigee-cassandra apigee-cassandra@PROJECT_ID.iam.gserviceaccount.com False apigee-connect apigee-connect@PROJECT_ID.iam.gserviceaccount.com False apigee-runtime apigee-runtime@PROJECT_ID.iam.gserviceaccount.com False apigee-metrics apigee-metrics@PROJECT_ID.iam.gserviceaccount.com False apigee-mart apigee-mart@PROJECT_ID.iam.gserviceaccount.com False apigee-watcher apigee-watcher@PROJECT_ID.iam.gserviceaccount.com False apigee-sync apigee-sync@PROJECT_ID.iam.gserviceaccount.com False apigee-udca apigee-udca@$PROJECT_ID.iam.gserviceaccount.com False
Here is a sample Kubernetes service accounts (KSA) created for Apigee:
kubectl get sa -n $NAMESPACE
apigee-cassandra-schema-setup-ORG_NAME-cb84b88-sa 1 xxd apigee-cassandra-user-setup-ORG_NAME-cb84b88-sa 1 xxd apigee-connect-agent-ORG_NAME-cb84b88-sa 1 xxd apigee-init 1 xxd apigee-mart-ORG_NAME-cb84b88-sa 1 xxd apigee-metrics-apigee-telemetry 1 xxd apigee-runtime-ORG_NAME-ENV_NAME-1d0dc5e-sa 1 xxd apigee-synchronizer-ORG_NAME-ENV_NAME-1d0dc5e-sa 1 xxd apigee-udca-ORG_NAME-ENV_NAME-1d0dc5e-sa 1 xxd apigee-watcher-ORG_NAME-cb84b88 1 xxd
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
For example, if you were setting the permissions for Apigee Synchronizer, you would run:
export KSA_NAME=$(kubectl get sa -n apigee -l app=apigee-synchronizer,env=$ENV_NAME,org=$ORG_NAME --output=jsonpath={.items..metadata.name})
gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:$PROJECT_ID.svc.id.goog[apigee/$KSA_NAME]" apigee-sync@$PROJECT_ID.iam.gserviceaccount.com
kubectl annotate serviceaccount \ --namespace $NAMESPACE \ $KSA_NAME \ iam.gke.io/gcp-service-account=GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
For example, if you were setting the permissions for Apigee Synchronizer, you would run:
export KSA_NAME=$(kubectl get sa -n apigee -l app=apigee-synchronizer,env=$ENV_NAME,org=$ORG_NAME --output=jsonpath={.items..metadata.name})
kubectl annotate serviceaccount --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-sync@$PROJECT_ID.iam.gserviceaccount.com
gcloud config set project $PROJECT_ID
kubectl run --rm -it --image google/cloud-sdk:slim \ --namespace $NAMESPACE workload-identity-test\ -- gcloud auth list
If you don't see a command prompt, try pressing Enter.
If the steps were correctly run, you should see a response like the following:
Credentialed Accounts ACTIVE ACCOUNT * GSA@PROJECT_ID.iam.gserviceaccount.com
kubectl delete secrets -n $NAMESPACE $(k get secrets -n $NAMESPACE | grep svc-account | awk '{print $1}')
kubectl logs -n $NAMESPACE -l app=apigee=synchronizer,env=$ENV_NAME,org=$ORG_NAME apigee-synchronizer
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-04-24 UTC.