Post Mortem через недоступність Quay.io

Прим. перев.: на початку серпня Red Hat публічно розповіла про вирішення проблем доступності, що виникали в попередні місяці у користувачів її сервісу Quay.io (в його основі - реєстр для образів контейнерів, що дістався компанії разом із покупкою CoreOS). Незалежно від вашої зацікавленості в цьому сервісі як такому, повчальний сам шлях, яким пройшли SRE-інженери компанії для діагностики та усунення причин аварії.

Post Mortem через недоступність Quay.io

19 травня, рано-вранці (за літнім північноамериканським східним часом, EDT), сервіс quay.io впав. Аварія торкнулася як споживачів quay.io, так і Open Source-проекти, які використовують quay.io як платформу для збирання та розповсюдження ПЗ. Red Hat цінує довіру як одних, так і інших.

Команда SRE-інженерів відразу підключилася до роботи та постаралася якнайшвидше стабілізувати роботу сервісу Quay. Однак поки вони цим займалися, клієнти втратили можливість push'ити нові образи, і лише періодично їм вдавалося pull'ити наявні. З невідомих причин база даних quay.io блокувалася після масштабування сервісу на повну потужність.

«Що змінилося?» - це перше питання, яке прийнято ставити в подібних випадках. Ми зауважили, що незадовго до проблеми кластер OpenShift Dedicated (на якому працює quay.io) почав оновлюватись до версії 4.3.19. Оскільки quay.io працює на Red Hat OpenShift Dedicated (OSD), регулярні оновлення були звичайною операцією і ніколи не призводили до проблем. Більше того, за попередні півроку ми кілька разів оновлювали кластери Quay без перерв у обслуговуванні.

Поки ми намагалися відновити роботу сервісу, інші інженери почали готувати новий кластер OSD із попередньою версією ПЗ, щоб у разі чого розгорнути все на ньому.

Аналіз причин

Основним симптомом збою була лавина з десятків тисяч підключень до БД, через яку екземпляр MySQL виявився фактично недієздатним. Через це було важко діагностувати проблему. Ми встановили обмеження на максимальну кількість підключень від клієнтів, щоб допомогти команді SRE оцінити проблему. Жодного незвичайного трафіку до бази даних не помітили: насправді більшість запитів були на читання, а лише деякі — на запис.

Ми також спробували виявити патерн у трафіку БД, який міг би спричинити цю лавину. Однак жодних закономірностей у логах знайти не вдалося. Чекаючи на готовність нового кластера з OSD 4.3.18, ми продовжували спроби запустити pod'и quay.io. Щоразу, коли кластер виходив на повну потужність, база даних зависала. Це означало, що необхідно було перезапустити екземпляр RDS на додаток до всіх pod'ам quay.io.

До вечора ми стабілізували сервіс у режимі read-only та відключили максимум несуттєвих функцій (наприклад, збір сміття у просторі імен), щоб знизити навантаження на БД. Зависання припинилися, але причину так і не було знайдено. Новий кластер OSD був готовий і ми перенесли сервіс, підключили трафік і продовжили моніторинг.

Quay.io стабільно працював на новому OSD-кластері, тому ми повернулися до логів бази даних, але так і не змогли виявити кореляцію, яка б пояснювала блокування. Інженери OpenShift працювали спільно з нами, намагаючись зрозуміти, чи зміни в Red Hat OpenShift 4.3.19 могли призвести до проблем з Quay. Однак нічого виявити не вдалося, а відтворити проблему в лабораторних умовах не вдалося.

Другий збій

28 травня, незадовго до полудня по EDT, quay.io знову впав з тим самим симптомом: функціонування бази даних блокувалося. І знову ми кинули усі сили на розслідування. Насамперед потрібно було відновити роботу сервісу. Однак цього разу перезавантаження RDS та перезапуск pod'ів quay.io ні до чого не привели: чергова лавина підключень захлеснула базу Але чому?

Quay написано на Python, і кожен pod працює як єдиний монолітний контейнер. У середовищі виконання контейнера одночасно виконується безліч паралельних завдань. Ми використовуємо бібліотеку gevent під gunicorn для обробки веб-запитів. Коли Quay надходить запит (через наш власний API, або через API Docker'а), йому призначається gevent worker. Зазвичай, цей worker повинен зв'язатися з базою даних. Після першого збою ми виявили, що gevent worker'и підключалися до бази даних, використовуючи стандартні налаштування.

Враховуючи значну кількість pod'ів Quay і тисячі запитів, що надходять в секунду, велика кількість підключень до бази даних теоретично могла перевантажити екземпляр MySQL. Завдяки моніторингу було відомо, що Quay в середньому опрацьовує 5 тис. запитів на секунду. Приблизно так само було і число підключень до бази даних. 5 тис. підключень із запасом вкладалися у можливості нашого екземпляра RDS (чого не можна сказати про десятки тисяч). З якоїсь причини відбувалися несподівані сплески числа підключеньПроте ми не помічали будь-якої кореляції з вхідними запитами.

На цей раз ми твердо вирішили знайти та усунути джерело проблеми, а не обмежитися перезавантаженням. У кодову базу Quay були внесені зміни, що лімітують кількість підключень до БД для кожного worker'а gevent. Це число стало параметром конфігурації: стало можливим змінювати його «на льоту», не збираючи новий образ контейнера. Щоб дізнатися, скільки підключень реально обробити, було проведено кілька випробувань зі staging-оточенням, в яких задавалися різні значення, щоб подивитися, як це позначиться на сценаріях тестування навантаження. У результаті виявилося, що Quay починає видавати помилки 502, коли кількість підключень перевищує 10 тис.

Ми відразу розгорнули цю нову версію в production і почали стежити за графіком підключень до бази даних. У минулому база блокувалася приблизно за 20 хвилин. За 30 безпроблемних хвилин у нас з'явилася надія, а за годину — впевненість. Ми відновили трафік на запис на сайті і розпочали postmortem-аналіз.

Зумівши обійти проблему, що призводить до блокування, ми не з'ясували її справжні причини. Підтвердилося, що вона не пов'язана з будь-якими змінами в OpenShift 4.3.19, оскільки те саме сталося і на версії 4.3.18, яка до цього працювала з Quay без будь-яких проблем.

У кластері явно ховалося ще щось.

Детальне вивчення

Quay.io шість років використовував стандартні налаштування для підключення до БД без будь-яких проблем. Що змінилося? Зрозуміло, що весь цей час трафік на quay.io неухильно зростав. У нашому випадку все виглядало так, ніби досягалося якесь граничне значення, яке служило тригером для лавини підключень. Ми продовжили вивчати логи БД після другого збою, але не виявили жодних закономірностей чи очевидних взаємозв'язків.

Тим часом команда SRE займалася поліпшеннями в області спостереження запитів Quay і загального здоров'я сервісу. Було розгорнуто нові метрики та панелі моніторингу, що показують, які частини Quay мають найбільший попит з боку клієнтів.

Quay.io нормально працював до 9 червня. Вранці (по EDT) ми знову стали свідками значного збільшення числа підключень до бази даних. Цього разу простою не сталосяоскільки новий параметр обмежував їх кількість і не дозволяв перевищити пропускну здатність MySQL. Однак приблизно протягом півгодини багато користувачів відзначали повільну роботу quay.io. Ми швидко зібрали всі можливі дані, скориставшись доданими інструментами моніторингу. Несподівано виявилася закономірність.

Перед самим стрибком кількості підключень велику кількість запитів надійшло на App Registry API. App Registry – це маловідома функція quay.io. Вона дозволяє зберігати такі штуки, як чарти Helm та контейнери з багатими (rich) метаданими. Більшість користувачів quay.io не працюють із цією функцією, проте їй активно користується Red Hat OpenShift. OperatorHub у складі OpenShift зберігає всі оператори App Registry. Ці оператори формують основу для екосистеми робочих навантажень OpenShift та операційної моделі (в рамках операцій другого дня, Day 2), орієнтованої на партнерів.

Кожен кластер OpenShift 4 використовує оператори із вбудованого OperatorHub'а для публікації каталогу операторів, доступних для встановлення, та надання оновлень для вже встановлених. Зі зростанням популярності OpenShift 4 збільшилася кількість кластерів на ньому по всьому світу. Кожен із цих кластерів завантажує вміст операторів, щоб запустити вбудований OperatorHub, використовуючи App Registry всередині quay.io як бекенд. У пошуках джерела проблеми ми втратили те, що з поступовим зростанням популярності OpenShift збільшувалося і навантаження на одну з функцій quay.io, що рідко використовуються..

Ми провели певний аналіз трафіку запитів App Registry та заглянули в код реєстру. Відразу ж з'явилися недоліки, через які запити до бази даних формувалися неоптимально. При невеликому навантаженні вони не завдавали жодного клопоту, проте при її зростанні ставали джерелом проблем. У App Registry виявилося два проблемних endpoint'а, які погано реагують на зростання навантаження: перший видавав список усіх пакетів у репозиторії, другий — повертав усі blob'и для пакета.

Усунення причин

Весь наступний тиждень ми оптимізували код самого App Registry та його оточення. Були перероблені явно неефективні SQL-запити, усунуті зайві виклики команди tar (вона запускалася при кожному витягуванні blob'ів), додано кешування скрізь, де можливо. Потім було проведено масштабне тестування продуктивності та порівняно швидкість роботи App Registry до та після змін.

Запити API, які раніше займали до півхвилини, тепер виконувались за мілісекунди.. Наступного тижня ми розгорнули зміни у production, та відтоді quay.io працює стабільно. За цей час спостерігалося кілька різких сплесків трафіку на endpoint'і App Registry, але виконані вдосконалення запобігли перебої в роботі бази даних.

Чого ми навчилися?

Зрозуміло, що будь-який сервіс намагається уникнути простоїв. У нашому випадку ми віримо, що останні збої допомогли зробити quay.io краще. Для себе ми винесли кілька основних уроків, якими хочемо поділитися:

  1. Дані про те, хто і як використовує ваш сервіс, не бувають зайвими. Оскільки Quay «просто працював», у нас ніколи не виникала потреба витрачати час на оптимізацію трафіку та керування навантаженням. Все це створило хибне відчуття безпеки, що сервіс може масштабуватися до безкінечності.
  2. Коли сервіс падає, відновлення його роботи – головний пріоритет. Оскільки Quay продовжував страждати від заблокованої бази даних під час першого збою, наші стандартні процедури не мали очікуваного ефекту і ми не змогли відновити роботу сервісу за їх допомогою. Це призвело до ситуації, коли довелося витрачати час на аналіз та збирання даних, сподіваючись знайти першопричину — замість того, щоб спрямувати всі зусилля на відновлення працездатності.
  3. Оцінюйте вплив кожної з функцій сервісу. Клієнти рідко використовували App Registry, тому він не був пріоритетним для нашої команди. Коли деякі функції продукту майже не використовуються, їх баги «випливають» рідко, і розробники перестають стежити за кодом. Легко стати жертвою помилки, що так і має бути, поки раптово ця функція не опиняється в центрі масштабного інциденту.

Що далі?

Робота із забезпечення стабільності сервісу ніколи не припиняється, і ми постійно покращуємо його. Обсяги трафіку на quay.io продовжують зростати, і ми розуміємо, що зобов'язані робити все можливе, щоб виправдати довіру клієнтів. Тому нині працюємо над такими завданнями:

  1. Розгортання реплік баз даних лише для читання, щоб допомогти сервісу обробляти відповідний трафік у разі виникнення проблем із основним екземпляром RDS.
  2. Оновлення екземпляра RDS. Поточна версія сама собою не є проблемою. Швидше, ми просто хочемо прибрати хибний слід (яким пішли під час збою); Підтримка ПЗ в актуальному стані дозволить усунути ще один фактор у разі майбутніх відключень.
  3. Додаткове кешування по всьому кластеру. Ми продовжуємо пошук областей, де кешування дозволить знизити навантаження на базу даних.
  4. Додавання firewall'а веб-застосунків (WAF), щоб бачити, хто і чому підключається до quay.io.
  5. Починаючи з наступного релізу, кластери Red Hat OpenShift відмовляться від App Registry на користь каталогів операторів (Operator Catalogs), що базуються на образах контейнерів, доступних на quay.io.
  6. Довгостроковою заміною App Registry може стати підтримка специфікацій артефактів Open Container Initiative (OCI). В даний час вона реалізується у вигляді рідного функціоналу Quay і буде доступна користувачам, коли саму специфікацію остаточно узгодять.

Все вищеперелічене є частиною інвестицій Red Hat, що продовжуються, в quay.io у міру того, як ми переходимо від невеликої команди «у дусі стартапу» до зрілої платформи, керованої SRE. Ми знаємо, що багато наших клієнтів покладаються на quay.io у своїй повсякденній роботі (включаючи Red Hat!) і намагаємося бути максимально відкритими щодо недавніх збоїв і зусиль, що продовжуються, стати кращими.

PS від перекладача

Читайте також у нашому блозі:

Джерело: habr.com

Додати коментар або відгук