Найти в Дзене
Mad Devs

Connection pooling для RDS-PostgreSQL с помощью terraform

В эпоху активного внедрения DevOps практик в процессы разработки софта — когда стена между Dev и Ops разрушается, и теперь уже одна команда ответственна за интеграцию и поставку продукта, к опсовым задачам добавилась фраза as a code. Теперь в оправданные сроки нужно не просто спроектировать и развернуть инфраструктуру — она должна быть разработана по методикам применяемым в команде, храниться в

В эпоху активного внедрения DevOps практик в процессы разработки софта — когда стена между Dev и Ops разрушается, и теперь уже одна команда ответственна за интеграцию и поставку продукта, к опсовым задачам добавилась фраза as a code. Теперь в оправданные сроки нужно не просто спроектировать и развернуть инфраструктуру — она должна быть разработана по методикам применяемым в команде, храниться в scm, быть воспроизводимой, отдельно хранить текущее состояние и еще куча пунктов, возникающих по мере развития infrastructure as a code.

В свое время, нами для этих целей был выбран terraform. На тот момент он единственный умел хранить состояния(локально и, самое главное, удаленно) и, что более важно, terraform не привязан к конкретной платформе, как тот-же AWS CloudFormation, что позволяет использовать единый декларативный язык для разработки инфраструктуры практически на любом более-менее популярном провайдере или даже конкретном сервисе.

Ниже я приведу вам пример использования terraform для решения кейса, случившегося у нашего заказчика, когда у очень мощного rds-инстанса свободная оперативная память упала до нуля, стали расти иопсы и cpu, что стало сказываться на tps.

Не секрет, что Postgres, не имея встроенного пулинга, очень не любит большое количество одновременных соединений. Для каждой конфигурации базы данных и системных мощностей есть свой предел, после которого расход оперативной памяти(и уменьшение дискового кеша), random access к диску, переключение контекста и другие ресурсоемкие операции значительно снизят производительность. Рассмотрим ситуацию, когда пришла пора апгрейда инстанса в связи с нехваткой памяти из-за over 1k одновременных подключений к БД.

-2

В качестве сервиса для пулинга мы будем использовать PgBouncer. Для этого, мы соберем docker-image, который запушим в Амазоновский регистри - ECR. Dockerfile для образа:

Простой скрипт для его сборки:

который будет вызываться терраформом при создании репозитория в AWS ECR:

Сервис на базе этого docker-образа будет запущен в ECS-кластере и приаттачен к балансировщику. Шаблон таска для сервиса выглядит следующим образом:

Для большей производительности мы используем "networkMode": "host".

Стоит помнить, что ECS не сможет запустить два таких таска/контейнера на одном ec2 инстансе, т.к. порт будет уже занят, и на время нового деплоя придется скейлить вниз сервис или увеличивать число EC2-инстансов в кластере. Для такого статичного сервиса, как PgBouncer нас это устраивает. Однако, для частых деплоев удобнее использовать bridge и динамические порты на хосте "hostPort": 0.

Application и Network балансировщики умеют работать с динамическими портами сервисов ECS. Для единой точки входа в наш сервис и балансировки, мы будем использовать Network Load Balancer. Это относительно новый сервис у AWS работающий на 4-ом уровне OSI. Обладает большой пропускной способностью и низкой задержкой. Так же, как и ALB, умеет слушать несколько портов и проксировать на несколько таргет-групп. Стоит также помнить, что Security Groups на него назначить нельзя. Для данного примера я сделал весьма открытую группу для ECS-инстансов, разрешив всем коннектиться на 5432 порт:

Для данного примера я не стал использовать Packer для сборки своего AMI. Мы берем свежий образ amazon-linux и конфигурируем его простеньким user-data скриптом:

Запустив на двух c4.large инстансах PgBouncer, и, спрятав их за NLB, мы потратили $180 не считая трафика, но сэкономили отложив апгрейд RDS-инстанса на порядок больше, высвободив около 40GB оперативной памяти, которая была занята бэкендами постгреса, держащими соединения. Настроив под новые реалии некоторые параметры бд, удалось более чем в два раза снизить ReadIOPS, уменьшить нагрузку на CPU и увеличить среднее количество TPS в 1.5 раза.

P.S. Полный пример для запуска PgBouncer и используемые модули лежат тут: https://github.com/maddevsio/terraform

Ранее статья была опубликована тут.