7 найкращих практик з експлуатації контейнерів за версією Google

Прим. перев.: Автор оригінальної статті - Théo Chamley, архітектор хмарних рішень Google. У цій публікації для блогу Google Cloud він представив коротку вичавку з детальнішого керівництва його компанії, названого «Best Practices for Operating Containers». У ньому фахівці Google зібрали найкращі практики з експлуатації контейнерів у контексті використання Google Kubernetes Engine і не тільки, торкнувшись широкого спектру тем: від безпеки до моніторингу та журналування. Отже, які практики в роботі з контейнерами є найбільш важливими на думку Google?

7 найкращих практик з експлуатації контейнерів за версією Google

Движок Kubernetes (заснований на Kubernetes сервіс для запуску контейнеризованих додатків у Google Cloud прим. перев.) — один із найкращих способів запуску робочих навантажень, які потребують масштабування. Кубернетес забезпечить безпроблемне функціонування більшості програм, якщо вони контейнеризовані. Але якщо ви хочете, щоб програмою було легко керувати, і хочете скористатися всіма перевагами Kubernetes, необхідно слідувати кращим практикам. Вони спростять експлуатацію програми, її моніторинг та налагодження, а також підвищать безпеку.

У цій статті ми пройдемося за списком того, що варто знати та робити для ефективного функціонування контейнерів у Kubernetes. Бажаючим заглибитись у деталі варто прочитати матеріал Best Practices for Operating Containers, а також звернути увагу на наш більш ранній пост про складання контейнерів.

1. Використовуйте свої механізми контейнерів для логування

Якщо програма запущена в кластері Kubernetes, для логів потрібно не так багато. Централізована система логування, ймовірно, вже вбудована у кластер, що використовується. У разі використання Kubernetes Engine за це відповідає Журналування Stackdriver. (Прим. перев.: А у разі використання власної інсталяції Kubernetes рекомендуємо придивитися до нашого Open Source-рішення loghouse.) Не ускладнюйте собі життя та використовуйте рідні механізми журналування контейнерів. Пишіть логи в stdout і stderr – вони будуть автоматично отримані, збережені та проіндексовані.

За бажання можна також писати логи в форматі JSON. Такий підхід дозволить легко додавати до них метадані. А разом з ними в Stackdriver Logging з'явиться можливість пошуку логів з використанням цих метаданих.

2. Переконайтеся, що контейнери є stateless і immutable

Для коректного функціонування контейнерів у кластері Kubernetes вони мають бути Stateless і immutable. Коли ці умови виконані, Kubernetes зможе виконувати свою роботу, створюючи та знищуючи сутність програми, коли і де це необхідно.

Без громадянства означає, що будь-який стан (постійні дані будь-якого виду) зберігаються поза контейнером. Для цього, залежно від потреб, можуть бути задіяні різні види зовнішніх сховищ: Хмарні сховища, Постійні диски, Redis, Хмарний SQL чи інші керовані бази даних. (Прим. перев.: Докладніше про це читайте також у нашій статті «Оператори для Kubernetes: як запускати stateful-додатки".)

Незмінний означає, що контейнер не буде модифікований під час свого життя: жодних оновлень, патчів, змін у конфігурації. Якщо вам потрібно оновити код програми або застосувати патч, створіть новий образ та закрийте його. Рекомендується виносити конфігурацію контейнера (порт для прослуховування, опції виконуваного середовища тощо) зовні - Секрети и ConfigMaps. Їх можна оновлювати без потреби збирати новий образ контейнера. Для простого створення пайплайнів зі збиранням образів можна використовувати Хмарна збірка. (Прим. перев.: Ми для цих цілей використовуємо Open Source-інструмент dapp.)

7 найкращих практик з експлуатації контейнерів за версією Google
Приклад оновлення конфігурації Deployment у Kubernetes за допомогою ConfigMap, примонтованого в поди як конфіг

3. Уникайте привілейованих контейнерів

Адже ви не запускаєте програми під root'ом на своїх серверах, вірно? Якщо зловмисник проникне у програму, він отримає доступ із правами root. Ті самі міркування справедливі й у тому, ніж запускати привілейовані контейнери. Якщо потрібно змінити налаштування на хості, можна видати контейнеру конкретні можливості за допомогою опції securityContext у Kubernetes. Якщо потрібно змінювати sysctls, у Kubernetes є окрема інструкція для цього. А взагалі, намагайтеся максимально використати init- і sidecar-контейнери для виконання подібних привілейованих операцій. Вони не потребують доступності ні для внутрішнього, ні для зовнішнього трафіку.

Якщо ви адмініструєте кластер, можете скористатися Pod Security Policy для обмежень у застосуванні привілейованих контейнерів.

4. Уникайте запуску під root

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

Найкращий шлях уникнути цього — насамперед не запускати нічого під root'ом. Для цього можна скористатися директивою USER в Dockerfile або runAsUser у Kubernetes. Адміністратор кластера може також налаштувати примусову поведінку за допомогою Pod Security Policy.

5. Зробіть програму простою для моніторингу

Як і логування, моніторинг - невід'ємна частина управління програмою. Популярним рішенням для моніторингу у спільноті Kubernetes є Прометей — система, яка автоматично виявляє поди та сервіси, що потребують моніторингу. (Прим. перев.: Див. також наш докладна доповідь по темі моніторингу за допомогою Prometheus та Kubernetes.) Stackdriver здатний моніторити кластери Kubernetes і включає свою версію Prometheus для моніторингу додатків.

7 найкращих практик з експлуатації контейнерів за версією Google
Панель моніторингу Kubernetes у Stackdriver

Prometheus очікує, що програма прокине метрики на HTTP endpoint. Для цього доступні клієнтські бібліотеки Prometheus. Такий самий формат використовують інші інструменти на кшталт OpenCensus и Істіо.

6. Зробіть доступним стан здоров'я програми

Управлінню додатком у production допомагає його здатність повідомляти про свій стан всієї системи. Чи запущено програму? Чи гаразд воно? Чи готове приймати трафік? Як поводиться? Найбільш поширеним способом вирішення цієї проблеми є реалізація перевірок здоров'я (health checks). У Kubernetes є два їх типи: liveness і readiness probes.

Для liveness probe (перевірки на життєздатність) програма повинна мати HTTP endpoint, що повертає відповідь «200 OK», якщо вона функціонує та її основні залежності задоволені. Для readiness probe (Перевірки на готовність до обслуговування) програма повинна мати інший HTTP endpoint, що повертає відповідь «200 OK», якщо програма знаходиться в здоровому стані, кроки по ініціалізації виконані і будь-який коректний запит не призводить до помилки. Kubernetes буде спрямовувати трафік на контейнер тільки у разі готовності програми відповідно до цих перевірок. Два endpoint'а можуть об'єднані, якщо різниця між станами життєздатності (liveness) та готовності (readiness) немає.

Докладніше про це можна прочитати у відповідній статті від Sandeep Dinesh, Developer Advocate з Google: «Kubernetes best practices: Setting up health checks with readiness and liveness probes».

7. Уважно обирайте версію образу

Більшість публічних і приватних образів використовують систему тегування, схожу на описану в Best Practices for Building Containers. Якщо образ застосовує систему, близьку до семантичного версіонуваннянеобхідно враховувати специфіку тегування. Наприклад, тег latest може часто переміщатися з образу на образ – на нього не можна покладатися, якщо вам потрібні передбачувані та відтворювані складання та інсталяції.

Можете використовувати тег X.Y.Z (Вони майже завжди незмінні), проте в такому випадку відстежуйте всі патчі та оновлення до образу. Якщо у використовуваного образу є тег X.YЦе хороший варіант золотої середини. Вибравши його, ви автоматично отримуєте патчі і одночасно спираєтеся на стабільну версію програми.

PS від перекладача

Читайте також у нашому блозі:

Джерело: habr.com

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