Run CloudSQL proxy as a K8s service in GKE

How can we use cloudsql proxy if the GKE cluster is not using VPC native

To access a Cloud SQL instance from an application running in Google Kubernetes Engine, you can use either a private IP address or the Cloud SQL Proxy Docker image. Private IP is the easiest way to connect from Google Kubernetes Engine if your cluster meets the requirements

To connect securely to Cloud SQL from Google Kubernetes Engine using a public IP address, you must use the Cloud SQL Proxy.

This blog helps you to run the cloudsql proxy as a K8s service

Before you start this procedure, you must have:

  • A GKE cluster running version 1.2 or higher, with the kubectl command-line tool installed and configured to communicate with the cluster.

  • A PostgreSQL instance created for master and read replica.

  • The Cloud SQL Admin API is enabled.

  • The location of the key file associated with a service account with the proper privileges for your Cloud SQL instance.

Create a secret to access the CloudSQL


kubectl create secret generic sql-access --from-file=$HOME/sql-access.json

Create a deployment for your Postgres Master Database using the Cloud SQL proxy

Create a file cloudsql-master.yaml with the below config:

Replace the values like PROJECT ID, CLUSTER REGION and DB NAME with your cluster details:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudsql-proxy-master
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cloudsql-proxy-master
  template:
    metadata:
      labels:
        app: cloudsql-proxy-master
    spec:
      containers:
      - name: cloudsql-proxy-master
        image: gcr.io/cloudsql-docker/gce-proxy:latest
        imagePullPolicy: Always
        command: ["/cloud_sql_proxy",
                  "-dir=/cloudsql",
                  "-instances=<PROJECT_ID>:<CLUSTER REGION>:<DB NAME>=tcp:0.0.0.0:5432",
                  "-credential_file=/credentials/sql-access.json"]
        ports:
          - name: sql-master
            containerPort: 5432
        volumeMounts:
          - mountPath: /cloudsql
            name: cloudsql
          - mountPath: /credentials
            name: sql-access
      volumes:
        - name: cloudsql
          emptyDir:
        - name: sql-access
          secret:
            secretName: sql-access

Create a deployment for your Postgres Read Replica Database using the Cloud SQL proxy

Create a file cloudsql-slave.yaml with the below config:

Replace the values like PROJECT ID, CLUSTER REGION and DB READ REPLICA NAME with your cluster details:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudsql-proxy-slave
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cloudsql-proxy-slave
  template:
    metadata:
      labels:
        app: cloudsql-proxy-slave
    spec:
      containers:
      - name: cloudsql-proxy-slave
        image: gcr.io/cloudsql-docker/gce-proxy:latest
        imagePullPolicy: Always
        command: ["/cloud_sql_proxy",
                  "-dir=/cloudsql",
                  "-instances=<PROJECT_ID>:<CLUSTER REGION>:<DB READ REPLICA NAME>=tcp:0.0.0.0:5432",
                  "-credential_file=/credentials/sql-access.json"]
        ports:
          - name: sql-slave
            containerPort: 5432
        volumeMounts:
          - mountPath: /cloudsql
            name: cloudsql
          - mountPath: /credentials
            name: sql-access
      volumes:
        - name: cloudsql
          emptyDir:
        - name: sql-access
          secret:
            secretName: sql-access

Check the deployment and pod details by running the below command:

  • kubectl get deployments

  • kubectl get pods

Create a service to use the cloudsql proxy with in the cluster.


---
apiVersion: v1
kind: Service
metadata:
  name: cloudsql-proxy-master
spec:
  ports:
  - port: 5432
    targetPort: sql-master
  selector:
    app: cloudsql-proxy-master
---
apiVersion: v1
kind: Service
metadata:
  name: cloudsql-proxy-slave
spec:
  ports:
  - port: 5432
    targetPort: sql-slave
  selector:
    app: cloudsql-proxy-slave

Check the service details by running the below command:

kubectl get svc

Output:


⇒  kubectl get svc
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes              ClusterIP   20.x.x.1        <none>        443/TCP          4h15m
cloudsql-proxy-master   ClusterIP   20.x.x.2        <none>        5432/TCP         4h15m
cloudsql-proxy-slave    ClusterIP   20.x.x.3        <none>        5432/TCP         4h15m

So now for eg: If your application is using an environment variable to access the master and slave, they can try like this:


MASTER_URL="postgres://username:password@cloudsql-proxy-master:5432/databasename"

SLAVE_URL="postgres://username:password@cloudsql-proxy-slave:5432/databasename"