On-Premises Helm Пошагово здесь: https://elma365.com/ru/help/install-kubernetes.html Pods Удалить evicted pods kubectl get po -A --all-namespaces -o json | jq '.items[] | select(.status.reason!=null) | select(.status.reason | contains("Evicted")) | "kubectl delete po \(.metadata.name) -n \(.metadata.namespace)"' | xargs -n 1 bash -c Предварительно должен быть установлен jq Полезное Перезапуск всех сервисов kubectl -n default rollout restart deploy kubectl -n default rollout restart ds Если namespace отличен от по умолчанию, заменить default на свой Более интересный вариант: #!/usr/bin/env bash function clearCompleted() { kubectl delete job $(kubectl get job -o=jsonpath='{.items[?(@.status.succeeded==1)].metadata.name}') > /dev/null 2>&1 } kubectl scale deploy --replicas=0 --all while [[ $(kubectl get pods -n default | grep -c "") -ne 0 ]] do clearCompleted echo "Waiting for all pods are Terminating." sleep 15 done kubectl scale deploy --replicas=1 --all kubectl scale --replicas=4 deployment/worker while true do clearCompleted echo "Waiting for all pods are Ready." kubectl wait pods --all -n default --for condition=Ready --timeout=60s > /dev/null 2>&1 && break sleep 15 done echo "All done." Установка порта отличного от 80 tar -xzf elma365.tar.gz elma365 sed -i -e 's/: 80/: 88/g' elma365/charts/front/templates/ingress.yaml   Проверка статуса узлов кластера etcdctl --cluster=true endpoint health   Переход на Cilium Gateway Не решен вопрос с CORS Перед переходом на Cilium Gateway необходимо выполнить шаги, описанные тут. Здесь мы рассмотрим вариант для single node редакция Enterprise версия 2026.4.42. Для редакции Hub все намного сложнее и будет описано позже. Из справки тут создаем gateway: kubectl apply -n kube-system -f - < 80:30514/TCP 4m13s ck-storage-rawfile-csi-controller ClusterIP None 189d ck-storage-rawfile-csi-node ClusterIP 10.152.183.56 9100/TCP 189d coredns ClusterIP 10.152.183.238 53/UDP,53/TCP 189d hubble-peer ClusterIP 10.152.183.166 443/TCP 189d metrics-server ClusterIP 10.152.183.180 443/TCP 189d Возможно можно как то настроить NodePort для ситуации single node, но эту гипотезу мы тут не проверяем. Так же load-balancer  отключен по k8s status - его нужно включить: k8s enable load-balancer Должны получить: Enabling load-balancer on the cluster. This may take a few seconds, please wait. load-balancer enabled. # k8s status cluster status: ready control plane nodes: 192.168.56.83:6400 (voter) high availability: no datastore: etcd network: enabled dns: enabled at 10.152.183.238 ingress: disabled load-balancer: enabled, L2 mode local-storage: enabled at /var/snap/k8s/common/rawfile-storage gateway enabled # kubectl get pod,svc -n metallb-system NAME READY STATUS RESTARTS AGE pod/metallb-controller-676c8f595c-5chlt 1/1 Running 0 2m6s pod/metallb-speaker-t2x96 1/1 Running 0 2m6s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/metallb-webhook-service ClusterIP 10.152.183.39 443/TCP 2m7s Неоходимо для нашего LoadBalancer назначить пул IP адресов (в нашем случае у нас single node и поэтому укажем только один): Использовать IP нашего узла НЕЛЬЗЯ. Необходимо указать свободный адрес в вашей сети. (а может и можно)! k8s set load-balancer.cidrs=192.168.56.73-192.168.56.73 Получилось: Configuration updated. # kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-gateway-cilium-gateway LoadBalancer 10.152.183.225 192.168.56.73 80:30514/TCP 86m ck-storage-rawfile-csi-controller ClusterIP None 189d ck-storage-rawfile-csi-node ClusterIP 10.152.183.56 9100/TCP 189d coredns ClusterIP 10.152.183.238 53/UDP,53/TCP 189d hubble-peer ClusterIP 10.152.183.166 443/TCP 189d metrics-server ClusterIP 10.152.183.180 443/TCP 189d Теперь переходим непосредственно к настройке ELMA365. Правим наш values-elma365.yaml. Отключаем Ingress и включаем Gateway API: global: gatewayAPI: enabled: true parentRefs: - name: cilium-gateway namespace: kube-system ingress: enabled: false Устанавливаем (обновляем) чарт ELMA365 как это мы делаем стандартно (у каждого свой подход), но суть - применить наши изменения. И тут начались танцы с бубном.... helm upgrade --install elma365 ./elma365 -f values-elma365.yaml --timeout=30m --debug --wait Получили (причем тут istio вообще?): level=DEBUG msg="number of dependencies in the chart" chart=messenger-vkteamsbot dependencies=0 level=DEBUG msg="number of dependencies in the chart" chart=messenger-whatsapp dependencies=0 level=DEBUG msg="number of dependencies in the chart" chart=postman dependencies=0 Error: unable to build kubernetes objects from release manifest: [resource mapping not found for name: "balancer-auth" namespace: "" from "": no matches for kind "AuthorizationPolicy" in version "security.istio.io/v1" ensure CRDs are installed first, resource mapping not found for name: "main-body-size-limit" namespace: "istio-system" from "": no matches for kind "EnvoyFilter" in version "networking.istio.io/v1alpha3" ensure CRDs are installed first] Изучив ~/elma365/charts/balancer/values.yaml было обнаружено интересное значение workloadSelector, про которое ничего не сказано в оффициальной справке: global: gatewayAPI: enabled: false parentRefs: - name: main-gateway namespace: istio-system workloadSelector: gateway.istio.io/managed: istio.io-gateway-controller annotations: {} hosts: [] Заменили значение на Смотрим ~/elma365/charts/balancer/templates/httproute.yaml а там захаркодено если включен gatewayAPI: --- apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: {{ template "balancer.name" . }}-auth labels: {{- include "balancer.labels" . | nindent 4 }} spec: selector: matchLabels: app: {{ template "balancer.name" . }} action: DENY rules: - to: - operation: ports: ["{{ $servicePort }}"] paths: ["/balancer*"] when: - key: request.headers[authorization] values: ["*"] Пробуем  удалить (далее сделаем патч к дистрибутиву и пробуем установить снова ELMA365 - эта проблема ушла но осталась вторая: level=DEBUG msg="number of dependencies in the chart" chart=textextractor dependencies=0 level=DEBUG msg="number of dependencies in the chart" chart=widget dependencies=0 Error: unable to build kubernetes objects from release manifest: resource mapping not found for name: "main-body-size-limit" namespace: "istio-system" from "": no matches for kind "EnvoyFilter" in version "networking.istio.io/v1alpha3" ensure CRDs are installed first Пробуем добавить отключение envoyFilter в нашей конфигурации, ведь мы никакой Envoy не устанавливали: gatewayAPI: enabled: true # annotations: {} parentRefs: - name: cilium-gateway namespace: kube-system # timeoutSeconds: "300s" # retries: # attempts: 3 envoyFilter: enabled: false # namespace: "istio-system" Установка пошла дальше! Ура! Ждем результат... Все поднялось без ошибок. Смотрим какие у нас появились ресурсы HTTPRoute: kubectl get httproute -A Получили что то похожее: NAMESPACE NAME HOSTNAMES AGE default balancer ["d.rmg365.ru"] 9m33s default fileprotection ["d.rmg365.ru"] 9m33s default front ["d.rmg365.ru"] 9m33s default hydra-adaptor ["d.rmg365.ru"] 9m33s default main ["d.rmg365.ru"] 9m33s default main-publicapi ["d.rmg365.ru"] 9m33s default notifier ["d.rmg365.ru"] 9m33s default notigate ["d.rmg365.ru"] 9m33s default vahter ["d.rmg365.ru"] 9m33s default web-forms ["d.rmg365.ru"] 9m33s Перенастроили reverse proxy на наш новый адрес, что мы указали ранее для LB и вуаля: Давайте попробуем все же обмануть LB и указать ему адрес хоста, чтобы не плодить у себя айпишники: k8s set load-balancer.cidrs=192.168.56.83-192.168.56.83 Вроде не ругнулось даже: Configuration updated. # kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-gateway-cilium-gateway LoadBalancer 10.152.183.225 192.168.56.83 80:30514/TCP 158m ck-storage-rawfile-csi-controller ClusterIP None 190d ck-storage-rawfile-csi-node ClusterIP 10.152.183.56 9100/TCP 190d coredns ClusterIP 10.152.183.238 53/UDP,53/TCP 190d hubble-peer ClusterIP 10.152.183.166 443/TCP 190d metrics-server ClusterIP 10.152.183.180 443/TCP 190d Эксперимент прошел удачно и мы вернули настройки reverse proxy как было в случае Ingress. Ну вот собственно и патч для 2026.4 (актуально для 2026.4.42, покка не исплавили) - balancer-httproute.patch.2026.4 --- elma365/charts/balancer/templates/httproute.yaml 2026-07-31 09:06:50.000000000 +0300 +++ ./httproute.yaml 2026-08-02 14:13:28.294230220 +0300 @@ -43,24 +43,4 @@ - name: {{ $serviceName }} port: {{ $servicePort }} {{- end }} ---- -apiVersion: security.istio.io/v1 -kind: AuthorizationPolicy -metadata: - name: {{ template "balancer.name" . }}-auth - labels: - {{- include "balancer.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - app: {{ template "balancer.name" . }} - action: DENY - rules: - - to: - - operation: - ports: ["{{ $servicePort }}"] - paths: ["/balancer*"] - when: - - key: request.headers[authorization] - values: ["*"] {{- end }} После загрузки нового дистро применяем патч: patch elma365/charts/balancer/templates/httproute.yaml < balancer-httproute.patch.2026.4 Переход на Cilium Gateway (Hub) Статья в разработке. Ищем пути поднятия системы Ранее мы рассмотрели переход для редакции Enterprise для single node. А теперь рассмотрим редакцию Hub на 4х узлах кластера. Итак мы имеем кластер следующего вида: # k8s status cluster status: ready control plane nodes: 192.168.56.151:6400 (voter), 192.168.56.152:6400 (voter), 192.168.56.153:6400 (voter) high availability: yes datastore: etcd network: enabled dns: enabled at 10.152.183.211 ingress: disabled load-balancer: enabled, L2 mode local-storage: enabled at /var/snap/k8s/common/rawfile-storage gateway enabled # kubectl get nodes -A -owide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME hc1n1 Ready control-plane,worker 189d v1.33.11 192.168.56.151 Ubuntu 24.04.4 LTS 6.17.13-19-pve containerd://1.7.31 hc1n2 Ready control-plane,worker 189d v1.33.11 192.168.56.152 Ubuntu 24.04.4 LTS 6.17.13-19-pve containerd://1.7.31 hc1n3 Ready control-plane,worker 136d v1.33.11 192.168.56.153 Ubuntu 24.04.4 LTS 6.17.13-19-pve containerd://1.7.31 hc1n4 Ready worker 186d v1.33.11 192.168.56.154 Ubuntu 24.04.4 LTS 7.0.14-5-pve containerd://1.7.31 При этом как видно у нас уже включен load-balancer, т.к. у нас ранее установлен portainer в LB варианте: portainer service/portainer-agent LoadBalancer 10.152.183.27 192.168.56.170 9001:31417/TCP 186d portainer service/portainer-agent-headless ClusterIP None 186d Создаем gateway из прошлой статьи. У нас подцепился нужный IP из преднастроенного пула: kube-system cilium-gateway-cilium-gateway LoadBalancer 10.152.183.249 192.168.56.171 80:31186/TCP 15s Применяем патч и обновляет ELMA365: helm upgrade --install elma365 ./elma365 -f values-elma365.yaml --timeout=30m --debug --wait И вот больше нет доступа к нашим ресурсам. Смотрим что там у нас с HTTPRoute: # kubectl get httproute -A NAMESPACE NAME HOSTNAMES AGE default balancer ["hc1.rmg365.ru"] 11m default fileprotection ["hc1.rmg365.ru"] 11m default front ["hc1.rmg365.ru"] 11m default hydra-adaptor ["hc1.rmg365.ru"] 11m default linkhub ["hc1.rmg365.ru"] 11m default main ["hc1.rmg365.ru"] 11m default main-publicapi ["hc1.rmg365.ru"] 11m default notifier ["hc1.rmg365.ru"] 11m default notigate ["hc1.rmg365.ru"] 11m default vahter ["hc1.rmg365.ru"] 11m default web-forms ["hc1.rmg365.ru"] 11m Возвращаемся к танцам с бубном касательно тенантов - это периодическим еняется от версии к версии... ... в процессе написания Ошибка при вызове Web API После обновления на релиз 2026.1 вариант Helm может перестать работать Web API. Чтобы решить эту проблему необходимо проверить наличие в values-elma365.yaml записи ingressClassName и если ее нет то добавить: # домен или ip адрес, по которому будет доступна система # host: 'host.randm.ru' host: 'host.rmg365.ru' ingress: # включение host в ingress (значение берется из host) # для установленного s3 minio через чарты elma365-extensions, укажите в блоке minio # значение в параметре hosts в файле values-extensions.yaml ingressClassName: nginx До версии 2026.1 этого не требовалось Проблемы Error: Kubernetes cluster unreachable: Get https://127.0.0.1:16443 После обновления сертификатов в кубике возможна неработоспособность helm - появляется ошибка или с неверным сертификатом или что то с портом. Необходимо обновить файл конфигурации кубика: microk8s.kubectl config view --raw > $HOME/.kube/config После этого helm должен ожить. Hub 2025.8.6+: Доступ к площадкам Начиная с данной версии вырезано в Ingress прописывание тенантов и как следствие система перестала работать как надо. Чтобы это вылечить, необходимо: в values-elma365.yaml указать: global: host: 'myhubdomain.ru' ingress: hostEnabled: false В реверс прокси для каждого адреса тенанта добавить в хидер: X-Company где, для конкретного названия, которое будет добавлено к полному имени .myhubdomain.ru edition: hub (solution: hub на текущий момент в природе не существует ) секцию hub прописываем как и раньше для каждого тенанта если надо включить фишки хаб сервисов, то hubEnabled: true 2026.1-2026.3: Не создаются площадки Начиная с указанной версии перестали создаваться и обновляться площадки. Это связано с некорректным значением в чарте дистрибутива. Для устранения данной проблемы необходимо создать следующий патч create-company.patch: --- elma365/templates/create-company.yaml 2026-04-10 11:06:27.000000000 +0300 +++ ./create-company.yaml 2026-04-08 08:20:01.000000000 +0300 @@ -1,4 +1,5 @@ {{- if eq .Values.global.solution "onPremise" }} +{{- if or (eq .Values.global.edition "standard") (eq .Values.global.edition "enterprise") }} apiVersion: batch/v1 kind: Job metadata: @@ -57,7 +58,7 @@ activeDeadlineSeconds: {{ default 1800 .Values.global.activeDeadlineSeconds }} ttlSecondsAfterFinished: 120 -{{- else if eq .Values.global.solution "hub" }} +{{- else if eq .Values.global.edition "hub" }} {{- range $index, $job := .Values.global.hub }} --- @@ -206,3 +201,4 @@ data: {} {{- end }} +{{- end }} После чего применить его: patch -u elma365/templates/create-company.yaml < create-company.patch rm -f elma365/templates/create-company.yaml.orig 2026.4+: Не создаются площадки Начиная с указанной версии перестали создаваться и обновляться площадки. Это связано с некорректным значением в чарте дистрибутива. Для устранения данной проблемы необходимо создать следующий патч create-company.patch: --- elma365/templates/create-company.yaml 2026-05-14 14:35:38.000000000 +0300 +++ ./create-company.yaml 2026-05-17 09:53:59.345172000 +0300 @@ -1,4 +1,5 @@ {{- if eq .Values.global.solution "onPremise" }} +{{- if or (eq .Values.global.edition "standard") (eq .Values.global.edition "enterprise") }} apiVersion: batch/v1 kind: Job metadata: @@ -64,7 +65,7 @@ activeDeadlineSeconds: {{ default 1800 .Values.global.activeDeadlineSeconds }} ttlSecondsAfterFinished: 120 -{{- else if eq .Values.global.solution "hub" }} +{{- else if eq .Values.global.edition "hub" }} {{- range $index, $job := .Values.global.hub }} --- @@ -83,9 +84,6 @@ template: metadata: labels: - {{- if .Values.global.helmLibrary }} - {{- include "helm-library.deployment.podLabels" . | nindent 8 }} - {{- end }} app: hub tier: elma365 sidecar.istio.io/inject: "false" @@ -208,3 +206,4 @@ data: {} {{- end }} +{{- end }} После чего применить его: patch -u elma365/templates/create-company.yaml < create-company.patch