Вимоги до розробки програми Kubernetes

Сьогодні я планую розповісти, як потрібно писати програми та які є вимоги для того, щоб ваш додаток добре працював у Kubernetes. Щоб із додатком не було ніякого головного болю, щоб не доводилося вигадувати і вибудовувати якісь «милиці» навколо нього — і працювало так, як це замислювалося самим Kubernetes.

Ця лекція в рамках «Вечірньої школи Сльорма з Кубернетес». Ви можете переглянути відкриті теоретичні лекції Вечірньої Школи на Youtube, згруповані в плейлист. Для тих, кому зручніше текст, а не відео, ми підготували цю статтю.

Звати мене Павло Селіванов, зараз я є провідним DevOps інженером компанії Mail.ru Cloud Solutions, ми робимо «хмари», ми робимо менеджер-кубернетиси і так далі. У мої завдання зараз якраз-таки входить допомога в розробці, розкочуванні цих хмар, розкочуванні додатків, які ми пишемо, і безпосередньо розробка інструментарію, який ми надаємо для наших користувачів.

Вимоги до розробки програми Kubernetes

Я DevOps-ом займаюся, думаю, що останні, напевно, років зо три. Але, в принципі, те, чим займається DevOps, я займаюся, напевно, років п'ять уже точно. До цього я займався швидше відмінськими речами. З Kubernetes я почав працювати дуже давно — вже, мабуть, минуло близько чотирьох років, відколи я почав з ним працювати.

Взагалі починав я, коли у Kubernetes була версії 1.3, напевно, а може бути і 1.2, коли він був ще в зародковому стані. Зараз він вже зовсім не в зародковому стані знаходиться і очевидно, що на ринку є величезний попит на інженерів, які в Kubernetes хотіли б вміти. І компанії мають дуже великий попит на таких людей. Тому, власне, й з'явилася ця лекція.

Якщо говорити за планом того, про що я розповідатиму, це виглядає ось так, в дужках написано (TL; DR) - «too long; don't read». Моя сьогоднішня презентація буде нескінченними списками.

Вимоги до розробки програми Kubernetes

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

Тому що за великим рахунком ця інформація — це «ctrl+c, ctrl+v», у тому числі нашої Вікі в розділі DevOps, де у нас написані вимоги до розробників: «хлопці, щоб ваш додаток ми запустили в Kubernetes, він має бути таким».

Тож вийшла презентація таким великим списком. Вибачте. Намагатимусь розповідати максимально, щоб було ненудно по можливості.

Що ми з вами зараз розбиратимемо:

  • це, по-перше, логи (журнали програми?), що з ними робити в Kubernetes, як з ними бути, якими вони мають бути;
  • що робити з конфігураціями в Kubernetes, які для Kubernetes найкращі-гірші способи конфігурувати програму;
  • поговоримо про те, що таке перевірки доступності взагалі, як вони мають виглядати;
  • поговоримо у тому, що таке graceful shutdown;
  • поговоримо ще раз про ресурси;
  • ще раз торкнемося теми зберігання даних;
  • і в кінці я розповім, що таке термін цей загадковий cloud-native додаток. Cloudnativeness, як прикметник від цього терміну.

Список

Я пропоную почати з ліг - з того, куди ці логи потрібно в Kubernetes пхати. Ось ви запустили до Kubernetes додаток. За класикою, раніше програми завжди писали логи кудись у файлик. Погані програми писали логи у файлик у домашній директорії розробника, який запустив цю програму. Хороші програми писали логи у файлик кудись у /var/log.

Вимоги до розробки програми Kubernetes

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

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

Виявляється, якщо ми говоритимемо про Kubernetes, що правильним місцем для того, щоб з докер-контейнера кудись написати логи, це просто писати їх із додатку до так званих Stdout/Stderr, тобто потоків стандартного виведення операційної системи, стандартного виведення помилок . Це найправильніший, найпростіший і найлогічніший спосіб, куди подіти логи в принципі в докері і саме в Кубернетіс. Тому що, якщо ваш додаток пише логи в Stdout/Stderr, то далі це вже завдання докеру та надбудови над ним Kubernetes, що з цими логами робити. Докер за замовчуванням складатиме свої спеціальні файли в JSON форматі.

Тут уже виникає питання, що ви з цими логами робитимете далі. Найпростіший спосіб, зрозуміло, ми маємо можливість зробити kubectl logs і подивитися ці логи цих «подів». Але, напевно, це не дуже добрий варіант — з логами треба щось робити далі.

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

Нам потрібен якийсь інструмент, по-доброму, який ці логи, які у нас докер складає у свої файли, візьме і кудись їх відправить. За великим рахунком, зазвичай ми всередині Kubernetes запускаємо у вигляді DaemonSet якийсь агент – збирач логів, якому просто сказано, де лежать логи, які складає докер. І цей агент-збирач їх просто бере, можливо, навіть шляхом якось парсить, можливо збагачує якоюсь додатковою метаінформацією і, в результаті, відправляє на зберігання кудись. Там уже можливі варіації. Найпоширеніше, напевно, Elasticsearch, де можна зберігати логи, їх можна звідти зручно діставати. Потім за допомогою запиту, за допомогою Kibana, наприклад, будувати за ними графіки, будувати за ними алерти і таке інше.

Найголовніша думка, ще раз її хочу повторити, про те, що всередині докера, зокрема всередині Kubernetes, складати ваші логи у файлик - це дуже погана ідея.

Тому що по-перше, логи всередині контейнера у файлі проблематично діставати. Потрібно спочатку зайти в контейнер, зробити туди exec, а потім дивитися вже логи. Наступний момент - якщо у вас логи у файлі, то в контейнерах зазвичай мінімалістичне оточення і там немає утиліт, які зазвичай потрібні для нормальної роботи з логами. Їх погріпати, подивитися, відкрити у текстовому редакторі. Наступний момент, коли у нас логи лежать у файлі усередині контейнера, у випадку, якщо цей контейнер видаляється, ви розумієте, логи загинуть разом з ним. Відповідно, будь-який рестарт контейнера — і ліг уже немає. Знову ж таки, поганий варіант.

І останній момент – це те, що усередині контейнерів у вас зазвичай існує ваша програма і все – вона зазвичай є єдиним запущеним процесом. Ні про який процес, який би ротував файли з вашими логами, взагалі не йдеться. Як тільки логи починають записуватися у файлик, це означає, що, даруйте, продакшн сервера ми почнемо втрачати. Тому що, по-перше, їх проблематично знайти, їх ніхто не відстежує, плюс їх ніхто не контролює - відповідно, файлик росте нескінченно, поки просто місце на сервері не скінчиться. Тому, ще раз кажу, що логи в докері, зокрема в Kubernetes, у файлик - це затія погана.

Наступний момент, тут я хочу знову ж таки про це поговорити - якщо вже ми торкаємося теми ліг, то добре б поговорити і про те, як логи повинні виглядати, для того, щоб з ними було зручно працювати. Як я казав, тема не відноситься безпосередньо до Kubernetes, але дуже добре ставиться до теми DevOps. До теми культури розробки та дружби двох цих різних відділів – Dev та Ops, щоб усім було зручно.

Отже, в ідеалі, на сьогоднішній день, логі потрібно писати в JSON форматі. Якщо у вас якийсь незрозумілий додаток ваш самописний, який пише логи в незрозумілих форматах, тому що ви там вставляєте якийсь print або щось на кшталт того, то саме час вже нагуглити якийсь фреймворк, якусь обгортку, яка дозволяє реалізовувати нормальне логування; включити там параметри логування в JSON, тому що JSON простий формат, його ширяти просто елементарно.

Якщо у вас JSON не прокочує за якимось критерієм, невідомо яким, то хоча б пишіть логи у форматі, який можна парсити. Тут, скоріше, варто замислюватися про те, що, наприклад, якщо у вас запущена купа якихось контейнерів або просто процесів з nginx, і у кожного свої налаштування логування, то, напевно, здається, вам буде парсувати їх дуже незручно. Тому що на кожну нову nginx instance вам потрібно написати власний парсер, тому що вони пишуть логи по-різному. Знову ж таки, напевно, тут варто задуматися про те, щоб усі ці nginx instance мали ту саму конфігурацію логування, і абсолютно однаково писали всі свої логи. Те саме стосується абсолютно всіх додатків.

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

Вимоги до розробки програми Kubernetes

Але stack trace - це завжди багаторядкові логи і як їх уникати. Тут питання у тому, що лог – це запис про подію, а стактрейс фактично логом не є. Якщо ми логі збираємо та складаємо їх кудись у Elasticsearch і по них потім малюємо графіки, будуємо якісь звіти роботи користувачів на вашому сайті, то коли у вас вилазить stack trace – це означає, що у вас відбувається якась непередбачувана, необроблена ситуація у вашому додатку. І stack trace має сенс закидати автоматично кудись у систему, яка їх вміє трікати.

Це те програмне забезпечення (те ж Sentry), яке зроблено спеціально для того, щоб працювати зі stack trace. Воно може створювати відразу ж автоматизовані завдання, призначати на когось, алертити, коли стактрейси відбуваються, групувати ці стактрейси по одному типу і так далі. В принципі, не має особливого сенсу говорити про стактрейси, коли ми говоримо про логи, тому що це все-таки різні речі з різним призначенням.

Конфігурація

Далі у нас щодо конфігурації в Kubernetes: що з цим робити і як програми всередині Kubernetes повинні конфігуруватися. Взагалі, я зазвичай говорю про те, що докер - він не про контейнери. Усі знають, що докер – це контейнери, навіть ті, хто особливо з докером не працював. Повторюся, Докер не про контейнери.

Докер, на мою думку, це про стандарти. І там стандарти всього практично: стандарти складання вашої програми, стандарти встановлення вашої програми.

Вимоги до розробки програми Kubernetes

І ця штука – ми їй користувалися і раніше, просто з приходом контейнерів це стало особливо популярно – ця штука називається ENV (environment) змінні, тобто змінні оточення, які є у вашій операційній системі. Це взагалі ідеальний спосіб конфігурувати вашу програму, тому що, якщо у вас є програми на JAVA, Python, Go, Perl не дай бог, і вони всі можуть читати змінні database host, database user, database password, то ідеально. У вас програми на чотирьох різних мовах конфігуруються в плані бази даних одним і тим же способом. Немає більше жодних різних конфігів.

Все можна налаштувати за допомогою ENV змінних. Коли ми говоримо про Kubernetes, там є чудовий спосіб оголошувати ENV змінні прямо всередині Deployment. Відповідно, якщо ми говоримо про секретні дані, то секретні дані з ENV змінних (паролі до баз даних і т.д.), ми можемо відразу запхати в секрет, створити секрет кластер і в описі ENV в Deployment вказати, що ми не безпосередньо оголошуємо значення цієї змінної, а значення цієї змінної database password читатимемо з секрету. Це стандартна поведінка Kubernetes. І це ідеальний варіант конфігурувати ваші програми. Просто на рівні коду, знову ж таки до розробників це стосується. Якщо ви DevOps, можна попросити: «Хлопці, будь ласка, навчіть вашу програму читати змінні оточення. І буде нам щастя для всіх».

Якщо ще й усі читатимуть однаково названі змінні оточення у компанії, то це взагалі шикарно. Щоб не було такого, що одні чекають на postgres database, інші database name, треті database ще щось, четверті dbn який-небудь там, щоб, відповідно, однаковість була.

Проблема настає, коли у вас змінних оточення стає так багато, що просто відкриваєш Deployment – ​​а там п'ятсот рядків змінних оточення. У такому разі змінні оточення ви вже просто переросли — і далі вже не треба мучити себе. У такому разі, було б сенс почати користуватися конфігами. Тобто, навчити вашу програму використовувати конфіги.

Тільки питання у тому, що конфіги – це не те, що ви думаєте. Config.pi - це не той конфіг, яким зручно користуватися. Або якийсь конфіг у вашому власному форматі, альтернативно обдарованому – це теж не той конфіг, який я маю на увазі.

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

Відповідно, крім YAML, можна ще, наприклад, скористатися JSON, парсить приблизно так само зручно, як YAML в плані читання звідти конфігурації програми. Читати людьми помітно незручніше. Можна скуштувати формат, а-ля ini. Його читати прямо дуже зручно, з погляду людини, але його може бути незручно автоматизовано обробляти, у тому плані, якщо ви колись захочете генерувати свої конфіги, ось ini формат вже може бути незручно генерувати.

Але в будь-якому випадку, хоч би який формат ви вибрали, суть у тому, що з точки зору Kubernetes — це дуже зручно. Ви можете весь свій конфіг покласти всередині Kubernetes, в ConfigMap. І потім цей configmap взяти і попросити всередині вашого пода замонтувати в якусь певну директорію, де ваш додаток буде конфігурацію з цього configmap читати так, ніби це просто файлик. Це, власне, те, що добре робити, коли у вас додатку стає конфігураційних опцій багато. Або просто структура якась складна, вкладеність є.

Якщо у вас є configmap, то дуже чудово ви можете навчити свою програму, наприклад, автоматично відстежувати зміни у файлі, куди замонтований configmap, та ще й автоматично релоадити вашу програму при зміні конфігів. Це взагалі ідеальний варіант.

Про це я вже теж, знову ж таки, говорив — секретну інформацію не конфігмап, секретну інформацію не змінні, секретну інформацію секретами. Звідти цю секретну інформацію підключатимуть у дипломи. Зазвичай ми всі описи кубернетівських об'єктів, дипломи, конфігмапи, послуги зберігаємо в git. Відповідно, запихати пароль до бази даних у git, навіть якщо це ваш git, який у вас внутрішній у компанії – погана ідея. Тому що як мінімум git пам'ятає все і видалити просто звідти паролі не так просто.

Перевірка здоров'я

Наступний момент – це така штука, яка називається Health check. Взагалі, Health check - це просто перевірка того, що ваш додаток працює. При цьому ми найчастіше говоримо про якісь веб-додатки, у яких, відповідно, з точки зору хелсчека (краще не перекладати тут і далі) це буде якийсь спеціальний URL, який вони обробляють стандартно, зазвичай роблять /health.

При зверненні на цей URL, відповідно, наша програма говорить або «так, окей, у мене все добре 200» або «ні, у мене все не добре, який-небудь 500». Відповідно, якщо у нас додаток не http, не веб-додаток, ми зараз говоримо якийсь демон, ми можемо придумати, як робити хелсчеки. Тобто, необов'язково, якщо додаток не http, все працює без хелсчека і зробити це ніяк не можна. Можна оновлювати періодично інформацію у файліку якусь, можна придумати до вашого daemon спеціальну якусь команду, типу, daemon status, Яка буде говорити «так, все нормально, daemon працює, він живий».

Для чого це потрібно? Перше найочевидніше, напевно, для чого потрібний хелсчек — для того, щоб розуміти, що програма працює. Тобто просто тупо, коли воно зараз підняте, воно виглядає як робоче, щоб точно бути впевненим, що воно працює. А то виходить так, що під додатком запущено, контейнер працює, інстенс працює, все нормально — а там користувачі вже обірвали всі телефони у техпідтримки і кажуть «ви що там, заснули, нічого не працює».

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

Знову ж таки, за допомогою хелсчека і за допомогою того, що ми звертаємося сюди, ми можемо розуміти в Kubernetes, що в додатку не просто контейнер піднявся, а пряма програма стартанула, вона на хелсчек вже відповідає, значить туди можна запускати трафік.

Вимоги до розробки програми Kubernetes

Те, про що я говорю зараз, називається Readiness/Liveness проби в рамках Kubernetes, відповідно, readiness проби у нас якраз відповідають за доступність програми в балансуванні. Тобто якщо readiness проби виконуються в додатку, тобто все окей, на додаток йде клієнтський трафік. Якщо readiness проби не виконуються, то додаток просто не бере участі, саме цей instance, не бере участі в балансуванні, він забирається з балансування, клієнтський трафік не йде. Відповідно, Liveness проби в рамках Kubernetes потрібні для того, щоб у випадку, якщо програма «залипла», її «рестартанути». Якщо liveness проба не працює у додатку, яке оголошено в Kubernetes, то додаток не просто забирається з балансування, він саме рестартиться.

І тут такий важливий момент, про який хотілося б сказати, з погляду практики, зазвичай все-таки частіше використовується і частіше потрібна readiness проба, ніж liveness проба. Тобто просто бездумно оголошувати і readiness, і liveness проби, тому що Kubernetes так уміє, а давайте використати все, що він уміє – не дуже гарна ідея. Поясню чому. Тому що є пунктик номер два в пробах - це про те, що непогано було б перевіряти сервіс у ваших хелсчеках. Це означає, що якщо у вас є веб-додаток, який віддає якусь інформацію, яку, у свою чергу, він, природно, повинен десь взяти. У базі даних, наприклад. Ну, і зберігає в цю ж базу даних інформацію, яка до цього REST API надходить. То відповідно, якщо у вас хелсчек відповідає просто типу звернулися на слєшхелс, додаток каже «200, окей, все добре», а при цьому у вас у додатку база даних недоступна, а додаток на хелсчек каже «200, окей, все добре». це поганий хелсчек. Так не має працювати.

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

Тому, у зв'язку з цим, знову ж таки повертаюся до Readiness/Liveness проб — чому readiness проба швидше за все вам потрібна, а liveness проба під питанням. Тому що, якщо ви описуватимете хелсчеки саме так, як я зараз сказав, то вийде у нас недоступна в частині instanceв или со всех instanceдо бази даних, наприклад. Коли у вас оголошена readiness проба, у нас хелсчеки почали фейлітися, і програми відповідно всі, з яких недоступна база даних, вони вимикаються просто з балансування і фактично «висять» просто в занедбаному стані і чекають, поки у них бази даних запрацюють.

Якщо у нас оголошена liveness проба, то уявіть, у нас зламалася база даних, а у вас у Kubernetes половина всього починає рестартувати, тому що liveness-проба падає. Це означає, що потрібно рестартувати. Це зовсім не те, що ви хочете, я навіть мав у практиці особистий досвід. У нас була програма, яка була чатом і яка була написана в JS і входила в базу даних Mongo. І була якраз проблема в тому, що це було на зорі моєї роботи з Kubernetes, ми описували readiness, liveness проби за принципом того, що Kubernetes вміє — значить будемо використовувати. Відповідно, рано чи пізно Mongo трошки «затупила» і проба почала фейлиться. Відповідно, по лівнес пробі піди почали «вбиватися».

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

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

Тому, readiness і liveness проби це різне, навіть більше того, можна теоретично робити різні хелсчеки, один типу реді, один типу лив, наприклад, і перевіряти різні речі. На readiness пробах перевіряти бекенди ваші. А на liveness пробі, наприклад, не перевіряти, з точки зору того, що liveness проби це взагалі просто додаток відповідає, якщо взагалі він може відповісти.

Тому що liveness проба за великим рахунком це коли ми залипли. Нескінченний цикл почався чи ще щось — і більше запити не обробляються. Тому є сенс навіть їх розділяти — і різну логіку в них реалізовувати.

Щодо того, чим потрібно відповідати, коли у вас відбувається проба, коли ви робите хелсчеки. Просто це біль насправді. Ті, хто знайомий із цим, напевно, будуть сміятися — але серйозно, я бачив сервіси у своєму житті, які у відповідь на запити у стовідсоткових випадках відповідають «200». Тобто, який успішний. Але при цьому в тілі відповіді вони пишуть «помилка така-то».

Тобто статус відповіді вам надходить – все успішно. Але при цьому ви повинні пропарсити тіло, тому що в тілі написано «вибачте, запит завершився з помилкою» і це реальність. Це я бачив у реальному житті.

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

Якщо все пройшло успішно, то відповідайте двосотою відповіддю. В принципі, будь-яка двохсота відповідь влаштує. Якщо ви дуже добре читали регсі та знаєте, що одні статуси відповіді відрізняються від інших, відповідайте відповідним: 204, 5, 10, 15, що завгодно. Якщо не дуже добре, то просто «два нуль нуль». Якщо все пішло погано і не відповідає Хелсчек, то відповідаєте будь-яким п'ятисотим. Знову ж таки, якщо ви розумієте, як потрібно відповідати, чим відрізняються різні статуси відповіді один від одного. Якщо не розумієте, то 502 - ваш варіант відповідати на хелсчеки, якщо щось пішло не так.

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

Тому я хочу повторити це ще раз, що перевіряти нижчележачі сервіси потрібно ті, без яких ваш додаток у ста відсотках випадках не може виконувати свою роботу. Тобто, логічно, якщо у вас REST API, через який користувач зберігає в базу або дістає з бази, то у разі відсутності бази даних, ви не можете працювати гарантовано з вашими користувачами.

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

Далі у нас теж одна з хворих тем під час запуску додатків.

Насправді це не тільки Kubernetes стосується за великим рахунком, просто так збіглося, що культура якась розробки масово і DevOps зокрема почала поширюватися приблизно в той же час, що і Kubernetes. Тому за великим рахунком, що виявляється, потрібно коректно (graceful) завершувати роботу вашої програми і без Kubernetes. І до Kubernetes люди так робили, але з приходом Kubernetes ми про це почали масово говорити.

Витончене завершення роботи

Загалом, що таке Graceful Shutdown і для чого це потрібно. Це про те, що коли ваш додаток з якоїсь причини завершує свою роботу, вам потрібно виконати app stop — або ви отримуєте, наприклад, сигнал операційної системи, ваш додаток його має розуміти і щось із цим робити. Найгірший варіант, звичайно, це коли ваш додаток отримує SIGTERM і такого типу «SIGTERM, висимо далі, працюємо, нічого не робимо». Це прямий відверто поганий варіант.

Вимоги до розробки програми Kubernetes

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

А який варіант добрий? Першим пунктом враховуємо завершення операцій. Хороший варіант – це коли ваш сервер таки враховує те, що він робить, якщо йому приходить SIGTERM.

SIGTERM – це м'яке завершення роботи, воно спеціально таке, його можна перехопити на рівні коду, його можна обробити, сказати про те, що зараз, зачекайте, ми спочатку закінчимо ту роботу, яка маємо, після цього завершимося.

З точки зору Kubernetes, як це виглядає. Коли ми говоримо поду, який працює в кластері Kubernetes, «будь ласка, зупинись, вдалися» або у рестарт нас відбувається, або оновлення, коли Kubernetes перетворює поди — Kubernetes надсилає в під повідомлення саме SIGTERM, чекає якийсь час, причому , ось цей час, на який він чекає, він теж конфігурується, є такий спеціальний параметр у дипломах і він називається Graceful ShutdownTimeout. Як ви розумієте, недарма він так називається і недарма ми про це зараз говоримо.

Там можна конкретно сказати, скільки потрібно почекати тим часом, коли ми послали в додаток SIGTERM і коли ми зрозуміємо, що додаток здається від чогось офігела або, «залипло» і не збирається завершуватися - і потрібно послати йому SIGKILL, тобто жорстко завершити його роботу. Тобто, відповідно, у нас працює якийсь демон, він опрацьовує операції. Ми розуміємо, що в середньому у нас операції, над якими працює демон, не тривають більше ніж 30 секунд за раз. Відповідно, коли приходить SIGTERM, ми розуміємо, що наш демон максимум може після SIGTERM доопрацьовувати 30 секунд. Ми його пишемо, наприклад, 45 секунд про всяк випадок і кажемо, що SIGTERM. Після цього 45 секунд чекаємо. За ідеєю, за цей час демон мав завершити свою роботу і завершитися сам. Але якщо раптом він не зміг, то він, швидше за все, залип — він більше не опрацьовує наші запити нормально. І його можна за 45 секунд сміливо, власне, прибити.

Причому тут насправді навіть 2 аспекти можна враховувати. По-перше, розуміти, що якщо у вас запит прийшов, ви почали з ним якось працювати і не дали відповідь користувачу, а вам прийшов SIGTERM, наприклад. Це має сенс доопрацювати і дати відповідь користувачу. Це пункт номер разів у цьому плані. Пункт номер два тут буде те, що якщо ви пишите свою програму, взагалі архітектуру будуєте таким чином, що у вас прийшов запит на вашу програму, далі ви запустили якусь роботу, файлики почали звідкись качати, базу даних перекачувати і ще що щось. Загалом, ваш користувач, ваш запит висить півгодини і чекає, поки ви йому відповісте — швидше за все, вам потрібно над архітектурою попрацювати. Тобто просто враховувати навіть здоровий глузд, що якщо у вас операції короткі, то має сенс SIGTERM ігнорувати та доопрацьовувати. Якщо у вас операції довгі, то немає сенсу в даному випадку ігнорувати SIGTERM. Має сенс переробити архітектуру так, щоби таких довгих операцій уникнути. Щоб користувачі просто не висіли, не чекали. Не знаю, зробити там якийсь websocket, зробити зворотні хуки, які ваш сервер вже буде відправляти клієнту, що завгодно інше, але не змушувати користувача півгодини висіти і чекати просто на сесію, поки ви йому відповісте. Тому що непередбачувано де вона може порватися.

Коли ваша програма завершується, слід віддавати якийсь адекватний exit-код. Тобто якщо ваш додаток попросили закритися, зупинитися, і він нормально сам зміг зупинитися, то не потрібно повертати якийсь там типу exit-код 1,5,255 і так далі. Все, що не нульовий код, принаймні в Linux системах, я в цьому точно впевнений, вважається неуспішним. Тобто вважається, що ваш додаток у такому разі завершився з помилкою. Відповідно, по-хорошому, якщо ваш додаток завершився без помилки, ви кажете 0 на виході. Якщо ваша програма завершилася з помилкою з якихось приводів, ви говорите не 0 на виході. І з цією інформацією можна працювати.

І останній варіант. Погано, коли користувач кидає запит і півгодини висить, поки ви його обробите. Але загалом ще хочеться сказати про те, що взагалі стоїть з боку клієнта. Не має значення у вас мобільний додаток, фронтенд і так далі. Необхідно враховувати, що взагалі сесія користувача може обірватися, може статися будь-що. Може бути запит надісланий, наприклад, недоопрацюватись і не повернутися відповідь. Ваш фронтенд або ваш мобільний додаток - взагалі будь-який фронтенд, давайте говорити так - повинні це враховувати. Якщо ви працюєте з websocket`ами, це взагалі найстрашніший біль, який був у моїй практиці.

Коли розробники якихось чергових чатів не знають, що, виявляється, websocket може порватися. У них коли там просто на проксі щось відбувається, ми просто конфіг міняємо, і вона робить reload. Природно, всі сесії, що довго живуть, рвуться при цьому. До нас вдаються розробники та кажуть: «Хлопці, ви чого, у нас там у всіх клієнтів чат відвалювався!». Ми їм кажемо: Ви чого? Ваші клієнти не можуть перепідключатися?». Вони кажуть: Ні, нам треба, щоб сесії не рвалися. Коротше кажучи, це марення насправді. Потрібно враховувати бік клієнта. Особливо, я ж говорю, з довгоживучими сесіями типу websocket, що вона може порватися і непомітно для користувача потрібно вміти такі сесії перевстановити. І тоді взагалі все бездоганно.

Ресурси

Взагалі, тут я розповім вам просто пряму історію. Знову ж таки з реального життя. Найхворішу, яку я чув про ресурси.

Ресурси в даному випадку, я маю на увазі, якісь реквести, ліміти, які ви можете ставити на поди у ваших кластерах Kubernetes. Найсмішніше, що я чув від розробника… Якось один із колег розробників на попередньому місці роботи сказав: «У мене додаток у кластері не запускається». Я подивився, що воно не запускається, а там воно чи не влазило по ресурсах, чи вони дуже маленькі ліміти поставили. Коротше, програма не може запуститися через ресурси. Я говорю: «Через ресурси не запускається, ви визначитеся скільки вам потрібно і поставте адекватне значення». Він каже: Що за ресурси? Я почав пояснювати, що ось Kubernetes, ліміти в реквестах і бла, бла, бла їх треба ставити. Людина слухала п'ять хвилин, кивала і каже: «Я прийшов сюди працювати розробником, не хочу знати нічого ні про які ресурси. Я прийшов нібито сюди писати код і все». Це сумно. Це дуже сумна концепція з погляду розробника. Особливо у сучасному світі, так би мовити, прогресуючого девопсу.

Навіщо взагалі потрібні ресурси? Ресурси Kubernetes бувають 2 типів. Одні називаються реквестами, другі – лімітами. Під ресурсами ми розумітимемо, в основному завжди лише два обмеження базових. Тобто обмеження процесорного часу і обмеження оперативної пам'яті для контейнера, який запущений в Kubernetes.

Ліміт обмежує верхню межу для використання ресурсу у вашому додатку. Тобто, відповідно, якщо ви кажете 1Гб ВП в лімітах, то більше 1Гб ВП ваш додаток використовувати не зможе. А якщо раптом захоче і спробує це зробити, то прийде процес, який називається oom killer, out of memory, тобто, і вб'є ваш додаток - тобто він просто рестартанет. По CPU програми не рестартяться. По CPU, якщо програма намагається використовувати дуже багато, більше, ніж зазначено в лімітах, CPU буде просто жорстко відбиратися. До рестартів це не призводить. Це ось ліміт – це верхня межа.

А є реквест. Реквест – це те, завдяки чому Kubernetes розуміє, як ноди у вашому кластері Kubernetes заповнені програмами. Тобто реквест – це такий собі commit вашої програми. Воно каже, що я хочу використовувати: «Я хотіла б, щоб ти під мене зарезервував стільки CPU і стільки пам'яті». Така проста аналогія. Що якщо у нас є node, який всього доступно, не знаю, 8 CPU. І туди приїжджає під, у якого в реквестах написано 1 CPU, отже, у нода залишилося 7 CPU. Тобто, відповідно, як тільки на цю ноду приїде 8 подів, у яких у кожного в реквестах стоїть під 1 цпу - на ноді, як би з точки зору Kubernetes, CPU скінчилося і більше подів із реквестами на цю ноду запустити не можна. Якщо на всіх нодах CPU закінчиться, то Kubernetes почне говорити, що в кластері немає відповідних нод, щоб запустити ваші поди, тому що закінчилося CPU.

Для чого потрібні реквести і чому без реквестів, я думаю, що в Kubernetes запускати нічого не потрібно? Уявімо собі гіпотетичну ситуацію. Ви запускаєте без реквестів ваш додаток, Kubernetes не знає, скільки у вас чого, на які ноди можна запихати. Ну і пхає, пхає, пхає на ноди. У якийсь момент у вас на вашу програму почне приходити трафік. І один із додатків починає раптово раптом використовувати ресурси до лімітів, які за лімітами у нього є. Виявляється, поруч ще один додаток і йому теж потрібні ресурси. На ноді починає реально фізично закінчуватися ресурси, наприклад ОП. На ноді реально фізично закінчуються ресурси, наприклад, оперативна пам'ять (ОП). Коли у ноди закінчується ОП, у вас перестануть відповідати насамперед докер, потім кублет, потім ОС. Вони просто підуть у несвідомість і працювати у вас ВСІ перестане точно. Тобто це призведе до того, що у вас залипне нода, і її потрібно буде рестартанути. Коротше, ситуація не дуже хороша.

А коли у вас реквести, ліміти ще не дуже відрізняються, хоча б не в рази лімітів більше або реквестів, то у вас може бути таке нормальне раціональне заповнення додатків по нодах кластерів Kubernetes. При цьому Kubernetes приблизно в курсі скільки чого він куди поклав, скільки де чого використовується. Тобто, це просто такий момент. Його важливо розуміти. І важливо контролювати, що це проставляється.

Зберігання даних

Наступний пункт у нас це для зберігання даних. Що з ними робити і взагалі, як бути з persistence у Kubernetes?

Я думаю, знову ж таки у нас, у рамках Вечірньої Школи, Тема про базу даних на Kubernetes була. І мені здається, що я навіть приблизно знаю, що сказали вам колеги на запитання: «Чи можна запускати в Kubernetes базу даних?». Мені чомусь, здається, що колеги вам повинні були сказати, що якщо ви ставите питання, чи можна в Kubernetes запускати базу даних, значить не можна.

Тут логіка проста. Про всяк випадок ще раз поясню, якщо ви прямий крутий чувак, який може побудувати досить стійку відмову систему розподіленого мережевого зберігання, зрозуміти, як підтягнути під цю справу базу даних, як взагалі cloud native в контейнерах повинні в базі даних працювати. Найімовірніше, у вас немає питання, як це запускати. Якщо у вас таке питання є, і ви хочете зробити так, щоб це все розвернулося і стояло прямо на смерть у продакшені і ніколи не падало, то такого не буває. Ось прямо простріліть собі ногу гарантовано при такому підході. Тож краще не треба.

Що робити з даними, які наш додаток хотів би зберігати, якісь картинки, які завантажують користувачі, якісь штуки, які в процесі роботи генерує наш додаток, при старті, наприклад? Що з ними в Kubernetes робити?

Взагалі в ідеалі, так, звичайно, Kubernetes дуже добре передбачений і взагалі спочатку замислювався під stateless програми. Тобто під додатки, які взагалі не зберігають інформацію. Це ідеальний варіант.

Але, природно, ідеальний варіант, він ніби існує далеко не завжди. Тож ну що? Пункт перший і найпростіший – візьміть якийсь S3, тільки не самопальне, яке теж незрозуміло як працює, а від якогось провайдера. Гарного нормального провайдера — і навчіть вашу програму користуватися S3. Тобто коли у вас користувач хоче завантажити файл, скажіть «ось сюди, будь ласка, в S3 його завантаж». Коли він захоче його отримати, скажіть: "Ось тобі посилання на S3 бек і ось звідси його візьми". Це ідеальний варіант.

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

У нас буде курс з Ceph, можете ознайомитися з програмою та залишити заявку.

Тому краще щось просте типу на сервері NFS. Kubernetes вміє з ними працювати, ви можете підмонтувати директорію під сервером NFS — ваш додаток просто як локальну директорію. При цьому, природно, потрібно розуміти, що знову ж таки, з вашим NFS потрібно щось робити, потрібно розуміти, що іноді, можливо, воно стане недоступним і передбачити питання, що ви робитимете в такому випадку. Можливо, його варто бекапити кудись на окрему машину.

Наступний момент, про який я говорив, це що робити, якщо в процесі роботи ваш додаток генерує якісь файли. Наприклад, воно, запускаючись, генерує якийсь статичний файлик, який заснований на якійсь інформації, яке додаток отримує тільки в момент запуску. Тут якийсь момент. Якщо таких даних небагато, то можна взагалі не морочитися, просто під себе цю програму покласти та працювати. Тільки тут питання яке, дивіться. Дуже часто лягають всякі системи, типу вордпресу та інше, особливо з доопрацьованими хитромудрими якими-небудь плагінами, хитромудрими пхп-розробниками, вони часто вміють робити так, що вони генерують якийсь файл під себе. Відповідно, один генерує один файлик, другий генерує другий файл. Вони різні. Балансування відбувається у кластері Kubernetes клієнтів просто випадково. Відповідно, разом виходить у instance працювати не вміють. Один віддає інформацію, інший віддає користувачеві іншу інформацію. Ось такого варто уникати. Тобто в Kubernetes все, що ви запускаєте, гарантовано повинне вміти працювати в кілька instances. Тому що Kubernetes штука зворушлива. Відповідно, посунути він може будь-що, коли завгодно, ні в кого не питаючи в цілому. Тож на це треба розраховувати. Все запущене в один instance рано чи пізно колись впаде. Чим більше, відповідно, у вас резервування, тим краще. Але знову ж таки, я кажу, якщо у вас таких файликів небагато, то їх можна прямо під себе покласти, вони невеликий обсяг важать. Якщо їх стає трохи більше, всередину контейнера їх, мабуть, пхати не варто.

Я б порадив, є у Kubernetes така чудова штука, ви можете використати volume. Зокрема є volume типу empty dir. Тобто це просто Kubernetes автоматично на тому сервері, де ви запустилися, створить директорію у себе у службових директоріях. І дасть вам її, щоб ви користувалися. Тут лише один важливий момент. Тобто ваші дані будуть зберігатися не всередині контейнера, а на хості, на якому ви запущені. Kubernetes навіть такі empty dirs при нормальному налаштуванні вміє контролювати і вміє контролювати їх максимальний розмір і не давати його перевищувати. Єдиний момент те, що у вас записано в empty dir, при рестартах пода не губиться. Тобто якщо ваш помилково впаде і підніметься знову, інформація в empty dir нікуди не подінеться. Під нею знову за нового старту може скористатися — і це добре. Якщо ваш під кудись поїде, то звичайно, він поїде без даних. Тобто, як тільки під нода, де він був запущений з empty dir, пропадає, empty dir видаляється.

Чим ще добрий empty dir? Наприклад, ним можна скористатися як кешем. Давайте уявимо, що у нас додаток генерує щось на льоту, віддає користувачам і це робить довго. Тому додаток, наприклад, генерує і віддає користувачам, і заразом складає під себе кудись, щоб наступного разу, коли користувач за тим самим прийде, віддати це відразу згенероване швидше. Empty dir можна попросити Kubernetes створити у пам'яті. І таким чином, у вас кеші взагалі можуть просто блискавично працювати — щодо швидкості звернення до диска. Тобто у вас empty dir в пам'яті, в ОС він зберігається в пам'яті, а при цьому для вас, для користувача всередині пода виглядає, як просто локальна директорія. Вам не потрібно додаток спеціально вивчати якийсь магії. Ви просто прямо берете і кладете в директорію ваш файлик, але, насправді, в пам'ять на ОС. Це теж дуже зручна фішка щодо Kubernetes.

Які проблеми у Minio існують? Головна проблема Minio - це в тому, що для того, щоб ця штука працювала, їй потрібно десь бути запущеною, і по ній має бути якась файлова система, тобто сховище. А тут ми зустрічаємося з тими самими проблемами, які є у Ceph. Тобто Minio десь має зберігати свої файли. Це просто HTTP інтерфейс до ваших файлів. Причому з функціоналом явно переможніше, ніж у амазонівської S3. Раніше воно не вміло нормально авторизувати користувача. Зараз воно, наскільки я знаю, воно вже вміє робити buckets з різною авторизацією, але знову ж таки, мені здається, головна проблема – це, так би мовити, система зберігання нижче під мінімум.

Empty dir у пам'яті як впливає на ліміти? Не впливає на ліміти. Він лежить у пам'яті, виходить, хоста, а не у пам'яті вашого контейнера. Тобто ваш контейнер не бачить empty dir у пам'яті як частину зайнятої своєї пам'яті. Це бачить хост. Відповідно, так, з точки зору kubernetes, коли ви починаєте таке використовувати, добре б розуміти, що ви частину своєї пам'яті віддаєте під empty dir. І, відповідно, розуміти, що пам'ять може закінчитися не тільки через додатки, але й через те, хтось у ці empty dir пише.

Cloudnativeness

І остання підтема, що таке Cloudnative. Навіщо воно потрібне. Cloudnativeness і так далі.

Тобто ті додатки, які вміють та написані для того, щоб працювати у сучасній хмарній інфраструктурі. Але, насправді, Cloudnative має ще один такий аспект. Що це не лише додаток, який враховує всі вимоги сучасної хмарної інфраструктури, а й уміє з цією сучасною хмарною інфраструктурою працювати, використовувати плюси та переваги того, що він у цих хмарах працює. Не просто переборювати себе і працювати в хмарах, а прямо використовувати плюси від того, що ви працюєте в хмарі.

Вимоги до розробки програми Kubernetes

Давайте візьмемо для прикладу просто Kubernetes. У вас програма запущена в Kubernetes. У вас завжди ваш додаток може, точніше адміни для вашої програми, завжди можуть зробити сервіс-аккаунт. Тобто облік для авторизації в самому Kubernetes в його сервері. Накрутити туди якісь права, які нам потрібні. І ви можете звертатися до Kubernetes з вашої програми. Що в такий спосіб можна робити? Наприклад, з програми отримувати дані про те, де знаходяться інші ваші програми, інші такі ж інстанси і разом якось кластеризуватися поверх Kubernetes, якщо така необхідність є.

Знову ж таки, нещодавно буквально у нас був кейс. У нас є один контролер, який займається тим, що моніторить чергу. І коли в цій черзі з'являються якісь нові завдання, він іде в Kubernetes – і всередині Kubernetes створює новий під. Дає цьому поду якесь нове завдання і в рамках цього пода, під виконує завдання, відправляє відповідь у сам контролер, і контролер потім із цією інформацією щось робить. Базу даних, наприклад, становить. Тобто це знову ж таки плюс того, що наша програма працює в Kubernetes. Ми можемо використовувати сам вбудований функціонал Kubernetes для того, щоб якось розширити та зробити більш зручним функціонал нашої програми. Тобто не городити якусь магію того, як запускати програму, як запускати воркер. У Kubernetes просто закинути запит в аппе, якщо програма написана на пітоні.

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

Те саме стосується масштабування. Звичайний Kubernetes може інтегруватися з хмарними провайдерами. Вміє розуміти, що якщо в кластері закінчилися ноди, тобто місце нода закінчилося, то треба додати - сам Kubernetes додасть вам нових нів у свій кластер і почне на них запускати поди. Тобто коли у вас приходить навантаження, у вас подов починає кількість збільшуватися. Коли ноди в кластері закінчуються для цих подів, Kubernetes запускає нові ноди і, відповідно, кількість подів ще може збільшуватися. І це дуже зручно. Це пряма можливість на льоту масштабувати кластер. Не дуже швидко, у плані того, що це не секунда, це швидше хвилина, щоб додавати нові ноди.

Але з мого знову ж таки досвіду, саме таке кльове, що я бачив. Коли на основі доби кластер Cloudnative скейлівся. Це був такий бекенд-сервіс, яким користувалися люди в бэкофісі. Тобто вони приходять на роботу о 9-й ранку, починають заходити в систему, відповідно, кластер Cloudnative, де це все запущено, починає пухнути, запускати нові поди, для того щоб всі, хто прийшов на роботу, могли з додатком працювати. Коли вони о 8-й вечора або о 6-й вечора йдуть з роботи, кластери Kubernetes помічають, що більше ніхто не користується додатком і починають зменшуватися. Економія прям процентів 30 гарантована. Це тоді працювало в Амазоні, в Росії на той момент не було взагалі нікого, хто б так круто вмів робити.

Я прямо кажу, економія відсотків 30 просто через те, що ми користуємося Kubernetes, користуємося можливостями хмари. Нині таке можна робити у Росії. Я не нікого рекламуватиму, звичайно, але скажемо так, є провайдери, які таке вміють робити, надавати прямо з коробки по кнопці.

Останній момент, на який також хочу звернути увагу. Для того, щоб ваша програма, ваша інфраструктура була Cloudnative, має сенс вже почати нарешті адаптувати підхід, який називається Infrastructure as a Code. Тобто це про те, що ваша програма, точніше вашу інфраструктуру потрібно точно так само, як і код вашої програми, вашої бізнес логіки описувати у вигляді коду. І працювати з ним як із кодом, тобто його тестувати, розкачувати, зберігати в git, CICD до нього застосовувати.

І це пряме те, що дозволяє вам, по-перше, завжди мати контроль над вашою інфраструктурою, завжди розуміти в якому вона стані. По-друге, уникати ручних операцій, які викликають помилки. По-третє, уникати просто того, що називається текучкою, коли вам постійно потрібно виконувати ті самі ручні операції. По-четверте, це дозволяє набагато швидше відновлюватись у разі збою. Ось у Росії щоразу, коли я про це говорю, перебуває обов'язково величезна кількість людей, які кажуть: «Ага, зрозуміло, та у вас підходи, коротше, нічого робити не треба». Але це правда. Якщо у вас щось зламалося в інфраструктурі, то з точки зору Cloudnative підходу і з точки зору Infrastructure as a Code, ніж це полагодити, піти на сервер, розібратися, що зламалося і відремонтувати, простіше видалити сервер і створити заново. І в мене це все відновиться.

Докладніше всі ці питання розглядаються на відеокурси по Kubernetes: Джуніор, Базовий, Мега. За посиланням ви можете ознайомитись з програмою та умовами. Зручно те, що можете освоїти Kubernetes, займаючись з дому або роботи по 1-2 години на день.

Джерело: habr.com

Додати коментар або відгук