Cloud SQL: управляемые базы
Как перестать администрировать PostgreSQL руками: что Cloud SQL берёт на себя, чего он не умеет, как подключаться безопасно и почему забытый dev-инстанс тихо съедает бюджет.
Cloud SQL — управляемая реляционная база (PostgreSQL, MySQL, SQL Server) в Google Cloud: сервер, диск, репликация, бэкапы и патчи — на стороне Google, вы работаете с обычной базой по обычному протоколу.
Зачем нужна «база как сервис»
PostgreSQL прекрасно ставится на виртуалку командой apt install. Проблема не в установке. Проблема начинается на второй месяц эксплуатации, и звучит она так:
- Кто накатывает security-патчи и следит за CVE в вашей версии?
- Где бэкапы, кто проверял, что они восстанавливаются, и как откатиться на «вчера, 14:32», если разработчик выполнил
DELETEбезWHERE? - Что произойдёт с сервисом, если зона, где живёт эта виртуалка, ляжет на два часа?
- Кто ночью заметит, что диск заполнился на 100% и база встала?
Cloud SQL отвечает на все эти вопросы галочками в конфигурации. Вы получаете обычный PostgreSQL — тот же psql, тот же SQL, те же миграции, — но с автоматическими бэкапами, восстановлением на точку во времени, резервной копией в другой зоне и обновлениями по расписанию.
Взамен вы теряете часть свободы: нет root-доступа к машине, нельзя поставить произвольное расширение (только из списка поддерживаемых), нельзя тонко крутить всё подряд в postgresql.conf (доступны database flags — заметное, но всё же подмножество). Для 95% приложений это честный обмен.
Создаём инстанс
Единица Cloud SQL — инстанс: по сути виртуальная машина с диском, на которой крутится СУБД. Внутри инстанса — одна или несколько баз данных.
gcloud sql instances create shop-db \
--database-version=POSTGRES_16 \
--tier=db-custom-2-7680 \
--region=europe-west1 \
--storage-size=20GB \
--storage-auto-increase \
--availability-type=ZONAL \
--backup-start-time=03:00 \
--enable-point-in-time-recovery
# база и пользователь приложения
gcloud sql databases create shop --instance=shop-db
gcloud sql users create app --instance=shop-db --password='...'
Разберём ключевые флаги, потому что каждый из них — это либо деньги, либо надёжность.
| Флаг | Что значит | На что влияет |
--tier | 2 vCPU, 7,5 ГБ RAM | Основная строка счёта. Считается по часам работы инстанса |
--storage-size | стартовый размер диска | Платите за выделенный объём, а не за занятый |
--storage-auto-increase | диск сам растёт при заполнении | Спасает от падения... и никогда не уменьшается обратно |
--availability-type | ZONAL или REGIONAL (HA) | REGIONAL примерно удваивает цену инстанса |
--enable-point-in-time-recovery | хранение WAL-логов | Позволяет откатиться на любую секунду в прошлом |
Важно про цену: у Cloud SQL нет бесплатного уровня. Даже самый маленький инстанс — это порядка $10–15 в месяц, потому что он работает круглосуточно. Здесь нет «scale to zero», как в Cloud Run: инстанс, к которому никто не обращается, стоит ровно столько же, сколько нагруженный. Для учёбы хватает $300 стартового кредита, а инстанс между занятиями можно останавливать: gcloud sql instances patch shop-db --activation-policy=NEVER (за диск платить всё равно придётся, но не за vCPU и RAM).
Бэкапы, PITR и реплики
Автоматические бэкапы
Cloud SQL раз в сутки в заданное окно снимает бэкап и хранит последние N (по умолчанию 7). Восстановление создаёт новый инстанс или перезаписывает существующий — обычная операция на несколько минут.
Но суточный бэкап — грубый инструмент: если беда случилась в 17:40, а бэкап был в 03:00, вы теряете почти день. Для этого есть point-in-time recovery: Cloud SQL дополнительно хранит журнал транзакций (WAL в PostgreSQL, binlog в MySQL) и умеет «доиграть» его от бэкапа до нужной секунды.
# откатываемся ровно на момент перед роковым DELETE
gcloud sql instances clone shop-db shop-db-restored \
--point-in-time='2026-07-14T17:39:30.000Z'
Обратите внимание: восстановление идёт в новый инстанс. Это правильно — вы сначала смотрите, те ли там данные, и только потом переключаете приложение. И да: PITR стоит денег (хранение логов), но это ровно та страховка, ради которой люди и переходят на управляемые базы.
Реплики чтения
Read replica — асинхронная копия базы, доступная только на чтение. Её создают, когда аналитические или тяжёлые SELECT-запросы мешают жить основной базе.
gcloud sql instances create shop-db-replica \
--master-instance-name=shop-db \
--region=europe-west4
Ключевое слово — асинхронная. Реплика отстаёт: обычно на доли секунды, под нагрузкой — на секунды. Классический баг: пользователь сохранил профиль (запись пошла в мастер), приложение тут же читает профиль с реплики и показывает старые данные. Правило: после записи читайте из мастера.
HA — это не реплика
Высокая доступность (--availability-type=REGIONAL) устроена иначе. Google держит в другой зоне standby-инстанс, а диск синхронно реплицируется между зонами. При отказе основной зоны происходит failover: standby поднимается под тем же адресом, приложение просто переподключается. Потери данных нет, простой — десятки секунд.
Разница по смыслу: replica — про масштабирование чтения, HA — про переживание аварии. И стоит HA примерно вдвое дороже: вы платите за два инстанса.
Как подключаться: три способа и один правильный
1. Публичный IP + authorized networks (плохо)
Самый быстрый способ: дать инстансу публичный адрес и разрешить список IP. Он же самый опасный. Во-первых, база торчит в интернет и её найдут сканеры. Во-вторых, соблазн написать 0.0.0.0/0 («у меня динамический IP, потом поправлю») практически непреодолим — а это «пусть подключается кто угодно, лишь бы знал пароль». Так утекают базы.
2. Private IP (правильно для продакшена)
Инстанс получает адрес внутри вашей VPC-сети и не имеет публичного адреса вообще. Достучаться до него можно только изнутри сети — с ваших виртуалок, из Cloud Run через VPC-коннектор, из GKE. Снаружи база не существует.
gcloud sql instances patch shop-db \
--network=projects/my-project/global/networks/default \
--no-assign-ip
3. Cloud SQL Auth Proxy (правильно для разработчика)
А как тогда зайти в приватную базу со своего ноутбука? Через Cloud SQL Auth Proxy — маленькую утилиту, которая делает три вещи:
- Слушает
127.0.0.1:5432на вашей машине, как будто это локальный Postgres. - Аутентифицируется в Google Cloud вашими учётными данными (
gcloud auth application-default login) и проверяет через IAM, есть ли у вас рольroles/cloudsql.client. - Поднимает шифрованный туннель до инстанса, получая эфемерный сертификат, живущий около часа.
# имя инстанса в формате PROJECT:REGION:INSTANCE
./cloud-sql-proxy --port 5432 my-project:europe-west1:shop-db
# в другом терминале — обычный psql, как будто база локальная
psql "host=127.0.0.1 port=5432 user=app dbname=shop"
Результат:
2026/07/14 12:03:41 Authorizing with Application Default Credentials
2026/07/14 12:03:42 [my-project:europe-west1:shop-db] Listening on 127.0.0.1:5432
2026/07/14 12:03:42 The proxy has started successfully and is ready for new connections!
Что здесь принципиально: у базы не открыт ни один порт наружу, пароль не ходит по открытой сети, доступ выдаётся и отзывается через IAM (уволился человек — убрали роль, и всё), а шифрование включено всегда. В продакшене тот же прокси встраивают как sidecar-контейнер рядом с приложением или используют библиотеку-коннектор прямо в коде.
from google.cloud.sql.connector import Connector
import sqlalchemy
connector = Connector()
def getconn():
# коннектор сам сходит в IAM, получит сертификат и поднимет TLS-туннель
return connector.connect(
"my-project:europe-west1:shop-db",
"pg8000",
user="app",
password="...",
db="shop",
ip_type="PRIVATE",
)
engine = sqlalchemy.create_engine(
"postgresql+pg8000://",
creator=getconn,
pool_size=5,
max_overflow=2,
pool_recycle=1800,
)
with engine.connect() as conn:
rows = conn.execute(sqlalchemy.text("SELECT count(*) FROM orders")).scalar()
print(rows)
Обратите внимание на pool_size и pool_recycle: у инстанса есть жёсткий лимит соединений, и «каждый воркер открывает по 20 коннектов» — верный способ упереться в него на ровном месте.
Как это работает
Cloud SQL — не магия, а автоматизация: под капотом это виртуальная машина Compute Engine с сетевым диском Persistent Disk, на которой Google сам поставил и настроил PostgreSQL. Понимание этого объясняет всё поведение сервиса:
- Почему нельзя уменьшить диск. Persistent Disk умеет расти на лету, но не умеет сжиматься. Единственный способ «уменьшить» — сделать дамп и залить в новый инстанс.
- Почему HA стоит вдвое. Потому что это буквально вторая машина со своей копией диска в другой зоне.
- Почему инстанс не масштабируется до нуля. Машина работает всегда — иначе первый же запрос ждал бы её загрузки.
- Почему бывает maintenance window. Обновление минорной версии — это перезапуск процесса СУБД: короткий разрыв соединений. Поэтому приложение обязано уметь переподключаться, а окно обслуживания лучше задать явно на ночь.
- Как работает failover. Клиенты обращаются не к IP конкретной машины, а к адресу инстанса; при аварии Google переводит этот адрес на standby. Ваш пул соединений в этот момент увидит обрыв — и должен молча переподключиться.
Частые ошибки
- Забытый dev-инстанс. Самая дорогая ошибка новичка. Инстанс не спит и не масштабируется в ноль: он тикает 24/7 и в конце месяца превращается в счёт. Останавливайте (
--activation-policy=NEVER) или удаляйте после экспериментов. 0.0.0.0/0в authorized networks. Даже «на пять минут». Базы находят автоматические сканеры за часы, а пароль подбирают.- Полагаться на storage-auto-increase. Диск вырос на 500 ГБ из-за раздувшегося лога — и назад уже не ужмётся, вы платите за эти 500 ГБ вечно. Ставьте
--storage-auto-increase-limitи алерты на заполнение. - Включить HA «на всякий случай» в тестовом окружении. Это ровно двойной счёт за окружение, доступность которого никому не нужна.
- Считать реплику бэкапом. Реплика повторяет всё, включая
DROP TABLE. От человеческой ошибки спасают только бэкапы и PITR. - Читать сразу после записи с реплики. Асинхронное отставание — не баг, а свойство. После записи читайте с мастера.
- Не проверять восстановление. Бэкап, который ни разу не восстанавливали, — это не бэкап, а надежда. Раз в квартал поднимайте клон и убеждайтесь, что данные на месте.
- Не ограничивать пул соединений. Лимит соединений на маленьких тирах невелик; десяток инстансов приложения с большими пулами исчерпают его мгновенно.
Итоги
- Cloud SQL — это обычный PostgreSQL/MySQL, у которого Google взял на себя железо, патчи, бэкапы и репликацию. SQL и клиенты остаются прежними.
- Бесплатного уровня нет: инстанс работает круглосуточно и стоит денег, даже когда простаивает. Для учёбы — останавливайте его.
- Автоматические бэкапы плюс point-in-time recovery позволяют откатиться на конкретную секунду; восстановление создаёт новый инстанс.
- Read replica — про масштабирование чтения (и она отстаёт). HA (
REGIONAL) — про переживание падения зоны, и стоит примерно вдвое дороже. - Правильное подключение: приватный IP плюс Cloud SQL Auth Proxy или коннектор. Никаких публичных адресов и
0.0.0.0/0. - Диск умеет расти автоматически и не умеет уменьшаться — это ловушка, за которую платят месяцами.