Архив метки: Kubernetes

Как использовать Kubernetes – важные аспекты и преимущества работы с платформой управления контейнерами

Что такое Kubernetes: важные аспекты использования Kubernetes

Kubernetes – это открытая система управления контейнерами, разработанная Google. Идея Kubernetes заключается в упрощении и автоматизации процесса развертывания, масштабирования и управления приложениями в контейнерах.

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

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

Использование Kubernetes имеет множество преимуществ. Во-первых, он позволяет создавать высокодоступные и масштабируемые системы, которые могут быть распределены по нескольким серверам. Во-вторых, Kubernetes автоматически управляет ресурсами и балансирует нагрузку, что позволяет максимально эффективно использовать доступные ресурсы. Кроме того, Kubernetes обеспечивает отказоустойчивость, автоматически восстанавливая перезапуск приложений в случае сбоев или ошибок.

Что такое Kubernetes: важные аспекты использования

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

Еще одной важной особенностью Kubernetes является его высокая отказоустойчивость. Kubernetes автоматически обнаруживает и восстанавливает неработоспособные компоненты, такие как узлы и контейнеры, чтобы поддерживать непрерывную работу приложений.

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

Для управления приложениями в Kubernetes используется декларативная модель. Вы определяете желаемое состояние системы в виде манифестов, которые содержат описание приложений, и Kubernetes самостоятельно приводит состояние системы к заданному состоянию.

Организация работы приложений в Kubernetes основана на концепции подов (Pods), которые содержат один или несколько контейнеров. Каждый под имеет уникальный IP-адрес и собственное пространство имен, что обеспечивает изоляцию и безопасность приложений.

Развертывание Kubernetes

Развертывание Kubernetes

1. Установка Kubernetes – начните с установки Kubernetes на каждый узел (мастер-ноду и рабочие ноды) в кластере. Для этого можно использовать инструменты, такие как kubeadm, kubespray или Kubermatic.

2. Создание мастер-ноды – настройте мастер-ноду, которая будет управлять весь кластером Kubernetes. Здесь необходимо указать параметры, такие как IP-адреса и порты, используемые для связи между нодами.

3. Подключение рабочих нод – подключите рабочие ноды к мастер-ноде, чтобы они могли выполнять контейнеры и приложения. Для этого укажите IP-адреса рабочих нод и установите необходимые зависимости.

4. Конфигурация хранения данных – определите способ хранения данных в кластере Kubernetes. Это может быть локальное хранилище, такое как локальные диски, или удаленное хранилище, такое как Amazon S3 или Google Cloud Storage.

5. Настройка сети – настройте сетевую конфигурацию для кластера Kubernetes. Это включает в себя создание сетевых политик, определение IP-адресов и настройку маршрутизации между нодами.

6. Проверка работоспособности – проведите проверку работоспособности кластера Kubernetes, чтобы убедиться, что все узлы и приложения функционируют корректно. Проверьте доступность мастер-ноды, рабочих нод и запущенных контейнеров.

7. Управление и масштабирование – после успешного развертывания Kubernetes можно управлять кластером, применять обновления, масштабировать приложения и контролировать состояние узлов.

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

Установка и конфигурация Kubernetes

Установка и конфигураци
я Kubernetes

Для установки Kubernetes необходимо выполнить несколько шагов:

1. Выбрать подходящий дистрибутив Kubernetes в зависимости от операционной системы и среды разработки.

2. Установить Docker или другой контейнерный движок на каждой ноде кластера.

3. Установить kubelet, kubeadm и kubectl на каждой ноде кластера. Kubeadm позволяет настраивать и инициализировать кластер, а kubelet и kubectl – управлять им.

4. Запустить и настроить кластер Kubernetes с помощью kubeadm init команды. При этом будет создана первая мастер-нода, и настройки будут сохранены в файле конфигурации, который будет использоваться при добавлении второй и последующих мастер-нод.

5. Добавить остальные ноды в кластер с помощью kubeadm join команды. При этом будет создан и сохранен файл конфигурации для работы новой ноды с кластером.

7. Настроить необходимые компоненты и плагины для работы с кластером, например, маршрутизацию сетевых запросов или логирование.

После завершения установки и конфигурации Kubernetes готов к работе, и вы можете начать развертывание и управление своими контейнеризованными приложениями.

Масштабирование Kubernetes

Масштабирование Kubernetes

Kubernetes предоставляет несколько методов масштабирования приложений:

  • Горизонтальное масштабирование – это процесс добавления или удаления экземпляров приложения (подов) для обеспечения равномерного распределения нагрузки и обработки большего количества запросов. Kubernetes автоматически управляет этим процессом, мониторя и регулируя количество подов в зависимости от текущей нагрузки.
  • Вертикальное масштабирование – это процесс изменения ресурсов, выделенных поду, таких как CPU и память, для повышения его производительности. Kubernetes позволяет гибко управлять ресурсами, выделенными каждому поду, и динамически изменять их в зависимости от потребностей приложения.

Помимо этого, Kubernetes также предоставляет механизмы для масштабирования хранилища данных и сетевой инфраструктуры. Например, можно использовать горизонтальное масштабирование хранилища данных, добавляя дополнительные узлы для увеличения пропускной способности или емкости хранения.

Благодаря масштабированию Kubernetes можно легко адаптировать приложение к изменяющимся требованиям и поддерживать его работоспособность даже при резком увеличении нагрузки. Это позволяет компаниям эффективно масштабировать свою инфраструктуру и обеспечивать высокий уровень производительности и доступности своих приложений.

Планирование и управление ресурсами

В Kubernetes используется понятие подов (Pods) – минимальной единицы развертывания, которая содержит один или несколько контейнеров, работающих вместе. Каждый под имеет определенные требования к ресурсам, таким как CPU и память.

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

Если ресурсы на узлах кластера исчерпаны, Kubernetes может автоматически масштабировать приложение, добавляя новые узлы или перезапуская контейнеры на других узлах с доступными ресурсами. Это позволяет обеспечить высокую доступность и отказоустойчивость приложения.

Кроме того, Kubernetes предоставляет возможности для управления ресурсами, такие как ограничение потребления ресурсов (limits) и разделение ресурсов (quotas). Ограничение потребления ресурсов позволяет задать максимально доступное количество CPU и памяти для каждого пода, чтобы избежать перегрузки узлов. Разделение ресурсов позволяет установить ограничения на общее количество ресурсов для всего кластера или определенной группы пользователей.

Благодаря планированию и управлению ресурсами в Kubernetes, вы можете эффективно использовать доступные ресурсы, обеспечивать стабильную работу приложения и масштабирование при необходимости.

Управление контейнерами на Kubernetes

Управление контейнерами на Kubernetes

Для управления контейнерами на Kubernetes используются объекты, называемые подами (Pods). Под представляет собой минимальную единицу развертывания и управления в Kubernetes. Каждый под включает один или несколько контейнеров, а также объединяет их в единую группу.

Для создания пода в Kubernetes необходимо создать описание этого пода в YAML или JSON формате. Описание пода включает информацию о контейнерах, их параметрах и другие настройки. Затем, созданный файл с описанием пода передается в Kubernetes API для развертывания.

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

Контейнеры в подах можно мониторить и управлять с помощью различных инструментов и интерфейсов, таких как Kubernetes Dashboard, командная строка и API. Они позволяют получать информацию о состоянии контейнеров, а также выполнять различные операции по их управлению.

Все эти возможности Kubernetes по управлению контейнерами делают его мощным инструментом для развертывания и управления контейнеризированными приложениями в кластерной среде.

Создание и управление контейнерами

Создание и управление контейнерами

Создание контейнеров осуществляется путем определения специального описания, известного как Dockerfile. В Dockerfile задаются инструкции по установке и настройке приложения, необходимые зависимости и прочие параметры. После написания Dockerfile контейнер может быть создан с помощью команды docker build.

После создания контейнера его необходимо запустить. Kubernetes предоставляет средства для запуска контейнеров внутри пода – минимальной единицы развертывания в Kubernetes. Под представляет собой группу одного или нескольких связанных контейнеров с общими ресурсами и настройками.

Управление контейнерами в Kubernetes осуществляется с помощью YAML-файлов с описанием желаемого состояния кластера. В YAML-файлах указываются метаданные пода, образы контейнеров, требуемые ресурсы и другие параметры. Для создания и управления контейнерами Kubernetes использует инструмент kubectl. С помощью kubectl можно создавать и удалять поды, масштабировать контейнеры, выполнить обновление приложений и многое другое.

Мониторинг и логирование контейнеров

Для мониторинга контейнеров существуют различные инструменты, такие как Prometheus, Grafana и Datadog. Они позволяют собирать и анализировать данные о работе приложений, использовании ресурсов, а также обнаруживать проблемы и осуществлять масштабирование.

Логирование контейнеров позволяет записывать события и ошибки, происходящие в приложениях. Для этого используются решения, такие как ELK Stack (Elasticsearch, Logstash и Kibana) или Fluentd. Они позволяют собирать, агрегировать и анализировать логи, что упрощает отладку и обнаружение проблем в приложениях.

Инструменты мониторингаИнструменты логирования
PrometheusELK Stack
GrafanaFluentd
Datadog

Кроме того, Kubernetes имеет встроенную функциональность для мониторинга и логирования, которая называется kube-state-metrics и kube-logging-agent. Они автоматически собирают и передают метрики и логи в специальные хранилища данных, такие как Prometheus и Elasticsearch.

Для эффективного мониторинга и логирования контейнеров рекомендуется настраивать оповещения и уведомления о проблемах с помощью инструментов управления и мониторинга, таких как Kubernetes Dashboard и Alertmanager.

Вопрос-ответ:

Что такое Kubernetes и зачем он нужен?

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

Видео:

Kubernetes CKS Full Course Theory + Practice + Browser Scenarios

Сообщение Как использовать Kubernetes – важные аспекты и преимущества работы с платформой управления контейнерами появились сначала на Программирование на Python.

Вопросы для собеседования по Kubernetes

Kubernetes фактически стала платформой для оркестровки контейнеров, революционизируя способы управления организациями и развертывания контейнерных приложений. Если вы готовитесь к собеседованию на работу, связанному с Kubernetes, крайне важно хорошо разбираться в его концепциях и передовых практиках. В этой статье мы составили список из 20 лучших вопросов для собеседования по Kubernetes вместе с подробными ответами, которые помогут вам преуспеть на собеседовании.

 

Топ-20 вопросов и ответов для собеседования по Kubernetes

Ниже приведены 20 лучших вопросов и ответов для  собеседования по Kubernetes:

1. Что такое Kubernetes и для чего он используется?

Kubernetes — это платформа оркестровки контейнеров с открытым исходным кодом, которая автоматизирует развертывание, масштабирование и управление контейнерными приложениями. Она упрощает управление контейнерами, повышает устойчивость приложений и обеспечивает эффективное использование ресурсов.

2. Объясните ключевые компоненты кластера Kubernetes.

Кластер Kubernetes состоит из:

  • Master Node: управляет кластером, планированием и общим контролем.
  • Worker Nodes (Minions): запускают контейнеры и отчитываются перед главным.
  • etcd: распределенное хранилище ключей-значений для настройки кластера.
  • Kubelet: обеспечивает работу контейнеров на узлах.
  • Kube Proxy: поддерживает сетевые правила на узлах.

 

3. Что такое Pod в Kubernetes?

Pod — это наименьший развертываемый модуль в Kubernetes, представляющий собой единственный экземпляр запущенного процесса в кластере. Модули могут содержать один или несколько контейнеров, совместно использующих сетевые ресурсы и ресурсы хранения.

4. Объясните разницу между Deployment и StatefulSet.

Развертывания используются для приложений без состояния, которые можно легко реплицировать и масштабировать по горизонтали. Наборы параметров состояния используются для приложений с отслеживанием состояния, которым требуются уникальные идентификаторы и стабильные сетевые идентификаторы, например базы данных.

5. Что такое сервис Kubernetes и почему он важен?

Сервис — это абстракция, которая предоставляет набор модулей в качестве сетевой службы. Это гарантирует, что запросы к сервису распределяются по нагрузке на исправные модули, обеспечивая стабильную конечную точку для связи внутри кластера.

6. Что такое метки и селекторы в Kubernetes и как они используются?

Метки — это пары ключ-значение, прикрепленные к ресурсам (например, Pod). Селекторы используются для фильтрации и выбора ресурсов на основе этих меток. Метки и селекторы жизненно важны для организации ресурсов в Kubernetes и управления ими.

7. Что такое пространство имен в Kubernetes и зачем вы его используете?

Пространство имен предоставляет способ разделить кластер Kubernetes на несколько виртуальных кластеров. Оно используется для изоляции ресурсов и предотвращения конфликтов имен, упрощая управление приложениями в многопользовательских средах.

8. Объясните Текущие обновления и откаты Kubernetes.

Текущие обновления позволяют обновлять приложение без простоев путем постепенной замены старых модулей на новые. В случае проблем откаты возвращают к предыдущей версии, обеспечивая стабильность приложения.

9. Что такое автоматическое масштабирование по горизонтали и как это работает?

Автоматическое масштабирование по горизонтали модулей автоматически регулирует количество реплик (Pods) в развертывании на основе процессора или пользовательских показателей. Это гарантирует, что приложения могут эффективно справляться с различными нагрузками.

10. Что такое Ingress в Kubernetes и как это работает?

Ingress — это объект API, который управляет внешним доступом к службам внутри кластера. Он действует как уровень маршрутизации, позволяя вам определять правила направления входящего трафика к сервисам на основе имен хостов, путей и многого другого.

11. Объясните концепцию постоянных томов (PVS) и утверждений о постоянных объемах (PVCS) в Kubernetes.

PVS — это ресурсы хранения в кластере, в то время как PVC’ы — это запросы модулей на хранение. PVC’ы привязываются к доступным PVS, обеспечивая сохраняемость данных при перезапусках модуля и перепланировании.

12. Что такое ConfigMap в Kubernetes и как ее можно использовать?

ConfigMap — это объект API, который предоставляет способ ввода конфигурационных данных в модули. Он полезен для отделения конфигурации от кода приложения и для управления настройками, зависящими от среды.

13. Какова роль менеджера контроллера Kubernetes?

Диспетчер контроллеров отвечает за управление различными процессами контроллера в кластере, такими как развертывания, ReplicationControllers и StatefulSets. Он гарантирует, что поддерживается желаемое состояние ресурсов.

14. Объясните, как масштабировать кластер Kubernetes.

Вы можете масштабировать кластер Kubernetes, добавив в кластер больше рабочих узлов или увеличив пропускную способность существующих узлов. Кроме того, вы можете масштабировать приложения внутри кластера с помощью автоматического масштабирования по горизонтали Pod.

15. Что такое диаграмма управления в Kubernetes и почему она полезна?

Диаграмма управления — это формат пакета, используемый для упаковки и развертывания приложений и ресурсов в Kubernetes. Это упрощает процесс развертывания и позволяет легко управлять версиями и совместно использовать конфигурации приложений.

16. Как Kubernetes обрабатывает развертывание обновлений или изменений конфигураций в кластере?

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

17. Что такое RBAC в Kubernetes (управление доступом на основе ролей) и почему они важны?

RBAC — это функция безопасности в Kubernetes, которая контролирует доступ к ресурсам кластера. Она назначает роли и разрешения пользователям и учетным записям служб, гарантируя, что только авторизованные объекты могут выполнять действия в кластере.

18. Что такое Kubernetes Helm и как он упрощает упаковку и развертывание приложений?

Helm — это менеджер пакетов для Kubernetes, который позволяет определять, устанавливать и обновлять даже самые сложные приложения Kubernetes. Это упрощает процесс упаковки приложений и их зависимостей в многоразовые версионные диаграммы.

19. Объясните разницу между набором демонов и развертыванием в Kubernetes.

Набор демонов гарантирует, что все или подмножество узлов в кластере запускают копию модуля. Обычно он используется для задач системного уровня. С другой стороны, развертывание используется для управления развертыванием и масштабированием модулей приложений.

20. Что такое сетевая политика Kubernetes и как она повышает сетевую безопасность в кластере?

Сетевая политика Kubernetes позволяет вам определять правила сетевого взаимодействия между модулями. Это помогает контролировать и защищать коммуникацию внутри кластера, указывая, какие модули могут взаимодействовать друг с другом.

 

Заключение

Эти 20 лучших вопросов и ответов для интервью в Kubernetes охватывают широкий спектр тем, от базовых концепций до расширенных функций Kubernetes. Подготовка к собеседованию в Kubernetes с учетом этих знаний продемонстрирует ваш опыт в оркестровке контейнеров и повысит ваши шансы на успех при получении роли, связанной с Kubernetes. Кроме того, будьте готовы обсудить практический опыт и примеры использования, связанные с Kubernetes, чтобы продемонстрировать свой опыт работы в реальном мире. Удачи на собеседовании по Kubernetes!

 

Часто задаваемые вопросы, связанные с вопросами для собеседования в Kubernetes

Ниже приведены некоторые часто задаваемые вопросы, связанные с вопросами для собеседования в Kubernetes:

1. Что такое контейнеры и чем они отличаются от виртуальных машин в контексте Kubernetes?

Контейнеры — это легкие автономные исполняемые пакеты, которые включают в себя все необходимое для запуска части программного обеспечения, включая код, среду выполнения, системные инструменты и библиотеки. В отличие от виртуальных машин, контейнеры совместно используют ядро основной операционной системы, что делает их более эффективными и переносимыми.

2. В чем разница между Kubernetes и Docker?

Docker — это платформа контейнеризации, в то время как Kubernetes — платформа оркестровки контейнеров. Docker используется для создания контейнеров и управления ими, в то время как Kubernetes используется для управления развертыванием, масштабированием и оркестровкой контейнерных приложений на кластере компьютеров.

3. Объясните роль узла Kubernetes.

Узел Kubernetes (также известный как minion) — это рабочая машина в кластере, ответственная за запуск контейнеров. Для управления модулями запускается агент Kubernetes (kubelet) и среда выполнения контейнера (например, Docker).

4. Что такое Диаграмма управления и как она упрощает развертывание приложений в Kubernetes?

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

5. Какова цель плоскости управления Kubernetes?

Плоскость управления Kubernetes состоит из таких компонентов, как сервер API, диспетчер контроллеров, планировщик и etcd. Ит-отдел управляет общим состоянием кластера, принимает решения о том, какие рабочие нагрузки где должны выполняться, и обеспечивает поддержание желаемого состояния ресурсов.



2023-10-31T09:04:54
Программное обеспечение

Топ-10 книг по Kubernetes на русском языке: выбирайте лучшие и развивайтесь в автоматизации и оркестрации приложений

Топ-10 книг по Kubernetes на русском языке: выбирайте лучшие и развивайтесь в автоматизации и оркестрации приложений

Современный мир IT-технологий невозможно представить без оркестрации приложений. Кubernetes – это платформа, которая позволяет автоматизировать процессы работы с приложениями и значительно упростить развертывание и масштабирование их работы. Если вы хотите заниматься разработкой приложений и быть в курсе всех новинок в области автоматизации, то вам однозначно стоит обратить внимание на книги по Kubernetes.

Мы составили для вас список лучших книг на русском языке, которые помогут разобраться во всех тонкостях работы с Kubernetes и увеличат ваши знания в этой области.

В этом списке вы встретите книги разного уровня сложности – от начального до продвинутого. Они помогут как новичкам в области автоматизации, так и профессионалам, которые уже занимаются разработкой приложений на Kubernetes.

Выбирайте книги, которые вам ближе по духу и начинайте погружаться в увлекательный мир оркестрации приложений! Читать

Введение в Kubernetes и создание собственного кластера

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

Одним из ключевых преимуществ Kubernetes является возможность создания собственного кластера при помощи https://cloud.obit.ru/, который можно настроить и настроить под конкретные потребности вашего проекта.

Кроме создания кластера cloud.obit.ru предоставляет услуги:

  • vStack cloud
  • VMware cloud
  • Хранилище 1С
  • Облако
  • Kubernetes
  • и другие услуги.

 

В этой статье мы рассмотрим процесс создания собственного кластера Kubernetes.

 

Шаг 1: Выбор платформы

Первым шагом в создании кластера kubernetes является выбор платформы, на которой он будет работать. Kubernetes может работать на различных облачных провайдерах, таких как Amazon Web Services (AWS), Google Cloud Platform (GCP) и Microsoft Azure. Вы также можете развернуть кластер Kubernetes на собственном оборудовании, используя физические серверы или виртуальные машины.

 

Шаг 2: Установка Kubernetes

После выбора платформы необходимо установить Kubernetes на выбранную инфраструктуру. В случае использования облачного провайдера это может включать в себя создание экземпляров виртуальных машин и настройку сетевых правил. Если вы развертываете Kubernetes на собственном оборудовании, вам понадобится установить и настроить необходимое программное обеспечение, включая контейнерный движок, такой как Docker.

 

Шаг 3: Конфигурация кластера

После установки Kubernetes необходимо настроить кластер, определив его параметры и поведение. Кластер Kubernetes состоит из нескольких узлов, включая мастер-узлы, ответственные за управление и координацию кластером, и рабочие узлы, на которых развертываются и запускаются контейнеры. Вам нужно будет указать количество и типы узлов, сетевые настройки и другие параметры, в зависимости от вашего проекта.

 

Шаг 4: Запуск и управление приложениями

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

 

Шаг 5: Масштабирование и обслуживание

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

 

Заключение

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



2023-05-26T00:00:57
Программное обеспечение

Kubernetes. установка elk из helm чарта xpack ilm

Для начала создаём namespase elk




kubectl create namespace elk




ну или




cat namespace.yml




kind: Namespace

apiVersion: v1

metadata:

  name: elk




kubectl apply -f namespace.yml




выкачиваем чарт




git clone https://github.com/elastic/helm-charts.git
cd helm-charts/
git checkout 7.9




Далее нам надо сгенерировать сертификаты на основе которых будет всё работать.




[root@prod-vsrv-kubemaster1 helm-charts]# mkdir mkdir /certs
[root@prod-vsrv-kubemaster1 helm-charts]# cd /certs/




Создаём файл в котором укажем наши доменные имена (logstash требователен к наличию домена в сертификате)




cat cnf




[req]

distinguished_name = req_distinguished_name

x509_extensions = v3_req

prompt = no



[req_distinguished_name]

C = KG

ST = Bishkek

L = Bishkek

O = test

CN = elasticsearch-master



[v3_req]

subjectKeyIdentifier = hash

authorityKeyIdentifier = keyid,issuer

basicConstraints = CA:TRUE

subjectAltName = @alt_names



[alt_names]

DNS.1 = elasticsearch-master

DNS.2 = kibana-kibana

DNS.3 = elasticsearch-master-headless

DNS.4 = logstash-logstash-headless

DNS.5 = elk.prod.test.local

DNS.6 = elasticsearch-master-0

DNS.7 = elasticsearch-master-1

DNS.8 = elasticsearch-master-2





openssl genpkey -aes-256-cbc -pass pass:123456789 -algorithm RSA -out mysite.key -pkeyopt rsa_keygen_bits:3072




Тут надо будет ввести пароль при генерации а дальше заполнить данные сертификата.
Я везде задал пароль 123456789
openssl req -new -x509 -key mysite.key -sha256 -config cnf -out mysite.crt -days 7300
Enter pass phrase for mysite.key:




создаём сертификат p12 который нужен elastic




openssl pkcs12 -export -in mysite.crt -inkey mysite.key -out identity.p12 -name «mykey»
Enter pass phrase for mysite.key:   вот тут вводим наш пароль 123456789
Enter Export Password:   ТУТ ОСТАВЛЯЕМ БЕЗ ПАРОЛЯ
Verifying — Enter Export Password:  ТУТ ОСТАВЛЯЕМ БЕЗ ПАРОЛЯ




docker run —rm -v /certs:/certs -it openjdk:oracle keytool -import -file /certs/mysite.crt -keystore /certs/trust.jks -storepass 123456789




появится сообщение в котором мы соглашаемся, что доверяем сертификату





Вытаскиваем приватный ключ чтоб он у нас был без пароля
openssl rsa -in mysite.key -out mysite-without-pass.key
Enter pass phrase for mysite.key:
writing RSA key




Всё готово, все нужные сертификаты для elasticsearch сгенерированы:




[root@prod-vsrv-kubemaster1 certs]# ll
total 32
-rw-r—r— 1 root root 575 Feb 10 10:15 cnf
-rw-r—r— 1 root root 3624 Feb 10 10:15 identity.p12
-rw-r—r— 1 root root 1935 Feb 10 10:15 mysite.crt
-rw-r—r— 1 root root 2638 Feb 10 10:15 mysite.key
-rw-r—r— 1 root root 2459 Feb 10 10:39 mysite-without-pass.key
-rw-r—r— 1 root root 1682 Feb 10 10:15 trust.jks




Создаём секрет с сертификатами
[root@prod-vsrv-kubemaster1 certs]# kubectl create secret generic elastic-certificates -n elk —from-file=identity.p12 —from-file=mysite.crt —from-file=mysite.key —from-file=mysite-without-pass.key —from-file=trust.jks




Создаём секрет с логином и паролем для elastic:
kubectl create secret generic secret-basic-auth -n elk —from-literal=password=elastic —from-literal=username=elastic




отметим что у нас в кластере уже установлен nfs-provisioner




Перейдём к настройке переменных у elastic




elasticsearch/values.yaml
Тут включаем xpack добавляем сертификаты и указываем директорию для снапшотов




esConfig:

  elasticsearch.yml: |

    path.repo: /snapshot

    xpack.security.enabled: true

    xpack.security.transport.ssl.enabled: true

    xpack.security.transport.ssl.verification_mode: certificate

    xpack.security.transport.ssl.keystore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.transport.ssl.truststore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.http.ssl.enabled: true

    xpack.security.http.ssl.truststore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.http.ssl.keystore.path: /usr/share/elasticsearch/config/certs/identity.p12





path.repo: /snapshot   — это наша директория для снапшотов, они будут сохраняться в отдельном volume




также добавляем в переменные наш логин и пароль что мы указали при создании секрета




extraEnvs:

  - name: ELASTIC_PASSWORD

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password

  - name: ELASTIC_USERNAME

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username




также подключаем директорию для сертификатов




secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/elasticsearch/config/certs





также указываем наш nfs провижинер




volumeClaimTemplate:

  accessModes: [ "ReadWriteOnce" ]

  storageClassName: nfs-storageclass

  resources:

    requests:

      storage: 3Gi




также выставляем antiAffinity soft (так как у нас 2 воркера а эластик запускается в 3х подах он не может стартануть) эта настройка говорит что на одной ноде могут быть запущены 2 пода из кластера уэластика.




antiAffinity: «soft»




также правим протокол на https




protocol: https




весь файл будет иметь следующий вид:




[root@prod-vsrv-kubemaster1 helm-charts]# cat elasticsearch/values.yaml




---

clusterName: "elasticsearch"

nodeGroup: "master"



# The service that non master groups will try to connect to when joining the cluster

# This should be set to clusterName + "-" + nodeGroup for your master group

masterService: ""



# Elasticsearch roles that will be applied to this nodeGroup

# These will be set as environment variables. E.g. node.master=true

roles:

  master: "true"

  ingest: "true"

  data: "true"

  remote_cluster_client: "true"

# ml: "true" # ml is not availble with elasticsearch-oss



replicas: 3

minimumMasterNodes: 2



esMajorVersion: ""



# Allows you to add any config files in /usr/share/elasticsearch/config/

# such as elasticsearch.yml and log4j2.properties

esConfig:

  elasticsearch.yml: |

    path.repo: /snapshot

    xpack.security.enabled: true

    xpack.security.transport.ssl.enabled: true

    xpack.security.transport.ssl.verification_mode: certificate

    xpack.security.transport.ssl.keystore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.transport.ssl.truststore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.http.ssl.enabled: true

    xpack.security.http.ssl.truststore.path: /usr/share/elasticsearch/config/certs/identity.p12

    xpack.security.http.ssl.keystore.path: /usr/share/elasticsearch/config/certs/identity.p12



#    key:

#      nestedkey: value

#  log4j2.properties: |

#    key = value



# Extra environment variables to append to this nodeGroup

# This will be appended to the current 'env:' key. You can use any of the kubernetes env

# syntax here

extraEnvs:

  - name: ELASTIC_PASSWORD

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password

  - name: ELASTIC_USERNAME

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username





#  - name: MY_ENVIRONMENT_VAR

#    value: the_value_goes_here



# Allows you to load environment variables from kubernetes secret or config map

envFrom: []

# - secretRef:

#     name: env-secret

# - configMapRef:

#     name: config-map



# A list of secrets and their paths to mount inside the pod

# This is useful for mounting certificates for security and for mounting

# the X-Pack license

secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/elasticsearch/config/certs

#    defaultMode: 0755



image: "docker.elastic.co/elasticsearch/elasticsearch"

imageTag: "7.9.4-SNAPSHOT"

imagePullPolicy: "IfNotPresent"



podAnnotations: {}

  # iam.amazonaws.com/role: es-cluster



# additionals labels

labels: {}



esJavaOpts: "-Xmx1g -Xms1g"



resources:

  requests:

    cpu: "1000m"

    memory: "2Gi"

  limits:

    cpu: "1000m"

    memory: "2Gi"



initResources: {}

  # limits:

  #   cpu: "25m"

  #   # memory: "128Mi"

  # requests:

  #   cpu: "25m"

  #   memory: "128Mi"



sidecarResources: {}

  # limits:

  #   cpu: "25m"

  #   # memory: "128Mi"

  # requests:

  #   cpu: "25m"

  #   memory: "128Mi"



networkHost: "0.0.0.0"



volumeClaimTemplate:

  accessModes: [ "ReadWriteOnce" ]

  storageClassName: nfs-storageclass

  resources:

    requests:

      storage: 3Gi



rbac:

  create: false

  serviceAccountAnnotations: {}

  serviceAccountName: ""



podSecurityPolicy:

  create: false

  name: ""

  spec:

    privileged: true

    fsGroup:

      rule: RunAsAny

    runAsUser:

      rule: RunAsAny

    seLinux:

      rule: RunAsAny

    supplementalGroups:

      rule: RunAsAny

    volumes:

      - secret

      - configMap

      - persistentVolumeClaim



persistence:

  enabled: true

  labels:

    # Add default labels for the volumeClaimTemplate fo the StatefulSet

    enabled: false

  annotations: {}



extraVolumes: []

  #  - name: extras

  #    emptyDir: {}



extraVolumeMounts: []

  # - name: extras

  #   mountPath: /usr/share/extras

  #   readOnly: true





extraContainers: []

  # - name: do-something

  #   image: busybox

  #   command: ['do', 'something']



extraInitContainers: []

  # - name: do-something

  #   image: busybox

  #   command: ['do', 'something']



# This is the PriorityClass settings as defined in

# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass

priorityClassName: ""



# By default this will make sure two pods don't end up on the same node

# Changing this to a region would allow you to spread pods across regions

antiAffinityTopologyKey: "kubernetes.io/hostname"



# Hard means that by default pods will only be scheduled if there are enough nodes for them

# and that they will never end up on the same node. Setting this to soft will do this "best effort"

antiAffinity: "soft"



# This is the node affinity settings as defined in

# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature

nodeAffinity: {}



# The default is to deploy all pods serially. By setting this to parallel all pods are started at

# the same time when bootstrapping the cluster

podManagementPolicy: "Parallel"



# The environment variables injected by service links are not used, but can lead to slow Elasticsearch boot times when

# there are many services in the current namespace.

# If you experience slow pod startups you probably want to set this to `false`.

enableServiceLinks: true



protocol: https

httpPort: 9200

transportPort: 9300



service:

  labels: {}

  labelsHeadless: {}

  type: ClusterIP

  nodePort: ""

  annotations: {}

  httpPortName: http

  transportPortName: transport

  loadBalancerIP: ""

  loadBalancerSourceRanges: []

  externalTrafficPolicy: ""



updateStrategy: RollingUpdate



# This is the max unavailable setting for the pod disruption budget

# The default value of 1 will make sure that kubernetes won't allow more than 1

# of your pods to be unavailable during maintenance

maxUnavailable: 1



podSecurityContext:

  fsGroup: 1000

  runAsUser: 1000



securityContext:

  capabilities:

    drop:

    - ALL

  # readOnlyRootFilesystem: true

  runAsNonRoot: true

  runAsUser: 1000



# How long to wait for elasticsearch to stop gracefully

terminationGracePeriod: 120



sysctlVmMaxMapCount: 262144



readinessProbe:

  failureThreshold: 3

  initialDelaySeconds: 10

  periodSeconds: 10

  successThreshold: 3

  timeoutSeconds: 5



# https://www.elastic.co/guide/en/elasticsearch/reference/7.9/cluster-health.html#request-params wait_for_status

clusterHealthCheckParams: "wait_for_status=green&timeout=1s"



## Use an alternate scheduler.

## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/

##

schedulerName: ""



imagePullSecrets: []

nodeSelector: {}

tolerations: []



# Enabling this will publically expose your Elasticsearch instance.

# Only enable this if you have security enabled on your cluster

ingress:

  enabled: false

  annotations: {}

    # kubernetes.io/ingress.class: nginx

    # kubernetes.io/tls-acme: "true"

  path: /

  hosts:

    - chart-example.local

  tls: []

  #  - secretName: chart-example-tls

  #    hosts:

  #      - chart-example.local



nameOverride: ""

fullnameOverride: ""



# https://github.com/elastic/helm-charts/issues/63

masterTerminationFix: false



lifecycle: {}

  # preStop:

  #   exec:

  #     command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]

  # postStart:

  #   exec:

  #     command:

  #       - bash

  #       - -c

  #       - |

  #         #!/bin/bash

  #         # Add a template to adjust number of shards/replicas

  #         TEMPLATE_NAME=my_template

  #         INDEX_PATTERN="logstash-*"

  #         SHARD_COUNT=8

  #         REPLICA_COUNT=1

  #         ES_URL=http://localhost:9200

  #         while [[ "$(curl -s -o /dev/null -w '%{http_code}n' $ES_URL)" != "200" ]]; do sleep 1; done

  #         curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['""$INDEX_PATTERN""'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}'



sysctlInitContainer:

  enabled: true



keystore: []



# Deprecated

# please use the above podSecurityContext.fsGroup instead

fsGroup: ""





========================================================================================




перейдём к настройке kibana:




kibana/values.yaml




Правим http на https
elasticsearchHosts: «https://elasticsearch-master:9200»




также




extraEnvs:

  - name: 'ELASTICSEARCH_USERNAME'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username

  - name: 'ELASTICSEARCH_PASSWORD'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password





также подключаем директорию с сертификатами




secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/kibana/config/certs





также добавляем в основной конфиг пути до сертификатов




kibanaConfig:

   kibana.yml: |

    server.ssl:

      enabled: true

      key: /usr/share/kibana/config/certs/mysite-without-pass.key

      certificate: /usr/share/kibana/config/certs/mysite.crt

    xpack.security.encryptionKey: "something_at_least_32_characters"

    elasticsearch.ssl:

      certificateAuthorities: /usr/share/kibana/config/certs/mysite.crt

      verificationMode: certificate





также настраиваем ingress чтобы по нашему домену открывалась кибана, отметим что строка:
nginx.ingress.kubernetes.io/backend-protocol: «HTTPS»
обязательна так как без неё ингрес по умолчанию проксирует всё на HTTP




ingress:

  enabled: true

  annotations:

    # kubernetes.io/ingress.class: nginx

    # kubernetes.io/tls-acme: "true"

     nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

  path: /

  hosts:

    - elk.prod.test.local





весь файл будет иметь вид:




 cat kibana/values.yaml




---

elasticsearchHosts: "https://elasticsearch-master:9200"



replicas: 1



# Extra environment variables to append to this nodeGroup

# This will be appended to the current 'env:' key. You can use any of the kubernetes env

# syntax here

extraEnvs:

  - name: 'ELASTICSEARCH_USERNAME'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username

  - name: 'ELASTICSEARCH_PASSWORD'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password



#  - name: "NODE_OPTIONS"

#    value: "--max-old-space-size=1800"

#  - name: MY_ENVIRONMENT_VAR

#    value: the_value_goes_here



# Allows you to load environment variables from kubernetes secret or config map

envFrom: []

# - secretRef:

#     name: env-secret

# - configMapRef:

#     name: config-map



# A list of secrets and their paths to mount inside the pod

# This is useful for mounting certificates for security and for mounting

# the X-Pack license

secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/kibana/config/certs



#  - name: kibana-keystore

#    secretName: kibana-keystore

#    path: /usr/share/kibana/data/kibana.keystore

#    subPath: kibana.keystore # optional



image: "docker.elastic.co/kibana/kibana"

imageTag: "7.9.4-SNAPSHOT"

imagePullPolicy: "IfNotPresent"



# additionals labels

labels: {}



podAnnotations: {}

  # iam.amazonaws.com/role: es-cluster



resources:

  requests:

    cpu: "1000m"

    memory: "2Gi"

  limits:

    cpu: "1000m"

    memory: "2Gi"



protocol: https



serverHost: "0.0.0.0"



healthCheckPath: "/app/kibana"



# Allows you to add any config files in /usr/share/kibana/config/

# such as kibana.yml

kibanaConfig:

   kibana.yml: |

    server.ssl:

      enabled: true

      key: /usr/share/kibana/config/certs/mysite-without-pass.key

      certificate: /usr/share/kibana/config/certs/mysite.crt

    xpack.security.encryptionKey: "something_at_least_32_characters"

    elasticsearch.ssl:

      certificateAuthorities: /usr/share/kibana/config/certs/mysite.crt

      verificationMode: certificate



#   kibana.yml: |

#     key:

#       nestedkey: value



# If Pod Security Policy in use it may be required to specify security context as well as service account



podSecurityContext:

  fsGroup: 1000



securityContext:

  capabilities:

    drop:

    - ALL

  # readOnlyRootFilesystem: true

  runAsNonRoot: true

  runAsUser: 1000



serviceAccount: ""



# This is the PriorityClass settings as defined in

# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass

priorityClassName: ""



httpPort: 5601



extraContainers: ""

# - name: dummy-init

#   image: busybox

#   command: ['echo', 'hey']



extraInitContainers: ""

# - name: dummy-init

#   image: busybox

#   command: ['echo', 'hey']



updateStrategy:

  type: "Recreate"



service:

  type: ClusterIP

  loadBalancerIP: ""

  port: 5601

  nodePort: ""

  labels: {}

  annotations: {}

    # cloud.google.com/load-balancer-type: "Internal"

    # service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0

    # service.beta.kubernetes.io/azure-load-balancer-internal: "true"

    # service.beta.kubernetes.io/openstack-internal-load-balancer: "true"

    # service.beta.kubernetes.io/cce-load-balancer-internal-vpc: "true"

  loadBalancerSourceRanges: []

    # 0.0.0.0/0



ingress:

  enabled: true

  annotations:

    # kubernetes.io/ingress.class: nginx

    # kubernetes.io/tls-acme: "true"

     nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

  path: /

  hosts:

    - elk.prod.test.local

  tls: []

  #  - secretName: chart-example-tls

  #    hosts:

  #      - chart-example.local



readinessProbe:

  failureThreshold: 3

  initialDelaySeconds: 10

  periodSeconds: 10

  successThreshold: 3

  timeoutSeconds: 5



imagePullSecrets: []

nodeSelector: {}

tolerations: []

affinity: {}



nameOverride: ""

fullnameOverride: ""



lifecycle: {}

  # preStop:

  #   exec:

  #     command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]

  # postStart:

  #   exec:

  #     command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]



# Deprecated - use only with versions < 6.6

elasticsearchURL: "" # "http://elasticsearch-master:9200"





==========================================================================================




перейдём к настройке logstash




logstash/values.yaml




включаем xpack




logstashConfig:

  logstash.yml: |

    http.host: 0.0.0.0

    xpack.monitoring.enabled: true

    xpack.monitoring.elasticsearch.username: '${ELASTICSEARCH_USERNAME}'

    xpack.monitoring.elasticsearch.password: '${ELASTICSEARCH_PASSWORD}'

    xpack.monitoring.elasticsearch.hosts: [ "https://elasticsearch-master:9200" ]

    xpack.monitoring.elasticsearch.ssl.certificate_authority: /usr/share/logstash/config/certs/mysite.crt





также настраиваем  приём на порт 5045 так как 5044 поднимается автоматически и если оставить input с 5044 то будет конфликт портов, настраиваем также фильтр по неймспейсу если приходят логи из неймспейса terminal-soft мы к ним добавляем тэг, убираем пару лишних  полей и отправляем в ластик, указывая имя индекса имя ilm политики  -которая должна быть предварительно создана.




logstashPipeline:

  logstash.conf: |

    input {

       exec { command => "uptime" interval => 30 }

       beats {

       port => 5045

       }

    }



    filter {

        if [kubernetes][namespace] == "terminal-soft" {

         mutate {

          add_tag => "tag-terminal-soft"

          remove_field => ["[agent][name]","[agent][version]","[host][mac]","[host][ip]"] }

        }

       }



    output {

      if "tag-terminal-soft" in [tags] {

        elasticsearch {

            hosts => [ "https://elasticsearch-master:9200" ]

            cacert => "/usr/share/logstash/config/certs/mysite.crt"

            manage_template => false

            index => "terminal-soft-%{+YYYY.MM.dd}"

            ilm_rollover_alias => "terminal-soft"

            ilm_policy => "terminal-soft"

            user => '${ELASTICSEARCH_USERNAME}'

            password => '${ELASTICSEARCH_PASSWORD}'

        }

      }

    }





также указываем логин пароль с которым будем подключаться к elasticearch




extraEnvs:

  - name: 'ELASTICSEARCH_USERNAME'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username

  - name: 'ELASTICSEARCH_PASSWORD'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password





также




secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/logstash/config/certs





также




antiAffinity: «soft»




также раскоментим сервис и укажем в нём порт куда всё пересылать 5045 (его мы задали выше в input)




service:

  annotations: {}

  type: ClusterIP

  ports:

    - name: beats

      port: 5044

      protocol: TCP

      targetPort: 5045





весь файл имеет вид:




[root@prod-vsrv-kubemaster1 helm-charts]# cat logstash/values.yaml




---

replicas: 1



# Allows you to add any config files in /usr/share/logstash/config/

# such as logstash.yml and log4j2.properties

#

# Note that when overriding logstash.yml, `http.host: 0.0.0.0` should always be included

# to make default probes work.

logstashConfig:

  logstash.yml: |

    http.host: 0.0.0.0

    xpack.monitoring.enabled: true

    xpack.monitoring.elasticsearch.username: '${ELASTICSEARCH_USERNAME}'

    xpack.monitoring.elasticsearch.password: '${ELASTICSEARCH_PASSWORD}'

    xpack.monitoring.elasticsearch.hosts: [ "https://elasticsearch-master:9200" ]

    xpack.monitoring.elasticsearch.ssl.certificate_authority: /usr/share/logstash/config/certs/mysite.crt



#    key:

#      nestedkey: value

#  log4j2.properties: |

#    key = value



# Allows you to add any pipeline files in /usr/share/logstash/pipeline/

### ***warn*** there is a hardcoded logstash.conf in the image, override it first

logstashPipeline:

  logstash.conf: |

    input {

       exec { command => "uptime" interval => 30 }

       beats {

       port => 5045

       }

    }



    filter {

        if [kubernetes][namespace] == "terminal-soft" {

         mutate {

          add_tag => "tag-terminal-soft"

          remove_field => ["[agent][name]","[agent][version]","[host][mac]","[host][ip]"] }

        }

       }



    output {

      if "tag-terminal-soft" in [tags] {

        elasticsearch {

            hosts => [ "https://elasticsearch-master:9200" ]

            cacert => "/usr/share/logstash/config/certs/mysite.crt"

            manage_template => false

            index => "terminal-soft-%{+YYYY.MM.dd}"

            ilm_rollover_alias => "terminal-soft"

            ilm_policy => "terminal-soft"

            user => '${ELASTICSEARCH_USERNAME}'

            password => '${ELASTICSEARCH_PASSWORD}'

        }

      }

    }





#    input {

#      exec {

#        command => "uptime"

#        interval => 30

#      }

#    }

#    output { stdout { } }



# Extra environment variables to append to this nodeGroup

# This will be appended to the current 'env:' key. You can use any of the kubernetes env

# syntax here

extraEnvs:

  - name: 'ELASTICSEARCH_USERNAME'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: username

  - name: 'ELASTICSEARCH_PASSWORD'

    valueFrom:

      secretKeyRef:

        name: secret-basic-auth

        key: password



#  - name: MY_ENVIRONMENT_VAR

#    value: the_value_goes_here



# Allows you to load environment variables from kubernetes secret or config map

envFrom: []

# - secretRef:

#     name: env-secret

# - configMapRef:

#     name: config-map



# Add sensitive data to k8s secrets

secrets: []

#  - name: "env"

#    value:

#      ELASTICSEARCH_PASSWORD: "LS1CRUdJTiBgUFJJVkFURSB"

#      api_key: ui2CsdUadTiBasRJRkl9tvNnw

#  - name: "tls"

#    value:

#      ca.crt: |

#        LS0tLS1CRUdJT0K

#        LS0tLS1CRUdJT0K

#        LS0tLS1CRUdJT0K

#        LS0tLS1CRUdJT0K

#      cert.crt: "LS0tLS1CRUdJTiBlRJRklDQVRFLS0tLS0K"

#      cert.key.filepath: "secrets.crt" # The path to file should be relative to the `values.yaml` file.





# A list of secrets and their paths to mount inside the pod

secretMounts:

  - name: elastic-certificates

    secretName: elastic-certificates

    path: /usr/share/logstash/config/certs





image: "docker.elastic.co/logstash/logstash"

imageTag: "7.9.4-SNAPSHOT"

imagePullPolicy: "IfNotPresent"

imagePullSecrets: []



podAnnotations: {}



# additionals labels

labels: {}



logstashJavaOpts: "-Xmx1g -Xms1g"



resources:

  requests:

    cpu: "100m"

    memory: "1536Mi"

  limits:

    cpu: "1000m"

    memory: "1536Mi"



volumeClaimTemplate:

  accessModes: [ "ReadWriteOnce" ]

  resources:

    requests:

      storage: 1Gi



rbac:

  create: false

  serviceAccountAnnotations: {}

  serviceAccountName: ""



podSecurityPolicy:

  create: false

  name: ""

  spec:

    privileged: true

    fsGroup:

      rule: RunAsAny

    runAsUser:

      rule: RunAsAny

    seLinux:

      rule: RunAsAny

    supplementalGroups:

      rule: RunAsAny

    volumes:

      - secret

      - configMap

      - persistentVolumeClaim



persistence:

  enabled: false

  annotations: {}



extraVolumes: ""

  # - name: extras

  #   emptyDir: {}



extraVolumeMounts: ""

  # - name: extras

  #   mountPath: /usr/share/extras

  #   readOnly: true



extraContainers: ""

  # - name: do-something

  #   image: busybox

  #   command: ['do', 'something']



extraInitContainers: ""

  # - name: do-something

  #   image: busybox

  #   command: ['do', 'something']



# This is the PriorityClass settings as defined in

# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass

priorityClassName: ""



# By default this will make sure two pods don't end up on the same node

# Changing this to a region would allow you to spread pods across regions

antiAffinityTopologyKey: "kubernetes.io/hostname"



# Hard means that by default pods will only be scheduled if there are enough nodes for them

# and that they will never end up on the same node. Setting this to soft will do this "best effort"

antiAffinity: "soft"



# This is the node affinity settings as defined in

# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature

nodeAffinity: {}



# The default is to deploy all pods serially. By setting this to parallel all pods are started at

# the same time when bootstrapping the cluster

podManagementPolicy: "Parallel"



httpPort: 9600



# Custom ports to add to logstash

extraPorts: []

#  - name: beats

#    containerPort: 5044



updateStrategy: RollingUpdate



# This is the max unavailable setting for the pod disruption budget

# The default value of 1 will make sure that kubernetes won't allow more than 1

# of your pods to be unavailable during maintenance

maxUnavailable: 1



podSecurityContext:

  fsGroup: 1000

  runAsUser: 1000



securityContext:

  capabilities:

    drop:

    - ALL

  # readOnlyRootFilesystem: true

  runAsNonRoot: true

  runAsUser: 1000



# How long to wait for logstash to stop gracefully

terminationGracePeriod: 120



# Probes

# Default probes are using `httpGet` which requires that `http.host: 0.0.0.0` is part of

# `logstash.yml`. If needed probes can be disabled or overrided using the following syntaxes:

#

# disable livenessProbe

# livenessProbe: null

#

# replace httpGet default readinessProbe by some exec probe

# readinessProbe:

#   httpGet: null

#   exec:

#     command:

#       - curl

#      - localhost:9600



livenessProbe:

  httpGet:

    path: /

    port: http

  initialDelaySeconds: 300

  periodSeconds: 10

  timeoutSeconds: 5

  failureThreshold: 3

  successThreshold: 1



readinessProbe:

  httpGet:

    path: /

    port: http

  initialDelaySeconds: 60

  periodSeconds: 10

  timeoutSeconds: 5

  failureThreshold: 3

  successThreshold: 3



## Use an alternate scheduler.

## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/

##

schedulerName: ""



nodeSelector: {}

tolerations: []



nameOverride: ""

fullnameOverride: ""



lifecycle: {}

  # preStop:

  #   exec:

  #     command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]

  # postStart:

  #   exec:

  #     command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]



service:

  annotations: {}

  type: ClusterIP

  ports:

    - name: beats

      port: 5044

      protocol: TCP

      targetPort: 5045

#    - name: http

#      port: 8080

#      protocol: TCP

#      targetPort: 8080



ingress:

  enabled: false

#  annotations: {}

#  hosts:

#    - host: logstash.local

#      paths:

#        - path: /logs

#          servicePort: 8080

#  tls: []





===========================================================================================




Перейдём к настройке filebeat




filebeat/values.yaml




filebeatConfig:

  filebeat.yml: |

    filebeat.inputs:

    - type: container

      paths:

        - /var/log/containers/*.log

      processors:

      - add_kubernetes_metadata:

          host: ${NODE_NAME}

          matchers:

          - logs_path:

              logs_path: "/var/log/containers/"



    output.logstash:

      enabled: true

      hosts: ["logstash-logstash:5044"]





полностью файл будет выглядеть следующим образом:




[root@prod-vsrv-kubemaster1 helm-charts]# cat filebeat/values.yaml




---

# Allows you to add any config files in /usr/share/filebeat

# such as filebeat.yml

filebeatConfig:

  filebeat.yml: |

    filebeat.inputs:

    - type: container

      paths:

        - /var/log/containers/*.log

      processors:

      - add_kubernetes_metadata:

          host: ${NODE_NAME}

          matchers:

          - logs_path:

              logs_path: "/var/log/containers/"



    output.logstash:

      enabled: true

      hosts: ["logstash-logstash:5044"]



# Extra environment variables to append to the DaemonSet pod spec.

# This will be appended to the current 'env:' key. You can use any of the kubernetes env

# syntax here

extraEnvs: []

#  - name: MY_ENVIRONMENT_VAR

#    value: the_value_goes_here



extraVolumeMounts: []

  # - name: extras

  #   mountPath: /usr/share/extras

  #   readOnly: true



extraVolumes: []

  # - name: extras

  #   emptyDir: {}



extraContainers: ""

# - name: dummy-init

#   image: busybox

#   command: ['echo', 'hey']



extraInitContainers: []

# - name: dummy-init

#   image: busybox

#   command: ['echo', 'hey']



envFrom: []

# - configMapRef:

#     name: configmap-name



# Root directory where Filebeat will write data to in order to persist registry data across pod restarts (file position and other metadata).

hostPathRoot: /var/lib

hostNetworking: false

dnsConfig: {}

# options:

#   - name: ndots

#     value: "2"

image: "docker.elastic.co/beats/filebeat"

imageTag: "7.9.4-SNAPSHOT"

imagePullPolicy: "IfNotPresent"

imagePullSecrets: []



livenessProbe:

  exec:

    command:

      - sh

      - -c

      - |

        #!/usr/bin/env bash -e

        curl --fail 127.0.0.1:5066

  failureThreshold: 3

  initialDelaySeconds: 10

  periodSeconds: 10

  timeoutSeconds: 5



readinessProbe:

  exec:

    command:

      - sh

      - -c

      - |

        #!/usr/bin/env bash -e

        filebeat test output

  failureThreshold: 3

  initialDelaySeconds: 10

  periodSeconds: 10

  timeoutSeconds: 5



# Whether this chart should self-manage its service account, role, and associated role binding.

managedServiceAccount: true



# additionals labels

labels: {}



podAnnotations: {}

  # iam.amazonaws.com/role: es-cluster



# Various pod security context settings. Bear in mind that many of these have an impact on Filebeat functioning properly.

#

# - User that the container will execute as. Typically necessary to run as root (0) in order to properly collect host container logs.

# - Whether to execute the Filebeat containers as privileged containers. Typically not necessarily unless running within environments such as OpenShift.

podSecurityContext:

  runAsUser: 0

  privileged: false



resources:

  requests:

    cpu: "100m"

    memory: "100Mi"

  limits:

    cpu: "1000m"

    memory: "200Mi"



# Custom service account override that the pod will use

serviceAccount: ""



# Annotations to add to the ServiceAccount that is created if the serviceAccount value isn't set.

serviceAccountAnnotations: {}

  # eks.amazonaws.com/role-arn: arn:aws:iam::111111111111:role/k8s.clustername.namespace.serviceaccount



# A list of secrets and their paths to mount inside the pod

# This is useful for mounting certificates for security other sensitive values

secretMounts: []

#  - name: filebeat-certificates

#    secretName: filebeat-certificates

#    path: /usr/share/filebeat/certs



# How long to wait for Filebeat pods to stop gracefully

terminationGracePeriod: 30



tolerations: []



nodeSelector: {}



affinity: {}



# This is the PriorityClass settings as defined in

# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass

priorityClassName: ""



updateStrategy: RollingUpdate



# Override various naming aspects of this chart

# Only edit these if you know what you're doing

nameOverride: ""

fullnameOverride: ""





==========================================================================================




Filebeat multiline.




Появилась задача: логи с контейнера в котором джава приложение приходят построчно, т.е. каждая строка это отдельный месседж при отображении в kibana, это не удобно читать, чтоб их объеденить в одно сообщение, добавим в filebeat фильтр




multiline.pattern: ‘^([0-9]{4}-[0-9]{2}-[0-9]{2})’
multiline.negate: true
multiline.match: after




в общем виде:




vim filebeat/values.yaml




---

# Allows you to add any config files in /usr/share/filebeat

# such as filebeat.yml

filebeatConfig:

  filebeat.yml: |

    filebeat.inputs:

    - type: container

      paths:

        - /var/log/containers/*.log

      processors:

      - add_kubernetes_metadata:

          host: ${NODE_NAME}

          matchers:

          - logs_path:

              logs_path: "/var/log/containers/"

      multiline.pattern: '^([0-9]{4}-[0-9]{2}-[0-9]{2})'

      multiline.negate: true

      multiline.match: after



    output.logstash:

      enabled: true

      hosts: ["logstash-logstash:5044"]





и обновляем наш чарт:
helm upgrade —install filebeat -n elk —values filebeat/values.yaml filebeat/




всё теперь логи будут формироваться относительно даты в самом начале сообщения.




===========================================================================================




Дополнение для работы snapshot




Создаём PV который дальше будем подкидывать в template elasticsearch  (напоминаю что у меня nfs-provisioner)
cat pvc-snapshot.yml




apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: elasticsearch-snapshot-dir

  namespace: elk

  labels:

   app: elasticsearch-snapshot

spec:

  storageClassName: nfs-storageclass

  accessModes:

    - ReadWriteMany

  resources:

    requests:

      storage: 5Gi





запускаем




kubectl apply -f pvc-snapshot.yml




смотрим имя созданного PV




kubectl get pv -n elk | grep elk

pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef   5Gi        RWX            Delete           Bound    elk/elasticsearch-snapshot-dir                                                                                              nfs-storageclass              21h





вот наше имя




pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef




теперь правим temaplate




vim elasticsearch/templates/statefulset.yaml




      volumes:

        - name: "pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef"

          persistentVolumeClaim:

            claimName: elasticsearch-snapshot-dir





И в этом же файле в ещё одном месте:




        volumeMounts:

          - name: pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef

            mountPath: "/snapshot"





на всякий случай файл имеет вид:




cat elasticsearch/templates/statefulset.yaml




---

apiVersion: {{ template "elasticsearch.statefulset.apiVersion" . }}

kind: StatefulSet

metadata:

  name: {{ template "elasticsearch.uname" . }}

  labels:

    heritage: {{ .Release.Service | quote }}

    release: {{ .Release.Name | quote }}

    chart: "{{ .Chart.Name }}"

    app: "{{ template "elasticsearch.uname" . }}"

    {{- range $key, $value := .Values.labels }}

    {{ $key }}: {{ $value | quote }}

    {{- end }}

  annotations:

    esMajorVersion: "{{ include "elasticsearch.esMajorVersion" . }}"

spec:

  serviceName: {{ template "elasticsearch.uname" . }}-headless

  selector:

    matchLabels:

      app: "{{ template "elasticsearch.uname" . }}"

  replicas: {{ .Values.replicas }}

  podManagementPolicy: {{ .Values.podManagementPolicy }}

  updateStrategy:

    type: {{ .Values.updateStrategy }}

  {{- if .Values.persistence.enabled }}

  volumeClaimTemplates:

  - metadata:

      name: {{ template "elasticsearch.uname" . }}

    {{- if .Values.persistence.labels.enabled }}

      labels:

        heritage: {{ .Release.Service | quote }}

        release: {{ .Release.Name | quote }}

        chart: "{{ .Chart.Name }}"

        app: "{{ template "elasticsearch.uname" . }}"

        {{- range $key, $value := .Values.labels }}

        {{ $key }}: {{ $value | quote }}

        {{- end }}

    {{- end }}

    {{- with .Values.persistence.annotations  }}

      annotations:

{{ toYaml . | indent 8 }}

    {{- end }}

    spec:

{{ toYaml .Values.volumeClaimTemplate | indent 6 }}

  {{- end }}

  template:

    metadata:

      name: "{{ template "elasticsearch.uname" . }}"

      labels:

        heritage: {{ .Release.Service | quote }}

        release: {{ .Release.Name | quote }}

        chart: "{{ .Chart.Name }}"

        app: "{{ template "elasticsearch.uname" . }}"

        {{- range $key, $value := .Values.labels }}

        {{ $key }}: {{ $value | quote }}

        {{- end }}

      annotations:

        {{- range $key, $value := .Values.podAnnotations }}

        {{ $key }}: {{ $value | quote }}

        {{- end }}

        {{/* This forces a restart if the configmap has changed */}}

        {{- if .Values.esConfig }}

        configchecksum: {{ include (print .Template.BasePath "/configmap.yaml") . | sha256sum | trunc 63 }}

        {{- end }}

    spec:

      {{- if .Values.schedulerName }}

      schedulerName: "{{ .Values.schedulerName }}"

      {{- end }}

      securityContext:

{{ toYaml .Values.podSecurityContext | indent 8 }}

        {{- if .Values.fsGroup }}

        fsGroup: {{ .Values.fsGroup }} # Deprecated value, please use .Values.podSecurityContext.fsGroup

        {{- end }}

      {{- if .Values.rbac.create }}

      serviceAccountName: "{{ template "elasticsearch.uname" . }}"

      {{- else if not (eq .Values.rbac.serviceAccountName "") }}

      serviceAccountName: {{ .Values.rbac.serviceAccountName | quote }}

      {{- end }}

      {{- with .Values.tolerations }}

      tolerations:

{{ toYaml . | indent 6 }}

      {{- end }}

      {{- with .Values.nodeSelector }}

      nodeSelector:

{{ toYaml . | indent 8 }}

      {{- end }}

      {{- if or (eq .Values.antiAffinity "hard") (eq .Values.antiAffinity "soft") .Values.nodeAffinity }}

      {{- if .Values.priorityClassName }}

      priorityClassName: {{ .Values.priorityClassName }}

      {{- end }}

      affinity:

      {{- end }}

      {{- if eq .Values.antiAffinity "hard" }}

        podAntiAffinity:

          requiredDuringSchedulingIgnoredDuringExecution:

          - labelSelector:

              matchExpressions:

              - key: app

                operator: In

                values:

                - "{{ template "elasticsearch.uname" .}}"

            topologyKey: {{ .Values.antiAffinityTopologyKey }}

      {{- else if eq .Values.antiAffinity "soft" }}

        podAntiAffinity:

          preferredDuringSchedulingIgnoredDuringExecution:

          - weight: 1

            podAffinityTerm:

              topologyKey: {{ .Values.antiAffinityTopologyKey }}

              labelSelector:

                matchExpressions:

                - key: app

                  operator: In

                  values:

                  - "{{ template "elasticsearch.uname" . }}"

      {{- end }}

      {{- with .Values.nodeAffinity }}

        nodeAffinity:

{{ toYaml . | indent 10 }}

      {{- end }}

      terminationGracePeriodSeconds: {{ .Values.terminationGracePeriod }}

      volumes:

        - name: "pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef"

          persistentVolumeClaim:

            claimName: elasticsearch-snapshot-dir



        {{- range .Values.secretMounts }}

        - name: {{ .name }}

          secret:

            secretName: {{ .secretName }}

            {{- if .defaultMode }}

            defaultMode: {{ .defaultMode }}

            {{- end }}

        {{- end }}

        {{- if .Values.esConfig }}

        - name: esconfig

          configMap:

            name: {{ template "elasticsearch.uname" . }}-config

        {{- end }}

{{- if .Values.keystore }}

        - name: keystore

          emptyDir: {}

        {{- range .Values.keystore }}

        - name: keystore-{{ .secretName }}

          secret: {{ toYaml . | nindent 12 }}

        {{- end }}

{{ end }}

      {{- if .Values.extraVolumes }}

      # Currently some extra blocks accept strings

      # to continue with backwards compatibility this is being kept

      # whilst also allowing for yaml to be specified too.

      {{- if eq "string" (printf "%T" .Values.extraVolumes) }}

{{ tpl .Values.extraVolumes . | indent 8 }}

      {{- else }}

{{ toYaml .Values.extraVolumes | indent 8 }}

      {{- end }}

      {{- end }}

      {{- if .Values.imagePullSecrets }}

      imagePullSecrets:

{{ toYaml .Values.imagePullSecrets | indent 8 }}

      {{- end }}

      {{- if semverCompare ">1.13-0" .Capabilities.KubeVersion.GitVersion }}

      enableServiceLinks: {{ .Values.enableServiceLinks }}

      {{- end }}

      initContainers:

      {{- if .Values.sysctlInitContainer.enabled }}

      - name: configure-sysctl

        securityContext:

          runAsUser: 0

          privileged: true

        image: "{{ .Values.image }}:{{ .Values.imageTag }}"

        imagePullPolicy: "{{ .Values.imagePullPolicy }}"

        command: ["sysctl", "-w", "vm.max_map_count={{ .Values.sysctlVmMaxMapCount}}"]

        resources:

{{ toYaml .Values.initResources | indent 10 }}

      {{- end }}

{{ if .Values.keystore }}

      - name: keystore

        image: "{{ .Values.image }}:{{ .Values.imageTag }}"

        imagePullPolicy: "{{ .Values.imagePullPolicy }}"

        command:

        - sh

        - -c

        - |

          #!/usr/bin/env bash

          set -euo pipefail



          elasticsearch-keystore create



          for i in /tmp/keystoreSecrets/*/*; do

            key=$(basename $i)

            echo "Adding file $i to keystore key $key"

            elasticsearch-keystore add-file "$key" "$i"

          done



          # Add the bootstrap password since otherwise the Elasticsearch entrypoint tries to do this on startup

          if [ ! -z ${ELASTIC_PASSWORD+x} ]; then

            echo 'Adding env $ELASTIC_PASSWORD to keystore as key bootstrap.password'

            echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x bootstrap.password

          fi



          cp -a /usr/share/elasticsearch/config/elasticsearch.keystore /tmp/keystore/

        env: {{ toYaml .Values.extraEnvs | nindent 10 }}

        envFrom: {{ toYaml .Values.envFrom | nindent 10 }}

        resources: {{ toYaml .Values.initResources | nindent 10 }}

        volumeMounts:

          - name: keystore

            mountPath: /tmp/keystore

          {{- range .Values.keystore }}

          - name: keystore-{{ .secretName }}

            mountPath: /tmp/keystoreSecrets/{{ .secretName }}

          {{- end }}

{{ end }}

      {{- if .Values.extraInitContainers }}

      # Currently some extra blocks accept strings

      # to continue with backwards compatibility this is being kept

      # whilst also allowing for yaml to be specified too.

      {{- if eq "string" (printf "%T" .Values.extraInitContainers) }}

{{ tpl .Values.extraInitContainers . | indent 6 }}

      {{- else }}

{{ toYaml .Values.extraInitContainers | indent 6 }}

      {{- end }}

      {{- end }}

      containers:

      - name: "{{ template "elasticsearch.name" . }}"

        securityContext:

{{ toYaml .Values.securityContext | indent 10 }}

        image: "{{ .Values.image }}:{{ .Values.imageTag }}"

        imagePullPolicy: "{{ .Values.imagePullPolicy }}"

        readinessProbe:

          exec:

            command:

              - sh

              - -c

              - |

                #!/usr/bin/env bash -e

                # If the node is starting up wait for the cluster to be ready (request params: "{{ .Values.clusterHealthCheckParams }}" )

                # Once it has started only check that the node itself is responding

                START_FILE=/tmp/.es_start_file



                # Disable nss cache to avoid filling dentry cache when calling curl

                # This is required with Elasticsearch Docker using nss < 3.52

                export NSS_SDB_USE_CACHE=no



                http () {

                  local path="${1}"

                  local args="${2}"

                  set -- -XGET -s



                  if [ "$args" != "" ]; then

                    set -- "$@" $args

                  fi



                  if [ -n "${ELASTIC_USERNAME}" ] && [ -n "${ELASTIC_PASSWORD}" ]; then

                    set -- "$@" -u "${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}"

                  fi



                  curl --output /dev/null -k "$@" "{{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}${path}"

                }



                if [ -f "${START_FILE}" ]; then

                  echo 'Elasticsearch is already running, lets check the node is healthy'

                  HTTP_CODE=$(http "/" "-w %{http_code}")

                  RC=$?

                  if [[ ${RC} -ne 0 ]]; then

                    echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' ${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with RC ${RC}"

                    exit ${RC}

                  fi

                  # ready if HTTP code 200, 503 is tolerable if ES version is 6.x

                  if [[ ${HTTP_CODE} == "200" ]]; then

                    exit 0

                  elif [[ ${HTTP_CODE} == "503" && "{{ include "elasticsearch.esMajorVersion" . }}" == "6" ]]; then

                    exit 0

                  else

                    echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' ${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with HTTP code ${HTTP_CODE}"

                    exit 1

                  fi



                else

                  echo 'Waiting for elasticsearch cluster to become ready (request params: "{{ .Values.clusterHealthCheckParams }}" )'

                  if http "/_cluster/health?{{ .Values.clusterHealthCheckParams }}" "--fail" ; then

                    touch ${START_FILE}

                    exit 0

                  else

                    echo 'Cluster is not yet ready (request params: "{{ .Values.clusterHealthCheckParams }}" )'

                    exit 1

                  fi

                fi

{{ toYaml .Values.readinessProbe | indent 10 }}

        ports:

        - name: http

          containerPort: {{ .Values.httpPort }}

        - name: transport

          containerPort: {{ .Values.transportPort }}

        resources:

{{ toYaml .Values.resources | indent 10 }}

        env:

          - name: node.name

            valueFrom:

              fieldRef:

                fieldPath: metadata.name

          {{- if eq .Values.roles.master "true" }}

          {{- if ge (int (include "elasticsearch.esMajorVersion" .)) 7 }}

          - name: cluster.initial_master_nodes

            value: "{{ template "elasticsearch.endpoints" . }}"

          {{- else }}

          - name: discovery.zen.minimum_master_nodes

            value: "{{ .Values.minimumMasterNodes }}"

          {{- end }}

          {{- end }}

          {{- if lt (int (include "elasticsearch.esMajorVersion" .)) 7 }}

          - name: discovery.zen.ping.unicast.hosts

            value: "{{ template "elasticsearch.masterService" . }}-headless"

          {{- else }}

          - name: discovery.seed_hosts

            value: "{{ template "elasticsearch.masterService" . }}-headless"

          {{- end }}

          - name: cluster.name

            value: "{{ .Values.clusterName }}"

          - name: network.host

            value: "{{ .Values.networkHost }}"

          - name: ES_JAVA_OPTS

            value: "{{ .Values.esJavaOpts }}"

          {{- range $role, $enabled := .Values.roles }}

          - name: node.{{ $role }}

            value: "{{ $enabled }}"

          {{- end }}

{{- if .Values.extraEnvs }}

{{ toYaml .Values.extraEnvs | indent 10 }}

{{- end }}

{{- if .Values.envFrom }}

        envFrom:

{{ toYaml .Values.envFrom | indent 10 }}

{{- end }}

        volumeMounts:

          - name: pvc-30e262ad-770c-45ad-8e3c-28d70a6400ef

            mountPath: "/snapshot"

          {{- if .Values.persistence.enabled }}

          - name: "{{ template "elasticsearch.uname" . }}"

            mountPath: /usr/share/elasticsearch/data

          {{- end }}

{{ if .Values.keystore }}

          - name: keystore

            mountPath: /usr/share/elasticsearch/config/elasticsearch.keystore

            subPath: elasticsearch.keystore

{{ end }}

          {{- range .Values.secretMounts }}

          - name: {{ .name }}

            mountPath: {{ .path }}

            {{- if .subPath }}

            subPath: {{ .subPath }}

            {{- end }}

          {{- end }}

          {{- range $path, $config := .Values.esConfig }}

          - name: esconfig

            mountPath: /usr/share/elasticsearch/config/{{ $path }}

            subPath: {{ $path }}

          {{- end -}}

        {{- if .Values.extraVolumeMounts }}

        # Currently some extra blocks accept strings

        # to continue with backwards compatibility this is being kept

        # whilst also allowing for yaml to be specified too.

        {{- if eq "string" (printf "%T" .Values.extraVolumeMounts) }}

{{ tpl .Values.extraVolumeMounts . | indent 10 }}

        {{- else }}

{{ toYaml .Values.extraVolumeMounts | indent 10 }}

        {{- end }}

        {{- end }}

      {{- if .Values.masterTerminationFix }}

      {{- if eq .Values.roles.master "true" }}

      # This sidecar will prevent slow master re-election

      # https://github.com/elastic/helm-charts/issues/63

      - name: elasticsearch-master-graceful-termination-handler

        image: "{{ .Values.image }}:{{ .Values.imageTag }}"

        imagePullPolicy: "{{ .Values.imagePullPolicy }}"

        command:

        - "sh"

        - -c

        - |

          #!/usr/bin/env bash

          set -eo pipefail



          http () {

              local path="${1}"

              if [ -n "${ELASTIC_USERNAME}" ] && [ -n "${ELASTIC_PASSWORD}" ]; then

                BASIC_AUTH="-u ${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}"

              else

                BASIC_AUTH=''

              fi

              curl -XGET -s -k --fail ${BASIC_AUTH} {{ .Values.protocol }}://{{ template "elasticsearch.masterService" . }}:{{ .Values.httpPort }}${path}

          }



          cleanup () {

            while true ; do

              local master="$(http "/_cat/master?h=node" || echo "")"

              if [[ $master == "{{ template "elasticsearch.masterService" . }}"* && $master != "${NODE_NAME}" ]]; then

                echo "This node is not master."

                break

              fi

              echo "This node is still master, waiting gracefully for it to step down"

              sleep 1

            done



            exit 0

          }



          trap cleanup SIGTERM



          sleep infinity &

          wait $!

        resources:

{{ toYaml .Values.sidecarResources | indent 10 }}

        env:

          - name: NODE_NAME

            valueFrom:

              fieldRef:

                fieldPath: metadata.name

        {{- if .Values.extraEnvs }}

{{ toYaml .Values.extraEnvs | indent 10 }}

        {{- end }}

        {{- if .Values.envFrom }}

        envFrom:

{{ toYaml .Values.envFrom | indent 10 }}

        {{- end }}

      {{- end }}

      {{- end }}

{{- if .Values.lifecycle }}

        lifecycle:

{{ toYaml .Values.lifecycle | indent 10 }}

{{- end }}

      {{- if .Values.extraContainers }}

      # Currently some extra blocks accept strings

      # to continue with backwards compatibility this is being kept

      # whilst also allowing for yaml to be specified too.

      {{- if eq "string" (printf "%T" .Values.extraContainers) }}

{{ tpl .Values.extraContainers . | indent 6 }}

      {{- else }}

{{ toYaml .Values.extraContainers | indent 6 }}

      {{- end }}

      {{- end }}





===========================================================================================




Начинаем установку:




[root@prod-vsrv-kubemaster1 helm-charts]# helm install elasticsearch -n elk —values elasticsearch/values.yaml elasticsearch/




[root@prod-vsrv-kubemaster1 helm-charts]# helm install kibana -n elk —values kibana/values.yaml kibana/




ждём когда запустится кибана и переходим по домену указанному в ingress у кибана в переменных








Сюда вбиваем наши логин и пароль из секрета созданного в самом начале, напомню elastic elastic




Переходим в
Stack Management Index Management index templates






на втором пункте нажимаем next, на третьем пишем @timespamp и выбираем date





потом нажимаем next далее:





теперь создаём политику на ролловер и удаление









Запускаем logstash и filebeat настраиваем snapshot




[root@prod-vsrv-kubemaster1 helm-charts]# helm install logstash -n elk —values logstash/values.yaml logstash/




[root@prod-vsrv-kubemaster1 helm-charts]# helm install filebeat -n elk —values filebeat/values.yaml filebeat/




теперь создаём репозиторий для снапшотов и их политику






тут указываем нашу директорию /snapshot она подключалась через отдельный вольюм






далее вводим
name terminal-soft




snapshot name:  <terminal-soft-{now/d}>    (кавычки обязательны)










Роли и пользователей можно настраивать тут:





======================================================================================================================================================




запускаем elastic в 1 instance




vim elasticsearch/values.yaml




replicas: 1

minimumMasterNodes: 1




[root@prod-vsrv-kubemaster1 helm-charts-7.9.4.elasticsearch-1-pod]# helm install elasticsearch -n elk —values elasticsearch/values.yaml elasticsearch/




[root@prod-vsrv-kubemaster1 helm-charts-7.9.4.elasticsearch-1-pod]# helm install kibana -n elk —values kibana/values.yaml kibana/




Создаём в kibana так же темплейт
Но задаём параметр number_of_replicas»: «0»





после запускаем logstash filebeat
[root@prod-vsrv-kubemaster1 helm-charts-7.9.4.elasticsearch-1-pod]# helm install logstash -n elk —values logstash/values.yaml logstash/
[root@prod-vsrv-kubemaster1 helm-charts-7.9.4.elasticsearch-1-pod]# helm install filebeat -n elk —values filebeat/values.yaml filebeat/
После этого настраиваем snapshot




====================================================================================================




Настройка доступов пользователю для индексов.




Создаём пространство:






указываем — что должно отображаться в пространстве:







Создаём роль для нашего индекса:





указываем привилегии как для кластера так и непосредственно для индекса terminal-soft





добавляем привилегии для пространства:





настраиваем доступы для пространства, — чтение/полный доступ/отключить






Создаём пользователя:





задаём пароль и созданную нами ранее роль:





Логинимся под нашим новым пользователем





Создаём index pattern







Проверяем:





как видим данные отображаются:





11.Восстановление из snapshot




Если требуется восстановить индексы из snapshot то делаем следующее:










Тут надо добавить параметр




«indexing_complete»: «true»
только в том случае если  при восстановлении возникает ошибка следующего вида:




Unable to restore snapshot




[illegal_state_exception] alias [terminal-soft] has more than one write index [terminal-soft-2021.03.04-000022,terminal-soft-2021.03.16-000034]








Поэтому когда производишь восстановление необходимо восстанавливать индекс из самого последнего снапшота.
т.е. Если нужен индекс за 10 число то снапшот смотрим где-то  за 15 число. Ну или добавляем пераметр «indexing_complete»: «true»




Источник: https://sidmid.ru/kubernetes-установка-elk-из-helm-чарта-xpack-ilm/



2023-05-03T01:28:39
Software

Kubernetes — Автоскейлинг приложений при помощи Prometheus и KEDA

Kubernetes позволяет автоматически масштабировать приложения (то есть Pod в развертывании или ReplicaSet) декларативным образом с использованием спецификации Horizontal Pod Autoscaler.




По умолчанию критерий для автоматического масштабирования — метрики использования CPU (метрики ресурсов), но можно интегрировать пользовательские метрики и метрики, предоставляемые извне.




Вместо горизонтального автомасштабирования подов, применяется Kubernetes Event Driven Autoscaling (KEDA) — оператор Kubernetes с открытым исходным кодом. Он изначально интегрируется с Horizontal Pod Autoscaler, чтобы обеспечить плавное автомасштабирование (в том числе до/от нуля) для управляемых событиями рабочих нагрузок. Код доступен на GitHub.




Краткий обзор работы системы





На схеме — краткое описание того, как все работает:




  1. Приложение предоставляет метрики количества обращений к HTTP в формате Prometheus.



  2. Prometheus настроен на сбор этих показателей.



  3. Скейлер Prometheus в KEDA настроен на автоматическое масштабирование приложения на основе количества обращений к HTTP.




Теперь подробно расскажу о каждом элементе.




KEDA и Prometheus




Prometheus — набор инструментов для мониторинга и оповещения систем с открытым исходным кодом, часть Cloud Native Computing Foundation. Собирает метрики из разных источников и сохраняет в виде данных временных рядов. Для визуализации данных можно использовать Grafana или другие инструменты визуализации, работающие с API Kubernetes.




KEDA поддерживает концепцию скейлера — он действует как мост между KEDA и внешней системой. Реализация скейлера специфична для каждой целевой системы и извлекает из нее данные. Затем KEDA использует их для управления автоматическим масштабированием.




Скейлеры поддерживают нескольких источников данных, например, Kafka, Redis, Prometheus. То есть KEDA можно применять для автоматического масштабирования развертываний Kubernetes, используя в качестве критериев метрики Prometheus.




KEDA Prometheus ScaledObject




Скейлер действует как мост между KEDA и внешней системой, из которой нужно получать метрики. ScaledObject — настраиваемый ресурс, его необходимо развернуть для синхронизации развертывания с источником событий, в данном случае с Prometheus.




ScaledObject содержит информацию о масштабировании развертывания, метаданные об источнике события (например, секреты для подключения, имя очереди), интервал опроса, период восстановления и другие данные. Он приводит к соответствующему ресурсу автомасштабирования (определение HPA) для масштабирования развертывания.




Когда объект ScaledObject удаляется, соответствующее ему определение HPA очищается.




Вот определение ScaledObject для нашего примера, в нем используется скейлер Prometheus:




apiVersion: keda.k8s.io/v1alpha1

kind: ScaledObject

metadata:

 name: prometheus-scaledobject

 namespace: default

 labels:

  deploymentName: go-prom-app

spec:

 scaleTargetRef:

   deploymentName: go-prom-app

 pollingInterval: 15

 cooldownPeriod:  30

 minReplicaCount: 1

 maxReplicaCount: 10

 triggers:

 - type: prometheus

  metadata:

    serverAddress:

http://prometheus-service.default.svc.cluster.local:9090

    metricName: access_frequency

    threshold: '3'

    query: sum(rate(http_requests[2m]))




Учтите следующие моменты:




  1. Он указывает на Deployment с именем go-prom-app.



  2. Тип триггера — Prometheus. Адрес сервера Prometheus упоминается вместе с именем метрики, пороговым значением и запросом PromQL, который будет использоваться. Запрос PromQL — sum(rate(http_requests[2m])).



  3. Согласно pollingInterval, KEDA запрашивает цель у Prometheus каждые пятнадцать секунд. Поддерживается минимум один под (minReplicaCount), а максимальное количество подов не превышает maxReplicaCount (в данном примере — десять).




Можно установить minReplicaCount равным нулю. В этом случае KEDA активирует развертывание с нуля до единицы, а затем предоставляет HPA для дальнейшего автоматического масштабирования. Возможен и обратный порядок, то есть масштабирование от единицы до нуля. В примере мы не выбрали ноль, поскольку это HTTP-сервис, а не система по запросу.




Магия внутри автомасштабирования




Пороговое значение используют в качестве триггера для масштабирования развертывания. В нашем примере запрос PromQL sum(rate (http_requests [2m])) возвращает агрегированное значение скорости HTTP-запросов (количество запросов в секунду), ее измеряют за последние две минуты.




Поскольку пороговое значение равно трем, значит, будет один под, пока значение sum(rate (http_requests [2m])) меньше трех. Если же значение возрастает, добавляется дополнительный под каждый раз, когда sum(rate (http_requests [2m])) увеличивается на три. Например, если значение от 12 до 14, то количество подов — четыре.




Теперь давайте попробуем настроить!




Установка KEDA




Вы можете развернуть KEDA несколькими способами, они перечислены в документации. Я использую монолитный YAML:




[root@kub-master-1 ~]# wget https://github.com/kedacore/keda/releases/download/v2.1.0/keda-2.1.0.yaml
[root@kub-master-1 ~]# kubectl apply -f keda-2.1.0.yaml




ну или можно установить через helm




helm repo add kedacore https://kedacore.github.io/charts
helm repo update
kubectl create namespace keda
helm install keda kedacore/keda —namespace keda




я ставил через монолитный файл.
проверим что всё поднялось:




[root@kub-master-1 ~]# kubectl get all -n keda

NAME                                          READY   STATUS    RESTARTS   AGE

pod/keda-metrics-apiserver-57cbdb849f-w7rfg   1/1     Running   0          70m

pod/keda-operator-58cb545446-5rblj            1/1     Running   0          70m



NAME                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE

service/keda-metrics-apiserver   ClusterIP   10.100.134.31   <none>        443/TCP,80/TCP   70m



NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/keda-metrics-apiserver   1/1     1            1           70m

deployment.apps/keda-operator            1/1     1            1           70m



NAME                                                DESIRED   CURRENT   READY   AGE

replicaset.apps/keda-metrics-apiserver-57cbdb849f   1         1         1       70m

replicaset.apps/keda-operator-58cb545446            1         1         1       70m





3. Пример работы




создаём namespace




kubectl create ns my-site




запускаем обычное приложение например apache:




[root@kub-master-1 ~]# cat my-site.yaml




---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-deployment-apache

  namespace: my-site

spec:

  replicas: 1

  selector:

    matchLabels:

      app: apache # по вот этому лейблу репликасет цепляет под

# тут описывается каким мокаром следует обновлять поды

  strategy:

    rollingUpdate:

      maxSurge: 1  # указывает на какое количество реплик можно увеличить

      maxUnavailable: 1 # указывает на какое количество реплик можно уменьшить

#т.е. в одно время при обновлении, будет увеличено на один (новый под) и уменьшено на один (старый под)

    type: RollingUpdate

## тут начинается описание контейнера

  template:

    metadata:

      labels:

        app: apache  # по вот этому лейблу репликасет цепляет под

    spec:

      containers:

        - image: httpd:2.4.43

          name: apache

          ports:

            - containerPort: 80

# тут начинаются проверки по доступности

          readinessProbe: # проверка готово ли приложение

            failureThreshold: 3 #указывает количество провалов при проверке

            httpGet:  # по сути дёргает курлом на 80 порт

              path: /

              port: 80

            periodSeconds: 10 #как часто должна проходить проверка (в секундах)

            successThreshold: 1 #сбрасывает счётчик неудач, т.е. при 3х проверках если 1 раз успешно прошло, то счётчик сбрасывается и всё ок

            timeoutSeconds: 1 #таймаут на выполнение пробы 1 секунда

          livenessProbe: #проверка на жизнь приложения, живо ли оно

            failureThreshold: 3

            httpGet:

              path: /

              port: 80

            periodSeconds: 10

            successThreshold: 1

            timeoutSeconds: 1

            initialDelaySeconds: 10 #означает что первую проверку надо сделать только после 10 секунд



# тут начинается описание лимитов для пода

          resources:

            requests: #количество ресурсов которые резервируются для pod на ноде

              cpu: 60m

              memory: 200Mi

            limits: #количество ресурсов которые pod может использовать(верхняя граница)

              cpu: 120m

              memory: 300Mi





[root@kub-master-1 ~]# cat my-site-service.yaml




---

apiVersion: v1

kind: Service

metadata:

  name: my-service-apache # имя сервиса

  namespace: my-site

spec:

  ports:

  - port: 80  # принимать на 80

    targetPort: 80 # отправлять на 80

  selector:

    app: apache  #отправлять на все поды с данным лейблом

  type: ClusterIP





[root@kub-master-1 ~]# cat my-site-ingress.yaml




---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: my-ingress

  namespace: my-site

spec:

  rules:

  - host: test.ru  #тут указывается наш домен

    http:

      paths:  #список путей которые хотим обслуживать(он дефолтный и все запросы будут отпаврляться на бэкенд, т.е. на сервис my-service-apache)

      - backend:

          serviceName: my-service-apache  #тут указывается наш сервис 

          servicePort: 80 #порт на котором сервис слушает

#        path: /  все запросы на корень '/' будут уходить на наш сервис





применяем:




[root@kub-master-1 ~]# kubectl apply -f my-site.yaml -f my-site-service.yaml -f my-site-ingress.yaml




проверяем:




[root@kub-worker-1 ~]# curl test.ru
<html><body><h1>It works!</h1></body></html>




[root@kub-master-1 ~]# kubectl get all -n my-site




NAME                                        READY   STATUS    RESTARTS   AGE

pod/my-deployment-apache-859486bd8c-k6bql   1/1     Running   0          20m



NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE

service/my-service-apache   ClusterIP   10.100.255.190   <none>        80/TCP    20m



NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE

deployment.apps/my-deployment-apache   1/1     1            1           20m



NAME                                              DESIRED   CURRENT   READY   AGE

replicaset.apps/my-deployment-apache-859486bd8c   1         1         1       20m





будем автоскейлить — для примера по метрике nginx nginx_ingress_controller_requests




запрос в prometheus будет следующий:




sum(irate( nginx_ingress_controller_requests{namespace=»my-site»}[3m] )) by (ingress)*10




т.е. считаем общее количество запросов в неймспейс my-site за 3 минуты




создаём keda сущность:




[root@kub-master-1 ~]# cat hpa-keda.yaml




apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

  name: prometheus-scaledobject

  namespace: my-site

spec:

  scaleTargetRef:

    name: my-deployment-apache

  minReplicaCount: 1   # Optional. Default: 0

  maxReplicaCount: 8 # Optional. Default: 100

  triggers:

  - type: prometheus

    metadata:

      serverAddress: http://prometheus-kube-prometheus-prometheus.monitoring.svc.cluster.local:9090

      metricName: nginx_ingress_controller_requests

      threshold: '100'

      query: sum(irate(nginx_ingress_controller_requests{namespace="my-site"}[3m])) by (ingress)*10




тут мы указываем в каком namespace нам запускаться:
namespace: my-site




указываем цель, т.е. наш deployment:
name: my-deployment-apache




задаём минимальное и максимальное количество реплик
minReplicaCount: 1 # значение по умолчанию: 0
maxReplicaCount: 8 # значение по умолчанию: 100




есть ещё 2 стандартные переменные отвечающие за то когда поды будут подыматься и убиваться:
pollingInterval: 30 # Optional. Default: 30 seconds
cooldownPeriod: 300 # Optional. Default: 300 seconds




указываем адрес нашего prometheus




serverAddress: http://prometheus-kube-prometheus-prometheus.monitoring.svc.cluster.local:9090
адрес идёт в виде сервис.неймспейс.svc.имя_кластера




указываем нашу метрику:
metricName: nginx_ingress_controller_requests




указываем пороговое значение при котором начнётся автоскейлинг:
threshold: ‘100’




и соответственно наш запрос в prometheus:
query:




всё можно применять:




[root@kub-master-1 ~]# kubectl apply -f hpa-keda.yaml




проверяем:




[root@kub-master-1 ~]# kubectl get horizontalpodautoscalers.autoscaling -n my-site

NAME                               REFERENCE                         TARGETS       MINPODS   MAXPODS   REPLICAS   AGE

keda-hpa-prometheus-scaledobject   Deployment/my-deployment-apache   0/100 (avg)   1         8         1          68m





[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS    RESTARTS   AGE

my-deployment-apache-859486bd8c-v59b8   1/1     Running   0          37m





а теперь накрутим запросов:




[root@kub-worker-1 ~]# for i in {1..5000}; do curl test.ru; done




проверяем:




[root@kub-master-1 ~]# kubectl get horizontalpodautoscalers.autoscaling -n my-site

NAME                               REFERENCE                         TARGETS            MINPODS   MAXPODS   REPLICAS   AGE

keda-hpa-prometheus-scaledobject   Deployment/my-deployment-apache   34858m/100 (avg)   1         8         7          71m





как видим количество запросов превысило наш лимит и стали создаваться новые поды:




[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS    RESTARTS   AGE

my-deployment-apache-859486bd8c-6885f   1/1     Running   0          49s

my-deployment-apache-859486bd8c-6mcq4   1/1     Running   0          64s

my-deployment-apache-859486bd8c-cdb6z   1/1     Running   0          64s

my-deployment-apache-859486bd8c-kpwb8   1/1     Running   0          64s

my-deployment-apache-859486bd8c-rmw8d   1/1     Running   0          49s

my-deployment-apache-859486bd8c-v59b8   1/1     Running   0          39m

my-deployment-apache-859486bd8c-xmv28   1/1     Running   0          49s





прекращаем запросы и спустя 5 минут, указанное в переменной cooldownPeriod ненужные поды будут убиты:




[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS        RESTARTS   AGE

my-deployment-apache-859486bd8c-6885f   0/1     Terminating   0          6m35s

my-deployment-apache-859486bd8c-6mcq4   1/1     Running       0          6m50s

my-deployment-apache-859486bd8c-cdb6z   0/1     Terminating   0          6m50s

my-deployment-apache-859486bd8c-kpwb8   0/1     Terminating   0          6m50s

my-deployment-apache-859486bd8c-rmw8d   0/1     Terminating   0          6m35s

my-deployment-apache-859486bd8c-v59b8   0/1     Terminating   0          44m

my-deployment-apache-859486bd8c-xmv28   0/1     Terminating   0          6m35s



[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS    RESTARTS   AGE

my-deployment-apache-859486bd8c-6mcq4   1/1     Running   0          7m48s





Источник: https://sidmid.ru/kubernetes-автоскейлинг-приложений-при-помощ/