Опишите свой опыт работы с кластерами Kubernetes и его ключевыми типами сущностей. Что такое namespace, pod и т.д.?
Как управлять stateful нагрузками?
Подсказки:
- Опишите, что такое nodes?
- Что такое namespaces и services?
- Что такое pods и контейнеры в контексте Kubernetes?
- Может ли один pod содержать более одного контейнера?
- Как добиться гарантий ресурсов для приложений реального времени? Намек - QoS
- В чём разница между ingress, endpoint и load balancer в контексте Kubernetes?
- Опишите свой опыт работы с развертыванием stateful приложений и его ключевыми проблемами
Выше ожиданий:
- Знает, какие метрики указывают на неправильно сконфигурированные лимиты памяти, когда pod-ы убиваются из-за недостатка памяти (OOMKilled), несмотря на то, что они кажутся в пределах лимита
- Знает метрики и процессы, которые важны при пиковых нагрузках на API-сервисы во время масштабирования
- Опыт работы с MetalLB и BGP: знает, что такое ECMP, как мигрировать из режима ARP в режим BGP без даунтайма
Основные концепции и компоненты
Nodes (узлы)
Nodes — это рабочие машины в кластере Kubernetes, на которых выполняются контейнерные приложения. Это физические или виртуальные машины, образующие инфраструктуру кластера.
Каждый узел содержит необходимые службы для запуска подов:
- kubelet — основной агент, который взаимодействует с control plane (управляющие сервисы кластера) и гарантирует, что контейнеры работают в подах
- container runtime (например, Docker, containerd или CRI-O) — отвечает за запуск контейнеров
- kube-proxy — поддерживает сетевые правила на узлах и выполняет перенаправление (forwarding) подключений
Узлы можно разделить на:
- Worker nodes — исполняют рабочие нагрузки приложений
- Control plane nodes — используются для компонентов control plane Kubernetes (сервер API, планировщик и т. д.)
Namespaces
Namespaces предоставляют механизм для изоляции групп ресурсов в рамках одного кластера. Они полезны, когда несколько пользователей или команд используют один кластер. Namespaces помогают:
- Разделить ресурсы кластера между несколькими пользователями (через квоты на ресурсы)
- Предоставить область для имён (ресурсы должны иметь уникальные имена в рамках пространства имён)
- Ограничить доступ и разрешения через RBAC
В Kubernetes по умолчанию существуют следующие namespaces:
- default — пространство имён по умолчанию для ресурсов
- kube-system — для системных компонентов
- kube-public — доступно для чтения всем пользователям
- kube-node-lease — хранит объекты аренды узлов
Пром кластерах Kubernetes обычно создают отдельные пространства имён для различных сред (dev, staging, prod) или команд.
Поды (pods) и контейнеры (containers)
Под — это наименьшая развертываемая единица в Kubernetes, представляющая собой единственный экземпляр работающего процесса. Ключевые характеристики:
- Поды инкапсулируют один или несколько контейнеров
- Контейнеры в одном поде разделяют одно и то же сетевое пространство (IP-адрес и пространство портов)
- Контейнеры в поде могут взаимодействовать через localhost
- Поды по своей природе являются временными — они не предназначены для восстановления после перезагрузки узла
Да, один под может содержать несколько контейнеров. Нужно только определить эти контейнеры в манифесте развертывания. Этот паттерн полезен для:
- Контейнеров-сателлитов — расширяют основной контейнер (например, средства отправки логов, агенты мониторинга)
- Инициализирующих контейнеров — выполняются перед запуском прикладных контейнеров и могут выполнять задачи настройки
- Контейнеров-посредников — проксируют сетевые подключения к/от основного контейнера
Сервисы (services)
Сервисы — это объекты Kubernetes, которые обеспечивают стабильную сеть для подов. Они:
- Предоставляют постоянный IP-адрес и имя DNS для набора подов
- Балансируют трафик между несколькими репликами подов
- Обеспечивают service discovery внутри кластера
Основные типы сервисов:
- ClusterIP — публикует сервис по внутреннему IP (по умолчанию)
- NodePort — публикует сервис по IP каждого узла на статическом порте
- LoadBalancer — публикует сервис с помощью внешнего по отношению к кластеру балансировщика нагрузки (обычно облачного провайдера)
- ExternalName — сопоставляет сервис с DNS-именем
Ingress vs. Endpoints vs. Load Balancer
Ключевое различие заключается в том, что Ingress работает на прикладном уровне (L7), а сервисы LoadBalancer обычно работают на транспортном уровне (L4). Endpoints — это просто "точки назначения", к которым сервисы направляют трафик.
-
Ingress: Объект API, который управляет внешним доступом к сервисам, обычно HTTP/HTTPS. Он предоставляет:
- Маршрутизацию на основе пути URL
- Терминацию TLS/SSL
- Виртуальное хостинг на основе имени
- Пользовательские правила для маршрутизации
-
Endpoints: Представляют фактические IP-адреса и порты подов, к которым сервис направляет трафик. Endpoints автоматически создаются и обновляются, когда поды приходят в соответствие к селектору сервиса, появляются и исчезают.
-
LoadBalancer: Тип сервиса, который создаёт внешний балансировщик нагрузки в поддерживаемых облачных средах. Он:
- Назначает внешний IP-адрес сервису
- Направляет внешний трафик соответствующим подо
- Интегрируется со службами балансировки нагрузки облачного провайдера
Управление ресурсами и QoS
Гарантии ресурсов и классы QoS
Для обеспечения гарантий ресурсов для задач в реальном времени Kubernetes предлагает классы Quality of Service (QoS), определяемые через параметры "requests" и "limits":
-
Гарантированный QoS: Установлены идентичные requests и limits на ресурсы. Эти поды имеют наивысший приоритет и не будут завершены во время конкуренции за ресурсы.
resources: requests: memory: "1Gi" cpu: "1" limits: memory: "1Gi" cpu: "1"
-
Burstable QoS: Указаны requests, которые ниже, чем limits. Эти поды имеют средний приоритет.
resources: requests: memory: "512Mi" cpu: "0.5" limits: memory: "1Gi" cpu: "1"
-
BestEffort QoS: Не указаны запросы или ограничения. Эти поды имеют самый низкий приоритет и первыми завершаются, когда ресурсов не хватает.
Для приложений с жёсткими требованиями к доступности и времени выполнения, таких как платформы для торговли в реальном времени, используют поды с гарантированным QoS с соответствующими настройками CPU и памяти, а также политики CPU Manager, установленные на "static" для выделения им ядер.
Устранение неполадок OOMKilled
Поды могут убивться из-за OutOfMemory, даже несмотря на то, что они находятся в пределах своего лимита памяти. Для этого важно посмотреть на этим метрики для расследования:
- container_memory_working_set_bytes: Фактическая память, используемая контейнером, именно это учитывает OOM-killer самого Kubernetes
- container_memory_usage_bytes: Общее использование памяти, включая кэшированные файлы, которые могут быть освобождены
- container_memory_rss: Resident Set Size — часть памяти, занимаемая процессом в ОЗУ и которую нельзя выгрузить, эта метрика используется планировщиком Linux
- container_memory_cache: Используемая память для кэша страниц
Общие причины:
- Не учтены накладные расходы среды выполнения контейнеров на память
- Приложения на базе JVM с плохо настроенными параметрами heap size
- Проблемы фрагментации памяти
- Не учтённое использование памяти ядром
- Не учитывается память sidecar-контейнеров
Производительность сервера API
Важные метрики для мониторинга, когда возрастают тайминги ответа api-server:
- apiserver_request_duration_seconds: Измеряет время выполнения запросов API
- apiserver_request_total: Общее количество запросов API, чтобы определить потенциальные узкие места
- etcd_request_duration_seconds: Длительность операций etcd, так как etcd часто является узким местом
- apiserver_current_inflight_requests: Количество текущих выполняемых запросов
- etcd_wal_fsync_duration, workqueue_depth и workqueue_adds_total: Указывают на потенциальные задержки в очереди и записи
Stateful нагрузки
Управление stateful приложениями
StatefulSets — это основной ресурс Kubernetes для управления stateful приложениями. Ключевые необходимые для них особенности:
- Стабильные, уникальные сетевые идентификаторы
- Стабильное, постоянное хранилище
- Поочередное, плавное развертывание и масштабирование
- Поочередное, автоматизированные выкатки релизов
При развертывании stateful приложений, таких как базы данных, ключевые моменты включают:
- Постоянное хранилище: Использование PersistentVolumes (PV) и PersistentVolumeClaims (PVC)
- Согласованность данных: Обеспечение надлежащей репликации и стратегий резервного копирования
- Высокая доступность: Настройка соответствующих правил affinity/anti-affinity между нодами
- Стабильность сети: Поддержание стабильных эндпоинтов для stateful компонентов
Сложности с stateful рабочими нагрузками
-
Управление хранилищем: Гарантирование стабильной работы хранилища даже при перепланировке или пересоздании подов.
-
Последовательность операций: Многие stateful приложения требуют, чтобы операции происходили в определённом порядке (например, мастер под БД должен стать доступен до реплик).
-
Сложность масштабирования: Масштабирование stateful приложений часто включает в себя сложные операции по перебалансировке данных.
-
Резервное копирование и восстановление: Реализация надлежащих стратегий резервного копирования, которые поддерживают согласованность данных.
Экспертное конфигурирование сети (большие кластеры Kubernetes и федерации)
MetalLB и BGP
MetalLB предоставляет реализацию балансировщика сетевой нагрузки для кластеров Kubernetes на baremetal. Он имеет два режима работы:
- L2 режим (ARP): Использует ARP/NDP для анонса сервисов
- Режим BGP: Использует протокол Border Gateway Protocol для анонса маршрутов до сервисов
BGP (Border Gateway Protocol) — это стандартный протокол, предназначенный для обмена информацией о маршрутизации и достижимости между автономными системами (АС) в Интернете.
ECMP (Equal-Cost Multi-Path) — это стратегия маршрутизации, при которой пересылка пакетов одному получателю может происходить по нескольким наилучшим путям с равным приоритетом маршрутизации. Это обеспечивает балансировку нагрузки между несколькими путями.
Чтобы перейти от режима ARP к режиму BGP без простоев:
- Разверните конфигурацию BGP наряду с существующей конфигурацией ARP
- Настройте BGP-спикеры и пиры
- Обновите аннотации сервиса, чтобы использовать режим BGP
- Постепенно переведите каждый сервис на BGP, добавив аннотации, специфичные для BGP
- Мониторьте трафик и убедитесь, что он правильно маршрутизируется через BGP
- После того, как все сервисы подтвердят работу в режиме BGP, удалите конфигурацию ARP