Achieving Cloud-Native Security: How the Auth Proxy Operator Connects GKE to Cloud SQL

Akhilesh V A Gopal
The Cloudside View
Published in
6 min readMar 21, 2023

--

When deploying applications on Google Kubernetes Engine, it’s highly probable that connecting to Cloud SQL will be necessary. Although there are various methods available for connecting application servers with database servers, most of these methods were originally intended for deployment on virtual machines and may seem outdated in a cloud-native environment. However, Google Cloud provides a cloud-native solution
for linking the applications running on GKE/GCE to databases hosted on
Cloud SQL through the use of Auth Proxy. The following are different types and methods available.

Cloud SQL Connector: To connect GKE to Cloud SQL, there are language-specific Cloud SQL connectors for Java, Python, and Go. If our application is written in one of those languages, then it’s good to use a Cloud SQL connector.

Cloud SQL Auth Proxy: The Cloud SQL Auth proxy provides IAM-based authorization and encryption when connecting to a Cloud SQL instance.

Cloud SQL Auth Proxy Operator: The Cloud SQL Auth Proxy Operator is a Kubernetes operator that automates the deployment and management of Cloud SQL Auth Proxy.

Highlighting the differences between Cloud SQL Connector & Cloud SQL Auth Proxy

Highlighting the differences between Cloud SQL Auth Proxy Operator & Cloud SQL Auth Proxy

Benefits of Auth Proxy Operator :

  • The Proxy Operator saves the developer from writing long YAML files.
  • Simple configuration of a single Cloud SQL Proxy specific resource — allowing multiple Kubernetes applications to share the same proxy.
  • Best practices by default — Google maintains the operator and updates
    it to the latest recommendations.
  • Automatic deployment when the proxy configuration changes.
  • Auth proxy operator provides strong encryption and authentication using IAM, which can help keep your database secure.

Let's go through setting up Auth Proxy Operator for a sample application

Pre-requisites :

  • Cloud SQL instance.
  • MySQL database and user account configured on the instance.
  • GKE cluster.
  • A Sample application that uses MySQL, to be deployed in GKE.
  • An IAM service account with Cloud SQL Client role and Log writer role.
  • A Kubernetes service account using workload identity.

Cloudshell is used for executing the below commands.

Click here and confirm to clone the Config files of a sample application into your Cloud Shell.

  • In the Cloud shell, enter the below command to Select a project.
    [Replace YOUR_PROJECT_ID with the Project ID]
gcloud config set project [YOUR_PROJECT_ID]
  • Enable the necessary Google Cloud APIs.
gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
container.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com

Create a Service account

  • Create a new service account.
gcloud iam service-accounts create php-sa
  • Add the Cloud SQL Client role to the service account.

[Replace YOUR_PROJECT_IDwith the Project ID]

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:php-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
  • Add the Cloud SQL Instance User role to the service account.

[Replace YOUR_PROJECT_IDwith the Project ID]

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:php-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.instanceUser"
  • Add the Log Writer role to the service account.

[Replace YOUR_PROJECT_IDwith the Project ID]

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:php-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"

Setup Cloud SQL

  • Create a Cloud SQL Instance.

[Replace PASSWORDwith a password for your MySQL Instance root user]

gcloud sql instances create php-instance \
--database-version=MYSQL_8_0 \
--cpu=1 \
--memory=4GB \
--region=us-central1 \
--root-password=PASSWORD \
--database-flags=cloudsql_iam_authentication=on
  • Create a Database on the MySQL Instance.
gcloud sql databases create phpdb --instance=php-instance
  • Create an IAM user for your MySQL Instance.

[Replace USERNAMEwith the email address of your service account]

gcloud sql users create USERNAME \
--instance=php-instance \
--type=cloud_iam_service_account

Setup Mysql database

  • Login to the MySQL Instance.

[Replace INSTANCE_IPwith the IP address of MySQL Instance]

mysql -u root -p -h INSTANCE_IP
  • Select phpdb as the current database.
use phpdb
  • Grant all privileges to the database user.
GRANT ALL PRIVILEGES ON phpdb.* TO 'php-sa'@'%';
  • Apply privilege changes to the user and exit MySQL Instance.
FLUSH PRIVILEGES; exit;

Setup GKE Cluster

  • Create a GKE cluster

[Replace YOUR_PROJECT_IDwith the Project ID]

gcloud container clusters create "php-cluster" --zone "us-central1-c" --no-enable-basic-auth --scopes "https://www.googleapis.com/auth/cloud-platform" --logging=SYSTEM,WORKLOAD --workload-pool "YOUR_PROJECT_ID.svc.id.goog" --no-enable-master-authorized-networks --machine-type "e2-standard-4" --spot --num-nodes "1"
  • Enable the GKE cluster as the default cluster to be used.
gcloud container clusters get-credentials php-cluster \
--zone us-central1-c

Setup a Kubernetes service account

Using the service-account.yaml file, create a Kubernetes service account [php-ksa] configured to have access to Cloud SQL by binding it to the Gcp service account using Workload Identity.

  • Run the kubectl apply command in Cloud Shell
kubectl apply -f service-account.yaml
  • Enable IAM binding of the Google Cloud Service Account and the Kubernetes Service Account.

Make the following replacements:

[YOUR_PROJECT_ID with the Project ID , YOUR-K8S-NAMESPACE with default ]

gcloud iam service-accounts add-iam-policy-binding \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:YOUR_PROJECT_ID.svc.id.goog[YOUR_K8S_NAMESPACE/php-ksa]" \
php-sa@YOUR_PROConclusionJECT_ID.iam.gserviceaccount.com
  • Annotate the Kubernetes Service Account with IAM binding.

[Replace YOUR_PROJECT_ID with the Project ID ]

kubectl annotate serviceaccount \
php-ksa \
iam.gke.io/gcp-service-account=php-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com

Setup Cloud SQL Auth Proxy Operator

  • Confirm that kubectl can connect to the cluster.
kubectl cluster-info
  • Install the Cloud SQL Auth Proxy Operator into your Kubernetes cluster:
curl https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy-operator/v0.2.0/install.sh | bash
  • Wait for the Cloud SQL Auth Proxy Operator to start.
kubectl rollout status deployment -n cloud-sql-proxy-operator-system cloud-sql-proxy-operator-controller-manager --timeout=90s
  • Confirm that the operator is installed and running by listing its pods:
kubectl get pods -n cloud-sql-proxy-operator-system

Deploy a sample app

  • Get the Cloud SQL instance connection name.
gcloud sql instances describe php-instance --format='value(connectionName)'
  • Given below is the authproxyworkload.yaml file.

[Replace <INSTANCE_CONNECTION_NAME> with instance connection name visible in the Cloud SQL instance overview page]

apiVersion: cloudsql.cloud.google.com/v1alpha1
kind: AuthProxyWorkload
metadata:
name: authproxyworkload-sample
spec:
workloadSelector:
kind: "Deployment"
name: "php-app"
instances:
- connectionString: "INSTANCE_CONNECTION_NAME"
portEnvName: "PMA_PORT"
hostEnvName: "PMA_HOST"
autoIAMAuthN: true
  • Now apply the proxy configuration to Kubernetes:
kubectl apply -f authproxyworkload.yaml
  • Given below is the deployment.yaml file.

[Replace YOUR_PROJECT_IDwith the Project ID]

apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
iam.gke.io/gcp-service-account: php-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
name: php-app
spec:
selector:
matchLabels:
app: php-app
template:
metadata:
labels:
app: php-app
spec:
serviceAccountName: php-ksa
containers:
- name: php-app
image: phpmyadmin
# This app listens on port 80 for web traffic by default.
ports:
- containerPort: 80
env:
- name: PORT
value: "80"
- name: PMA_HOST
value: "set-by-proxy"
- name: PMA_PORT
value: "set-by-proxy"
- name: PMA_PMADB
value: "phpdb"
- name: PMA_USER
value: "php-sa"
  • Now apply the Deployment to Kubernetes cluster:
kubectl apply -f deployment.yaml
  • Using the service.yaml file, add a load balancer in the front end of the deployment so that you can access it through the internet:
kubectl apply -f service.yaml
  • Now get the details of the running services :
kubectl get services
  • Copy the External IP address of the load balancer service and paste it on a browser to view the deployed sample app.

Conclusion

Cloud SQL Proxy Operator is an open-source Kubernetes operator that automates most of the difficult steps needed to connect a workload in a Kubernetes cluster to Cloud SQL databases.

The Cloud SQL Auth Proxy Operator makes it easy to add a proxy container to your Kubernetes workloads, configured correctly for production use. The operator introduces a custom resource AuthProxyWorkload, which specifies the Cloud SQL Auth Proxy configuration for a workload. The operator reads this resource and adds a properly configured Cloud SQL Auth Proxy container to the matching workload pods.

Writing the Kubernetes configuration for a proxy to the production level requires a great deal of deep Kubernetes and proxy knowledge. The Cloud SQL Proxy team has worked to encapsulate that knowledge in this operator. This saves you from having to know all the details to configure your proxy.

Thank you for reading. I hope you found this helpful.

--

--