Не будем подробно представлять Kubernetes — он уже стал де-факто стандартом для масштабируемого запуска микросервисов и зарекомендовал себя как эффективное решение для реальной эксплуатации. K8s позволяет запускать различные типы рабочих процессов и предоставляет все необходимые компоненты для публикации сервисов, защиты приложений, настройки авторизации и многого другого.
В Kubernetes появилась возможность расширять функциональность с помощью пользовательских ресурсов (Custom Resources). С этим обновлением появилась возможность реализовывать собственные сервисы и контроллеры поверх Kubernetes, не решая инфраструктурные задачи. Разработка становится быстрее, запуск — возможен где угодно. Именно такие обещания стоят за этой архитектурой. В последние годы пользовательские ресурсы и контроллеры на их основе стали всё более популярными. Существенным сдвигом в этой области стало появление Crossplane — он позволил управлять ресурсами, находящимися за пределами кластера.
К сожалению, у пользовательских контроллеров есть серьёзная проблема: по ряду причин они не способны эффективно обрабатывать большие объёмы данных. Всё хранилище данных в Kubernetes построено на базе ETCD, что ограничивает масштабируемость, гибкость и производительность при работе со сложными или объёмными рабочими нагрузками. О каких именно проблемах идёт речь?
-
ETCD изначально был спроектирован для хранения конфигурационных данных, а размер кластера остаётся весьма ограниченным.
-
В используемой модели согласованности ETCD не поддерживает шардирование — все узлы являются полными репликами, и Kubernetes взаимодействует только с лидером.
-
ETCD не может выполнять фильтрацию данных на уровне хранилища, поэтому API-сервер Kubernetes вынужден загружать все записи и фильтровать их на клиентской стороне.
-
При использовании одного экземпляра ETCD конфигурационные данные самого кластера смешиваются с пользовательскими, и если высоконагруженные сервисы начнут создавать нагрузку, это может заблокировать или замедлить нормальную работу кластера, поставив под угрозу его стабильность.
-
Kubernetes — это многопользовательская система с механизмами изоляции, но в конечном итоге все данные попадают в одно хранилище. Это означает, что сбой в базе данных влияет на весь кластер, а злоумышленник может получить доступ ко всем данным.
На этом этапе стоит упомянуть проект Kine. Kine предлагает альтернативу ETCD — вместо него можно использовать MySQL или PostgreSQL, самые популярные реляционные СУБД. Это решение помогает решить проблему с масштабированием хранилища, но не устраняет другие ограничения, описанные выше.
Надеюсь, мне удалось собрать основные причины, по которым разработчики используют пользовательские ресурсы и контроллеры для решения инфраструктурных задач, а также объяснить, почему они избегают разработки приложений для работы с большими объёмами данных.
Проблема решаема…
…но прежде чем перейти к решению, давайте разберём основные ограничения контроллеров пользовательских ресурсов в Kubernetes.
|
Ограничение |
Описание |
|
Конечная согласованность |
Обновления могут не сразу стать видимыми во всей системе |
|
Отсутствие транзакций |
Отсутствие поддержки транзакций с гарантией ACID |
|
Ограниченные возможности фильтрации данных |
Отсутствие расширенных возможностей запросов и фильтрации данных внутри Kubernetes |
|
Реляционная логика |
Нет поддержки сложных связей и объединений между сущностями |
|
Большие объёмы данных |
Хранение и обслуживание больших объёмов данных в масштабе невозможно |
Пора познакомиться с HariKube. HariKube — это прослойка (middleware), которая прозрачно распределяет нагрузку между несколькими независимыми от вендора базами данных, обеспечивая низкую задержку, высокую пропускную способность и облачную архитектуру, оптимизированную для разработки. Благодаря распределению данных и оптимизированной маршрутизации запросов к базам данных HariKube достигает выдающейся производительности. Перенаправляя ресурсоёмкие рабочие нагрузки с ETCD на другие хранилища данных, он обеспечивает стабильную отзывчивость и эффективную работу в масштабе.
HariKube обеспечивает изоляцию данных между пространствами имён (namespace), типами ресурсов и сервисами, что помогает компаниям соблюдать требования безопасности и соответствия (compliance), не жертвуя масштабируемостью и производительностью. И, наконец, он упрощает рабочий процесс разработчиков, скрывая инфраструктурную сложность. Вам остаётся сосредоточиться только на структурах данных и бизнес-логике — платформа сама позаботится о маршрутизации и хранении данных.
HariKube полностью прозрачен: Kubernetes «не замечает», что работает не с ETCD. HariKube используется в продакшене для обработки больших объёмов данных и их распределения между хранилищами.
Как это работает?

-
Пользователь инициирует операцию CRUD для ресурса Kubernetes (например, для пользовательского ресурса).
-
Запрос направляется на API-сервер Kubernetes, который перенаправляет его через прослойку.
-
HariKube перехватывает запрос и определяет, где следует хранить данные, согласно заданным правилам маршрутизации.
-
Если найдено соответствующее правило маршрутизации, запрос направляется в определённую базу данных (например, в MySQL).
-
Если соответствующее правило маршрутизации не найдено, запрос обрабатывается в ETCD — хранилище данных по умолчанию в Kubernetes.
-
Соответствующее хранилище (MySQL или ETCD) выполняет операцию CRUD.
-
Когда бэкенд возвращает ответ, он проходит обратно через ту же цепочку до пользователя.
HariKube поддерживает несколько вариантов бэкендов, каждый из которых имеет свои особенности по доступу к данным и фильтрации. В таблице ниже перечислены совместимые хранилища и указано, поддерживают ли они фильтрацию данных на уровне хранилища для эффективной выборки.
|
База данных |
Фильтрация на уровне хранилища* |
Изоляция данных |
Снижение задержки |
Повышение пропускной способности |
Поддержка больших объёмов данных* |
|
❌ |
✅ |
✅ |
✅ |
❌ |
|
|
❌ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
✅ |
|
|
✅ |
✅ |
✅ |
✅ |
❌ |
*Поддержка работы с большими объёмами данных с использованием фильтрации на уровне хранилища недоступна в стандартной (vanilla) версии Kubernetes. Для этого необходимо перекомпилировать Kubernetes. Подробнее об этом мы расскажем далее.
Теперь давайте перейдём к практике.
Для начала настроим базы данных в файле docker-compose.yml.
version: '3.8' services: etcd2479: image: bitnami/etcd:3.5 container_name: etcd2479 network_mode: "host" environment: - ETCD_LISTEN_CLIENT_URLS=http://127.0.0.1:2479 - ETCD_LISTEN_PEER_URLS=http://127.0.0.1:2480 - ETCD_INITIAL_CLUSTER=default=http://127.0.0.1:2480 - ETCD_ADVERTISE_CLIENT_URLS=http://127.0.0.1:2479 - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://127.0.0.1:2480 command: etcd --auto-compaction-mode=revision --auto-compaction-retention=5m etcd2579: image: bitnami/etcd:3.5 container_name: etcd2579 network_mode: "host" environment: - ETCD_LISTEN_CLIENT_URLS=http://127.0.0.1:2579 - ETCD_LISTEN_PEER_URLS=http://127.0.0.1:2580 - ETCD_INITIAL_CLUSTER=default=http://127.0.0.1:2580 - ETCD_ADVERTISE_CLIENT_URLS=http://127.0.0.1:2579 - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://127.0.0.1:2580 command: etcd --auto-compaction-mode=revision --auto-compaction-retention=5m mysql3306: image: linuxserver/mariadb:10.11.8 container_name: mysql3306 network_mode: "host" environment: - MYSQL_ROOT_PASSWORD=passwd pgsql5432: image: postgres:17-alpine3.20 container_name: pgsql5432 network_mode: "host" environment: - POSTGRES_PASSWORD=passwd
После этого выполните команду docker-compose up -d для запуска баз данных
Теперь создадим файл конфигурации маршрутизации данных — назовём его topology.yml
backends: - name: rbac endpoint: http://127.0.0.1:2579 regexp: prefix: (clusterrolebindings|clusterroles|rolebindings|roles|serviceaccounts) key: (clusterrolebindings|clusterroles|rolebindings|roles|serviceaccounts) - name: kube-system endpoint: mysql://root:passwd@tcp(127.0.0.1:3306)/kube_system namespace: namespace: kube-system - name: pods endpoint: postgres://postgres:passwd@127.0.0.1:5432/pods prefix: prefix: pods - name: shirts endpoint: sqlite://./db/shirts.db?_journal=WAL&cache=shared customresource: group: stable.example.com kind: shirts
Разберём конфигурацию маршрутизации
-
ETCD с маршрутизацией по регулярным выражениям: направляет ресурсы RBAC Kubernetes в хранилище ETCD.
-
Маршрутизация MySQL по namespace: все объекты в пространстве имён kube-system направляются в MySQL-бэкенд. Поддерживаются только встроенные типы ресурсов; для пользовательских необходимо создать отдельное правило.
-
Маршрутизация PostgreSQL по префиксу: все ресурсы pods (кроме тех, что в kube-system) направляются в PostgreSQL-бэкенд.
-
Точка подключения SQLite для пользовательских ресурсов: все ресурсы типа shirts из группы
stable.example.comнаправляются во встроенную легковесную базу данных SQLite. -
Остальные объекты сохраняются в базе данных по умолчанию.
Когда окружение настроено, можно запускать middleware.
docker login registry.harikube.info* docker run -d \ --name harikube \ --net=host \ -e TOPOLOGY_CONFIG=/topology.yml \ -v $(pwd)/topology.yml:/topology.yml \ -v harikube_data:/db \ registry.harikube.info/harikube/middleware:beta-v1.0.0-3 \ --listen-address=0.0.0.0:2379 --endpoint=multi://http://localhost:2479
*Docker-образы пока не опубликованы — для получения пробной версии обратитесь через сайт проекта.
Заключительный шаг — запуск кластера Kubernetes. Как уже упоминалось, HariKube полностью совместим с Kubernetes и работает с ним без дополнительных настроек. Однако для поддержки работы с большими объёмами данных потребуется перекомпиляция компонентов API Server и Controller Manager. Инструкции по перекомпиляции можно найти по ссылке (будет приведена далее), но для упрощения в этом руководстве используется Kind с базовой версией Kubernetes.
Создайте конфигурационный файл Kind — kind-config.yml.
kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 featureGates: "CustomResourceFieldSelectors": true "WatchList": true "WatchListClient": true nodes: - role: control-plane kubeadmConfigPatches: - | kind: ClusterConfiguration apiServer: extraArgs: storage-media-type: application/json etcd-servers: "http://<PUBLIC_IP_OF_HOST>:2379"
Запустите кластер, выполнив команду:
kind create cluster --name harikube-cluster --config kind-config.yml
Убедитесь, что HariKube распределил данные согласно файлу topology.yml:
-
etcdctl --endpoints=http://127.0.0.1:2479get / --prefix --keys-only
База данных по умолчанию для остальных объектов -
etcdctl --endpoints=http://127.0.0.1:2579get / --prefix --keys-only
Только объекты, связанные с RBAC -
docker exec -t mysql3306 mysql -uroot -ppasswd -Dkube_system -e "select name from kine"
Объекты из пространства имёнkube-system -
docker exec -it pgsql5432 su postgres -c "psql -d pods -c 'select name from kine'"
Все pod’ы, за исключением тех, что вkube-system
Теперь можно создать первый пользовательский ресурс. Для начала примените файл с определением ресурса, выполнив следующую команду:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/customresourcedefinition/shirt-resource-definition.yaml
Затем создайте несколько экземпляров ресурса.
cat | kubectl apply -f - <<EOF --- apiVersion: stable.example.com/v1 kind: Shirt metadata: name: example1 spec: color: blue size: S --- apiVersion: stable.example.com/v1 kind: Shirt metadata: name: example2 spec: color: blue size: M --- apiVersion: stable.example.com/v1 kind: Shirt metadata: name: example3 spec: color: green size: M EOF
Проверьте, что HariKube сохранил все ресурсы типа shirt в базе данных SQLite:
-
docker run -it --rm -v harikube_data:/data alpine/sqlite /data/shirts.db -cmd "select name from kine"
Все 3 объекта типаshirt, которые мы создали
Вот и всё! Теперь вы можете представить свою собственную топологию данных и расширить возможности Kubernetes. Наслаждайтесь низкой задержкой, высокой пропускной способностью, изоляцией данных, «неограниченным» хранилищем и простотой разработки.
HariKube поддерживает как плоские, так и иерархические топологии, позволяя организовывать базы данных в удобном вам виде.
Спасибо за внимание! Делитесь мыслями в комментариях.
Если проблемы масштабируемости в Kubernetes, обработка больших объемов данных и оптимизация инфраструктуры — это те вопросы, с которыми вы сталкиваетесь регулярно, возможно, вам уже стоит задуматься о новых подходах к решению этих задач. Мы подготовили несколько открытых уроков, которые помогут вам эффективно справиться с этим и улучшить производительность ваших систем:
-
14 июля, 20:00 — От кода до Kubernetes за полтора часа
-
17 июля, 20:00 — Взаимодействие микросервиса на Go и Elasticsearch
-
22 июля, 20:00 — Инфраструктура как код на примере Terraform
Все открытые уроки по всем IT-направлениям уже собраны в календаре.
ссылка на оригинал статьи https://habr.com/ru/articles/921632/
Добавить комментарий