Ныряем в готовые кластеры Kubernetes с Deckhouse и werf

от автора

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

Вот и я, столкнувшись с Managed Kubernetes от Selectel, захотел использовать что-то готовое, желательно от российских разработчиков. Я обратил внимание на платформу Deckhouse, которую к тому моменту можно уже было ставить в готовые кластеры k8s. В этой статье я расскажу про свой путь интеграции D8 и werf в инфраструктуру Selectel и те проблемы, с которыми столкнулся в процессе.


Я прекрасно осведомлен, что EE-версия не требует столько усилий и запускается поверх облака Selectel с cloud provider OpenStack, однако данная опция мне недоступна. Поэтому работать будем с тем, что есть, а именно — с облачной платформой, Managed Kubernetes и Container Registry.

Подсчет инфраструктуры


Будем считать, что у нас уже есть Git-хранилище. Я предпочитаю использовать GitLab, поэтому дальнейшая интеграция будет именно с ним.

Для начала рассчитаем ресурсы. В идеологии Deckhouse есть разделение узлов на конкретные роли:

  • Master — узлы Control Plane. На них крутится ETCD и K8S Apiserver. В Selectel они будут от нас скрыты.
  • System — узлы для системных компонентов. Сюда встанут различные компоненты мониторинга. Сюда же стоит вынести и другие кластерные компоненты — например, контроллер Container Storage Interface (CSI). Скорее всего это будут узлы со значительным объемом памяти.
  • Frontend – узлы для ingress и всяческого приема трафика. На них запускается Ingress, VPN и тому подобное.
  • Worker – узлы общего назначения, для приложений.


Чтобы просто запустить приложение, то есть для минимального кластера, будет достаточно нескольких нод из группы Worker. Однако создание продакшена потребует разделения ролей, а также настройку автоскейлинга. Именно поэтому важно создание нод группы System — в отличие от Worker, на них будет постоянный набор компонентов и эта группа будет относительно стабильна.

В различных примерах конфигурации, которые я приведу в статье, будут показаны примеры как для минимального кластера, так и production-ready решения. Они будут разделены по файлам с суффиксами:

  • simple – для простого кластера,
  • ha – для отказоустойчивого решения.

Для своего проекта я выбрал следующую конфигурацию:

  • два Frontend-узла,
  • три Worker-узла,
  • один System-узел.

Создание инфраструктуры


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


Воспользуемся Terraform — стандартом индустрии. Тем более у облака Selectel есть свой terraform provider в актуальном состоянии. Он поможет нам исключительно с PaaS-сервисами, такими как базы, кластера k8s. Для работы с виртуальными машинами и сетью в облаке нам потребуется еще и OpenStack terraform provider. Также у Selectel есть отличный репозиторий с примерами — его мы и будем использовать при создании виртуальной инфраструктуры.

В ходе работ я выяснил, что пример создания проекта с ключом не работает. О чем впоследствии был заведен issue.

Запустим наш проект и получим готовый кластер:

terraform init env TF_VAR_sel_token=yyy_xxx TF_VAR_user_password=xxx terraform plan env TF_VAR_sel_token=yyy_xxx TF_VAR_user_password=xxx terraform apply

Подготовка кластера Deckhouse


Теперь, когда мы получили готовый кластер, можно подготовить его к установке Deckhouse. Чтобы провести установку, нам потребуется создать Storage Class для нашего региона. Я собрал все это в один Chart, который:

  • при первичной установке создает Storage Class для кластера, исходя из зоны,
  • при повторной установке создает Ingress, Auth provider и другие ресурсы D8.

Скачаем конфигурацию кластера из панели Selectel:

Установим Сhart в кластер:

export KUBECONFIG=~/.kube/d8test.yaml werf converge --skip-build

Установка Deckhouse


Теперь установим Deckhouse. Вы всегда можете воспользоваться официальной документацией, однако я подготовил готовый конфиг для нашего кластера:

apiVersion: deckhouse.io/v1 kind: InitConfiguration deckhouse:   releaseChannel: Alpha   bundle: Managed   configOverrides:     global:       modules:         publicDomainTemplate: '%s.d8test.example.com'       storageClass: "fast.ru-3a"     certManagerEnabled: true     deckhouseWebEnabled: true     chronyEnabled: false     userAuthnCrdEnabled: true     userAuthnEnabled: true     userAuthzEnabled: true     namespaceConfiguratorEnabled: true     namespaceConfigurator:       configurations:       - annotations:           extended-monitoring.flant.com/enabled: "true"         includeNames:         - "production"         - "loki-logging"     dashboard:       accessLevel: ClusterAdmin       auth:         allowScale: true         externalAuthentication:           authURL: http://auth.dashboard-auth.svc.cluster.local/_tech/is_auth           authSignInURL: https://dashboard.d8test.example.com/_tech/auth           useBearerTokens: true 

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

Произведем установку:

docker run --pull=always -it -v "$PWD/config.yml:/config.yml" \   -v "$HOME/.kube/d8test.yaml:/kubeconfig" registry.deckhouse.io/deckhouse/ce/install:alpha bash dhctl bootstrap-phase install-deckhouse --kubeconfig=/kubeconfig --config=/config.yml

Deckhouse устанавливается без проблем за 5 минут.

Установим Сhart в кластер еще раз, чтобы развернулись недостающие ресурсы:

export KUBECONFIG=~/.kube/d8test.yaml werf converge --skip-build

После применения оставшихся ресурсов останется дождаться получения прямого IP нашим кластером:

export KUBECONFIG=~/.kube/d8test.yaml kubectl –n d8-ingress get svc

После чего потребуется направить на него DNS-запись *.d8test.example.com для компонентов.

Но что мы получим на выходе?

Managed K8S + D8 = ❤


А на выходе — полнофункциональный кластер с мониторингом, cert-manager, Ingress на основе nginx и возможностью сбора логов встроенным агентом на базе Vector.

Конечно, не обошлось и без ложки дегтя. Так как control plane контролирует Selectel, у нас нет возможности настроить multitenancy или же сконфигурировать Dex как OIDC-провайдер. Итого, что не работает:

  • Периодически отваливается сбор логов с ошибкой версии объекта:
  • Watcher Stream received an error. Retrying. error=WatchError(ErrorResponse { status: «Failure», message: «too old resource version: 114794284 (114797507)», reason: «Expired», code: 410 }).
  • Нет авторизации в Kubernetes API через Dex.
  • Не работает incluster VPN.

К счастью, это можно обойти. В Dashboard есть возможность внешней авторизации — именно ее я и использовал, сделав специальный Chart c nginx, который возвращает в Dashboard token. Установить его можно командой werf converge.

С логами я разобрался аналогичным образом — создав Chart, который раз в час перезапускает поды.

Документация по обоим чартам находится в связанных репозиториях.

Продолжим погружение


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

На текущий момент ноды кластера Selectel работают на относительно старом образе с Ubuntu 18.04 и ядром четвертой ветки. Это не позволит нам полностью раскрыть werf вкупе с Gitlab Kubernetes runner. По имеющейся у меня информации, вскоре образ для нод будет обновлен. До тех пор сборку будем производить на выделенных виртуальных машинах с Gitlab Runner. Чтобы их настроить, укажите количество раннеров в Terraform. Также потребуется активировать создание bastion хоста. Сами раннеры можно легко сконфигурировать с помощью Ansible. Шаг с установкой werf на Gitlab Runner я намеренно пропускаю, так как он и так отлично расписан в официальной документации.

Когда сборочная инфраструктура будет готова, перейдем к созданию Kubeconfig для работы werf. Можно воспользоваться статьей на сайте Deckhouse.


С начала года Selectel начал предоставлять Container Registry as a Service (CRaaS) в облаке. Это значит, что доставка приложений будет еще быстрее, ведь скачка образов происходит в рамках одной инфраструктуры по быстрым сетям провайдера. Но не все так просто — об этом сервисе мы поговорим отдельно.

werf и CRaaS


Статья писалась продолжительное время, во время бета-тестирования CRaaS. Описанные проблемы были успешно решены с техподдержкой Selectel. В werf добавлены подсказки для работы с Container Registry от Selectel.

Создадим реестр и получим к нему доступ. Подробнее в документации Selectel.

Создадим простейший проект с Pipeline в Gitlab:

variables:   WERF_REPO: ${SEL_REGISTRY_DOMAIN}/${SEL_REGISTRY}  before_script:   - type trdl && . $(trdl use werf 1.2 ea)   - werf version   - type werf && source $(werf ci-env gitlab --as-file)   - werf cr login ${SEL_REGISTRY_DOMAIN}  after_script:   - werf cr logout ${SEL_REGISTRY_DOMAIN}  stages:   - deploy  .base_deploy:   stage: deploy   script:     - werf converge   except: [schedules]   tags: [werf]  Deploy to test:   extends: .base_deploy   environment:     name: test   when: manual  Deploy to production:   extends: .base_deploy   environment:     name: production   when: manual 

Кроме того, нам потребуются несколько переменных в CI/CD GitLab:

  • WERF_KUBECONFIG_BASE64 — его мы получили в предыдущем параграфе,
  • SEL_REGISTRY_DOMAIN со значением cr.selcloud.ru
  • SEL_REGISTRY c именем реестра — в нашем случае example,
  • WERF_USERNAME со значением token,
  • WERF_PASSWORD с токеном, который мы получили из панели Selectel.

На удивление, все заработало сразу и без проблем. Однако на первых порах образы были не оптимизированы и предоставленные в рамках беты бесплатные 20 ГБ довольно быстро закончились. Встал вопрос очистки.

В Pipeline добавился блок очистки, аналогичный представленному в документации werf:

stages:   - deploy   - cleanup  .base_clean_up:   stage: cleanup   script:     - werf cleanup              rules:              - if: $CI_PIPELINE_SOURCE == "schedule"                when: always   tags: [werf]   resource_group: cleanup  Clean up:   extends: .base_clean_up 

В этот момент стало понятно, что werf не поддерживает очистку данной реализации Registry.

К счастью, это можно исправить. У CRaaS был развитый API, который позволял сделать очистку. API позволяло:

  • быстро получить список тегов и репозиториев,
  • сделать очистку образов,
  • получить токен для доступа к Registry.

Сходу нашлась и проблема, которую можно отнести к проблемам реализации Container Registry от Selectel: werf позволял класть образы в корень репозитория — например, cr.selcloud.ru/example:67a03ef931a263cd83c0fd3dcd7d4468f12d44e13755dad35e3f, но ни API, ни личный кабинет облака не отображали подобные образы. Баг-репорт я отправил в техподдержку Selectel, а в werf добавил подсказку.

К слову, на стороне Selectel сейчас тоже существует проверка:

Мне же в тот момент пришлось пересоздать реестр — других вариантов не было.
Пришлось скорректировать Pipeline, исправив переменную WERF_REPO:

variables:   WERF_REPO: ${SEL_REGISTRY_DOMAIN}/${SEL_REGISTRY}/${CI_PROJECT_PATH} 

Так и появилась первая реализация CRaaS в werf и добавлен раздел в документацию.

На этом приключения не закончились. В реализации были не учтены некоторые вещи:

  • работа с лимитами на запросы к API,
  • работа у новых юзеров, у которых нет токенов, — сборка могла выдать ошибку.

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

.base_clean_up:   stage: cleanup   variables:     WERF_PARALLEL: 0   script:     - werf cleanup   rules:   - if: $CI_PIPELINE_SOURCE == "schedule"     when: always   tags: [werf]   resource_group: cleanup 

Добавилась переменная WERF_PARALLEL, которая ограничивают количество одновременных задач. А для беспроблемной работы у новых пользователей появилась вторая реализация, которая учитывала ошибки первой.

Осенью столкнулся с другой бедой — любое удаление образа из Registry приводило к полной блокировке реестра. Пришлось перенастроить работу garbage collector на стороне GitLab, перенеся очистку на глубокую ночь по Москве. Сообщил о проблеме техподдержке Selectel, и они оперативно ее исправили.

Неделю назад CRaaS вышел в коммерческий релиз, что сопровождается обновлением API. Поэтому в разработке третья версия работы с CRaaS для werf. Stay tuned!

Итоговый Pipeline, который я использую у себя в проекте, вы сможете найти на GitHub.

В заключение хочу поблагодарить команду werf (в особенности aigrychev ), которые быстро отвечали на вопросы по работе с утилитой, и команду DevShop, с чьего разрешения я и публикую эти наработки.


ссылка на оригинал статьи https://habr.com/ru/company/selectel/blog/706372/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *