$30 off During Our Annual Pro Sale. View Details »

Поуки от 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. View Slide

  2. Поуки от 15 години
    инциденти в продукция
    Димитър Димитров

    View Slide

  3. 15* години
    челен опит с мотиката
    Димитър Димитров

    View Slide

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

    View Slide

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

    View Slide

  6. 1. Философстване

    View Slide

  7. “To err is human.”

    View Slide

  8. Всяка грешка е възможност за развитие.
    Прогресираме, като се учим от грешките си.
    Ако не грешим, най-вероятно сме спрели.
    To err is human.

    View Slide

  9. Още по-добре 😄
    ● https://github.com/danluu/post-mortems –
    интересна и богата колекция от различни
    инциденти на предимно софтуерни компании.
    ● https://k8s.af/ – Kubernetes Failure Stories.
    Да се учим от грешките на другите!

    View Slide

  10. ● Полезно е да се говори по темата
    ● Не е зле да имате incident response процес
    ● Който е blame-free и фокусиран над фактите
    ● И да оставяте писмена следа за случката и
    поуките
    ● А ако от време на време тренирате incident
    response, ще сте 🥇
    На практика:

    View Slide

  11. 2. Мъдри мисли

    View Slide

  12. “Complex systems contain changing
    mixtures of failures latent within them.”
    Richard I. Cook, MD

    View Slide

  13. Richard I. Cook, MD
    “Complex systems run in degraded mode.
    [They] run as broken systems.”

    View Slide

  14. “Catastrophe
    is always just around the corner.”
    Richard I. Cook, MD

    View Slide

  15. Richard I. Cook, MD
    “[...] accident reviews nearly always note
    that the system has a history of prior
    ‘proto-accidents’ that nearly generated
    catastrophe.”

    View Slide

  16. Richard I. Cook, MD
    “Catastrophe requires multiple failures –
    single point failures are not enough.”

    View Slide

  17. Richard I. Cook, MD
    “Failure free operations require
    experience with failure.”

    View Slide

  18. ● От Richard I. Cook, MD
    ● Труд от 1998-2000 г.
    ● https://how.complexsystems.fail/
    How Complex Systems Fail

    View Slide

  19. “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/

    View Slide

  20. “[...] 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/

    View Slide

  21. “All incidents can be worse.”
    Resilience Engineering: The What and
    How, John Allspaw, DevOpsDays DC 2019
    John Allspaw, former CTO @ Etsy

    View Slide

  22. 3. Истории от фронта

    View Slide

  23. ● Head of Infrastructure в Dext (преди известни
    като Receipt Bank) през последните 5 години
    ● Програмист по душа, със силен интерес към
    инфраструктурата
    ● Силен интерес към нещата “под капака”
    ● Очарова се лесно от заплетени бъгове и
    инциденти
    Контекст: за мен

    View Slide

  24. ● Продуктова компания на около 10 години, ~500
    човека
    ● Няколко тясно-свързани услуги и сравнително
    хомогенна инфраструктура
    ● The long game
    ● Инженерен екип от около 120 човека, 13 човека
    инфраструктурен отдел
    ● Remote working от самото начало
    Контекст: за Dext, част 1

    View Slide

  25. Контекст: за 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

    View Slide

  26. ...от общо 223 инцидента (and counting),
    регистрирани от средата на 2015 г.
    досега.
    Пет примера

    View Slide

  27. №1

    View Slide

  28. След скорошна миграция от PostgreSQL 12
    към 13, DBA екипа реагира на аларма, че
    една от логическите реплики е спряла да
    наваксва.
    №1 – репликацията се счупи!

    View Slide

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

    View Slide

  30. №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.”

    View Slide

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

    View Slide

  32. ● Индексите в базите са на практика
    сортирани елементи и разчитат силно на
    колации
    ● Ако промените колацията, променяте
    правилата на сортиране и…
    ● Изведнъж някои елементи в индекса стават
    недостижими!
    №1 – колации и индекси в RDBMS

    View Slide

  33. №1 – пример

    View Slide

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

    View Slide

  35. ● Можело е да го избегнем, ако сме били пуснали
    index rebuild на новосъздадената PG 13 база,
    преди да я вкараме в употреба – имало го е в
    чеклиста, но сме си го спестили
    ● Внимавайте с колациите :)
    №1 – изводи

    View Slide

  36. №1 – ресурси
    ● https://postgresql.verite.pro/blog/2018/08/27/glib
    c-upgrade.html
    ● https://www.citusdata.com/blog/2020/12/12/dont-l
    et-collation-versions-corrupt-your-postgresql-ind
    exes/

    View Slide

  37. №2

    View Slide

  38. След една от първите ни миграции към
    Kubernetes на app, събиращ логове и
    статистики, забелязваме, че той започва
    да издиша, въпреки повечето ресурс.
    №2 – гърлото на бутилката

    View Slide

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

    View Slide

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

    View Slide

  41. №2 – фактите
    ● Не виждаме увеличение в броя requests към
    него
    ● Гледайки average response time, не виждаме
    съществена промяна – приложението
    обработва заявки сравнително бързо и горе-
    долу за същото време, за което и преди

    View Slide

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

    View Slide

  43. №2 – какво се оказва?
    ● Точно 5 секунди е много съмнително
    ● 5 секунди е default timeout на DNS клиентите
    ● Kubernetes има нужда от специален DNS
    сървър за service discovery
    ● Приложението ни прави по няколко DNS
    заявки на request
    ● Особеност на DNS-а в Kubernetes умножава
    тези заявки x5

    View Slide

  44. №2 – какво се оказва?
    => Претоварен DNS (CoreDNS) в Kubernetes.

    View Slide

  45. №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

    View Slide

  46. №3

    View Slide

  47. Забелязваме, че за последния месец,
    цената за трафик, която плащаме на AWS,
    е скочила с близо 30% – с почти
    $3000/месец! А нямаме такъв растеж на
    заявките.
    №3 – $3000/месец повече в AWS сметката

    View Slide

  48. ● Имаме система за background jobs (Sidekiq),
    работеща с Redis
    ● Донадградили (побългарили) сме си я
    ● Събираме статистика за състоянието ѝ от
    Redis на всеки 10 секунди
    ● Не сме догледали и взимаме всички payloads
    на всички enqueued jobs
    ● Имаме едни опашки с хиляди jobs, някои от
    които са мегабайти
    №3 – какво се оказа?

    View Slide

  49. => Огромен трафик между Redis сървъра и
    приложението ни, който е превъртял
    електромера.
    №3 – какво се оказа?

    View Slide

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

    View Slide

  51. №4

    View Slide

  52. №4 – автоматичен failover код
    Звъни аларма, основното ни приложение е
    долу. Почти всички потребители виждат
    грозни HTTP 502/504 грешки. Инцидентът
    продължава 12 минути.

    View Slide

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

    View Slide

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

    View Slide

  55. => Сами се прецакваме с калпав failover код.
    №4 – какво се оказа?

    View Slide

  56. 1. Error handling-ът е трудно начинание
    2. Know your tools! Няколко пропуска в
    разбирането ни за Ansible (който изпълнява
    деплоите към онзи момент) са допринесли за
    пропуските ни в логиката.
    №4 – изводи

    View Slide

  57. №5

    View Slide

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

    View Slide

  59. №5 – email-in down for 11 hours
    1. Клиентите могат да изпращат документи
    на специален имейл адрес
    2. Ние ги обработваме с верига от background
    jobs (Sidekiq)
    3. Част от jobs във веригата са “unique” (с наша,
    побългарена имплементация) – ако вече има
    нареден job, не се нарежда втори

    View Slide

  60. №5 – какво се оказа?
    1. “Uniqueness” кодът ни е неатомарен и сме
    ударили рядък случай, в който сме създали
    unique token за job, но не сме наредили самия
    job
    2. Това води до stuck-ване на целия email-in
    processing pipeline
    3. Имаме аларма за това!
    4. Но тя била mute-ната преди 1 година и
    забравена...

    View Slide

  61. ● 15 минути триаж и премахване на
    “запушването” и
    ● 8 часа борба с последствията от огромния
    беклог...
    №5 – ефект

    View Slide

  62. 1. Писане на атомарен код е сложно
    2. Винаги mute-вайте за ограничено време
    3. Know your tools! Клиентската библиотека за
    Redis в Ruby прави 1 silent retry на всички
    операции и чупи гаранциите за атомарност
    на някои команди
    №5 – изводи

    View Slide

  63. 4. Още (random) изводи и съвети

    View Slide

  64. Съвети (предимно web-app specific)
    1. Разучете добре всяко звено на request пътя
    2. Събирайте логове от всяко от тях
    3. (Cloud) LB logs = много ценни! AWS LBs са били
    безупречно стабилни до момента и логовете
    им – особено полезни
    4. Опознайте добре мониторинг
    инструментите си; свикнете с “нормалното”
    5. Дефинирайте поне бизнес аларми

    View Slide

  65. 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

    View Slide

  66. APM е добре, но пробвали ли сте ASH
    (active session history)?

    View Slide

  67. View Slide

  68. Благодаря!
    mitio
    [email protected]
    @mitio
    ddimitrov.name

    View Slide