Установка#

Для работы с Global Server на кластере Kubernetes требуется:

  • jump-хост, с которого будет установлен и будет обслуживаться кластер

  • готовый к работе кластер Kubernetes, отвечающий вашим требованиям по производительности и отказоустойчивости

  • развернутая PostgreSQL с базой данных для Global ERP

  • NFS-хранилище

Чтобы получить простейший кластер Kubernetes:

  1. установите kubelet, kubeadm и kubectl

  2. запустите kubeadm init на ведущем хосте для инициализации кластера и получите токен для присоединения других нод к кластеру

  3. подключите ведомые хосты при помощи команды kubeadm join и токена

  4. установите сетевой плагин CNI, такой как Flannel или Calico.

Подробнее читайте в документации Kubernetes.

Настройка узла администрирования (jump host)#

Установка необходимых пакетов#

На jump-хост необходимо установить следующие пакеты:

sudo apt-get install mc htop 
sudo apt-get install -y kubectl
sudo apt-mark hold kubectl
sudo apt install nfs-common

Совет

Версия kubectl должна соответствовать версии в платформе kubernetes или быть новее

Настройка работы с docker образами#

Если требуется работа с образами из docker регистра

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER

Insecure Docker Registry#

Если кластер запускается в закрытой сети, docker регистр может не использовать SSL (Insecure Docker Registry). Запуск Insecure Docker Registry для хранения своих docker-образов не самый лучший вариант с точки зрения безопасности, но порой это самое простое и разумное решение в закрытых сетях.

Для настройки нужно изменить (или создать, если такового нет) конфигурационный файл /etc/docker/daemon.json, добавив в него следующие строки:

{
    "insecure-registries" : ["myregistry.example.local:1234"]
}

, где myregistry.example.local:1234 - адрес и порт локального докер регистра

скрипт для создания файла:

cat <<EOF | sudo tee /etc/docker/daemon.json
{
    "insecure-registries" : ["myregistry.example.local:1234"]
}
EOF

После чего выполнить перезапуск сервиса с помощью:

sudo systemctl restart docker

Настройка авторизации kubernetes кластера#

Получите конфигурационный файл авторизации для кластера Kubernetes. При создании кластера при помощи kubeadm init, такой файл сохраняется по пути /etc/kubernetes/admin.conf.

Пример файла:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJUkMwZFZrYXhBTE13RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBeE1UZ3hOekUzTkRoYUZ3MHpOREF4TVRVeE56SXlORGhhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURRK0FxbVlpT2dJZnJhQ3NocXJOZ2hGQVA2dWtKSG1idjhpTGQzeDIvcXBGVENacDFldCtmTW9QMmcKSDluaXloRm00NjNTbXZzS0JCRml2Um5YbGpLOE9EMmM2U2E1NkVndEQzY3dmR0hsLzczTFQzQUZVeE5vL2RsLwo5dkNnNWQvbG5Ya3VqUVJmRmVQZHJUc3AyMU5YOGc2a25WbmRYaFlidExJNmVpbUF0SE92L1dCYndmbU9HZllBCkovdCt6Y3c2eG11OGFrcGFTeFN0ZWxlUGxSSG5XWnJ2U0w2LzJ1a094aHZFVnpJbFAxQy9yMGcvblhUZjVIcWUKSU9pSFM3TGRKVWxrUW5HblNVRDJ2cWJYOUV5S0tJMWV5dS83NHBiaE1qdE9HdFVDMHQxUUhRM0JWaWx6dXZTTwp0TTg2U1JBeVR4aURud2tyYmYrUmEzQ3BiRmNkQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL
    server: https://127.0.0.1:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJR04ydFhtNkEzc2N3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBeE1UZ3hOekUzTkRoYUZ3MHlOVEF4TVRjeE56SXlORGxhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDcy9rekkKOWxudHRtRVdQa2xhWWVMYzZnc2pOWENQV0JFM1QvenVYeE8yNDdRMW5yZDFQcXdwdWVHMmYySUNOVWVXb0RJTgpQOHZYa2JQWTRZNkdZUUt0SFdVS1czejVUL2RNdVVRVFFabkVoZEk2cEs0M05saHBHVy81WWt0dWRuNU1KT1ZoCk5OV0pxYXVmazNMV3VmQUZKWWJXSTkrcmRvYS9NRHNib0p1ZXk0S1dGeGdaVkR3SGdORUxmUmc2N01RbVYxV2oKdHVnTnJFcXJEdDdJQzVWQ0V0RVBqWGlxSzJZNHJxVWMzQlJyWVZydkVRMXZYREhYbDBSTytUYVpEMVVxSTVDawpUYUVVYjNnY2tlbVdjYXEwdGVQNjIyZFUvL09LbktoNnJ5VU0xZkFXUFBFa1pKbEF3VHZLOW15L2p3OXdJaXJKCkhib0RpZEltZGZ0aWhvTC9BZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkg4Y1pPR3lyNlRsSk0wWgprTTZtS2grS2ZpRGtNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUE5SVduWENrY0lraGFSODlxV1VH
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBclA1TXlQWlo3YlpoRmo1SldtSGkzT29MSXpWd2oxZ1JOMC84N2w4VHR1TzBOWjYzCmRUNnNLYm5odG45aUFqVkhscUF5RFQvTDE1R3oyT0dPaG1FQ3JSMWxDbHQ4K1UvM1RMbEVFMEdaeElYU09xU3UKTnpaWWFSbHYrV0pMYm5aK1RDVGxZVFRWaWFtcm41Tnkxcm53QlNXRzFpUGZxM2FHdnpBN0c2Q2Juc3VDbGhjWQpHVlE4QjREUkMzMFlPdXpFSmxkVm83Ym9EYXhLcXc3ZXlBdVZRaExSRDQxNHFpdG1PSzZsSE53VWEyRmE3eEVOCmIxd3gxNWRFVHZrMm1ROVZLaU9RcEUyaEZHOTRISkhwbG5HcXRMWGordHRuVlAvemlweW9lcThsRE5Yd0ZqengKSkdTWlFNRTd5dlpzdjQ4UGNDSXF5UjI2QTRuU0puWDdZb2FDL3dJREFRQUJBb0lCQUZCTTFxMnVGTDVRR3k3dApDTFdvbkZyNVZPUXFDUzZ3cllVa1h2N3pLVDZLNGZyRnl0amtsNXZpeWRBaHZ3ZlJYWUtncDdzWXN2RkVrOXdICmoxWDNML3ZWbWpJOWwzeE96emRSQkRXQURQVjVQTVcxN1p4NVlINmdyU1p3cHgwR2FjZkVsS2tUa2srTmI3bnEKQXJPRHFkTnB3UFlqdnM1amZWYS85NS95WkdwSHYwMWJTajQvejZlL1RKS0NFaXVhZys5Z2JTbWswS2k4MWxzYgpIMEp3ZEZPWXpBUHkrQTFScUZPdHVyTnNRclRqZ1ZMWTBvSUliSkVDcHdDQitWZDJaNDVsYWtoREtTUWZ3dkFPCjVuTVJucEZ3S29Kb0NiSE9yUUpIbmJnOHJsVVV5Y3Jqb0xaYTliOUxRZlMvMk54Ti9YNTBsV3JNWk1LWGxVbGIKMkU5bGJSa0NnWUVBNHhaZDNnWU9Sc3dHQTJjVk1vK0YrdERoTkY4UUdmeVVDWkZxRDRZMVRR=

Настройте авторизацию kubernetes

# создаем каталог с конфигурацией
mkdir ~/.kube && \
chmod -R 0700 ~/.kube && \
cd ~/.kube

# сохраняем файл 
cat <<EOF | tee ~/.kube/config
apiVersion: v1
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJUkMwZFZrYXhBTE13RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBeE1UZ3hOekUzTkRoYUZ3MHpOREF4TVRVeE56SXlORGhhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURRK0FxbVlpT2dJZnJhQ3NocXJOZ2hGQVA2dWtKSG1idjhpTGQzeDIvcXBGVENacDFldCtmTW9QMmcKSDluaXloRm00NjNTbXZzS0JCRml2Um5YbGpLOE9EMmM2U2E1NkVndEQzY3dmR0hsLzczTFQzQUZVeE5vL2RsLwo5dkNnNWQvbG5Ya3VqUVJmRmVQZHJUc3AyMU5YOGc2a25WbmRYaFlidExJNmVpbUF0SE92L1dCYndmbU9HZllBCkovdCt6Y3c2eG11OGFrcGFTeFN0ZWxlUGxSSG5XWnJ2U0w2LzJ1a094aHZFVnpJbFAxQy9yMGcvblhUZjVIcWUKSU9pSFM3TGRKVWxrUW5HblNVRDJ2cWJYOUV5S0tJMWV5dS83NHBiaE1qdE9HdFVDMHQxUUhRM0JWaWx6dXZTTwp0TTg2U1JBeVR4aURud2tyYmYrUmEzQ3BiRmNkQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL
    server: https://127.0.0.1:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJR04ydFhtNkEzc2N3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBeE1UZ3hOekUzTkRoYUZ3MHlOVEF4TVRjeE56SXlORGxhTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDcy9rekkKOWxudHRtRVdQa2xhWWVMYzZnc2pOWENQV0JFM1QvenVYeE8yNDdRMW5yZDFQcXdwdWVHMmYySUNOVWVXb0RJTgpQOHZYa2JQWTRZNkdZUUt0SFdVS1czejVUL2RNdVVRVFFabkVoZEk2cEs0M05saHBHVy81WWt0dWRuNU1KT1ZoCk5OV0pxYXVmazNMV3VmQUZKWWJXSTkrcmRvYS9NRHNib0p1ZXk0S1dGeGdaVkR3SGdORUxmUmc2N01RbVYxV2oKdHVnTnJFcXJEdDdJQzVWQ0V0RVBqWGlxSzJZNHJxVWMzQlJyWVZydkVRMXZYREhYbDBSTytUYVpEMVVxSTVDawpUYUVVYjNnY2tlbVdjYXEwdGVQNjIyZFUvL09LbktoNnJ5VU0xZkFXUFBFa1pKbEF3VHZLOW15L2p3OXdJaXJKCkhib0RpZEltZGZ0aWhvTC9BZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkg4Y1pPR3lyNlRsSk0wWgprTTZtS2grS2ZpRGtNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUE5SVduWENrY0lraGFSODlxV1VH
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBclA1TXlQWlo3YlpoRmo1SldtSGkzT29MSXpWd2oxZ1JOMC84N2w4VHR1TzBOWjYzCmRUNnNLYm5odG45aUFqVkhscUF5RFQvTDE1R3oyT0dPaG1FQ3JSMWxDbHQ4K1UvM1RMbEVFMEdaeElYU09xU3UKTnpaWWFSbHYrV0pMYm5aK1RDVGxZVFRWaWFtcm41Tnkxcm53QlNXRzFpUGZxM2FHdnpBN0c2Q2Juc3VDbGhjWQpHVlE4QjREUkMzMFlPdXpFSmxkVm83Ym9EYXhLcXc3ZXlBdVZRaExSRDQxNHFpdG1PSzZsSE53VWEyRmE3eEVOCmIxd3gxNWRFVHZrMm1ROVZLaU9RcEUyaEZHOTRISkhwbG5HcXRMWGordHRuVlAvemlweW9lcThsRE5Yd0ZqengKSkdTWlFNRTd5dlpzdjQ4UGNDSXF5UjI2QTRuU0puWDdZb2FDL3dJREFRQUJBb0lCQUZCTTFxMnVGTDVRR3k3dApDTFdvbkZyNVZPUXFDUzZ3cllVa1h2N3pLVDZLNGZyRnl0amtsNXZpeWRBaHZ3ZlJYWUtncDdzWXN2RkVrOXdICmoxWDNML3ZWbWpJOWwzeE96emRSQkRXQURQVjVQTVcxN1p4NVlINmdyU1p3cHgwR2FjZkVsS2tUa2srTmI3bnEKQXJPRHFkTnB3UFlqdnM1amZWYS85NS95WkdwSHYwMWJTajQvejZlL1RKS0NFaXVhZys5Z2JTbWswS2k4MWxzYgpIMEp3ZEZPWXpBUHkrQTFScUZPdHVyTnNRclRqZ1ZMWTBvSUliSkVDcHdDQitWZDJaNDVsYWtoREtTUWZ3dkFPCjVuTVJucEZ3S29Kb0NiSE9yUUpIbmJnOHJsVVV5Y3Jqb0xaYTliOUxRZlMvMk54Ti9YNTBsV3JNWk1LWGxVbGIKMkU5bGJSa0NnWUVBNHhaZDNnWU9Sc3dHQTJjVk1vK0YrdERoTkY4UUdmeVVDWkZxRDRZMVRR=
EOF

Проверяем доступ

kubectl cluster-info
kubectl get nodes -o wide

При успешном подключении должны получить вывод:

Kubernetes control plane is running at https://0.0.0.0:6443
CoreDNS is running at https://0.0.0.0:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
NAME           STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION    CONTAINER-RUNTIME
k8s-master01   Ready    control-plane   46d   v1.29.1   0.0.0.0         <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-27-amd64   containerd://1.6.27
k8s-worker01   Ready    <none>          46d   v1.29.1   0.0.0.0         <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-27-amd64   containerd://1.6.27
k8s-worker02   Ready    <none>          46d   v1.29.1   0.0.0.0         <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-27-amd64   containerd://1.6.27
k8s-worker03   Ready    <none>          46d   v1.29.1   0.0.0.0         <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-27-amd64   containerd://1.6.27

Требования к ос для nscli#

  • GNU/Linux, а именно:

    • Debian 11 и выше

  • Python 3.9

Требование к железу для запуска nscli#

  • 2 ядра

  • 200 Мб оперативной памяти

  • 30 Гб свободного места

Установка утилиты Nscli#

Nscli автоматизирует работу по развертыванию кластера Global.

Установка:

#Скачиваем из репозитория
cd ~
wget --backups=1 --user=<пользователь> --ask-password "https://repo.global-system.ru/artifactory/general/ru/bitec/gs-ctk-nscli/4.8.2/gs-ctk-nscli-4.8.2.zip"
unzip -o gs-ctk-nscli-4.8.2.zip -d nscli

где <пользователь> - учетная запись, полученная через контактное лицо технической поддержки.

Совет

В закрытой среде требуется установить все пакеты, указанные в скрипте ~/nscli/bin/installpkg.sh вручную

Перейдите в каталог с утилитой и выполняем первичную установку

cd ~/nscli
# выполняем скрипты установки
./bin/initvenv.sh

Jump-хост готов к работе.

Настройка рабочего пространства в kubernetes#

Для настройки подключаемся по ssh к jump-хосту

Перейдите в каталог с утилитой

cd ~/nscli

Запустите мастер создания манифеста рабочего пространства

./namespace.sh create_install_scripts

Примечание

В более современных версиях nscli доступна команда ./namespace.sh create_namespace

В режиме диалога введите параметры рабочего пространства:

  • Имя рабочего пространства - имя воркспейса, который будет создан в kubernetes

  • Адрес докер регистра - адрес ресурса с хранилищем образов (Публичный докер регистр Global: dockerhub.global-system.ru)

  • Имя файла для хранения мастер ключа - полный путь с именем файла, в котором будет храниться мастер ключ для шифрования паролей

  • Пользователь для авторизации докера - имя пользователя для авторизации, при анонимном доступе поле можно оставить пустым.

  • Пароль для авторизации докера - пароль для авторизации в регистре (вводится два раза)

  • Тип репозитория - тип репозитория, по умолчанию nfs

  • Имя сервера nfs - указываем ip адрес или доменное имя заранее настроенного NFS сервера

  • Путь - путь для подключения тома

Примечание

В NFS-репозитории будет храниться комплект приложений. Для хранения другой информации, в том числе пользовательских файлов, используются прикладное хранилище Appvolume и другие NFS-хранилища, настраиваемые позже с помощью скрипта resgroup.sh в составе утилиты nsctl (читайте подробнее в документации gs-ctk).

Пример работы мастера создания пространства имен:

k8sadmin@k8s-terminal02:~/nscli$ ./namespace.sh create_install_scripts
Введите имя рабочего пространства:gs-cluster-k8s
Введите адрес докер регистра:dockerhub.global-system.ru
Для безопасного хранения паролей необходимо сгенерировать приватный ключ.
Укажите имя файла для хранения мастер ключа:/home/k8sadmin/.gs-ctk.priv
Введите пользователя для авторизации докера:userk8s
Введите пароль для авторизации докера:**********
Введите пароль для авторизации докера:**********
Выберите тип репозитория:nfs
Необходимо задать параметры для Network File System
Введите имя сервера:0.0.0.0
Введите путь:/mnt/nfs/gs-cluster-k8s
k8sadmin@k8s-terminal02:~/nscli$

Примечание

В новейших версиях доступна команда:

./namespace.sh install_namespace

Если команда присутствует, вам будет автоматически предложено ей воспользоваться. После успешного выполнения переходите сразу к пункту «Подготовка комплекта приложений appkit».

Рекомендуем пользоваться этой командой. Она не только развернет пространство имен и под nsctl, как предыдущий способ, но также проверит:

  • установку сетевого плагина

  • готовность нод к развертыванию контейнеров

  • наличие связи между подами

  • возможность записи в системное хранилище

Вы можете запустить диагностику кластера отдельно по команде ./namespace.sh diagnose.

Примечание

Если в вашем кластере используются taints и tolerations, тогда для запуска пода nsctl нужно дополнить шаблон nscli/profile/namespace/template/deploy.yaml, добавив туда раздел с tolerations.

Пример:

...
spec:
  tolerations:
    - key: "node"
      operator: "Equal"
      value: "first"
      effect: "NoSchedule"
  containers:
...

Для добавления tolerations к подам, которые создает nsctl, смотри раздел «Хуки»

Разрешите запуск скрипта установки рабочего пространства

chmod +x ~/nscli/workspace/install_scripts/gs-cluster-k8s/install.sh

Создайте рабочее пространство

~/nscli/workspace/install_scripts/gs-cluster-k8s/install.sh

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

namespace/gs-cluster-k8s created
secret/docker-registry-secret created
configmap/values created
role.rbac.authorization.k8s.io/worker created
rolebinding.rbac.authorization.k8s.io/worker-pods created
deployment.apps/nsctl created

Подготовка комплекта приложений appkit#

Комплект приложений определяет перечень артефактов, необходимых для разворачивания кластера системы Global ERP:

  • Дистрибутив сервера приложений (globalserver)

  • Образ прикладного решения (applib)

  • Профиль с шаблонами конфигурационных файлов (profile)

Опционально в комплект приложений также входит:

  • Исходный код для отладки прикладного решения (appsrc)

Комплект можно хранить в виде zip-архивов (globalserver.zip, applib.zip, profile.zip) или в распакованном виде в одноименных папках (globalserver/, applib/, profile/). Во втором случае файлы перед загрузкой на сетевое хранилище самой утилитой запаковываются в архив.

В профиле с шаблонами конфигурационных файлов находятся:

  • Конфигурация сервера приложений globalserver/template/config/global3.config.xml

  • Конфигурация сборщика телеметрии globalserver/template/config/otel-sdk.config.yaml и globalserver/template/config/otel-globalserver.config.yaml

  • Конфигурация менеджера заданий globalscheduler/template/config/quartz.properties

  • Конфигурация проектных настроек системных логов globalscheduler/template/config/logback-LoggerContext-ext.xml

  • Конфигурация проектных настроек логов сессии globalscheduler/template/config/logback-LoggerContext-session-ext.xml

Если в комплекте при загрузке его на сетевое хранилище, профиль отсутствует, то nscli создаст стандартный профиль, который, обычно, не требует изменений.

Как работать и настраивать файлы с логами можно посмотреть в документации по логам

Для создания комплекта приложений используйте каталог ~/nscli/workspace/appkit/v1

mkdir -p ~/nscli/workspace/appkit/v1/

Подготовте и загрузите в этот каталог дистрибутивы.

mv globalserver.zip ~/nscli/workspace/appkit/v1
mv applib.zip ~/nscli/workspace/appkit/v1

Подготовте комплект приложений для работы

./appkit.sh push --namespace gs-cluster-k8s --source workspace/appkit/v1 --destination appkits/v1

Утилита создаст, при необходимости, стандартный профиль, упакует комплект приложений, а также создаст контрольные суммы

Не найден профиль с шаблонами конфигурации, создать профиль по умолчанию?[да,нет]:да
Загружен файл:globalserver.zip
Загружен файл:profile.zip
Загружен файл:applib.zip

Подготовка комплекта группы groupkit#

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

./groupkit.sh push --namespace gs-cluster-k8s --source workspace/groupkit/v1 --destination groupkits/v1

Работа с постоянными томами#

Данные в кластере Kubernetes могут храниться несколькими способами: непосредственно в контейнере или на томах (volumes). При хранении данных в контейнере возникают проблемы:

  • При сбое или остановке контейнера данные теряются.

  • Данные контейнера недоступны для других контейнеров, даже если все контейнеры находятся в одном поде.

Чтобы решить эти проблемы, используются тома Kubernetes. Тома имеют разный жизненный цикл в зависимости от сценария использования:

  • У временных томов (ephemeral volume, EV) жизненный цикл совпадает с жизненным циклом пода. Когда под, использующий такой том, прекращает свое существование, том тоже удаляется. Временные тома могут использоваться только одним подом, поэтому объявление томов происходит непосредственно в манифесте пода.

  • У постоянных томов (persistent volume, PV) свой жизненный цикл, не зависящий от жизненного цикла пода. Благодаря разделению жизненных циклов такие тома можно переиспользовать позднее с другими подами. Для работы с постоянными томами поды и другие рабочие нагрузки используют Persistent Volume Claim (PVC).

Кластеру Глобал ERP потребуется постоянный том для хранения метрик.

Kubernetes поддерживает разные типы хранилищ, ниже представлен пример хранилища на основе локального каталога.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-50
spec:
  capacity:
    storage: 50Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/disk1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-worker01
cat <<EOF | tee ~/nscli/workspace/local-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-50
spec:
  capacity:
    storage: 50Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/disk1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-worker01
EOF
kubectl apply -f ~/nscli/workspace/local-pv.yaml

Создание секретов#

Секреты используются для безопасного хранения учетных данных

  • Создайте секрет для доступа к статистике haproxy

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-haproxy-auth
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: t0p-Secret
    
    cat <<EOF | tee ~/nscli/workspace/haproxy-sercret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-haproxy-auth
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: t0p-Secret
    EOF
    
    kubectl apply -f ~/nscli/workspace/haproxy-sercret.yaml
    
    • При необходимости, создайте ssl-сертификат для haproxy и поместите его в секрет

    Создайте ssl-сертификат с помощью openssl, заменив «example» домены на собственные.

    Пример создания ssl-сертификата:

    openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
    -keyout ca.key -out ca.crt -subj '/CN=example.com' 
    

    Пример создания мультидоменного ssl-сертификата:

    openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
    -keyout ca.key -out ca.crt -subj '/CN=example.com' \
    -addext 'subjectAltName=DNS:example.com,DNS:example.net'
    

    Создайте секрет, заменив значения шаблона <cert-b64> и <key-b64> на значения, сгенерированные с помощью следующих команд:

    cat ./ca.crt | base64
    cat ./ca.key | base64
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: haproxy-tls
      namespace: gs-cluster-k8s
    type: Opaque
    data:
      tls.crt: |
        <cert-b64>
      tls.key: |
        <key-b64>
    
    cat <<EOF | tee ~/nscli/workspace/haproxy-tls.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: haproxy-tls
      namespace: gs-cluster-k8s
    type: Opaque
    data:
      tls.crt: |
        $(cat ./ca.crt | base64 -w 0)
      tls.key: |
        $(cat ./ca.key | base64 -w 0)
    EOF
    
    kubectl apply -f ~/nscli/workspace/haproxy-tls.yaml
    
  • Создайте секрет с admin аккаунтом globalserver-а

    apiVersion: v1
    kind: Secret
    metadata:
      name: gs-admin-auth
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: Secret#123#Pass!
    
    cat <<EOF | tee ~/nscli/workspace/admin-auth-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: gs-admin-auth
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: Secret#123#Pass!
    EOF
    
    kubectl apply -f ~/nscli/workspace/admin-auth-secret.yaml
    
  • Создайте секрет с аккаунтом пользователя БД, заменив значения шаблона <username> и <password> на корректные

    apiVersion: v1
    kind: Secret
    metadata:
      name: db-user-secret
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: <username>
      password: <password>
    
    cat <<EOF | tee ~/nscli/workspace/db-user-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-user-secret
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: <username>
      password: <password>
    EOF
    
    kubectl apply -f ~/nscli/workspace/db-user-secret.yaml
    
  • Создайте секрет с аккаунтом клиентского пользователя RabbitMQ

    apiVersion: v1
    kind: Secret
    metadata:
      name: rabbitmq-global
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: globalrabbitmq
      password: globalrabbitmq
    
    cat <<EOF | tee ~/nscli/workspace/rabbitmq-global.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: rabbitmq-global
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: globalrabbitmq
      password: globalrabbitmq
    EOF
    
    kubectl apply -f ~/nscli/workspace/rabbitmq-global.yaml
    
  • Создайте секрет с аккаунтом администратора RabbitMQ

    apiVersion: v1
    kind: Secret
    metadata:
      name: rabbitmq-admin
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: Secret#123#Pass!
    
    cat <<EOF | tee ~/nscli/workspace/rabbitmq-admin.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: rabbitmq-admin
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: Secret#123#Pass!
    EOF
    
    kubectl apply -f ~/nscli/workspace/rabbitmq-admin.yaml
    
  • Создайте секрет с токеном планировщика, заменив значение шаблона <key> на корректное

    Внимание

    Токен планировщика должен быть закодирован в Base64, читайте подробнее здесь.

    apiVersion: v1
    kind: Secret
    metadata:
      name: scheduler-token-secret
      namespace: gs-cluster-k8s
    data:
      private.key: <key>
    
    cat <<EOF | tee ~/nscli/workspace/scheduler-token-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: scheduler-token-secret
      namespace: gs-cluster-k8s
    data:
      private.key: <key>
    EOF
    
    kubectl apply -f ~/nscli/workspace/scheduler-token-secret.yaml
    
  • Создайте секрет с аккаунтом администратора Графаны.

    apiVersion: v1
    kind: Secret
    metadata:
      name: grafana-admin
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: admin
    
    cat <<EOF | tee ~/nscli/workspace/grafana-admin-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: grafana-admin
      namespace: gs-cluster-k8s
    type: kubernetes.io/basic-auth
    stringData:
      username: admin
      password: admin
    EOF
    
    kubectl apply -f ~/nscli/workspace/grafana-admin-secret.yaml
    

Сервис аккаунт для получения метрик cAdvisor#

  • Создайте сервис аккаунт

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: prometheus-cadvisor
      namespace: gs-cluster-k8s
    
    cat <<EOF | tee ~/nscli/workspace/cadvisor-sa.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: prometheus-cadvisor
      namespace: gs-cluster-k8s
    EOF
    
    kubectl apply -f ~/nscli/workspace/cadvisor-sa.yaml
    
  • Создайте роль

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: prometheus-cadvisor
    rules:
    - apiGroups: [""]
      resources:
      - nodes
      - nodes/proxy
      - services
      - endpoints
      - pods
      verbs: ["get", "list", "watch"]
    - apiGroups:
      - extensions
      resources:
      - ingresses
      verbs: ["get", "list", "watch"]
    - nonResourceURLs: ["/metrics"]
      verbs: ["get"]
    
    cat <<EOF | tee ~/nscli/workspace/cadvisor-role.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: prometheus-cadvisor
    rules:
    - apiGroups: [""]
      resources:
      - nodes
      - nodes/proxy
      - services
      - endpoints
      - pods
      verbs: ["get", "list", "watch"]
    - apiGroups:
      - extensions
      resources:
      - ingresses
      verbs: ["get", "list", "watch"]
    - nonResourceURLs: ["/metrics"]
      verbs: ["get"]                                
    EOF
    
    kubectl apply -f ~/nscli/workspace/cadvisor-role.yaml
    
  • Создайте биндинг роли

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: prometheus-cadvisor
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: prometheus-cadvisor
    subjects:
    - kind: ServiceAccount
      name: prometheus-cadvisor
      namespace: gs-cluster-k8s
    
    cat <<EOF | tee ~/nscli/workspace/cadvisor-role-binding.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: prometheus-cadvisor
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: prometheus-cadvisor
    subjects:
    - kind: ServiceAccount
      name: prometheus-cadvisor
      namespace: gs-cluster-k8s
    EOF
    
    kubectl apply -f ~/nscli/workspace/cadvisor-role-binding.yaml
    

Настройка параметров кластера#

Параметры кластера настраиваются с помощью пода nsctl

Для настройки нужно подключится к поду nsctl, который был запущен при создании рабочего пространства.

Получите список подов рабочего простнанства

kubectl get pods --namespace gs-cluster-k8s
NAME                     READY   STATUS    RESTARTS   AGE
nsctl-7f97cb6df4-8kjkc   1/1     Running   0          57m

Получите доступ по ssh в под nsctl

kubectl -n gs-cluster-k8s exec -it nsctl-7f97cb6df4-8kjkc -- /bin/bash

Совет

В более новых версиях nscli доступна команда ./namespace.sh shell для подключения к поду nsctl.

Выполните первоначальную настройку

# создаем группу
./resgroup.sh create --name gs-cluster-1 
# указываем актуальный appkit
./resgroup.sh switch_appkit --name gs-cluster-1 --path appkits/v1
# если вы загружали groupkit, то укажите его следующей командой
# ./resgroup.sh switch_groupkit --name gs-cluster-1 --path appkits/v1
# создаем эксклюзивный экземпляр
./resbook.sh create --name global-server-excl --group gs-cluster-1 --class_name global_server_excl
# создаем клонируемые экземпляры
./resbook.sh create --name global-server-share --group gs-cluster-1 --class_name global_server_share
#экземпляр шедулера
./resbook.sh create --name global-scheduler --group gs-cluster-1 --class_name global_scheduler
# ресурсы балансировщика и мониторинга
./resbook.sh create --name haproxy --group gs-cluster-1 --class_name haproxy
./resbook.sh create --name grafana --group gs-cluster-1 --class_name grafana
# ресурс RabbitMQ
./resbook.sh create --name rabbitmq --group gs-cluster-1 --class_name rabbitmq

Примечание

О группах и книгах ресурсов читайте в документации gs-ctk.

Сконфигурируйте характеристики

./resgroup.sh init_spec --name gs-cluster-1

Введите необходимые характеристики или оставьте значения по умолчанию

Инициализация характеристик для группы ресурсов gs-cluster-1
Установка характеристик для книги ресурсов:global-scheduler
Отслеживать метрики:true
Дополнительно отсылать метрики во внешнюю систему:true
Введите максимальный размер(java -Xmx) для globalscheduler:800M
Введите запрос CPU для globalscheduler:1
Введите запрос MEMORY для globalscheduler:1G
Введите лимиты CPU для globalscheduler:1
Введите лимиты MEMORY для globalscheduler:1G
Введите запрос CPU для systemagent:1
Введите запрос MEMORY для systemagent:250M
Введите лимиты CPU для systemagent:1
Введите лимиты MEMORY для systemagent:500M
Установка характеристик для книги ресурсов:global-server-excl
Отслеживать метрики:true
Дополнительно отсылать метрики во внешнюю систему:true
Введите максимальный размер(java -Xmx) для globalserver:3500M
Введите запрос CPU для globalserver:2
Введите запрос MEMORY для globalserver:4G
Введите лимиты CPU для globalserver:2
Введите лимиты MEMORY для globalserver:4G
Введите запрос CPU для systemagent:1
Введите запрос MEMORY для systemagent:250M
Введите лимиты CPU для systemagent:1
Введите лимиты MEMORY для systemagent:500M
Установка характеристик для книги ресурсов:global-server-share
Отслеживать метрики:true
Дополнительно отсылать метрики во внешнюю систему:true
Введите максимальный размер(java -Xmx) для globalserver:3500M
Введите запрос CPU для globalserver:2
Введите запрос MEMORY для globalserver:4G
Введите лимиты CPU для globalserver:2
Введите лимиты MEMORY для globalserver:4G
Введите запрос CPU для systemagent:1
Введите запрос MEMORY для systemagent:250M
Введите лимиты CPU для systemagent:1
Введите лимиты MEMORY для systemagent:500M
Установка характеристик для книги ресурсов:grafana
Введите запрос CPU для grafana:1
Введите запрос MEMORY для grafana:500M
Введите лимиты CPU для grafana:2
Введите лимиты MEMORY для grafana:1Gi
Установка характеристик для книги ресурсов:haproxy
Введите запрос CPU для haproxy:1
Введите запрос MEMORY для haproxy:500M
Введите лимиты CPU для haproxy:2
Введите лимиты MEMORY для haproxy:1G

Сконфигурируйте параметры кластера

./resgroup.sh init_values --name gs-cluster-1

Предупреждение

Если вы захотите использовать Ingress, прочитайте статью о том, как это сделать.

Инициализация значений для группы ресурсов gs-cluster-1
Введите timezone подов:Europe/Moscow
Введите поисковые домены для resolv.conf(если их несколько вводите через пробел):

Введите url базы данных:jdbc:postgresql://dbhost:5432/global
Введите alias базы данных:global
Введите имя секрета для пользователя БД:db-user-secret
Введите тип прикладного хранилища:nfs
Введите адрес сервера(server):127.0.0.1
Введите путь(path):/mnt/nfs/gs-cluster-k8s/globalfilestorage
Хотить добавить больше хранилищ?:нет

Установка значений для книги ресурсов:global-scheduler
Введите адрес доступа к prometheus:kube-gs-resgoup-grafana-internal:9090
Введите адрес доступа к loki:kube-gs-resgoup-grafana-internal:3100
Введите адрес доступа к tempo:kube-gs-resgoup-grafana-internal:3201
Введите адрес доступа к внешнему prometheus:external.prometheus.domain:9090
Введите адрес доступа к внешнему loki:external.loki.domain:3100
Введите адрес доступа к внешнему tempo:external.tempo.domain:3201
Введите имя секрета с токеном планировщика:scheduler-token-secret

Установка значений для книги ресурсов:global-server-excl
Введите адрес доступа к prometheus:kube-gs-resgoup-grafana-internal:9090
Введите адрес доступа к loki:kube-gs-resgoup-grafana-internal:3100
Введите адрес доступа к tempo:kube-gs-resgoup-grafana-internal:3201
Введите адрес доступа к внешнему prometheus:external.prometheus.domain:9090
Введите адрес доступа к внешнему loki:external.loki.domain:3100
Введите адрес доступа к внешнему tempo:external.tempo.domain:3201
Введите внешний ip(external_ip):127.0.0.1
Введите имя секрета для администратора:gs-admin-auth

Установка значений для книги ресурсов:global-server-share
Введите количество экземпляров:3
Введите адрес доступа к prometheus:kube-gs-resgoup-grafana-internal:9090
Введите адрес доступа к loki:kube-gs-resgoup-grafana-internal:3100
Введите адрес доступа к tempo:kube-gs-resgoup-grafana-internal:3201
Введите адрес доступа к внешнему prometheus:external.prometheus.domain:9090
Введите адрес доступа к внешнему loki:external.loki.domain:3100
Введите адрес доступа к внешнему tempo:external.tempo.domain:3201
Введите имя секрета для администратора:gs-admin-auth

Установка значений для книги ресурсов:grafana
Использовать Ingress?[да,нет]:нет
Введите внешний ip(external_ip):127.0.0.1
Введите класс хранилища:nfs-storage
Введите размер хранилища:5Gi
Введите имя системного пользователя с правами на доступ к метрикам cAdvisor:prometheus-cadvisor
Введите имя секрета с аккаунтом администратора Grafana:grafana-admin

Установка значений для книги ресурсов:haproxy
Использовать Ingress?[да,нет]:нет
Введите внешний ip(external_ip):127.0.0.1
Введите имя секрета basic-auth для авторизации статистики:secret-haproxy-auth
Введите имя tls секрета для доступа по https:

Установка значений для книги ресурсов:rabbitmq
Введите название секрета для доступа к RabbitMQ:rabbitmq-global 
Введите название секрета для доступа к консоли RabbitMQ:rabbitmq-admin
Введите название создаваемого виртуального хоста RabbitMQ:globalrabbitmq
Использовать Ingress?[да,нет]:нет
Введите внешний ip(external_ip):10.40.1.100
Введите внешний порт:15672
Подключить RabbitMQ?[да,нет]:да
Введите адрес RabbitMQ:gs-cluster-1-rabbitmq-internal.gs-k8s.svc.cluster.local
Введите порт RabbitMQ:5672
Введите виртуальный хост RabbitMQ:globalrabbitmq
Введите секрет RabbitMQ:db-user-secret

Совет

В последних версиях nsctl доступна команда ./tester.sh test-write --resgroup gs-cluster-1, которую можно использвать для проверки записи во все используемые группой ресурсов хранилища.

При использовании ssl в haproxy укажите имя секрета, содержащего сертификат:

Введите имя tls секрета для доступа по https: haproxy-tls

Включение книг и групп ресурсов#

Запустите кластер

./resgroup.sh start_appkit --name gs-cluster-1
./resbook.sh enable_all --group gs-cluster-1
./resgroup.sh enable --name gs-cluster-1

Установка схемы базы данных#

На этом этапе сервер приложений должен быть доступен для открытия через браузер. Однако войти не получится - не проинициализирована база данных.

./appkit.sh switch_und_upgrade --namespace gs-cluster-k8s --resgroup gs-cluster-1 --remote_appkit appkits/v1
./invoker.sh run --namespace gs-cluster-k8s --app nsctl --cmd "./resgroup.sh start_appkit --name gs-cluster-1"

Получение и установка лицензии#

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

Что дальше?#

  • Подумайте о настройке комплекта группы, если вы используете собственные сертификаты

  • Настройте JGroups

  • Публикуйте через Ingress

  • Проводите регулярные обновления прикладного решения и образов контейнеров