Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Поуки от 15 години инциденти в продукция

Поуки от 15 години инциденти в продукция

Запис: https://www.youtube.com/watch?v=_ms0aQscrgk&list=PLX-Eu7bfT8M_MRzsoi9BWIwXuYegGnykT&index=6

Като ръководител на инфраструктурния екип в Dext, чувствам, че нося лична отговорност както за бързото разрешаване на всеки инцидент в продукция, така и за тяхното предотвратяване (ха-ха, невъзможно). Бил съм на първа линия по време на много инциденти и това ме е научило на много. Ще ви споделя няколко по-интересни и запомнящи се инцидента или проблема от реална продукционна среда и ще ви споделя какви изводи съм си направил от тях. Освен самите случки, които, надявам се, ще бъдат забавни за странична аудитория, "поуките" ще се въртят около какви инструменти за метрики, аларми и дебъгване са ни били особено полезни, какъв процес следваме по време на инцидент и как това ни помага (или пречи), включително и как комуникираме и ескалираме. Ще засегна и някои моменти около устойчиви софтуерни архитектури и размисли около пускане на по-рискови промени в продукция.

Dimitar Dimitrov

November 05, 2021
Tweet

More Decks by Dimitar Dimitrov

Other Decks in Programming

Transcript

  1. Какво да очаквате 1. Малко философстване по темата 2. Мисли

    на други, по-умни от мен 3. Разкази на очевидец от окопите 4. Изводи, съвети, предложения 5. Да не ми стигне времето
  2. • Да научим нещо заедно • Идеи как да избегнете

    сходни мотики • Или, поне да се позабавлявате на чужд гръб • Да се вместя в 30 минути KPI – поне 3 въпроса, които да ме изпотят 😅 Основните ми цели днес
  3. Всяка грешка е възможност за развитие. Прогресираме, като се учим

    от грешките си. Ако не грешим, най-вероятно сме спрели. To err is human.
  4. Още по-добре 😄 • https://github.com/danluu/post-mortems – интересна и богата колекция

    от различни инциденти на предимно софтуерни компании. • https://k8s.af/ – Kubernetes Failure Stories. Да се учим от грешките на другите!
  5. • Полезно е да се говори по темата • Не

    е зле да имате incident response процес • Който е blame-free и фокусиран над фактите • И да оставяте писмена следа за случката и поуките • А ако от време на време тренирате incident response, ще сте 🥇 На практика:
  6. Richard I. Cook, MD “[...] accident reviews nearly always note

    that the system has a history of prior ‘proto-accidents’ that nearly generated catastrophe.”
  7. • От Richard I. Cook, MD • Труд от 1998-2000

    г. • https://how.complexsystems.fail/ How Complex Systems Fail
  8. “TTR is more important than TBF (for most types of

    F)” John Allspaw, former CTO @ Etsy https://www.kitchensoap.com/2010/11/07/mttr-mtbf-for-most-types-of-f/
  9. “[...] listing human error as a root cause isn’t where

    you should end, it’s where you should start your investigation. Getting behind what led to a ‘human error’ is where the good stuff happens.” John Allspaw, former CTO @ Etsy https://www.kitchensoap.com/2011/04/07/resilience-engineering-part-i/
  10. “All incidents can be worse.” Resilience Engineering: The What and

    How, John Allspaw, DevOpsDays DC 2019 John Allspaw, former CTO @ Etsy
  11. • Head of Infrastructure в Dext (преди известни като Receipt

    Bank) през последните 5 години • Програмист по душа, със силен интерес към инфраструктурата • Силен интерес към нещата “под капака” • Очарова се лесно от заплетени бъгове и инциденти Контекст: за мен
  12. • Продуктова компания на около 10 години, ~500 човека •

    Няколко тясно-свързани услуги и сравнително хомогенна инфраструктура • The long game • Инженерен екип от около 120 човека, 13 човека инфраструктурен отдел • Remote working от самото начало Контекст: за Dext, част 1
  13. Контекст: за Dext, част 2 • Основно уеб приложения: UI

    и API за мобилните, едно по-голямо user-facing • Предимно Ruby on Rails с PostgreSQL бекенд • Изцяло хостнати в AWS • Контейнери в self-managed Kubernetes • Self-managed ELK стек, Prometheus + Thanos, Grafana, Datadog • Tрафик ~15 mil reqs/day, 24/7 usage
  14. След скорошна миграция от PostgreSQL 12 към 13, DBA екипа

    реагира на аларма, че една от логическите реплики е спряла да наваксва. №1 – репликацията се счупи!
  15. №1 – репликацията се счупи! • Репликацията е спряла, поради

    грешка за unique index violation • Действително, има unique index грешка: основната база праща ред с имейл адрес, който вече съществува в таблицата • Оказва се, че на основната база са се появили дублирани стойности за някои полета. Изглежда като че не работят unique indexes!
  16. №1 – какво се оказва? • С миграцията от PG

    12 → 13, мигрирахме и от Ubuntu 16.04 към 20.04 • Процесът по миграция включва копиране на binary файловете на базата, вкл. индексите • С новата версия на Ubuntu идва и GNU libc 2.28 (Aug 2018), която носи “a major update of its Unicode locale data with new collation information.”
  17. • “Колация” е колекция от правила, дефиниращи подредбата на текст

    (кой символ преди кой се води) • Тя определя как ще бъдат сортирани списък стрингове • Има много колации, от които можем да избираме • Колациите се променят с времето №1 – collation какво?
  18. • Индексите в базите са на практика сортирани елементи и

    разчитат силно на колации • Ако промените колацията, променяте правилата на сортиране и… • Изведнъж някои елементи в индекса стават недостижими! №1 – колации и индекси в RDBMS
  19. • Изключително трудно да се оцени изцяло • Малко (за

    щастие) количество дублирани записи (адска мъка да се оправят, контакт с потребителите) • Неизвестно количество заявки, които не са връщали съществуващи резултати, защото не са намерили ключ в индекса №1 – ефекти от проблема
  20. • Можело е да го избегнем, ако сме били пуснали

    index rebuild на новосъздадената PG 13 база, преди да я вкараме в употреба – имало го е в чеклиста, но сме си го спестили • Внимавайте с колациите :) №1 – изводи
  21. След една от първите ни миграции към Kubernetes на app,

    събиращ логове и статистики, забелязваме, че той започва да издиша, въпреки повечето ресурс. №2 – гърлото на бутилката
  22. №2 – гърлото на бутилката • Преди е работело окей

    с 10-20 процеса, сега дори 80 не му стигат! • Започват да се затлачват други неща по тръбата – опашки, от които то трябва да консумира • Застрашава се видимостта ни към приложенията
  23. №2 – фактите • Приложението е single-threaded и разчита на

    паралелизация с процеси • Нормалното време за обработка на заявки е стотни от секундата • През тази система обикновено текат 1000-2000 заявки в секунда
  24. №2 – фактите • Не виждаме увеличение в броя requests

    към него • Гледайки average response time, не виждаме съществена промяна – приложението обработва заявки сравнително бързо и горе- долу за същото време, за което и преди
  25. • Сещаме се да погледнем максималното време за изпълнение на

    заявките • Изскача нещо интересно – тук-таме има заявки, които отнемат 5 секунди • Малко са на фона на всички – няколко десетки заявки, на фона на хиляди, но! • При очакван throughput от 1-2к/секунда, да имаш няколко десетки запушени процеса е ☠ №2 – фактите
  26. №2 – какво се оказва? • Точно 5 секунди е

    много съмнително • 5 секунди е default timeout на DNS клиентите • Kubernetes има нужда от специален DNS сървър за service discovery • Приложението ни прави по няколко DNS заявки на request • Особеност на DNS-а в Kubernetes умножава тези заявки x5
  27. №2 – изводи 1. Beware of averages! Предпочитайте персентили и

    хвърляйте око на максимумите. 2. Научете какво е percentile. Mean = 50th percentile, max = 100th percentile. Например, Response time 95th percentile = 1s значи, че 95% от всички requests са максимум 1s. 3. It’s always DNS¹! 4. ¹Or BGP
  28. Забелязваме, че за последния месец, цената за трафик, която плащаме

    на AWS, е скочила с близо 30% – с почти $3000/месец! А нямаме такъв растеж на заявките. №3 – $3000/месец повече в AWS сметката
  29. • Имаме система за background jobs (Sidekiq), работеща с Redis

    • Донадградили (побългарили) сме си я • Събираме статистика за състоянието ѝ от Redis на всеки 10 секунди • Не сме догледали и взимаме всички payloads на всички enqueued jobs • Имаме едни опашки с хиляди jobs, някои от които са мегабайти №3 – какво се оказа?
  30. => Огромен трафик между Redis сървъра и приложението ни, който

    е превъртял електромера. №3 – какво се оказа?
  31. 1. Безос летя в космоса заради такива като нас 2.

    Public cloud сметката става много трудна за контрол от едно ниво на сложност нататък 3. Парите за трафик са най-трудното нещо за разпарчатосване и разгадаване 4. Measure & observe: ако можете да си пуснете някакъв вид автоматизиран anomaly detection => 🥇 №3 – изводи
  32. №4 – автоматичен failover код Звъни аларма, основното ни приложение

    е долу. Почти всички потребители виждат грозни HTTP 502/504 грешки. Инцидентът продължава 12 минути.
  33. 1. Деплойваме по няколко пъти на ден, рутинно 2. Деплоят

    е blue-green – вдига второ копие на приложението, чака то да стане готово, превключва трафика към него и чак накрая спира старото копие 3. Написали сме failover код, който да върне трафика към оригиналното копие, ако с новото нещо не е наред №4 – автоматичен failover код
  34. 1. Върви деплой. Вдигнали сме новото копие. То е готово.

    Пуснали сме трафик към него и чакаме да видим, че е потекъл. 2. На 1 от 19-те машини проверката за потекъл трафик не минава. Всички останали 18 са наред и вече спират старото копие. 3. На проблемната машина тръгва rescue код, който връща трафика глобално към старото копие. Което вече има само 1 сървър... №4 – какво се оказа?
  35. 1. Error handling-ът е трудно начинание 2. Know your tools!

    Няколко пропуска в разбирането ни за Ansible (който изпълнява деплоите към онзи момент) са допринесли за пропуските ни в логиката. №4 – изводи
  36. №5 – email-in down for 11 hours Рано сутрин от

    съпорта ни съобщават за множество сигнали от клиенти, че не обработваме документите, които ни изпращат по имейл.
  37. №5 – email-in down for 11 hours 1. Клиентите могат

    да изпращат документи на специален имейл адрес 2. Ние ги обработваме с верига от background jobs (Sidekiq) 3. Част от jobs във веригата са “unique” (с наша, побългарена имплементация) – ако вече има нареден job, не се нарежда втори
  38. №5 – какво се оказа? 1. “Uniqueness” кодът ни е

    неатомарен и сме ударили рядък случай, в който сме създали unique token за job, но не сме наредили самия job 2. Това води до stuck-ване на целия email-in processing pipeline 3. Имаме аларма за това! 4. Но тя била mute-ната преди 1 година и забравена...
  39. • 15 минути триаж и премахване на “запушването” и •

    8 часа борба с последствията от огромния беклог... №5 – ефект
  40. 1. Писане на атомарен код е сложно 2. Винаги mute-вайте

    за ограничено време 3. Know your tools! Клиентската библиотека за Redis в Ruby прави 1 silent retry на всички операции и чупи гаранциите за атомарност на някои команди №5 – изводи
  41. Съвети (предимно web-app specific) 1. Разучете добре всяко звено на

    request пътя 2. Събирайте логове от всяко от тях 3. (Cloud) LB logs = много ценни! AWS LBs са били безупречно стабилни до момента и логовете им – особено полезни 4. Опознайте добре мониторинг инструментите си; свикнете с “нормалното” 5. Дефинирайте поне бизнес аларми
  42. 1. Из документацията на New Relic: “the default number of

    traces at the trace origin is 10 traces per minute” 2. Обърнете внимание на sampling profiling – много observability инструменти са sampling profilers (какъвто е “distributed tracing” продукта на New Relic) Съвети, част 2