Proxmox -> LXC (OpenVZ) -> Docker -> Kubernetes-кластер
Прочитав заголовок, сразу же вспоминается персонаж сказок Кащей бессмертный, смерть которого на конце иглы, игла в яйце, яйцо в утке, утка в зайце, заяц в ларце, ларец в цепях на дубу, дуб на черной горе. Короче есть, но достать не легко. Так и тут: чтобы обеспечить отказоустойчивость сервиса реализуется целая гора сервисов, которые обеспечивают работу одного или группы сервисов какого-то приложения. Вот и я решил организовать нечто подобное.
Что нужно сделать можно понять из загаловка, но я все таки оглашу план:
- Установка менеджера ВМ Proxmox VE
- Запуск в контейнерах LXC кластера kubernetes:
- мастер-нода: kube-master
- воркер-ноды: kube-worker1 и kube-worker2
- Базовая настройка инфраструктуры кластера
- установка балансировщика MetaLB
- установка ingress-контроллера haproxy
- установка storage-контроллера OpenEBS
- установка менеджера сертификатов cert-manager
Пунктов не много, выглядит не сложно. Можно приступать! )
В установке самого poxmox ничего хитрого нет - качаем образ, записываем на флэшку, устанавливаем и готово, можно запускать виртуальные машины. Из нюансов связанных с установкой proxmox, следует обратить внимание на IP адрес. Не смотря на то, что изначально он получается через DHCP, в результирующей системе он таки будет настроен как статический на том интерфейсе для которого он был настроен.
1 Подготовка образа контейнеров LXC
После установки нам понадобятся образы ОС, т.н. “golden image” из которых будут запускаться наши контейнеры. Proxmox имеет собственный репозиторий таких контейнеров, список которых можно получить с помощью следующих команд:
|
|
На момент установки мне выводился такой список:
|
|
Из которого, на всякий случай, было скачано сразу несколько образов:
|
|
Далее, приступаем к созданию контейнеров LXC перейдя в веб панель, которая должна быть доступна по адресу https://<ip_address>:8006
с логином root и паролем, который был задан при установке. Рассказывать о том что где находится в этой панели думаю нет смысла, т.к. все достаточно просто и интуитивно понятно. Встаем на наш хост и нажимаем кнопку Create CT
, чтобы создать контейнер. Для начала создадим контейнер c именем kube-master
, на котором соответственно у нас будет развернута master-нода kubernetes. Т.к. внутри у нас должен работать docker, то убираем галочку напротив Unprivileged container
, задаем пароль или публичный ключ ssh, выбираем образ ubuntu-20.04-standard_20.04-1_amd64.tar.gz, устанавливаем колличество ресурсов процессора, диска и памяти. В моем случае это: 15Гб диск, 4Гб ОЗУ и 4 потока. Для начала мне кажется этого достаточно, а в случе необходимости, всегда можно добавить. Так же сразу следует подумать о том, чтобы контейнер автоматически запускался при перезагрузке хоста виртуализации. Для этого нужно в его настройках переключить параметр Sart at boot
в Yes. Теперь в консоли ‘Shell’ сервера ВМ нужно добавить в получившийся файл конфигурации, находящийся в /etc/pve/lxc/<ID контейнера>.conf
, следующие строки приведенные ниже. Это нужно для того чтобы можно было запустить docker с драйвером overlay2, с которым дружит kebernetes и чтобы kubelet имел необходимые права.
|
|
2 Настройка первого контейнера
Теперь переходим в консоль самого контейнера и устанавливаем docker
|
|
Теперь нужно проверить какой драйвер хранилища (Storage Driver) использует docker:
|
|
Если это что-то отличное от overlay2
- значит на хостовой машине, на самом proxmox, не подключен модуль ядра overlay
. Чтобы это исправить делаем следующее:
|
|
перезагружаем proxmox, и проверяем что модуль подключился:
|
|
Если предыдущая операция прошла успешно, но драйвер все равно не overlay2, то можно попробовать указать его через конфигурационный файл /etc/docker/daemon.json
|
|
Так же для успешного запуска kubelet необходимо сделать следующее:
|
|
Все готово для создания кластера kubernetes. Все остальные ноды будут разворачиваться аналогичным образом.
3 Разворачиваем кластер Kubernates
3.1 Установка основных компонентов
Изначально я руководствовался официальной документацией и начал с этой страницы. Ниже идет текст взятый отсюда.
Устанавливаем (если не устанавливали ранее) стандартный набор для добавления внешних репозиториев + open-iscsi
|
|
Скачиванм gpg ключ
|
|
Добавляем сам репозиторий в apt
|
|
И устанавливаем пакеты, которые будем использовать
|
|
На этой стадии можно создать резервную копию нашего контейнера или выполнить операцию ‘Convert to template’. Я выбрал второй вариант, чтобы при разворачивании последующих контейнеров не устанавливать docker и kubernetes. Единственное что нужно помнить при таком подходе - это что после создания клона из шаблона необходимо менять IP-адрес, ну и возможно параметры выделяемых ресурсов, таких как диск, память, процессор.
Создаем файл конфигурации для оркестратора kubeadm, где вместо <server_ip_address>
вписываем IP адрес контейнера:
|
|
Разворачиваем мастер-ноду, с отключенной проверкой наличия swap и системы.
|
|
проверка системы отключается чтобы не ловить ошибку подобного вида:
|
|
Создаем пользователя, который будет админом кластера adduser admin0
и выполняем следующие действия:
|
|
Дальнейшие действия будем выполнять от имени пользователя admin0
Далее нам необходимо установить аддон, который будет реализовать CNI (Container Network Interface). Собственно тот интерфейс, через который контейнеры будут общаться между собой.
Обратившись к README.md
официального репозитория на github’e, устанавливаем этот аддон:
|
|
Чтобы при нажатии кнопки Tab происходило автодополнение команд kubectl, выполним такую команду:
|
|
Так же для удобства деплоя стандартных сервисов и не только установим helm, выполнив следующий набор действий:
|
|
3.2 Подключение worker-нод
Воркер-ноды системно ничем не отличаются от мастер-ноды, и по этой причине я просто клонировал два контейнера из созданного мной ранее шаблона контейнера, поменял IP-адреса, добавил им дискового пространства - до 50Гб и урезал колличество потоков CPU до двух. Думаю, пока хватит.
После успешного запуска master-ноды в конце вывода должна быть строка для подключения worker-нод
|
|
Или так, что приведет к тому же результату, но будет создан новый токен, который будет действителен в течении суток:
|
|
Единственное, чтобы kubeadm не ругался при проверке системы, к этой строке нужно будет добавить ключ --ignore-preflight-errors=SystemVerification
, т.е. результирующая строка подключения worker-нод будет выглядеть примерно так:
|
|
В итоге на местер-ноде, выполнив команду kubectl get nodes
, мы должны увидеть следующую картину:
|
|
4 Настройка кластера
4.1 Установка балансировщика MetalLB и ingress-контроллера
MetalLB нужен чтобы ingress-контроллер знал в каком диапазоне IP-адресов он может работать. В моем случае это будет лишь один адрес, но тем ни мение - на всякий случай, лучше чтобы он был.
Для его установки, сначала, нам понадобится создать файл конфигурации, где вместо <IP_ingress-node>
указать IP мастер-ноды:
|
|
затем немного изменить конфигурацию сервиса kube-proxy
|
|
после чего можно установить сам MetalLB по средствам helm. Для этого делаем слудующее:
|
|
Теперь убеждаемся, что все запустилось с помощью команды kubectl get all -n metallb-system
. Вывод должен быть примерно таким:
|
|
Если все нормально, то приступаем к установке ingress-контроллера.
Добавим репозиторий haproxy в helm:
|
|
И установим сам haproxy-ingress:
|
|
Проверяем работу сервисов ingress-контроллера командой kubectl -n ingress-controller get services
. В результате мы должны увидеть нечто подобное:
|
|
Где ключевым моментом будет являться наличие значения в колонке “EXTERNAL-IP”. Так же можно попробовать открыть этот адрес в браузере и получить 404 ошибку от бэкенда по умолчанию.
4.2 Установка storage-контроллера OpenEBS
Это необходимо для того чтобы было проще управлять persistent-хранилищами наших деплойментов и не думать каждый раз где и что нам создать. Данный контроллер позволяет автоматизировать сей процесс. Конечно, в случае организации более масштабного клатсера следовало бы использовать Ceph, GlusterFS или хотя бы NFS, но для небольшого кластера, я думаю, хватит и базовой установки. Чтобы установить его в наш кластер необходимо выполнить следующие действия:
|
|
После чего в нашем кластере должно появиться два класса хранилищ. Проверяем, выполнив команду kubectl get sc
. В результате мы должны увидеть примерно такой вывод:
|
|
Собственно openebs-hostpath я и собираюсь задействовать в перспективе. Этот класс обеспечивает автоматическое создание Persistent Volume на ноде, где будет распологаться POD. Создаваемые им хранилища находятся (в случае использования настроек по умолчанию) в папке /var/openebs/local/
на нодах где будет запрашиваться пространство для постоянного хранилища.
4.3 Установка cert-manager
Данный менеджер упрощает, как следует из названия, процесс создания TLS-сертификатов. И на мой взгляд, просто необходим, если вы планируете публикацию сервисов в интернете с использованием центров сертификации, например - LetsEncrypt.
|
|
4.4 Установка HAProxy
Так же можно сразу создать эмитент для кластера, который будет подписывать наши сертификаты, на примере Let’s Encrypt. Для этого создаем манифест примерно такого содержания:
|
|
Проверить список эмитентов можно выполнив kubectl get clusterissuers
. Результат вывода примерно такой:
|
|
5 Опциональные действия
Если есть желание управлять кластером удаленно, на удаленной машине в рамках локальной сети, то нужно будет обеспечить на ней наличие kubectl и конфига подключения, который, на мой взгляд, легче всего получить так:
|
|
Так же не помешает helm, который ставится по стандартной схеме, так же как на мастер-ноде kubernetes.
На этом можно считать что задача выполнена. Следующим шагом будет деплой Wordpress + MySQL, но это будет уже следующей статьей.