GKE: Cloud SQL Proxy as a standalone service

Victor Bolshov
3 min readJul 19, 2019

--

[see below for Russian translation]

FOR THE IMPATIENT: the manual page gives you a config with which SQLProxy listens only to connections from localhost (127.0.0.1). You have to change TCP config for the proxy to listen to connections from outside:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:0.0.0.0:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

Now, in a lil bit more detail ;-)

Cloud SQL in Google Cloud Platform is a nice utility — a managed database, with good performance, automatic backups, fully production-ready.

On this page of the manual you can find out how to connect to Cloud SQL from Kubernetes engine. Of all options, Cloud SQL Proxy is said to be the most secure & robust. The manual describes the so-called “sidecar” approach, that is, they start a SQLProxy container in the same deployment as the application, then the app can connect as “mysql:host=127.0.0.1;…”

What if you want to connect to the same DB instance from several apps/services? Yes, it doesn’t look right from the first glance. However, CloudSQL is somewhat expensive, and smaller projects would benefit from using one CloudSQL instance (maybe with multiple databases) for all application services. Also, you may want to start Jobs that connect to the same DB. Having a new SQLProxy container next to every app service/job results in both running multiple instances of sql-proxy and duplicating the sql-proxy deployment configuration.

That is, you might want to have SQLProxy started as a standalone service, not as a “sidecar” container. However, if you simply create another service+deployment using the very same config from the manual, you won’t be able to connect to SQLProxy! It happens because of this line in deployment config:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

With this, proxy will only listen to connections from 127.0.0.1, and you may check it with kubectl logs <sqlproxy pod name>

Solution is simple:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:0.0.0.0:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

Notice the tcp configuration change to 0.0.0.0:3306. Now proxy listens to connections from everywhere (but don’t worry, unless you specifically want it and take appropriate steps, you won’t be able to connect from outside of the cluster).

Hope that can save a bit of research to fellow readers!

Русский вариант

ДЛЯ НЕТЕРПЕЛИВЫХ: мануал приводит конфиг, с которым SQLProxy слушает только соединения с localhost (127.0.0.1). Надо изменить конфиг TCP, чтобы заставить его слушать соединения извне:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:0.0.0.0:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

Ну и немного деталей ;-)

Cloud SQL отличная штука — управляемая БД, с хорошей производительностью, автоматическими бэкапами, готова для продакшн.

На этой странице мануала вы узнаете, как подключиться к Cloud SQL из Kubernetes engine. Из всех вариантов самый безопасный и вообще лучший — это Cloud SQL Proxy. Там описан так называемый подход коляска мотоцикла”, в котором контейнер с SQLProxy запускается в том же деплойменте, что и приложение, и тогда из приложения можно коннектиться примерно так: “mysql:host=127.0.0.1;…”

Что если нужно подключаться к одному инстансу Cloud SQL из разных сервисов приложения? На первый взгляд кажется, что это как-то неправильно. Однако, CloudSQL довольно дороная штука, и небольшие проекты могут выиграть от того, чтобы использовать один инстанс CloudSQL (возможно, с несколькими БД) для всех сервисов приложения. К тому же, может возникнуть законное желание запускать Задачи (Jobs), которые подключаются к той же БД. Если запускать контейнер с SQLProxy рядом с каждым сервисом/задачейприложения приводит к дублированию как инстансов sql-proxy, так и конфигов, необходимых для его запуска.

В общем, может возникнуть желание запускать SQLProxy как отдельный сервис. Однако, если тупо создать еще один Service+Deployment и использовать тот же конфиг из мануала, подключиться к SQLProxy не выйдет. Вот из-за этой строчки:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

Прокси слушает тольео соединения с 127.0.0.1, это видно, если посмотреть логи: kubectl logs <sqlproxy pod name>

Решение:

command: ["/cloud_sql_proxy",
"-instances=<INSTANCE_CONNECTION_NAME>=tcp:0.0.0.0:3306",
"-credential_file=/secrets/cloudsql/credentials.json"]

Мы изменили конфиг TCP на 0.0.0.0:3306. Теперь прокси слушает коннекты отовсюду (но не беспокойтесь, законнектиться из-за пределов вашего кластера не получится, если только вы специально не откроете такую возможность).

Надеюсь, кому-то это сэкономит час-другой!

--

--

Victor Bolshov

I am a PHP programmer, I like opensource software, linux etc.