17
0
0
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
Назад

Как запускать Spark на Kubernetes в реальных проектах: инструменты, масштабирование, мониторинг

Время чтения 3 минуты
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
17
0
0
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники

Привет, я — Максим Захаренко, СЕО Облакотеки. Опираясь на этот опыт, поделюсь практическими советами по настройке, масштабированию и управлению Spark-кластерами в Kubernetes. Расскажу, какие инструменты хорошо себя показали, а где нас ждали сложности, как мы мониторим кластеры и изолируем ресурсы, а главное — о граблях, на которые наступили, и о найденных решениях.

Как запускать Spark на Kubernetes в реальных проектах: инструменты, масштабирование, мониторинг

Apache Spark давно стал стандартом фактически для обработки больших данных, а Kubernetes — для оркестрации контейнеров. Многие пытаются объединить эти технологии, однако сделать это эффективно непросто. В Облакотеке мы с партнерами уже несколько лет помогаем клиентам запускать Spark на Kubernetes в реальных проектах. Например, Spark+K8s уже применялся для рекомендательных систем, обработки телеметрии IoT, анализа логов и формирования BI-отчетов.

Инструменты для запуска Spark в Kubernetes

Ручной запуск spark-submit: самый прямой путь — использовать встроенную поддержку Kubernetes в Spark. Команда spark-submit –master k8s://… запускает драйвер и executors в виде подов в кластере. Мы начинали с этого метода. 

Плюсы: полный контроль конфигурации; можно указать нужные права доступа, volume, сетевые настройки под задачу. 

Минусы: нужно прописывать десятки параметров (образ Docker, ресурсы, namespace, секреты и т. д.); легко ошибиться. Хорошо для экспериментов, но для постоянных задач неудобно.

Helm-чарты: существуют готовые Helm-чарты для Spark (например, Bitnami), позволяющие быстро развернуть кластер Spark (мастер и воркеры) в Kubernetes. Мы применяли их, когда требовался постоянный Spark-сервис для команды аналитиков.

Helm упрощает деплой, но иногда требует доработки шаблонов под конкретные нужды (настройку логов, политик размещения и т. п.). Иначе говоря, Helm — хорошее начало, но порой без «напильника» не обойтись.

Spark Operator: мы перешли на специальный Kubernetes-оператор для Spark, который позволяет описывать Spark-приложения в виде CRD SparkApplication. Установив оператор в кластер, мы запускаем задачи простым созданием объекта SparkApplication — оператор сам создает поды драйвера, следит за их выполнением и при сбоях перезапускает приложение. 

Это сильно упростило жизнь: развертывание стало декларативным и повторяемым. В проектах с регулярными batch-расчетами оператор отлично показал себя, позволяя запускать пайплайны по расписанию (через CronJob).

Конечно, оператор привносит и свою сложность. Нужно освоить формат манифестов SparkApplication, а обновление версии Spark часто вынуждает обновлять и сам оператор. Тем не менее плюсы перевешивают: теперь мы управляем десятками Spark-заданий единообразно и с минимумом ручного труда.

Масштабирование: горизонтальное и автоматическое

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

Горизонтальное масштабирование задач: в Kubernetes каждый Spark executor — отдельный под. Можно сразу задать нужное число executors, но еще лучше включить Dynamic Allocation (динамическое выделение), чтобы Spark сам добавлял или убирал executors по ходу работы приложения. Раньше для динамического масштабирования требовался внешний Shuffle Service на узлах, поэтому сначала мы отключали эту функцию и брали запас executors (расточительно). В Spark 3.x появился shuffle tracking, убравший необходимость во внешнем сервисе. Теперь мы включаем Dynamic Allocation — Spark сам масштабируется под нагрузку и освобождает ресурсы, когда они не нужны.

Автоскейлинг кластера: если кластер не имеет свободных ресурсов для новых подов, включается автомасштабирование — в облаке добавляются новые узлы, а после завершения работы лишние узлы удаляются. Мы держим небольшой резерв мощностей, иначе крупная задача может долго ждать, пока поднимутся дополнительные VM.

Мониторинг и безопасная изоляция ресурсов

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

Логи и метрики: логи всех Spark-подов централизованно отправляются в хранилище (Elasticsearch). Метрики Spark мы экспортируем в Prometheus и отслеживаем на дашбордах Grafana: они сразу показывают, если что-то идет не так.

Безопасность и разделение сред: на одном Kubernetes-кластере могут одновременно работать разные проекты, поэтому каждый проект получает свой namespace с лимитами на ресурсы и отдельными учетными записями (RBAC), чтобы никто не съел чужие ресурсы. Если приложение превысит лимит памяти, Kubernetes просто остановит контейнер (неприятно для этой задачи, но окружающие не пострадают).

Сетевые политики: как-то строгие правила сети (NetworkPolicy) нарушили работу Spark — драйвер не смог связаться с экзекьюторами, так как межподовый трафик был запрещен. Помогло добавление исключения — разрешить обмен внутри одного namespace между подами Spark. С тех пор всегда учитываем этот момент в настройках сети, иначе Spark просто не взлетит.

Секреты доступа: пароли, ключи API и другие чувствительные данные храним в Kubernetes Secrets и монтируем в поды Spark как переменные среды или файлы.
Секреты не попадают в образы или исходный код. Однажды мы столкнулись с утечкой: пароль к базе данных оказался в логах, когда его передали в аргументах запуска. Теперь подобные конфигурации тщательно проверяем и маскируем секреты в логах.

Подводные камни и уроки

Ни один серьезный проект не обходится без накладок. Вот несколько проблем, с которыми мы столкнулись и как мы их решили.

Холодный старт: первые запуски Spark-подов иногда тормозят из-за долгой загрузки Docker-образов. Большой образ (несколько ГБ) + непрогретый узел — драйвер подолгу ждет появления всех executors. Мы решили это так: оптимизировали Docker-образ (убрав лишнее и уменьшив размер), выставили политику IfNotPresent для образов (чтобы не скачивать их повторно) и настроили предварительную аутентификацию к registry. В результате время старта сократилось до десятков секунд.

Spark UI: по умолчанию в Kubernetes нет удобного способа доступа к веб-интерфейсу Spark. Сначала мы использовали kubectl port-forward к драйверу, но после завершения приложения UI пропадал. Теперь же оператор создает Ingress для каждого Spark-драйвера — интерфейс доступен прямо во время работы задачи. Для завершенных приложений выручает History Server. В итоге даже в Kubernetes мы всегда можем заглянуть в Spark UI и найти узкое место у зависшей задачи.

Заключение

Apache Spark на Kubernetes уже перешел из разряда эксперимента в рабочий инструмент, который ускоряет получение ценности из данных. Порог входа всё еще высок: требуется освоить Docker, YAML, настройки сети и ресурсов, но взамен вы получаете унифицированную инфраструктуру, автомасштабирование и изоляцию ресурсов.

Мой совет: используйте готовые инструменты (операторы, чарты), но будьте готовы разобраться в деталях, а также сразу настройте мониторинг — это сбережет время.
Не бойтесь экспериментов: почти любую проблему можно решить, если понимать, как работают Spark и Kubernetes. Сегодня запуск Spark в Kubernetes становится обыденным явлением, и надеюсь, наши советы помогут вам избежать лишних ошибок и успешно реализовать свои проекты.

Комментарии0
Тоже интересно
Комментировать
Поделиться
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники