Пропустити навігацію EPAM

Технічна підтримка мікросервісів 24/7: як ми вибудовували процес

Андрій Трубіцин

Java Solution Architect, EPAM

Всім привіт. Мене звати Андрій Трубіцин, я співпрацюю з ЕРАМ як Java Solution Architect. У цій статті я розповім, як ми побудували процес технічної підтримки мікросервісів в режимі нон-стоп для великого американського клієнта.

Це був перший досвід впровадження такого підходу протягом 4 років моєї роботи у харківському офісі ЕРАМ, і він був нелегким для команди: потрібно було розібратися у новій для нас системі - Opsgenie та її інтеграції, знайти бажаючих виходити на нічні чергування, спланувати роботу та поставити процес на рейки. На нашому проекті через мікросервісну архітектуру дуже часті релізи та динамічний ритм. Ми завжди в тонусі, багатьом колегам до душі такий інтенсив. Проте, важливо щоб баланс роботи та особистого життя зберігався без втрати якості безперервних постачань оновлень (у тому числі і в середовище промислової експлуатації).

Якщо ви працюєте над рішенням на мікросервісах або маєте справу із частими релізами для вимогливого клієнта, вірогідно, вас зацікавить наш досвід використання Opsgenie як системи управління аваріями.

Бізнес-проблема

Сьогодні практично будь-яка компанія перебуває в умовах гострої конкурентної боротьби. Важливо разом із клієнтами встигати за змінами ринку за допомогою своєчасної цифрової трансформації бізнесу. Платформи мають бути швидкими та адаптивними – це одна з умов виживання та запорука збільшення доходів клієнта. Мікросервіси, зокрема, дають можливість зменшити time to market. Зворотній бік медалі – часті релізи, відкладене end-to-end-тестування та інші фактори можуть спричиняти збої, на які бізнес прагне швидко реагувати.

Це стало причиною того, що одного чудового вечора протягом чергового зідзвону один з наших американських клієнтів повідомив, що хоче організувати технічну підтримку свого продукту 24 години на добу, 7 днів на тиждень.

Як я вже зазначив раніше, продукт побудований на мікросервісній архітектурі і до нього застосовується підхід безперервного постачання оновлень. Це означає, що зміна, внесена інженерами, після проходження по CI / CD-процесу з різними тестами і рівнями контролю якості потрапляє до промислового середовища приблизно за 25-30 хвилин.

Над продуктом працюють понад 200 осіб, 70 з них базуються в Харкові. До складу кожної проєктної команди входять розробники, системні інженери, автоматизатори. Разом вони відповідають за написання коду і тестів, за процес оновлення мікросервіса в продукті (CI / CD pipeline) і «викочування» в промислову середу експлуатації. Вимоги до якості високі: на проєкті використовується статичний аналіз вихідного коду, вузлова перевірка тестами, тестування компонентів на моделях, інтеграційне і функціональне тестування, перевірка на наявність слабких місць і продуктивності тощо.

Але все ж таки іноді в промисловому середовищі відбуваються збої. Інженери не завжди можуть усунути їх оперативно: клієнт надає свої сервіси в Північній Америці, різниця в часі становить 7-10 годин. Крім того, у всіх інженерів є власний перелік планових завдань, і якщо вони будуть відволікатися на усунення збоїв, то може бути порушений графік розробки нових можливостей продукту.

Проте клієнт вимагав, щоб на момент виникнення несправності хтось почав працювати над ними протягом 30 хвилин у будь-який час доби. Це означає, що повинен бути хтось, хто міг би отримати повідомлення про збій і включитися в роботу протягом півгодини. Отже безперервно на відстані витягнутої руки у «чергового» інженера повинні знаходитися телефон і ноутбук з надійним інтернет-з'єднанням.

Також клієнт хотів мати можливість ескалувати проблему, якщо з будь-яких причин у заздалегідь обумовлений час інженер не відповів, що взявся за роботу; лід команди повинен отримувати дзвінок з описом проблем, наступним  прийняти повідомлення має архітектор, після нього - сам замовник. Якщо ця ієрархія буде «пробиватися» і проблема доходитиме до клієнта, нам загрожуватимуть фінансові санкції.

Початок шляху

На старті наша робота складалася з наступних етапів:

  1. Зрозуміти, на які події повинна реагувати система управління аваріями, а які вона може ігнорувати. Треба було проаналізувати цілий продукт, зібрати перелік усіх потенційних негативних моментів і направити його клієнту.
  2. Обговорити кожну подію з переліку з замовником, щоб виявити критично важливі для нього моменти
  3. Сформувати фінальний перелік завдань, які програмісти контролюватимуть 24/7. Насправді, не всі збої вимагають негайного реагування і виправдовують додаткові витрати клієнта на цілодобову техпідтримку.

    Критерії, за якими ми сформували список критичних для нас подій, стосуються основного бізнес-флоу замовника. Якщо один з мікросервісів, який обслуговує цю частину системи, дає сигнал про відмову (видає помилку, відпрацьовує повільніше певних SLA або виявляється недоступним), це проблема, яка потребує негайного втручання програмістів.
  4. Зробити PoC. Ми вивчили документацію обраної системи управління аваріями, отримали доступ до їх «пісочниці», побудували свій Proof of Concept на базі тестового сервісу, який моделював би різні виняткові ситуації, і відпрацювали схему взаємодії з Opsgenie.

    Після презентації результатів клієнту і документування процессу команди взяли систему в роботу, щоб у плановій імплементації додати функціонал техпідтримки 24/7 в бізнес-флоу замовника. Технічну сторону завдання виконали архітектор і технічний лідер однієї з команд.
  5. Налагодити та впровадити новий процес в роботу команди. Цим займався, переважно, наш проєктний менеджер, і він стикнувся з непростим завданням. Від самого початку стало зрозуміло, що команді на «чергуванні» потрібні саме розробники (зазвичай збої трапляються в ході бізнес-процесу сервісів, а не зі зміною стендів, наприклад). Однак це не можуть бути ті самі люди, які працюють над розширенням функціоналу, технічним боргом та іншими завданнями. Їхній режим передбачає регулярні зустрічі у денний час, написання коду, перерву на обід. Ввечері ці розробники можуть піти на зустріч з друзями / кататися на велосипеді / дивитися кіно - словом, розпоряджатися вільним часом на власний розсуд. Та й вночі вони повинні відпочивати. Також ми зрозуміли, що інженерам старшого віку і сімейним людям такий режим не підходить апріорі.

Разом з тим ми усвідомлювали, що «черговими» не можуть бути сторонні фахівці, тому що необхідно розуміти, як працює той чи інший сервіс в продукті. Отже, на зв'язку все ж таки повинні бути окремі розробники з команди. Ми встановили, кому з колег потенційно цікаво взятися за цю задачу і раз на півтора-два місяці «чергувати» протягом тижня з хорошим інтернет-з'єднанням і ноутбуком під рукою (за чергування 24/7, до речі, передбачені певні грошові бонуси).

Приблизно половина людей у команді погодилися брати участь, і з початку 2019 роки ми працюємо в такому режимі. Зазначу, що під час зміни інженери живуть звичайним життям, без наджорстких обмежень. Головне - у разі аварії бути доступним практично миттєво.

Як працює система управління аваріями

Як я вже згадував, для автоматизації процесу управління аваріями клієнт вибрав сервіс Opsgenie. Всі приклади, які я буду наводити, стосуються цього сервісу.

Opsgenie дозволяє створити команду, для якої ви можете скласти розклад чергувань. Якщо з якихось причин потрібно вибірково змінити розклад, то немає необхідності переробляти його повністю, можна просто оновити деякі дати і сервіс сам адаптує розклад і правки і видасть фінальний варіант. Приклад - на зображенні нижче.

Потім ми налаштовуємо правила ескалації: скільки часу виділяється на підтвердження того, що команда знає про проблему і працює над її усуненням; що робити, якщо співробітник на зміні не підтвердив початок роботи над проблемою. У наведеному нижче прикладі після 30 хвилин очікування система дзвонитиме адміністратору групи, а якщо проблема не буде вирішена за дві години, то по тривозі піднімається вже вся команда.

Після того як в Opsgenie внесені команда, розклад і правила ескалації, треба налаштовувати його інтеграцію з вашими сервісами в промисловому середовищі експлуатації. Обраний нами сервіс управління аваріями надає можливість інтегруватися з кількома сотнями систем і сервісів. Для вивантаження мікросервісів на стенди ми використовуємо публічну хмару AWS.

Як ми інтегрували мікросервіси та Opsgenie

Для прикладу розглянемо конфігурацію реакції системи управління аваріями на зупинку одного з сервісів (наприклад, в Java-додатку закінчилася пам'ять в контейнері), запущеному в ECS-кластері AWS. Така конфігурація працює на нашому проєкті, але деякі деталі змінені згідно політики конфіденційності компанії.

Перший крок - створення інтеграційного посилання в системі управління аваріями в розділі інтеграції. Воно включає в себе унікальний ключ, за яким сервіс визначить наш мікросервіс. Ніяких параметрів вводити не потрібно, система все зробить сама.

Для інтеграції з Opsgenie з боку мікросервіса створюємо SNS Topic і прописуємо посилання, яке ми згенерували протягом попереднього кроку.

Resources:
    MicroserviceECSAlarmTopic:
        Type: AWS:: SNS::Topic
        Condition: InLive
        Properties:
            TopicName: "MicroserviceECSAlarmsTopic"
            Subscription:
            - Endpoint:
https://api.opsgenie.com/v1/json/amazonsns?apiKey=eeeeeeee-cccc-ffff-bbbb-aaaaaaaaaaaa
            Protocol:
https

Потім створюємо правило, за яким ми слухатимемо певний тип повідомлень від ECS-кластера і відправляти на створений нами SNS Topic повідомлення про те, що Docker-контейнер з нашим мікросервісом зупинився.

ECSStoppedRule:
    Type: "AWS::Events::Rule"
    Condition: InLive
    Properties:
        Name: 'MicroserviceECSStoppedRule'
        Description: "Notify when the microservice goes down"
        EventPattern:
      
      source: ["aws.ecs"]
    
        detail-type: ["ECS Task State Change", "ECS Container Instance State Change"]
            detail:
  
              clusterArn: #############
          
      lastStatus: [ "STOPPED" ]
                stoppedReason: [ "Essential container in task exited", "Task stopped by user" ]
      
          group: #############    
        State: "ENABLED"
        Targets:
            - Arn: !Ref MicroserviceECSAlarmTopic
            Id: " MicroserviceECSAlarmTopic "
            InputTransformer:
                InputPathsMap:
                    detail: "$.detail"
                InputTemplate: '"The microservice has stopped working with the following details: <detail>"

В секції EventPattern ми описуємо повідомлення, які хочемо слухати. Для цього в параметрі source: [ «aws.ecs»] вказуємо, що слухаємо повідомлення від ECS-кластера в хмарі AWS; в параметрі detail-type ми задаємо конкретні типи повідомлень: запуск / зупинка завдання нашого мікросервіса або зміна стану Docker-контейнера з нашим мікросервісом. Із зазначених повідомлень ми обираємо тільки ті, що призвели до зупинки Docker-контейнера з нашим мікросервісом; це робиться через параметр detail, в якому ми прописали останній статус і причини зупинки.

Далі, в секції Targets вказуємо, що саме ми хочемо зробити у разі отримання описаних вище повідомлень. У наведеному прикладі ми готуємо нове повідомлення на основі інформації, вивільненої з отриманого. Вона витягується в параметрі InputPathsMaps, де ми оголошуємо нову змінну detail і заносимо в неї значення з параметра detail отриманого повідомлення. У параметрі InputTemplate ми формуємо тіло нового повідомлення і використовуємо змінні з InputPathsMaps.

Тепер нам потрібно вивантажити описаний CloudFormation-шаблон на стенд в хмарі Amazon і сподіватися, що вночі нас не турбуватимуть :) У нашої команди, до речі, протягом першого місяця роботи за такою системою виникло 26 критичних ситуацій, другого - 5, а згодом - максимум одна щомісяця. Тобто активними чергування бувають нечасто. Все завдяки тому, що інженери стали писати якісніший код.

До слова, про турбування вночі. На старті роботи з нами трапився цікавий випадок. Коли ми з проектним менеджером і технічним лідером займалися PoC, ми створили тестовий розклад і розподілили між собою тренувальні чергування. Обговорили, що можемо отримувати SMS і дзвінки вночі в разі збоїв, були готові. PoC пройшло успішно, ми впровадили систему, почали працювати і забули про це.

І ось одного разу проєктному менеджеру вночі надійшов дзвінок. Він подумав, що сталася ескалація на сервіс, який ми нещодавно відправили в production (в нашому звичайному флоу менеджер отримує повідомлення, якщо команда довго не може вирішити проблему), і став дзвонити черговому інженеру, з'ясовувати, чому той не вирішує питання. В онлайн-режимі посеред ночі вони зайшли в Opsgenie і переконалися, що жодної проблеми немає. Але у нас дуже відповідальний менеджер і він вирішив будь-що докопатися до істини, впевнитися, що все в порядку. Тому посеред ночі розбудили ще й архітектора, який спочатку теж не зрозумів, що до чого і, в свою чергу, подзвонив тімліду.

В результаті на світанку сонні менеджер, черговий інженер, архітектор і технічний лідер нарешті ще раз прочитали SMS і побачили, що сполох підняв тестовий сервіс зі старого PoC, який система видалила з середовища розробки. Після цього усі заспокоїлися, видалили тестовий розклад і спокійно пішли досипати. Висновок: будьте уважними, щоб не прокидатися через хибну тривогу :)

Уроки, які ми засвоїли

Подумайте заздалегідь, хто з вашої команди погодиться на чергування. Молодь охоче береться за періодичну роботу в форматі 24/7, людей сімейних і тих, хто старше за віком, грошові бонуси не завжди мотивують.

Сформуйте повний список виняткових ситуацій і обговоріть його з клієнтом. Це непростий процес, який вимагає ітеративної роботи. При цьому саме замовник допоможе зрозуміти, які з потенційних проблем критичні для бізнесу і вимагають негайного вирішення, а які, незважаючи на технічну важливість, можуть почекати (наприклад, відмова обслуговування одного з примірників мікросервіса через закінчення пам'яті - технічно суттєвий дефект, але він не є для критичним для бізнесу, адже хмарна мікросервісна платформа запустить новий екземпляр іншого сервісу або використає механізми повторних запитів).

Приділяйте час тестуванню. На нашому проекті задіяні крос-функціональні команди. Тобто розробники пишуть unit-, компонентні, інтеграційні та end-to-end-тести. Вони не завжди охоче це роблять, але після впровадження техпідтримки 24/7 вони усвідомили всю важливість процесу і почали ставитися до нього з більшою відповідальністю. Зрештою, від якісного тестування багато в чому залежить їхній спокій протягом чергування.

Поясніть команді, чому не варто грати в пінг-понг (звісно, це фігуральне висловлювання). Якщо під час чергування виникла проблема з чужим кодом або на чужій «ділянці роботи», це не привід переводити стрілки. В екстрених випадках треба не перекидати відповідальність, а засукавши рукава виправляти ситуацію. Індивідуалізму в такому процесі не місце, і менеджерам варто звернути на це увагу команди. Залучати колег бажано тільки в разі ескалації або надвисокої складності завдання.

Висновки

За час роботи з Opsgenie і техпідтримкою мікросервісів 24/7 ми переконалися, що цей підхід дозволяє значно поліпшити якість коду в системі (до речі, однією з перших його застосувала Amazon). Зазначу, що технічна сторона питання не вимагає багато часу: щоб прописати одну виняткову ситуацію на одному мікросервісі, вистачає одного-двох днів. У нашому випадку найскладнішими у запуску техпідтримки 24/7 були все ж таки нетехнічні моменти.

Особливих зусиль вимагало формування розкладу і обговорення фінансових питань з клієнтом таким чином, щоб і процес запрацював, і члени команди, які погодилися страхувати продукт позмінно, були задоволені. У нашому випадку це тривало близько півроку - від підписання контракту і бюджетування до написання коду і виходу команди у новому режимі. Проте зараз клієнт задоволений результатами і швидкістю реакції, а команда адаптувалася до особливого графіку. Початковий контракт був підписаний на рік, але ми вже знаємо, що він буде продовжений.

Якщо ви робите продукт з мікросервісною архітектурою або на проекті багато релізів і клієнт хоче мати можливість усунення неполадок в режимі 24/7, подумайте про використання Opsgenie або іншої системи управління аваріями для якісного налагодження процесу. Але головне - слухайте команду і приділяйте увагу людському фактору.