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

Avatar for Dimitar Dimitrov

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