Як ми на проєкті розгортали інфраструктуру платіжного процесингу в AWS
Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!
Добрий день! Мене звати Дмитро Дзюбенко, я співзасновник та CTO компанії Corefy — white label SaaS платформи, яка дозволяє запустити власну платіжну систему в кілька кліків. Зараз на базі нашої платформи функціонують платіжні провайдери та компанії, які успішно закривають внутрішні потреби з прийому платежів. Основна цінність платформи для клієнтів — усунення складнощів інтеграції платіжних провайдерів. Ми інтегруємо платіжних провайдерів та еквайрів з усього світу, тому клієнтам достатньо однієї інтеграції з нашою платформою, щоб мати можливість підключити будь-який платіжний метод.
У цій статті я розкажу про наш досвід розгортання інфраструктури платіжного процесингу в Amazon Web Services (AWS). Cтаття написана за мотивами моєї доповіді 2021 року на вебінарі AWS Cloud for Financial Services, тож я розповім про наш досвід, виходячи з того часу.
2018: перехід на AWS за місяць
У 2018 році наш продукт складався з:
● Платіжного шлюзу. На той час ми закривали обробку карткових даних за допомогою сторонніх провайдерів, адже більшість інтеграцій передбачала перенаправлення на іншого платіжного провайдера, де вже клієнт вводить карткові дані. Оскільки наша платформа підтримує будь-який платіжний метод, ми можемо інтегрувати мобільні гаманці, роботу з інвойсами, криптопроцесинги, тощо.
● Шлюзу виплат. Його основна функціональність (розщеплення суми, робота з P2P-платежами) значних змін з того часу не зазнала.
● Сервісу обмінних курсів. Для платіжних провайдерів важливо мати можливість працювати в декількох валютах, тому з самого початку у нас був сервіс обмінних курсів. Він також досі працює майже в незмінному вигляді.
Цих можливостей було достатньо для деяких наших клієнтів, тож на цих «трьох стовпах» ми запустилися у 2018 році.
При запуску головним для нас було зробити це швидко і недорого, при цьому забезпечивши здатність системи до масштабування.
Чому швидко? Так склалося, що перший клієнт з’явився неочікувано. Ми довго працювали над платформою, а потім нам пощастило — нарешті з’явився клієнт, якого потрібно було якнайшвидше запустити в production. За місяць ми повинні були перейти на Amazon Web Services з наших самопальних кластерів, які були розгорнуті на OVH VPS за допомогою Kontena. На той момент досвіду роботи з AWS у нас було зовсім трохи, але завдяки розширенню команди нам вдалося завершити проєкт вчасно.
Ода сервісам AWS
Інфраструктура була зроблена методом наклікування (ClickOps) у консолі управління Amazon, без жодної автоматизації. Оскільки у нас на той момент був лише один клієнт, трафіку було небагато. З появою нових клієнтів навантаження потроху збільшувалося, проте не різко.
Ключовими сервісами, які ми використовували, були ElastiCache, RDS та ECS.
ElastiCache — прекрасний сервіс, який дає можливість працювати з Memcached і Redis. Він підтримує роботу не лише з одиничними нодами, а і з кластерами, а також можливість робити снапшоти. Все це можна розгортати у різних зонах доступності. Всі можливості, які є в Redis, доступні в сервісі ElastiCache.
RDS — це мій улюблений сервіс, який дає можливість працювати із різними СУБД (MySQL, PostgreSQL, Oracle) і не перейматися стосовно фізичних проблем. Його можна розгортати як на Provisioned storage, так і в звичайному режимі. Він відкидає потреби в організації кастомних бекапів, бо для більшості потреб буде достатньо снапшотів, які не впливають на швидкодію вашого серверу БД. Ще одна із можливостей — розгортання вашої бази даних зі снапшота, який був зроблений у певний момент часу (point in time recovery).
ECS — це оркестратор docker-контейнерів від AWS, що був базовим для нас довгий час — в ньому крутяться практично всі наші ресурси. На той момент EKS тільки з’явився на AWS і мав обмежений інструментарій, який підтримує його, тому ми не могли навіть почати роботу із ним. Сам AWS доволі багато зусиль вкладає в розвиток ECS. Щоправда, більшість направлені на інтеграцію з внутрішніми сервісами — FireLens (логи), App Mesh, Blue-green deployment (CodeDeploy), Container Insights (CloudWatch), SecretManagement (SSM), Serverless (Fargate). Є і комічні моменти. Наприклад, лише нещодавно у них з’явилася можливість видаляти task definition. Зауважу, що платити за control plane ноди, як у випадку із EKS, тут не потрібно.
У результаті роботи в 2018 році ми отримали наступну архітектуру: у нас було 2 зони доступності, кілька дрібних сервісів, база даних (primary/secondary), а також Redis. Але через ClickOps, брак часу та досвіду ми запустились на одному NAT у двох зонах доступності.
Основними проблемами, з якими ми зіткнулися за цей час, були кредити EBS та інстансів T2. EBS має ліміт на кількість вводів-виводів в секунду в залежності від об’єму диска, і при запуску інстанса цей ліміт дуже маленький. Якщо ви почнете інтенсивно використовувати диск з новим EBS, швидше за все, ви скоро досягнете ліміту і всі операції стануть дуже повільними. Ми використовуємо в роботі фреймворк Symfony, який прогріває кеш свого ядра перед стартом. Ось він нам тоді і поставив задачку із зірочкою — ми навіть на tmpfs пробували переходити.
2019: проходження сертифікації PCI DSS
На початок 2019 року карткового процесингу у нас ще не було, але ми його спроєктували і були готові починати розробку. Постав вибір: залишитися в Amazon, де у нас було трохи більше півроку досвіду, або повернутися в OVH. Оскільки ніхто з команди не мав практичного досвіду проходження сертифікації Payment Card Industry Data Security Standard (PCI DSS), питання вибору провайдера інфраструктури для нас було дуже важливим. Ми провели великий SWOT-аналіз, щоб відповісти на нього.
У провайдера OVH є пакети для полегшення проходження PCI DSS. Вони надають кластер на виділених серверах та забирають на себе частину відповідальності при проходженні сертифікації. Але, як ми і припускали, менеджити це не так-то і просто, адже для цього теж потрібен досвід. Оскільки увесь світ іде в «хмарки», переходити на виділений сервер для нас було б не дуже правильно, тож ми вирішили залишатися в AWS. Ми зважували, як пройти сертифікацію, як масштабуватися. Також хотілося обрати популярну технологію, а не якийсь андеграунд типу OpenStack. Тим паче, нам потрібна була можливість знайти спеціалістів для підтримки.
AWS не був би AWS, якби не мав рецепта розгортання інфраструктури, сумісної з PCI DSS. Для цього вони зробили прекрасний CloudFormation. Він активно підтримується і туди з часом додаються нові модулі, певні покращення. Силами однієї людини за тиждень ми підняли staging оточення. Це також дало нам можливість розгорнути production за один день.
Для проходження сертифікації PCI DSS ми вирішили робити все в окремому обліковому записі. У результаті всіх цих дій ми отримали вже дві інфраструктури. Я вважаю, що на той час це було правильним рішенням, хоча в майбутньому воно принесло нам купу додаткової роботи та болю. Там була невелика кількість ресурсів, вони були всі описані в коді, всі вимоги PCI DSS були дотримані, і до цієї інфраструктури мали доступ лише два оператори. Ця інфраструктура працювала в трьох зонах доступності, зі своїми ключами KMS. Комунікації із preprocessing були реалізовані по HTTP API та SQS, щоб не ускладнювати нашу інфраструктуру внутрішніми пірингами. Це дало нам можливість заявити, що процесинг карткових транзакцій — це окрема система з власним API, і єдиним клієнтом цього API є наш продукт Corefy.
Протягом 2019 року ми отримали багато нового досвіду. У першу чергу, це проходження сертифікації PCI DSS. Також ми навчилися працювати з EBS та зрозуміли, що capacity planning проводити обов’язково, адже щойно ми запустили карткову інфраструктуру, наші партнери почали направляти трафік, а об’єми цього трафіку інколи були неочікуваними. Сьогодні ми обробляємо 3000 операцій на день, завтра 30000, післязавтра — 300000. Іноді про такі зміни ми дізнавалися через алерти або візуальний моніторинг трафіку.
Як робити не треба
Розповім про важливу проблему, з якою потрібно розібратися на старті роботи з автоскейлінгом. Протягом 2019 року ми кілька разів автоскейлінгом «вбили» собі кластер, тому що неправильно були виставлені хелсчеки для наших бекендів. Може бути така ситуація: якщо у вас недостатньо ресурсів, щоб сказати, що ваш екземпляр сервісу готовий, і ви занадто часто його опитуєте, балансувальник навантаження буде думати, що сервіс взагалі не може приймати трафік і забере його з розподілу трафіку. Поки піднімається та «прогрівається» новий сервіс, збільшується кількість трафіку на інші екземпляри, де ефект може повторитися. Таким чином, лавиноподібно, всі сервіси кластера стають недоступними.
Цікава історія склалася із базою даних. На той час вона жила на сімействі інстансів T з дефолтними дисками. Коли ви бачите, що кредити EBS вже підходять до мітки нижче 100, і не очікуєте на зменшення трафіку, апгрейдити екземпляр типу T — погане рішення. Щойно ви це зробите, у вас не буде запасу кредитів на EBS, вони починаються з нуля, і база даних банально «вижере» burst rate при старті і не зможе стабільно працювати. Простіше кажучи, захлинеться від навантаження. Це був перший серйозний інцидент при роботі з базою даних, який навчив нас закладати достатньо запасу потужності. До нас прийшло розуміння того, що у нашому випадку екземпляри сімейства T підходять тільки для інфраструктури PoC.
2020: міграція з RDS на виділені сервери
Продуктивність застосунків почала місцями просідати, адже обсяги трафіку та об’єм даних БД зросли. Іноді ми отримували неочікувану поведінку від застосунку при великій кількості трафіку або коли, наприклад, якийсь один платіжний провайдер був недоступний.
Ми навчилися працювати з суттєвими змінами трафіку (x3-x5), зберігати і обробляти десятки гігабайтів даних в день. Під час експлуатації на таких навантаженнях проявилися нові типи проблем. Наприклад, не було реконектів до Redis в деяких процесах, або відбувалося неправильне перепідключення у роботі з базою даних. Інколи це створювало паразитний трафік і ми «забивали» connection pool Postgres.
Вартість інфраструктури, кількість дрібних інцидентів та відсутність розуміння capacity RDS інстансів відносно роботи нашого процесинга призвели до того, що ми прийняли рішення про міграцію з RDS на виділені сервери. Протягом декількох місяців ми опановували нові інструменти та планували переїзд. Вибір пав на Patroni, де ми побудували майже класичну схему: у нас був Haproxy, через NLB трафік йшов на інстанси з PostgreSQL, де стояв Patroni. etcd було 5 інстансів у трьох зонах доступності, тож при падінні одного з них у нас точно залишався кворум. Це рішення, запущене на трьох серверах, дало нам змогу обробляти більше даних за менші гроші. Чим не щастя для бізнесу? Для початку ми взяли i3en екземпляри, а потім проапгрейдили їх до i3en.2xlarge.
Проблеми, з якими ми зіткнулися
1. Спочатку розсипався кластер etcd, а через це розсипався кластер Patroni. Кворум не допоміг. Переключення мастера відбувалося самостійно, а ми довго не могли зрозуміти в чому справа. Як виявилося, проблема була в синхронізації часу. Пізніше ми вирішили її за допомогою chrony.
2. Некоректна конфігурація. Параметри не відповідали можливостям машин, на яких працювали сервіси. Основною причиною було те, що не відбувався їх перегляд при міграціях.
3. NLB скидав підключення на порт 5432, якщо ми оновлюємо target на 5433. В нашій архітектурі на одному балансері було розділення по портах на writer та reader. Про цю проблему ми повідомили службу підтримки. Нам запропонували надіслати все повністю для того, щоб це можна було відтворити. У нас не було бажання витрачати на це час і зусилля, тому ми просто «забили». Майте на увазі, що досвід комунікації з службою підтримки може бути не найкращим.
4. Wraparound. Це проблема, з якою я не бажаю зіштовхнутися нікому. 2 листопада 2020 року о 08:58 наш сервер почав відхиляти всі спроби щось у нього записати. Це був початок найбільшого інциденту з базою даних за весь час. Ми мали фізичні копії в бекапах, і потрібно було розгортатися з бекапа в аварійному режимі, але не виходило через проблему на фізичному рівні із лічильниками XID. Ми вирішили транкейтити топові таблиці, робити дамп мінімальної кількості даних, і тоді з нього розгортати процесинг, а потім додавати дані уже в процесі роботи.
Це неповний список, але більшість проблем, з якими ми зіштовхнулися, були результатом відсутності сегрегації ресурсів. Коли у нас фонові процеси та веб крутилися, наприклад, на одному кластері ECS — це одне розділення. Друге розділення — доменне. Спілкування з платіжними провайдерами може відбуватися як в різних чергах, так і на різних кластерах.
У підсумку року ми мали більше 10 кластерів ECS і 100 черг. Ще у нас було 4 кластера PostgreSQL, preprocessing, картковий процесинг і портал мерчанта (окремий застосунок зі своїм кластером бази даних, який ми надаємо клієнтам-платіжним системам для перепродажу своїх каналів). Також було чотири публічні балансувальники навантаження на всього один продукт. Завершили злиття двох акаунтів AWS в один. Через систему проходило більше 10 мільйонів транзакцій на місяць, тож у нас було по 2,5 ТБ в двох БД.
Ми вже розуміли профіль навантаження та могли планувати його на довгі періоди. Ми взяли Savings Plans на EC2 Instance i3n для наших баз даних на рік і зекономили близько 35% на них. Тюнінг скейлінга кластерів та насиченість їх spot-ами теж дозволили суттєво зекономити та закупити Savings Plans для критичних кластерів на C5.
2021: переїзд на AWS Aurora
Кількість інцидентів, чергувань і нестабільності в роботі сервісу призвели до того, що ми перевезли картковий процесинг на AWS Aurora. Вирішили спробувати з меншого проєкту, а при успішній експлуатації мігрувати інші. Поступовість була необхідна для оцінки вартості експлуатації, бо прогнозувати кількість read та write IOPS було важко.
Ми почали активно оцифровувати в Terraform усю розгорнуту інфраструктуру. Звісно, це не зовсім приємний процес, коли треба проводити багато import та працювати з production, який не весь описаний в коді.
Ретроспектива
В результаті отриманого досвіду хочу зробити певні висновки ретроспективно, через призму цінності, яку ми могли б отримати:
● Описуйте всю інфраструктуру в коді з першого ж дня. Це допоможе у створенні документації, забезпеченні можливості стороннім особам зайти у ваш проєкт з вашою мінімальною участю, здійсненні аудиту та розгортанні інших аналогічних інфраструктур. Ми це упустили, а тепер надолужуємо.
● Пріоретизуйте та переглядайте цілі на період. Наприклад, якщо є бажання економити — це одне, а якщо падіння обходиться дуже дорого — це зовсім інше. Наша міграція з AWS RDS на Aurora пройшла через наш виділений самокерований інстанс. За 2020 рік ми отримали купу негативу і поганий досвід користувачів саме через базу даних. Звісно, як команда ми виросли у плані
архітектури й інфраструктури. Але якщо порівнювати збитки та репутаційні втрати з сумою, яку ми могли витратити на Aurora, то обрати Aurora було б раціональніше. Є така ментальна пастка: коли рахуєш вартість сервісу, іноді здається, що простіше самим все побудувати. Але потрібно також враховувати вартість обслуговування системи, роботи людей, засобів моніторингу, бекапів і всього іншого, що Amazon дає «з коробки».
● Робіть cost planning, щоб уникнути неприємних сюрпризів. Планування зростання тісно пов’язане з плануванням витрат. Тобто, ви можете брати Savings Plans, які дозволять вам рости органічніше та дешевше. Не нехтуйте цією можливістю.
● Проєктуйте свої застосунки одразу таким чином, щоб вони працювали на spot clusters. Інстанс може «вмерти» в будь-який момент, і ваш застосунок повинен вміти справлятися з цим.
● Не допускайте розростання ресурсів в одному акаунті. Ми не розпланували розвиток наших облікових записів, тож певний час в одному акаунті у нас жили development, production та ще якісь ресурси компанії, які не стосуються процесингу. Саме тому, коли прийшов час розгортати PCI DSS-інфраструктуру, ми робили це в окремому акаунті, бо просто не могли зробити це в основному, наповненому купою сторонніх ресурсів. Зараз ми прийшли до того, що розділяти акаунти дійсно необхідно. Ми переносимо їх в інший root-акаунт, щоб зробити SSO і розділити ворклоади за типами (development, production), виділити окремі акаунти для ресурсів, логів і усього того, що не стосується процесингу.
Маленька подяка AWS
Завдяки рішенню працювати із AWS у 2018 році, ми мали змогу більше сконцентруватися на розробці продукту, ніж на вирішенні інфраструктурних проблем. Варто сказати, що підтримка в AWS є платною. Чим більше ви витрачаєте загалом на інфраструктуру, тим дорожче для вас коштуватиме підтримка, навіть якщо ви нею не користуєтесь.
З позитивних аспектів хотів би відзначити роботу акаунт менеджерів та архітекторів, які з’являються автоматично при чеку $5k+. Багато роботи було проведено із ними для оптимізації використання сервісів AWS, щоб зменшити загальний чек.
Існує безліч програм, націлених на те, щоб підсадити вас на «голку» і збільшити ваш чек в AWS. Проте для освоєння певних сервісів вони пропонують credits, дозволяючи вам зекономити. Наприклад, якщо ви будете розвивати компанію чи продукт в напрямку Machine Learning, то це прекрасна можливість отримати декілька сотень, а то й тисяч доларів для ваших PoC.
Плани
Ми прийняли стратегічне рішення перейти на K8s, побудувати data warehouse та реорганізувати наші AWS акаунти. Про все це розповім детально в наступних статтях.
34 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів