Як оновити Ruby екосистеми без простоїв: 4-етапна структура

Як оновити Ruby для сервісу з 10+ тісно пов'язаними пакетами — без спричинення простоїв?

Задача: Один інтерпретатор Ruby для складного сервісу

Ось в чому справа:

Наш Ruby-сервіс включає понад 10 взаємопов'язаних пакетів. Всі вони працюють разом під єдиним інтерпретатором Ruby 2 в контейнері ECS.

pic

Ми хочемо оновити кожен пакет у системі до Ruby 3, при цьому зберігаючи всю систему працездатною на Ruby 2.

Будь-яка помилка може порушити роботу сервісу.

Нам потрібен був обережний, поетапний підхід.

Поетапний підхід

Ось як ми це зробили:

1. Почати з незалежних пакетів

  • Ми почали з утилітних пакетів, які не мають залежностей.
  • Потім оновлювали залежні пакети, залишаючи основний пакет для останнього.

2. Забезпечити сумісність обох версій

  • Ми оновили кожен пакет, щоб він працював як з Ruby 2, так і з Ruby 3.
  • Це дозволило нам зберегти роботу системи на Ruby 2, поки ми по черзі оновлювали кожен пакет.

pic

3. Перевірка кожного пакету

  • Компіляція: Ми переконалися, що кожен пакет компілюється як для Ruby 2, так і для Ruby 3.
  • Юніт-тести: Ruby — це інтерпретована мова, тому для перевірки правильності коду ми повинні були виконати тести. Ми запускали тести для обох версій Ruby, щоб виявити помилки під час виконання.
  • Інтеграційні тести: Після оновлення кожного пакету ми запускали інтеграційні тести на Ruby 2, щоб переконатися, що система працює як очікується.

4. Останні кроки

  • Коли всі пакети стали сумісними з Ruby 3, ми переключили сервіс на Ruby 3.
  • Протягом місяця ми моніторили логи сервісу, зберігаючи підтримку Ruby 2, на випадок, якщо доведеться відкотити зміни.
  • Після стабільного місяця ми видалили підтримку Ruby 2.

Цей процес дозволив здійснити плавне оновлення.

pic

Уроки, які ми винесли

Ось що спрацювало для нас:

  1. Юніт-тести критичні: Оскільки Ruby є інтерпретованою мовою, помилки під час виконання можуть з’явитися навіть після успішної компіляції. Комплексні юніт-тести є необхідними для виявлення помилок.
  2. Розділяй і володарюй: Призначивши різним інженерам незалежні пакети, ми змогли працювати паралельно та пришвидшити процес.
  3. Діліться знаннями: Ми створили спільний канал в Slack та документ. Це допомогло уникнути дублювання зусиль і пришвидшило пошук рішень.

Підсумок

Оновлення тісно пов'язаних систем вимагає ретельного планування.

Ось кроки, що дозволили нам зберегти працездатність сервісу під час оновлення:

  • Почати з незалежних пакетів
  • Забезпечити сумісність з обома версіями Ruby
  • Ретельне тестування на кожному етапі
  • Моніторинг після оновлення перед видаленням підтримки Ruby 2

З цим методом ми змогли здійснити плавне оновлення без простоїв.

Перекладено з: How to Upgrade Ruby Ecosystems Without Downtime: A 4-Step Framework

Leave a Reply

Your email address will not be published. Required fields are marked *