Важливим моментом у роботі розподілених систем є обробка збоїв. Kubernetes допомагає в цьому, використовуючи контролери, які стежать за станом вашої системи і перезапускають сервіси, що перестали працювати. Однак Kubernetes може примусово зупиняти роботу ваших програм, щоб забезпечити загальну життєздатність системи. У цій серії ми розглянемо, як можна допомогти Kubernetes виконувати свою роботу більш ефективно та скорочувати час простою додатків.
До початку застосування контейнерів більшість програм працювали на віртуальних або фізичних машинах. Якщо програма давала збій або зависала, потрібно багато часу, щоб зняти завдання, що виконується, і заново завантажити програму. У гіршому випадку комусь доводилося вирішувати цю проблему вручну вночі, у найневрочніший час. Якщо важливе завдання виконували всього 1-2 робочі машини, такий збій у роботі був абсолютно неприйнятним.
Тому замість ручного перезавантаження почали використовувати моніторинг на рівні процесів для автоматичного перезапуску програми у разі аварійного завершення. Якщо програма дала збій, процес моніторингу захоплює exit-код та перезавантажує сервер. З появою таких систем як Kubernetes цей вид реагування на збої системи був просто інтегрований в інфраструктуру.
Kubernetes використовує петлю подій «спостереження – фіксація відмінностей – здійснення дії», щоб переконатися, що ресурси зберігають працездатність шляхом з контейнерів до самих вузлів.
Це означає, що вам більше не потрібно запускати моніторинг процесів вручну. Якщо ресурс не пройшов перевірку працездатності Health Check, Kubernetes просто автоматично надасть йому заміну. При цьому Kubernetes робить набагато більше, ніж просто стежить за збоями ваших програм. Він може створювати більше копій програми для роботи на кількох машинах, оновлювати програму або одночасно запускати кілька версій вашої програми.
Тому існує безліч причин, через які Kubernetes може перервати роботу абсолютно здорового контейнера. Наприклад, якщо ви оновлюєте своє розгортання, Kubernetes повільно зупинятиме старі поди, одночасно запускаючи нові. Якщо ви відключаєте вузол, Kubernetes припинить роботу всіх подів у цьому вузлі. Нарешті, якщо у вузла закінчаться ресурси, Kubernetes відключить усі поди, щоб звільнити ці ресурси.
Тому дуже важливо, щоб ваша програма припиняла роботу з мінімальним впливом на кінцевого користувача та мінімальним часом відновлення. Це означає, що перед відключенням воно має зберегти всі дані, які необхідно зберегти, закрити всі мережеві підключення, завершити роботу, що залишилася, і встигнути виконати інші невідкладні завдання.
На практиці це означає, що ваша програма повинна вміти обробляти повідомлення SIGTERM – сигнал завершення процесу, який є стандартним сигналом для утиліти kill в ОС сімейства Unix. Отримавши це повідомлення, програма повинна вимкнутись.
Після того, як Kubernetes вирішив завершити pod, відбувається ціла низка подій. Давайте розглянемо кожен крок, який робить Kubernetes при завершенні роботи контейнера або пода.
Припустимо, що ми хочемо завершити один із подів. У цей момент він перестане отримувати новий трафік – контейнери, що працюють у поді, не будуть порушені, але весь новий трафік буде заблокований.
Давайте розглянемо хук preStop – це спеціальна команда або HTTP-запит, який надсилається контейнерам у поді. Якщо ваша програма при отриманні SIGTERM не коректно вимикається, ви можете використовувати preStop для правильного завершення роботи.
Більшість програм при отриманні сигналу SIGTERM завершують свою роботу коректно, але якщо ви використовуєте сторонній код або якусь систему, яку не можете повністю контролювати, хук preStop служить чудовим способом викликати витончене вимкнення без зміни програми.
Після виконання цього хука Kubernetes надішле контейнерам у поді сигнал SIGTERM, який дасть їм знати, що скоро вони будуть відключені. Отримавши цей сигнал, код перейде до процесу відключення. Цей процес може включати зупинку будь-яких довгоживучих з'єднань, таких, як підключення до бази даних або потік WebSocket, збереження поточного стану тощо.
Навіть якщо ви використовуєте хук preStop, дуже важливо перевірити, що саме відбувається з вашим додатком, коли ви посилаєте йому сигнал SIGTERM, як воно поводиться при цьому, щоб події або зміни в роботі системи, викликані відключенням пода, не стали для вас несподіванкою.
У цей момент, перш ніж розпочати подальші дії, Kubernetes буде чекати протягом зазначеного часу, званого terminationGracePeriodSecond, або періодом для коректного відключення при отриманні сигналу SIGTERM.
За промовчанням цей період становить 30 секунд. Важливо, що він триває паралельно з preStop hook і сигналом SIGTERM. Kubernetes не чекатиме, поки закінчиться preStop hook і SIGTERM — якщо ваша програма завершить роботу до закінчення періоду TerminationGracePeriod, Kubernetes негайно перейде до наступного кроку. Тому перевірте, щоб значення даного періоду в секундах було не менше часу, необхідного для коректного відключення пода, і якщо воно перевищує 30с, збільште період до потрібної величини YAML. У наведеному прикладі він становить 60с.
І нарешті, останній крок - якщо контейнери все ще продовжують працювати після закінчення GracePeriod, вони пошлють сигнал SIGKILL і будуть примусово видалені. У цей момент Kubernetes також вичистить решту об'єктів пода.
Kubernetes припиняє роботу подов з багатьох причин, тому переконайтеся, що у будь-якому випадку ваш додаток буде завершено коректно, щоб забезпечити стабільну роботу сервісу.
Небагато реклами 🙂
Дякую, що залишаєтеся з нами. Вам подобаються наші статті? Бажаєте бачити більше цікавих матеріалів? Підтримайте нас, оформивши замовлення або порекомендувавши знайомим,
Dell R730xd вдвічі дешевше в дата-центрі Equinix Tier IV в Амстердамі? Тільки в нас
Джерело: habr.com