I would like to connect my Kubernetes cluster to Google Cloud SQL.
I have at least 10 different deployed pods which presently connect to MySQL [docker image deployed to k8s] using a JDBC url + username/password.
It it possible to use a single instance of the Google Cloud SQL Proxy and connect all the pods through this proxy to the Cloud SQL database? Ideally I would like to replace the mysql running in the container with the proxy.
I would prefer not having to run the proxy inside each deployment. The only samples I found seem to indicate the proxy needs to be declared in each deployment.
With Google "Private IP" the cloud proxy is now irrelevant!
I found a solution.
Deploy the proxy with the yml below, and expose the deployment as a service. Most importantly, make the proxy listen on 0.0.0.0, instead of default 127.0.0.1. All the secrets as per the Google Cloud sql documentation
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
template:
metadata:
name: mysql
labels:
name: mysql
spec:
containers:
- image: b.gcr.io/cloudsql-docker/gce-proxy:1.05
name: cloudsql-proxy
command: ["/cloud_sql_proxy", "--dir=/cloudsql",
"-instances=MYSQL:ZONE:DATABASE_INSTANCE=tcp:0.0.0.0:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]
volumeMounts:
- name: cloudsql-oauth-credentials
mountPath: /secrets/cloudsql
readOnly: true
- name: ssl-certs
mountPath: /etc/ssl/certs
ports:
- containerPort: 3306
name: mysql
volumes:
- name: cloudsql-oauth-credentials
secret:
secretName: cloudsql-oauth-credentials
- name: ssl-certs
hostPath:
path: /etc/ssl/certs
The solution is slightly more expensive than having the proxy in the same deployment as the client software, since there is an extra TCP connection.
However there are many benefits:
You can create a deployment and a service to expose the cloudsql proxy to other pods like so:
apiVersion: v1
kind: Service
metadata:
name: cloudsqlproxy
spec:
ports:
- port: 3306
targetPort: database-port
selector:
app: cloudsqlproxy
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: cloudsqlproxy
spec:
template:
metadata:
labels:
app: cloudsqlproxy
spec:
volumes:
- name: service-account-token
secret:
secretName: service-account-token
containers:
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.11
imagePullPolicy: Always
command:
- /cloud_sql_proxy
- -instances=<project>:<cloudsqlinstance>=tcp:0.0.0.0:3306
- -credential_file=/secrets/cloudsql/credentials.json
ports:
- name: database-port
containerPort: 3306
volumeMounts:
- name: service-account-token
mountPath: /secrets/cloudsql
readOnly: true
So within any of your pods, the database your MYSQL_HOST:MYSQL_PORT
will be cloudsqlproxy:3306
For multiple databases through the same proxy, you'd have the same deployment structure for the proxy, except that you will now expose 2 ports from the pod, like so:
apiVersion: extensions/v1beta1
...
spec:
template:
...
spec:
volumes:
...
containers:
- name: cloudsql-proxy
...
ports:
- name: database-port1
containerPort: 3306
- name: database-port2
containerPort: 3307
...
Then you'd create 2 services to for discovery on those ports like so:
apiVersion: v1
kind: Service
metadata:
name: cloudsqlproxy-db1
spec:
ports:
- port: 3306
targetPort: database-port1
selector:
app: cloudsqlproxy
---
apiVersion: v1
kind: Service
metadata:
name: cloudsqlproxy-db2
spec:
ports:
- port: 3306
targetPort: database-port2
selector:
app: cloudsqlproxy
So, with both services set to port 3306
, you can connect to each database on that port:
mysql --host=cloudsqlproxy-db1 --port=3306 ...
mysql --host=cloudsqlproxy-db2 --port=3306 ...
Reference: https://github.com/GoogleCloudPlatform/cloudsql-proxy/blob/master/Kubernetes.md