Kubernetes как решение всех проблем! «Быть или не быть?» — вот в чем вопрос!
Disclaimer
Не смотря на публичность данной статьи, скорее всего, я пишу это в первую очередь для себя, как разговор с резиновой уточкой. После более чем двухгодового плавания с «хипстерскими» технологиями, я должен сделать шаг в сторону и адекватно оценить насколько это было обоснованно и будет адекватно для моего любого следующего проекта.
Тем не менее, я очень надеюсь, что эта публикация найдет своего читателя и поможет многим подготовлено подойти к выбору или отказу от Kubernetes.
Я попытаюсь описать весь опыт, полученный нами в `Lazada Express Logistics`, компании являющейся частью `Lazada Group`, которая в свою очередь — часть `Alibaba Group`. Мы разрабатываем и осуществляем поддержку систем автоматизирующих по-максимуму весь операционный цикл доставки и фулфилмента в 6 крупнейших странах Юго-восточной Азии.
Предпосылки к использованию
Однажды представитель компании, продающей облачные решения по всему миру, спросил у меня: «А что для Вас 'облако'?». Помешкав пару секунд (и подумав:«Хммм… наш диалог явно не о взвешенных в атмосфере конденсациях водяного пара...»), я ответил, что, мол, это как будто один сверх-надежный компьютер с неограниченными ресурсами и практически не имеющий накладных расходов на передачу потоков данных(cеть, диск, память, т.д.). Словно это мой лэптоп работающий для всего мира и способный держать такую нагрузку, а я в одиночку способен им управлять.
Собственно зачем нам это облачное чудо? Все в общем-то очень просто! Мы стремимся облегчить жизнь разработчиков, системных администраторов, devops-ов, тех-менеджеров. А такая вещь, как правильно приготовленное облако, многократно облегчает жизнь всем. Да и помимо всего прочего, мономорфные системы работающие на бизнес всегда дешевле и порождают меньше рисков.
Мы задались целью найти простую, удобную и надежную платформу приватного облака для всех наших приложений и для всех типов ролей в команде перечисленных выше. Провели небольшое исследование: Docker, Puppet, Swarm, Mesos, Openshift + Kubernetes, Kubernetes — Openshift… остановились на последнем — Kubernetes безо всяких аддонов.
Функционал описанный на самой первой странице отлично вписывался и годился для всего нашего предприятия. Подробное изучение документации, болтовня с коллегами и небольшой опыт быстрой пробы. Все это дало уверенность, что авторы продукта не врут, и мы сможем получить наше великолепное облако!
Засучили рукава. И понеслось…
Проблемы и их решения
3-х уровневая архитектура
Все идет с основ. Для того чтобы создать систему, способную хорошо жить в кластере Kubernetes, вам придется продумать архитектуру и процессы разработки, настроить кучу механизмов и средств доставки, научиться мириться с ограничениями/концепциями мира Docker и изолированных процессов.
Как итог: мы приходим к выводу, что идеология микро-сервисной и сервисно-ориентированной архитектуры как не кстати годится для наших задач. Если вы читали статью Мартина Фаулера(перевод) на эту тему, то более-менее должны представлять какой титанический труд должен быть проделан, прежде чем первый сервис оживет.
Мой чек-лист разделяет инфраструктуру на три слоя, а затем примерно описывает то, о чем на каждом из уровней нужно помнить при создании подобных систем. Три слоя о которых идет речь:
- Hardware — сервера, физические сети
- Cluster — в нашем случае Kubernetes и системные сервисы поддерживающие его (flannel, etcd, confd, docker)
- Service — непосредственно процесс упакованный в Docker — микро/макро сервис в своем домене
Вообще идея 3-х слойной архитектуры и задач связанных с ней — это тема отдельной статьи. Но в свет она выйдет не раньше, чем этот самый чек-лист будет безукоризненно полон. Это может и не случиться никогда :)
Квалифицированные специалисты
Насколько тема приватных облаков актуальна и интересна все больше и больше среднему и крупному бизнесу, настолько же актуален вопрос о квалифицированных архитекторах, devops-ах, разработчиках, администраторах баз данных способных с этим работать.
Причина тому — новые технологии, которые, поступая на рынок, не успевают обрастать нужным объемом документации, обучающих статей и ответов на `Stack Overflow`. Однако, не смотря на это, такие технологии, как в нашем случае, Kubernetes — становятся очень популярными и создают дефицит кадров.
Решение простое — нужно взращивать специалистов внутри компании! Благо, в нашем случае, мы уже знали что такое Docker и как его готовить — остальное пришлось нагонять.
Continuous Delivery/Integration
Не смотря на всю прелесть технологии «умного облачного кластера», нам были необходимы средства общения и установки объектов внутрь Kubernetes. Пройдя дорогу от самописного bash скрипта и сотен ветвей логики, мы закончили вполне понятными и читаемыми рецептами для Ansible. Для полноценного превращения Docker файлов в живые объекты нам понадобилось:
- Набор стандартных решений:
- Team City — для автоматизированных деплоев
- Ansible — для сборки шаблонов и доставки/установки объектов
- Docker Registry — для хранения и доставки Docker образов
- images-builder — скрипт для рекурсивного поиска Docker файлов в репозитории и отправки образов на их основе после сборки в централизованное registry
- Ansible Kubernetes Module — модуль для установки объектов с различными стратегиями в зависимости от объекта (создать или обновить/создать или заменить/создать или пропустить)
По мимо всего прочего мы изучали вопрос о Kubernetes Helm. Но тем не менее, не смогли найти той самой killer-feature, которая могла бы заставить нас отказаться или заменить Ansible шаблонизацию на Helm чарты. Других полезных способностей этого решения мы не смогли найти.
Например, как делать проверку того, что один из объектов успешно установлен и можно продолжить выкатку других? Или как делать более тонкие настройки и установки контейнеров, которые уже работают, и нужно просто выполнить пару команд внутри их?
Эти и многие другие вопросы обязывают относиться к Helm как к простому шаблонизатору. Но зачем это?.. если Jinja2, входящая в состав Ansible, даст фору любому не профильному решению.
Сервисы хранящие состояние
Как полноценное решение для любого типа сервисов, включая statefull(имеющие состояние), Kubernetes поставляется с набором драйверов для работы с сетевыми блочными устройствами. В случае с AWS, единственный приемлемый вариант — EBS.
Как вы можете убедится, треккер k8s пестрит кучей багов связанных с EBS, и решаются они довольно медленно. На сегодня, мы не страдаем от каких-то серьезных проблем, помимо того, что, иногда, для создания объекта с персистентным хранилищем требуется до 20 минут. Интеграция EBS-k8s очень, очень, очень сомнительного качества.
Однако, даже если вы используете другие решения для хранилищ и не испытываете особых проблем, то, все равно, будете нуждаться в качественных решениях для всего, что может хранить данные. Мы потратили уйму времени, чтобы заполнить пробелы и предоставить качественные решения для каждого из случаев:
- PostgreSQL кластер (статья на Хабре, статья на Medium)
- RabbitMQ кластер
- Redis кластер
- Скрипт для бэкапов PostgreSQL
Помимо всего прочего, Kubernetes, да и Docker мир, в принципе, обязывает, иногда, к множеству хитростей и тонкостей, которые очевидны на первый взгляд, но требуют дополнительного решения.
Небольшой пример.
Собирать логи внутри запущенного Docker контейнера нельзя. НО очень много систем и фреймворков не готовы к стримингу в `STDOUT`. Нужно заниматься `патчингом` и осознанной разработкой на системном уровне: писать в пайпы, заботиться о процессах и т.д. Немного времени и у нас есть Monolog Handler для `php`, который способен выдавать логи так, как их поймет Docker/k8s
API Gateway
Как часть любой микро-сервисной и сервисно-ориентированной архитектуры, вам, скорее всего, понадобится некий шлюз. Но это для архитектуры, здесь же хочу заострить внимание почему это особо важно для кластера и вложенных в него сервисов.
Все довольно просто — нужна единая точка
Есть ряд задач которые мы решали в разрезе Kubernetes кластера:
- Контроль доступа и лимитация запросов извне — как пример небольшой LUA скрипт проливает свет на проблему
- Единая точка аутентификации/авторизации пользователей для любых сервисов
- Отсутствие множества сервисов требующих доступ по HTTP из `мира` — резервирование портов на серверах для каждого желающего сервиса управляется тяжелее, чем роутинг в Nginx
- Интеграция Kubernetes-AWS для работы с AWS Load Balancer
- Единая точка мониторинга HTTP статусов — удобно даже для внутреннего общения сервисов
- Динамическая маршрутизация запросов на сервисы или версии сервисов, A/B тесты (альтернативно проблема может решаться разными pod-ами за сервисом Kubernetes)
Искушенный пользователь Kubernetes поспешит спросить о Kubernetes Ingress Resource, который предназначен именно для решения подобных задач. Все верно! Но мы требовали немного больше `фич`, как вы могли заметить, для нашего API Gateway чем есть в Ingress. Тем более, это всего лишь обертка для Nginx, с которым мы и так умеем работать.
Текущее состояние
Несмотря на мириады нюансов и проблем связанных с установкой, использованием и поддержкой представленного выше решения, будучи достаточно упорными, вы скорее всего, придете к успеху и получите, примерно, то, что на сегодняшний день имеем мы.
Что же из себя представляет платформа в текущем состоянии — немного сухих фактов:
- Всего 2-3 человека для поддержки всей платформы
- Один репозиторий хранящий всю информацию обо всей инфраструктуре
- От 10-50 независимых автоматизированных релизов в день — CI/CD mode
- Ansible как средство управления кластером
- Считанные часы для создания идентичного `life` окружения — локально на minikube или на реальных серверах
- AWS-based архитектура на базе EC2 + EBS, CentOS, Flannel
- 500~1000 pod-ов в системе
- Лист технологий завернутых в Docker/K8s: Go, PHP, JAVA/Spring FW/Apache Camel, Postgres/Pgpool/Repmgr, RabbitMQ, Redis, Elastic Search/Kibana, FluentD, Prometheus, etc
- Инфраструктура вне кластера отсутствует, за исключением мониторинга на уровне `Hardware`
- Централизованное хранилище логов на базе Elastic Search внутри Kubernetes кластера
- Единая точка сбора метрик и алертинга проблем на базе Prometheus
Список отражает множество фактов, но опущенными остаются явные преимущества и приятные особенности Kubernetes как системы управления Docker процессами. Подробнее с этими вещами можно ознакомится на оффициальном сайте Kubernetes, в статьях на том же Хабре или Medium.
Длинный список наших пожеланий, которые находятся на стадии прототипов или пока еще покрывают небольшую часть системы, тоже очень большой:
- Система профилирования и трэйсинга — например, zipkin
- Anomaly detection — машинно обучаемые алгоритмы для анализа проблем по сотням метрик, когда мы не можем или не хотим понимать что значит каждая метрика/набор метрик в отдельности, но хотим знать о проблеме связанной с этими метриками
- Автоматическое планирование мощностей и масштабирование как количества pod-ов в сервисе так и серверов в кластере на основе определенных метрик
- Интеллектуальная система управления бэкапами — для любых stateful сервисов, в первую очередь баз данных
- Система мониторинга сетей и визуализации связей — внутри кластера, между сервисами и pod-ами, прежде всего (интересный пример)
- Federation mode — распределенный и связнный режим работы нескольких кластеров
Тaк быть или не быть?
Опытный читатель, скорее всего, уже догадался, что статья врядли даст однозначный ответ на такой, казалось бы, простой короткий вопрос. Множество деталей и мелочей могут сделают вашу систему безумно крутой и производительной. Или другое множество багов и кривых имплементаций превратят вашу жизнь в ад.
Решать вам! Но мое мнение по поводу всего этого: «БЫТЬ!.. но очень аккуратно»
Комментарии (16)
arykalin
07.07.2017 19:01А что вы используете для конфигурации nginx? Мы сейчас пробуем читать сервисы из etcd кубернета и делать конфигурацию с помощью confd. Правда для этого пришлось переключиться обратно на etcd V2 API т.к. confd не умеет работать с etcd v3.
ZmeeeD
07.07.2017 19:04А как вы лимитируете что светить наружу а что нет? Не все же сервисы подключать… у нас простая конфигурация нутри самого nginx как часть проекта API gateway (не динамическая). Какие-то переменные приходят из ENV ну а внутри естественно собирается с confd
arykalin
08.07.2017 03:49Через аннотации сервиса, паблик\не паблик, там же пермишены если надо. А confd через темплейты разруливает. Нам просто нужна была динамическая конфигурация сервисов из нескольких неймспейсов.
galeev_roman
07.07.2017 23:15Прошу прощения, если не увидел в тексте, а как вы осуществляете документацию текущего API для взаимодействия с подпроектами вашей группы проектов? То есть вы свои контейнеры обновляете, как хотите, это круто, но как остальные части проекта про это узнают?
romangoward
07.07.2017 23:59+2Самое интересное, как обычно, не рассказали: любой
online shopping
сегодня привязан кPCI DSS
, а у сервисов уровняAlibaba
— всегда свой процессинг. И тут у контейнеров в целом, да и у k8s в частности — всё, мягко говоря, не очень хорошо.
reistlin87
08.07.2017 07:57+2А в чем для вас преимущества Kubernetes перед Swarm?
ZmeeeD
11.07.2017 06:23Отчасти исторически сложилось (старый Swarm, год назад, был не готов к продакшену, про текущий надо смотреть), отчасти то как k8s более обширно пошел по рынку.
farcaller
Вы ямлы пишете руками? не надоедает? jsonnet пробовали?
nightvich
А в чем сложность написания yaml?
farcaller
В k8s часто приходится писать одни и те же параметры и значения от ConfigSet к Deployment к Service и внутри них. Выше шанс опечатки, да и надоедает как-то все лейблы расставлять везде одинаково.
farcaller
Рефакторил тут правила calico, нарисовался пример.
Надо сделать ServiceAccount с конкретными правами. В чистом k8s это три объекта:
В jsonnet мешанину текста легко упросить до читаемого:
Чем удобнее — все это в реальном времени рендерится в текстовом редакторе (vscode), и любая опечатка будет найдена компилятором при наборе текста, а не при
kubectl apply
.