PGAdapter can be used as a sidecar proxy on Kubernetes. This directory contains a small sample application that shows how to set this up.
These steps create a GKE cluster where the sample app can be deployed. You can skip these steps if you already have a GKE cluster, and instead modify your existing deployment to include PGAdapter.
See https://cloud.google.com/kubernetes-engine/docs/deploy-app-cluster for more details on how to set up a GKE cluster.
- Create an Autopilot cluster named example-cluster and update it to use Workload Identity.
export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_COMPUTE_REGION>
gcloud config set project $PROJECT_ID
gcloud container clusters create-auto example-cluster \
--region=$REGION
gcloud container clusters update example-cluster \
--region=$REGION \
--workload-pool=$PROJECT_ID.svc.id.goog
- Get authentication credentials for the cluster.
gcloud container clusters get-credentials example-cluster \
--region $REGION
This command configures kubectl
to use the cluster you created.
- Create a repository and build the sample application
gcloud artifacts repositories create example-repo \
--repository-format=docker \
--location=$REGION \
--description="Example Docker repository"
docker build --platform linux/amd64 \
-t ${REGION}-docker.pkg.dev/${PROJECT_ID}/example-repo/example-app .
- Authenticate and push the Docker image to Artifact Registry
gcloud auth configure-docker ${REGION}-docker.pkg.dev
docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/example-repo/example-app
The first step to running PGAdapter in Kubernetes is creating a Google Cloud IAM service account (GSA) to represent your application. It is recommended that you create a service account unique to each application, instead of using the same service account everywhere. This model is more secure since it allows you to limit permissions on a per-application basis.
The service account must be granted access to the Cloud Spanner database that the
application will be connecting to. It is enough to assign the Cloud Spanner Database User
role for this example to the service account.
export GSA_NAME=pgadapter-example-gsa
gcloud iam service-accounts create $GSA_NAME \
--description="PGAdapter Example Service Account" \
--display-name="PGAdapter Example Service Account"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/spanner.databaseUser"
Next, you need to configure Kubernetes to provide the service account to PGAdapter. This example uses GKE's Workload Identity for this. This method allows you to bind a Kubernetes Service Account (KSA) to a Google Service Account (GSA). The GSA will then be accessible to applications using the matching KSA.
- Create a Kubernetes Service Account (KSA)
export KSA_NAME=pgadapter-example-ksa
kubectl create serviceaccount $KSA_NAME --namespace default
- Enable the IAM binding between your
$GSA_NAME
and$KSA_NAME
:
gcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/$KSA_NAME]" \
${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
- Add an annotation to
$KSA_NAME
to complete the binding:
kubectl annotate serviceaccount \
$KSA_NAME \
iam.gke.io/gcp-service-account=${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
- Deploy the example application and PGAdapter to Kubernetes. The script below replaces the placeholders in the deployment manifest with your values.
export SPANNER_PROJECT_ID=$PROJECT_ID
export SPANNER_INSTANCE_ID=<YOUR_SPANNER_INSTANCE_ID>
export SPANNER_DATABASE_ID=<YOUR_SPANNER_DATABASE_ID>
sed -e 's|<YOUR_KSA_NAME>|'"${KSA_NAME}"'|g' \
-e 's|<YOUR_REGION>|'"${REGION}"'|g' \
-e 's|<YOUR_PROJECT_ID>|'"${PROJECT_ID}"'|g' \
-e 's|<YOUR_SPANNER_PROJECT_ID>|'"${SPANNER_PROJECT_ID}"'|g' \
-e 's|<YOUR_SPANNER_INSTANCE_ID>|'"${SPANNER_INSTANCE_ID}"'|g' \
-e 's|<YOUR_SPANNER_DATABASE_ID>|'"${SPANNER_DATABASE_ID}"'|g' \
manifests/example-app-deployment.yaml > manifests/my-app-deployment.yaml
kubectl apply -f manifests/my-app-deployment.yaml
- Expose the deployment to the Internet
kubectl expose deployment pgadapter-gke-example \
--type LoadBalancer --port 80 --target-port 8080
- Inspect the running Pods by using
kubectl get pods
kubectl get pods
- Inspect the pgadapter-gke-example Service by using
kubectl get service
kubectl get service pgadapter-gke-example
From this command's output, copy the Service's external IP address from the EXTERNAL-IP column.
- View the output of the application
Use the EXTERNAL-IP address from the previous command.
curl http://<EXTERNAL-IP>