ELMA365 On-Premises > Подготовка инфраструктуры > Kubernetes / Отказоустойчивый Kubernetes-кластер

Отказоустойчивый Kubernetes-кластер

Deckhouse — это полнофункциональная платформа на базе Open Source-компонентов, которая, кроме Kubernetes, включает дополнительные модули для мониторинга, балансировки трафика, автомасштабирования, безопасного доступа и не только. Модули преднастроены, интегрированы друг с другом и готовы к работе. Управление всеми компонентами кластера и платформы, а также их обновление полностью автоматизированы.

Deckhouse в реестре российского ПО и сертифицирован в CNCF.

Установка состоит из следующих этапов:

  1. Архитектура кластера Kubernetes.
  2. Рекомендуемые системные требования.
  3. Подготовка конфигурационного файла.
  4. Установка Kubernetes-кластера на базе Deckhouse.
  5. Добавление frontend-узлов.
  6. Добавление system-узлов.
  7. Добавление worker-узлов.
  8. Добавление master-узлов.
  9. Добавление Local Path Provisioner.
  10. Добавление балансировщика OpenELB - VIP.
  11. Добавление Ingress Nginx Controller - LoadBalancer.
  12. Добавление пользователя для доступа к веб-интерфейсу кластера.
  13. Привилегии запускаемых нагрузок.
  14. Установка HELM.

Шаг 1: Архитектура кластера Kubernetes

В рамках статьи рассматривается внедрение инфраструктуры отказоустойчивого кластера Kubernetes на базе платформы Deckhouse.

  1. Структура Kubernetes-кластера.

fail-safe-kubernetes-cluster-1

Чтобы развернуть минимальную структуру Kubernetes-кластера на базе платформы Deckhouse, потребуются:

  • персональный компьютер;
  • master-узел — три ноды;
  • worker-узел — три ноды;
  • system-узел — две ноды;
  • frontend-узел — две ноды.

В рассматриваемом примере web‑трафик от пользователей поступает на виртуальный IP‑адрес 192.168.1.13, размещённый на frontend-нодах. Шаблон доменного имени для доступа к web-сервисам платформы Deckhouse выберите %s.example.com.

Deckhouse автоматически настраивает и управляет узлами кластера и его компонентами control plane, постоянно поддерживая их актуальную конфигурацию. При развёртывании master-узлов автоматически создаются все необходимые компоненты для control plane с помощью модуля control-plane-manager.

Deckhouse создаёт сущности Kubernetes по мере необходимости и так же их удаляет. Например, если в вашем кластере нет frontend-нод и с master-нод не снято ограничение taint, вы не сможете установить IngressNginxController.  В кластере будут отсутствовать необходимые сущности, как ingressClass и так далее. При добавлении system-нод Deckhouse автоматически развернёт компоненты мониторинга и web-сервисы для доступа к интерфейсу платформы. Web-сервисы автоматически привяжутся на %s.example.com.

  1. Загрузка образов Deckhouse в локальный реестр образов.

Кластер Kubernetes с помощью Deckhouse можно развернуть в закрытом окружении, из которого нет доступа в интернет. Для этого предварительно скачайте на компьютере с доступом в интернет образы платформы Deckhouse и загрузите их в локальный реестр образов. Подробнее читайте в статье «Загрузка образов Deckhouse».

Шаг 2: Рекомендуемые системные требования

  1. Персональный компьютер:
  • ОС: Windows 10+, macOS 10.15+, Linux (Ubuntu 18.04+, Fedora 35+);
  • установленный docker для запуска инсталлятора Deckhouse;
  • доступ до проксирующего registry или до частного хранилища образов контейнеров с образами контейнеров Deckhouse;
  • SSH-доступ по ключу до узла, который будет master-узлом будущего кластера.
  1. Ноды Kubernetes:

Наименование

vCPU

RAM (GB)

Жесткий диск (GB)

LAN (Gbit/s)

Kubernetes worker

8

16

60

1

Kubernetes system

8

16

200

1

Kubernetes master

4

8

60

1

Kubernetes frontend

4

6

60

1

  • доступ до проксирующего registry или до частного хранилища образов контейнеров с образами контейнеров Deckhouse;

Начало внимание

Deckhouse поддерживает работу только с Bearer token схемой авторизации в registry.

Конец внимание

  • доступ до прокси-сервера для скачивания deb/rpm-пакетов ОС при необходимости;
  • на узле не должно быть установлено пакетов container runtime, например, containerd или docker.

Начало внимание

Установка непосредственно с master-узла в настоящий момент не поддерживается. Установщик в виде Docker-образа нельзя запускать на том же узле, на котором планируется развёртывание master-узла, так как на узле не должно быть установлено пакетов container runtime, например, containerd или docker. При отсутствии менеджмент узлов установите docker на любой другой ноде будущего кластера, запустите Docker-образ установщика, установите Deckhouse и удалите Docker-образ установщика c ноды вместе с docker.

Конец внимание

Шаг 3: Подготовка конфигурационного файла

Чтобы установить Deckhouse, подготовьте YAML-файл конфигурации установки. Для получения YAML-файла конфигурации воспользуйтесь сервисом Быстрый старт на сайте Deckhouse. Сервис сгенерирует актуальный YAML-файл для текущей версий платформы.

  1. Сгенерируйте YAML-файл сервисом Быстрый старт, выполнив следующие шаги:
  1. Выберите инфраструктуру — Bare Metal.
  2. Ознакомьтесь с информацией об установке.
  3. Укажите шаблон для DNS-имён кластера. В нашем случае — %s.example.com.
  4. Сохраните config.yml.
  1. Внесите необходимые изменения в config.yml. Для этого выполните следующие действия:
  1. Задайте адресное пространство Pod’ов кластера в podSubnetCIDR.
  2. Задайте адресное пространство Service’ов кластера в serviceSubnetCIDR.
  3. Задайте нужную версию Kubernetes в kubernetesVersion.
  4. Проверьте канал обновления в releaseChannel (Stable).
  5. Проверьте шаблон доменного имени в publicDomainTemplate (%s.example.com).
    Используется для формирования доменов системных приложений в кластере. Например, Grafana для шаблона %s.example.com будет доступна, как grafana.example.com.
  6. Проверьте режим работы модуля cni-flannel в podNetworkMode.
    Режим работы flannel, допустимые значения VXLAN (если ваши сервера имеют связность L3) или HostGW (для L2-сетей).
  7. Укажите локальную сеть, которую будут использовать узлы кластера в internalNetworkCIDRs.
    Список внутренних сетей узлов кластера, например, '192.168.1.0/24', который используется для связи компонентов Kubernetes (kube-apiserver, kubelet и т. д.) между собой.

Пример файла первичной конфигурации кластера — config.yml.

Для установки через интернет:

apiVersion: deckhouse.io/v1
kind: ClusterConfiguration
clusterType: Static
podSubnetCIDR: 10.111.0.0/16
serviceSubnetCIDR: 10.222.0.0/16
kubernetesVersion: "1.23"
clusterDomain: "cluster.local"
---
apiVersion: deckhouse.io/v1
kind: InitConfiguration
deckhouse:
  releaseChannel: Stable
  configOverrides:
    global:
      modules:
        publicDomainTemplate: "%s.example.com"
    cniFlannelEnabled: true
    cniFlannel:
      podNetworkMode: VXLAN
---
apiVersion: deckhouse.io/v1
kind: StaticClusterConfiguration
internalNetworkCIDRs:
  - 192.168.1.0/24

Для офлайн-установки без доступа в интернет:

Шаг 4: Установка Kubernetes-кластера на базе Deckhouse

Установка Deckhouse Platform Community Edition сводится к установке кластера, который состоит из единственного master-узла. Инсталлятор Deckhouse доступен в виде образа контейнера, в который необходимо передать конфигурационные файлы и SSH-ключи доступа на master-узел. Далее подразумевается, что используется SSH-ключ ~/.ssh/id_rsa. В основе инсталлятора лежит утилита dhctl.

  1. Запустите установщик.

Начало внимание

Установка непосредственно с master-узла в настоящий момент не поддерживается. Установщик в виде Docker-образа нельзя запускать на том же узле, на котором планируется развёртывание master-узла, так как на узле не должно быть установлено пакетов container runtime, например, containerd или docker.

Конец внимание

Установщик запускается на персональном компьютере, подготовленном на этапе архитектура кластера Kubernetes. На ПК перейдите в директорию с файлом конфигурации config.yml, подготовленным на этапе подготовка конфигурационного файла.

Для запуска установщика через интернет выполните команду:

sudo docker run --pull=always -it -v "$PWD/config.yml:/config.yml" -v "$HOME/.ssh/:/tmp/.ssh/" registry.deckhouse.io/deckhouse/ce/install:stable bash

Для офлайн-установки без доступа в интернет:

  1. Установите Deckhouse. Для этого внутри контейнера установщика выполните команду:

dhctl bootstrap --ssh-user=<username> --ssh-host=<master_ip> --ssh-agent-private-keys=/tmp/.ssh/id_rsa \
--config=/config.yml \
--ask-become-pass

где:

  • <username> — в параметре --ssh-user укажите имя пользователя, от которого генерировался SSH-ключ для установки;
  • <master_ip> — IP адрес master-узла подготовленного на этапе архитектура кластера Kubernetes.

Процесс установки может занять 15-30 минут при хорошем соединении.

Шаг 5: Добавление frontend-узлов

Перед добавлением frontend-нод предварительно создайте новый custom resource NodeGroup с именем frontend. Параметр nodeType в custom resource NodeGroup задайте как Static.

  1. Создайте на ноде master 1 файл frontend.yaml с описанием статичной NodeGroup с наименованием frontend:

apiVersion: deckhouse.io/v1
kind: NodeGroup
metadata:
  name: frontend
spec:
  nodeTemplate:
    labels:
      node-role.deckhouse.io/frontend: ""
    taints:
      - effect: NoExecute
        key: dedicated.deckhouse.io
        value: frontend
  nodeType: Static

  1. Примените файл frontend.yaml, выполнив команду:

kubectl create -f frontend.yaml

  1. Для добавления frontend-нод выполните следующие действия:
  1. Получите код скрипта в кодировке Base64 для добавления и настройки нового узла frontend, выполнив команду на ноде master 1:

kubectl -n d8-cloud-instance-manager get secret manual-bootstrap-for-frontend -o json | jq '.data."bootstrap.sh"' -r

  1. Зайдите на узел, который хотите добавить по SSH (в данном случае frontend 1) и вставьте полученную на первом шаге Base64‑строку:

echo <Base64-КОД-СКРИПТА> | base64 -d | bash

Дождитесь окончания выполнения скрипта. Нода добавлена.

Чтобы добавить новые frontend-ноды, выполните действия из пункта 3.

Шаг 6: Добавление system-узлов

Перед добавлением system-нод предварительно создайте новый custom resource NodeGroup с именем system. Параметр nodeType в custom resource NodeGroup задать как Static.

  1. Создайте на ноде master 1 файл system.yaml с описанием статичной NodeGroup с наименованием system:

apiVersion: deckhouse.io/v1
kind: NodeGroup
metadata:
  name: system
spec:
  nodeTemplate:
    labels:
      node-role.deckhouse.io/system: ""
    taints:
      - effect: NoExecute
        key: dedicated.deckhouse.io
        value: system
  nodeType: Static

  1. Примените файл system.yaml, выполнив команду:

kubectl create -f system.yaml

  1. Для добавления system-нод выполните следующие действия:
  1. Получите код скрипта в кодировке Base64 для добавления и настройки нового узла system, выполнив команду на ноде master 1:

kubectl -n d8-cloud-instance-manager get secret manual-bootstrap-for-system -o json | jq '.data."bootstrap.sh"' -r

  1. Зайдите на узел, который хотите добавить по SSH (в данном случае system 1) и вставьте полученную на первом шаге Base64‑строку:

echo <Base64-КОД-СКРИПТА> | base64 -d | bash

Дождитесь окончания выполнения скрипта. Нода добавлена.

Чтобы добавить новые system-ноды, выполните действия из пункта 3.

Шаг 7: Добавление worker-узлов

Перед добавлением worker-нод предварительно создайте новый custom resource NodeGroup с именем worker. Параметр nodeType в custom resource NodeGroup задать как Static.

  1. Создайте на ноде master 1 файл worker.yaml с описанием статичной NodeGroup с наименованием worker:

apiVersion: deckhouse.io/v1
kind: NodeGroup
metadata:
  name: worker
spec:
  nodeType: Static
  kubelet:
    maxPods: 200

  1. Примените файл worker.yaml, выполнив команду:

kubectl create -f worker.yaml

  1. Для добавления worker-нод выполните следующие действия:
  1. Получите код скрипта в кодировке Base64 для добавления и настройки нового узла worker, выполнив команду на ноде master 1:

kubectl -n d8-cloud-instance-manager get secret manual-bootstrap-for-worker -o json | jq '.data."bootstrap.sh"' -r

  1. Зайдите на узел, который хотите добавить по SSH (в данном случае worker 1) и вставьте полученную на первом шаге Base64-строку:

echo <Base64-КОД-СКРИПТА> | base64 -d | bash

Дождитесь окончания выполнения скрипта. Нода добавлена.

Чтобы добавить новые worker-ноды, действия из пункта 3.

Шаг 8: Добавление master-узлов

  1. Получите код скрипта в кодировке Base64 для добавления и настройки нового узла master, выполнив команду на ноде master 1:

kubectl -n d8-cloud-instance-manager get secret manual-bootstrap-for-master -o json | jq '.data."bootstrap.sh"' -r

  1. Зайдите на узел, который хотите добавить по SSH (в данном случае master 2) и вставьте полученную на первом шаге Base64-строку:

echo <Base64-КОД-СКРИПТА> | base64 -d | bash

Дождитесь окончания выполнения скрипта. Нода добавлена.

Чтобы добавить новые master-ноды, выполните действия из шага 8.

Шаг 9: Добавление Local Path Provisioner

По умолчанию storageclass отсутствует в Deckhouse. Создайте custom resource LocalPathProvisioner, позволяющий пользователям Kubernetes использовать локальное хранилище на узлах. Для этого выполните следующие действия:

  1. Создайте на master-узле файл local-path-provisioner.yaml, содержащий конфигурацию для LocalPathProvisioner.
  1. Установите нужную Reclaim policy (по умолчанию устанавливается Retain). В рамках статьи для параметра reclaimPolicy установлено "Delete" (PV после удаления PVC удаляются).

Пример файла local-path-provisioner.yaml:

apiVersion: deckhouse.io/v1alpha1
kind: LocalPathProvisioner
metadata:
  name: localpath-deckhouse-system
spec:
  nodeGroups:
  - system
  - worker
  path: "/opt/local-path-provisioner"
  reclaimPolicy: "Delete"

  1. Примените файл local-path-provisioner.yaml в Kubernetes. Для этого выполните команду:

kubectl apply -f local-path-provisioner.yaml

  1. Установите созданный LocalPathProvisioner, как storageclass по умолчанию (default-class), выполнив команду:

kubectl patch storageclass localpath-deckhouse-system -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

LocalPathProvisioner с наименованием localpath-deckhouse-system создан и готов предоставлять локальные хранилища на узлах c NodeGroup system и worker.

Шаг 10: Добавление балансировщика OpenELB-VIP

Для правильной работы Ingress-контроллера требуется прямой выход в интернет с белым IP-адресом на Ingress-узле кластера с использованием NodePort, или можно установить балансировщик OpenELB, который будет заниматься балансировкой трафика так, как это организовано у любого облачного провайдера. Этот балансировщик использует Keepalived для поддержки IP-адреса службы.

Разверните OpenELB в режиме VIP Mode. Для того:

  1. Получите конфигурационный файл values-openelb.yaml.

Для установки через интернет:

helm repo add elma365 https://charts.elma365.tech
helm repo update
helm show values elma365/openelb > values-openelb.yaml

Получение конфигурационного файла для установки в закрытом контуре без доступа в интернет.

  1. Измените конфигурационный файл values-openelb.yaml.

Запланируйте размещение подов openelb-manager на frontend-нодах кластреа. Для этого измените секции tolerations и nodeSelector:

## Настройки openelb
openelb:
  manager:
    apiHosts: ":50051"
    webhookPort: 443
    tolerations:
      - key: CriticalAddonsOnly
        operator: Exists
      - effect: NoExecute
        key: dedicated.deckhouse.io
        operator: Equal
        value: frontend
    nodeSelector:
      kubernetes.io/os: linux
      node-role.deckhouse.io/frontend: ""
...

Заполнение параметров подключения к приватному registry для установки в закрытом контуре без доступа в интернет.

  1. Установите OpenELB в Kubernetes.

Для установки через интернет:

helm upgrade --install openelb elma365/openelb -f values-openelb.yaml -n openelb-system --create-namespace

Для офлайн-установки без доступа в интернет:

  1. Настройте отказоустойчивость openelb-manager.

Для достижения отказоустойчивости увеличьте количестесво реплик openelb-manager, выполнив команду на ноде master 1:

kubectl scale --replicas=2 deployment openelb-manager -n openelb-system

Выполните следующую команду, чтобы проверить находится ли openelb-manager в состоянии READY: 1/1 и STATUS: Running. Если да, OpenELB успешно установлен.

kubectl get po -n openelb-system

  1. Создайте пул IP-адресов для OpenELB.

Создайте на ноде master 1 файл vip-eip.yaml с описанием EIP‑объекта. Объект Eip функционирует как пул IP-адресов для OpenELB.

Пример файла vip-eip.yaml:

apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
  name: vip-eip
spec:
  address: 192.168.1.13
  protocol: vip

Примените файл vip-eip.yaml в Kubernetes, выполнив команду:

kubectl apply -f vip-eip.yaml

  1. Переместите поды keepalived на frontend-узлы.

По умолчанию поды keepalived размещаются openelb-manager на worker-узлах. В рамках статьи поды keepalived нужно разместить на frontend‑узлах.

Внесите изменения в DaemonSet openelb-keepalive-vip, выполнив команду на ноде master 1:

kubectl patch ds -n openelb-system openelb-keepalive-vip -p '{"spec":{"template":{"spec":{"nodeSelector":{"kubernetes.io/os":"linux","node-role.deckhouse.io/frontend":""},"tolerations":[{"key":"dedicated.deckhouse.io","value":"frontend","effect":"NoExecute"}]}}}}'

Проверьте, что изменения, внесённые в DaemonSet openelb-keepalive-vip применились и поды разместились на нодах frontend:

kubectl get po -o wide -n openelb-system

Шаг 11: Добавление Ingress Nginx Controller - LoadBalancer

Deckhouse устанавливает и управляет NGINX Ingress Controller при помощи Custom Resources. Если узлов для размещения Ingress-контроллера больше одного, он устанавливается в отказоустойчивом режиме и учитывает все особенности реализации инфраструктуры облаков и bare metal, а также кластеров Kubernetes различных типов.

  1. Создайте на ноде master 1 файл ingress-nginx-controller.yml, содержащий конфигурацию Ingress-контроллера.

Пример файла ingress-nginx-controller.yml:

  1. Примените файл ingress-nginx-controller.yml в Kubernetes, выполнив команду:

kubectl create -f ingress-nginx-controller.yml

После установки ingress-контроллера Deckhouse автоматически создаст сервис nginx-load-balancer в namespace d8-ingress-nginx, но не свяжет данный сервис с OpenELB.

  1. Добавьте annotations и labels для OpenELB в сервис nginx-load-balancer, выполнив команду на ноде master 1:

kubectl patch svc -n d8-ingress-nginx nginx-load-balancer -p '{"metadata":{"annotations":{"eip.openelb.kubesphere.io/v1alpha2":"vip-eip","lb.kubesphere.io/v1alpha1":"openelb","protocol.openelb.kubesphere.io/v1alpha1":"vip"},"labels":{"eip.openelb.kubesphere.io/v1alpha2":"vip-eip"}}}'

  1. Проверьте, что изменения внесённые в сервис nginx-load-balancer применились, в EXTERNAL-IP появился ip-адрес 192.168.1.13. Для этого выполните следующую команду:

kubectl get svc -n d8-ingress-nginx

Шаг 12: Добавление пользователя для доступа к веб-интерфейсу кластера

  1. Создайте на ноде master 1 файл user.yml, содержащий описание учётной записи пользователя и прав доступа.

Пример файла user.yml:

  1. Примените файл user.yml в Kubernetes, выполнив команду:

kubectl create -f user.yml

Шаг 13. Привилегии запускаемых нагрузок

Разрешите переназначить политику привилегий для запускаемых подов:

kubectl label namespace elma365 security.deckhouse.io/pod-policy=privileged --overwrite

Шаг 14: Установка HELM

  1. Перейдите на страницу релизов Helm и скачайте архив helm-vX.Y.Z-linux-amd64.tar.gz нужно версии.

Для установки через интернет:

wget https://get.helm.sh/helm-vX.Y.Z-linux-amd64.tar.gz

Для офлайн-установки без доступа в интернет:

  1. Распакуйте архив и переместите бинарный файл helm:

tar -zxvf helm-vX.Y.Z-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/helm