- PVSM.RU - https://www.pvsm.ru -

7 лучших практик по эксплуатации контейнеров по версии Google

Прим. перев.: Автор оригинальной статьи — Théo Chamley, архитектор облачных решений Google. В этой публикации для блога Google Cloud он представил краткую выжимку из более детального руководства его компании, названного «Best Practices for Operating Containers [1]». В нём специалисты Google собрали лучшие практики по эксплуатации контейнеров в контексте использования Google Kubernetes Engine и не только, затронув широкий спектр тем: от безопасности до мониторинга и журналирования. Итак, какие практики в работе с контейнерами наиболее важны по мнению Google?

7 лучших практик по эксплуатации контейнеров по версии Google - 1

Kubernetes Engine [2] (основанный на Kubernetes сервис для запуска контейнеризированных приложений в Google Cloud — прим. перев.) — один из лучших способов запуска рабочих нагрузок, нуждающихся в масштабировании. Kubernetes [3] обеспечит беспроблемное функционирование большинства приложений, если они контейнеризированы. Но если вы хотите, чтобы приложением было легко управлять, и хотите воспользоваться всеми преимуществами Kubernetes, необходимо следовать лучшим практикам. Они упростят эксплуатацию приложения, его мониторинг и отладку, а также повысят безопасность.

В этой статье мы пройдёмся по списку того, что стоит знать и делать для эффективного функционирования контейнеров в Kubernetes. Желающим углубиться в детали стоит прочитать материал Best Practices for Operating Containers [1], а также обратить внимание на наш более ранний пост [4] о сборке контейнеров.

1. Используйте родные механизмы контейнеров для логирования

Если приложение запущено в кластере Kubernetes, для логов нужно не так много. Централизованная система логирования, вероятно, уже встроена в используемый кластер. В случае использования Kubernetes Engine за это отвечает Stackdriver Logging [5]. (Прим. перев.: А в случае использования собственной инсталляции Kubernetes рекомендуем присмотреться к нашему Open Source-решению — loghouse [6].) Не усложняйте себе жизнь и используйте родные механизмы журналирования контейнеров. Пишите логи в stdout и stderr — они будут автоматически получены, сохранены и проиндексированы.

При желании можно также писать логи в формате JSON [7]. Такой подход позволит легко добавлять к ним метаданные. А вместе с ними в Stackdriver Logging появится возможность поиска по логам с использованием этих метаданных.

2. Убедитесь, что контейнеры — stateless и immutable

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

Stateless означает, что любое состояние (постоянные данные любого вида) хранятся вне контейнера. Для этого, в зависимости от потребностей, могут быть задействованы разные виды внешних хранилищ: Cloud Storage [8], Persistent Disks [9], Redis [10], Cloud SQL [11] или другие управляемые базы данных. (Прим. перев.: Подробнее об этом читайте также в нашей статье «Операторы для Kubernetes: как запускать stateful-приложения [12]».)

Immutable означает, что контейнер не будет модифицирован во время своей жизни: никаких обновлений, патчей, изменений в конфигурации. Если вам нужно обновить код приложения или применить патч, создайте новый образ и задеплойте его. Рекомендуется выносить конфигурацию контейнера (порт для прослушивания, опции исполняемой среды и т.п.) вовне — в Secrets [13] и ConfigMaps [14]. Их можно обновлять без необходимости собирать новый образ контейнера. Для простого создания пайплайнов со сборкой образов можно использовать Cloud Build [15]. (Прим. перев.: Мы для этих целей используем Open Source-инструмент dapp [16].)

7 лучших практик по эксплуатации контейнеров по версии Google - 2
Пример обновления конфигурации Deployment в Kubernetes с помощью ConfigMap, примонтированного в поды в качестве конфига

3. Избегайте привилегированных контейнеров

Вы ведь не запускаете приложения под root'ом на своих серверах, верно? Если злоумышленник проникнет в приложение, он получит доступ с правами root. Те же соображения справедливы и для того, чтобы не запускать привилегированные контейнеры. Если требуется изменять настройки на хосте, можно выдать контейнеру конкретные capabilities с помощью опции securityContext [17] в Kubernetes. Если требуется изменять sysctls, у Kubernetes есть отдельная аннотация [18] для этого. А вообще, старайтесь максимально использовать init- [19] и sidecar-контейнеры для выполнения подобных привилегированных операций. Они не нуждаются в доступности ни для внутреннего, ни для внешнего трафика.

Если вы администрируете кластер, можете воспользоваться Pod Security Policy [20] для ограничений в применении привилегированных контейнеров.

4. Избегайте запуска под root

О привилегированных контейнерах уже сказано, но будет ещё лучше, если в дополнение к этому вы не будете запускать под root'ом приложения внутри контейнера. Если злоумышленник найдёт в приложении с правами root удалённую уязвимость с возможностью исполнения кода, после чего сможет выйти из пределов контейнера через пока ещё неизвестную уязвимость, то получит root'а на хосте.

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

5. Сделайте приложение простым для мониторинга

Как и логирование, мониторинг — неотъемлемая часть управления приложением. Популярным решением для мониторинга в сообществе Kubernetes является Prometheus [22] — система, которая автоматически обнаруживает поды и сервисы, требующие мониторинга. (Прим. перев.: См. также наш подробный доклад [23] по теме мониторинга с помощью Prometheus и Kubernetes.) Stackdriver [24] способен мониторить кластеры Kubernetes и включает в себя свою версию Prometheus для мониторинга приложений.

7 лучших практик по эксплуатации контейнеров по версии Google - 3
Панель мониторинга Kubernetes в Stackdriver

Prometheus ожидает, что приложение пробросит метрики на HTTP endpoint. Для этого доступны клиентские библиотеки Prometheus [25]. Такой же формат используют другие инструменты вроде OpenCensus [26] и Istio [27].

6. Сделайте доступным состояние здоровья приложения

Управлению приложением в production помогает его способность сообщать о своём состоянии всей системе. Запущено ли приложение? В порядке ли оно? Готово ли принимать трафик? Как себя ведёт? Наиболее распространённым способом решения этой проблемы является реализация проверок здоровья (health checks). У Kubernetes есть два их типа: liveness и readiness probes [28].

Для 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 [29]».

7. Внимательно выбирайте версию образа

Большинство публичных и приватных образов используют систему тегирования, похожую на описанную в Best Practices for Building Containers [30]. Если образ применяет систему, близкую к семантическому версионированию [31], необходимо учитывать специфику тегирования. Например, тег latest может часто перемещаться с образа на образ — на него нельзя полагаться, если вам нужны предсказуемые и воспроизводимые сборки и инсталляции.

Можете использовать тег X.Y.Z (они почти всегда неизменны), однако в таком случае отслеживайте все патчи и обновления к образу. Если у используемого образа есть тег X.Y, это хороший вариант золотой середины. Выбрав его, вы автоматически получаете патчи и в то же время опираетесь на стабильную версию приложения.

P.S. от переводчика

Читайте также в нашем блоге:

Автор: shurup

Источник [39]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/sistemnoe-administrirovanie/294639

Ссылки в тексте:

[1] Best Practices for Operating Containers: https://cloud.google.com/solutions/best-practices-for-operating-containers

[2] Kubernetes Engine: https://cloud.google.com/kubernetes-engine/

[3] Kubernetes: https://cloud.google.com/kubernetes/

[4] более ранний пост: https://cloud.google.com/blog/products/gcp/7-best-practices-for-building-containers

[5] Stackdriver Logging: https://cloud.google.com/logging/

[6] loghouse: https://github.com/flant/loghouse

[7] формате JSON: https://cloud.google.com/logging/docs/structured-logging

[8] Cloud Storage: https://cloud.google.com/storage/docs

[9] Persistent Disks: https://cloud.google.com/kubernetes-engine/docs/how-to/stateful-apps

[10] Redis: https://cloud.google.com/memorystore/docs/redis/

[11] Cloud SQL: https://cloud.google.com/sql/docs/

[12] Операторы для Kubernetes: как запускать stateful-приложения: https://habr.com/company/flant/blog/326414/

[13] Secrets: https://kubernetes.io/docs/concepts/configuration/secret/

[14] ConfigMaps: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/

[15] Cloud Build: https://cloud.google.com/cloud-build/

[16] dapp: https://github.com/flant/dapp

[17] securityContext: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container

[18] отдельная аннотация: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/

[19] init-: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

[20] Pod Security Policy: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privileged

[21] Pod Security Policy: https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies

[22] Prometheus: https://prometheus.io/

[23] подробный доклад: https://habr.com/company/flant/blog/412901/

[24] Stackdriver: https://cloud.google.com/monitoring/kubernetes-engine/

[25] клиентские библиотеки Prometheus: https://prometheus.io/docs/instrumenting/clientlibs/

[26] OpenCensus: http://opencensus.io/

[27] Istio: https://istio.io/

[28] liveness и readiness probes: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/

[29] Kubernetes best practices: Setting up health checks with readiness and liveness probes: https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes

[30] Best Practices for Building Containers: https://cloud.google.com/solutions/best-practices-for-building-containers#properly_tag_your_images

[31] семантическому версионированию: https://semver.org/lang/ru/

[32] Новая статистика CNCF о контейнерах, cloud native и Kubernetes: https://habr.com/company/flant/blog/422949/

[33] 7 принципов проектирования приложений, основанных на контейнерах: https://habr.com/company/flant/blog/353272/

[34] 11 способов (не) стать жертвой взлома в Kubernetes: https://habr.com/company/flant/blog/417905/

[35] Наш опыт с Kubernetes в небольших проектах: https://habr.com/company/flant/blog/331188/

[36] Собираем Docker-образы для CI/CD быстро и удобно вместе с dapp: https://habr.com/company/flant/blog/324274/

[37] Практики Continuous Delivery с Docker: https://habr.com/company/flant/blog/322686/

[38] Смерть микросервисного безумия в 2018 году: https://habr.com/company/flant/blog/347518/

[39] Источник: https://habr.com/post/425085/?utm_campaign=425085