Mattermost + Jitsi + k8s
В данной статье будет показан процесс установки мессенджера Mattermost в связке с Jitsi для ВКС в самой простой, на мой взгляд, конфигурации в Kubernetes кластер.
Почему выбор пал именно на эти приложения:
— При необходимости все можно запустить в закрытом контуре
— Нет привязки к облачным провайдерам
Ну и главная причина, почему я начал все это настраивать:
— В моем конкретном случае связка Яндекс-Телемост/Мессенджер не позволяет аккаунтам из разных организаций Яндекс 360 работать в одном рабочем пространстве.
Обязательно уберу этот пункт, когда они исправятся :-)
— И пока что я не нашел подобной статьи на Хабре даже по отдельности :-)
Исходные данные:
— Kubernetes кластер (например yandex), c worker-нодами имеющими белый ip адрес (необходимо при работе в открытой сети Интернет).
— В кластере установлен nginx ingress controller, в статье класс определен как nginx-external
— В кластере установлен cert-manager для ssl
— Есть возможность настроить DNS записи для вашего домена
— Установлен helm 3
— Есть доступ к S3 бакету (или его аналогу), известны accesskey и secretkey
— Установлена БД Postgresql, известны данные для подключения к БД c правами администратора. Связь между БД и Mattermost в данном примере без SSL.
— Есть доступ к кластеру через kubectl с правами администратора
Установка Jitsi
Скачать helm чарт
helm repo add jitsi https://jitsi-contrib.github.io/jitsi-helm/
helm pull jitsi/jitsi-meet
Скопировать values.yaml из чарта и переопределить параметры:
values-work.yaml:
enableAuth: true
enableGuests: true
# Where Jitsi Web UI is made available
# such as jitsi.example.com
publicURL: "meet.app-code.ru"
tz: Europe/Moscow
websockets:
## Colibri (JVB signalling):
colibri:
enabled: true
## XMPP (Prosody signalling):
xmpp:
enabled: true
web:
extraEnvs:
RESOLUTION: "720"
RESOLUTION_MIN: "720"
RESOLUTION_WIDTH: "1280"
RESOLUTION_WIDTH_MIN: "1280"
VIDEOQUALITY_PREFERRED_CODEC: VP9
#https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-configuration/#videoquality
VIDEOQUALITY_ENFORCE_PREFERRED_CODEC: "0" # 0 = fallback if some endpoints dont support, 1 = breaks receiving video for any endpoint that doesn't support preferred codec
TART_BITRATE: "8000000" # 8000kbps
# START_AUDIO_MUTED
# value: "0" # if nth joiner, automute (user can toggle unmute) [moderator will only be muted AFTER first participant joins]
# START_VIDEO_MUTED
# value: "0" # if nth joiner, automute (user can toggle unmute) [moderator will only be muted AFTER first participant joins]
# 0 = automute on join, user can toggle unmute #https://github.com/jitsi/jitsi-meet/issues/8144 (2021-Q1: pre-join page overrides start muted)
START_WITH_AUDIO_MUTED: "1"
# 0 = automute on join, user can toggle unmute #https://github.com/jitsi/jitsi-meet/issues/8144 (2021-Q1: pre-join page overrides start muted)
# START_WITH_VIDEO_MUTED: "1"
# 'distracting'
ENABLE_NOISY_MIC_DETECTION: "false"
ENABLE_NO_AUDIO_DETECTION: "true"
TOOLBAR_BUTTONS: "microphone,camera,desktop,fullscreen,chat,recording,localrecording,settings,raisehand,filmstrip,invite,shortcuts,tileview,videobackgroundblur,download,help,hangup,select-background"
ingress:
enabled: true
ingressClassName: "nginx-external"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: meet.app-code.ru
paths: ['/']
tls:
- secretName: jitsi-web-certificate
hosts:
- meet.app-code.ru
jicofo:
xmpp:
password: y7d75Aj2FSocL98V9wb6PXF5NzWw47ncscmYbwjgnEBYj9r7mP
jvb:
xmpp:
user: jvb
password: upEH3JFsBHeFzQPirREWdT8c5CAHgzcma3ck5RpXg
useNodeIP: true
## UDP transport port:
UDPPort: 30000
## Use a pre-defined external port for NodePort or LoadBalancer service,
# if needed. Will allocate a random port from allowed range if unset.
# (Default NodePort range for K8s is 30000-32767)
nodePort: 30000
service:
enabled: true
type: NodePort
externalTrafficPolicy: ~
nodeSelector:
node-group: public
extraCommonEnvs:
XMPP_CROSS_DOMAIN: "true"
AUTH_TYPE: "jwt"
JWT_APP_ID: "jitsimeet"
JWT_ALLOW_EMPTY: "false"
prosody:
enabled: true
persistence:
enabled: true
size: 4Gi
storageClassName: yc-network-ssd
extraEnvs:
- name: JWT_APP_SECRET
value: "e8pFe6QQYdwuVh6tEdxeFkMR9aFnTkCuWSfVurrQz"
Некоторые пояснения к содержимому:
publicURL
— Урл по которому будет доступен Jitsiweb.extraEnvs
— Параметры, которые на мой взгляд оптимальны для первого запускаweb.ingress.annotations
— Необходимо указать параметры вашего cert-manager для запроса сертификата
В блоке jvb
необходимые параметры, чтобы заработал UDP трафик при звонках. Важно так же понимать, что необходимо открыть указанные порты в Группах безопасности (фаервол), если это применимо к вашей инфраструктуре. Также указать nodeSelector
если у вас отдельная группа нод с белыми IP адресами:
jvb:
useNodeIP: true
## UDP transport port:
UDPPort: 30000
## Use a pre-defined external port for NodePort or LoadBalancer service,
# if needed. Will allocate a random port from allowed range if unset.
# (Default NodePort range for K8s is 30000-32767)
nodePort: 30000
service:
enabled: true
type: NodePort
externalTrafficPolicy: ~
nodeSelector:
node-group: public
Блок extraCommonEnvs
включает авторизацию по JWT токену и задает App ID:
extraCommonEnvs:
XMPP_CROSS_DOMAIN: "true"
AUTH_TYPE: "jwt"
JWT_APP_ID: "jitsimeet"
JWT_ALLOW_EMPTY: "false"
В блоке prosody
задается JWT токен:
prosody:
enabled: true
persistence:
enabled: true
size: 4Gi
storageClassName: yc-network-ssd
extraEnvs:
- name: JWT_APP_SECRET
value: "e8pFe6QQYdwuVh6tEdxeFkMR9aFnTkCuWSfVurrQz"
Параметры publicURL, extraCommonEnvs.JWT_APP_ID, prosody.extraEnvs.JWT_APP_SECRET будут ипользованы при настройке интеграции с mattermost
Все пароли и токены замените на свои!.
Установить jitsi:
helm -n jitsi-ext upgrade --install --create-namespace \
jitsi \
-f values-work.yaml \
jitsi/jitsi-meet
Проверить, что все запущено, должно быть примерно такое состояние:
$ kubectl -n jitsi-ext get pods,service,ingress
NAME READY STATUS RESTARTS AGE
pod/jitsi-jitsi-meet-jicofo-86cb554b75-dnn6k 1/1 Running 0 49s
pod/jitsi-jitsi-meet-jvb-675db788db-2svt2 1/1 Running 0 49s
pod/jitsi-jitsi-meet-web-b677f9f88-wkszq 1/1 Running 0 49s
pod/jitsi-prosody-0 1/1 Running 0 49s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/jitsi-jitsi-meet-jvb NodePort 10.21.90.27 30000:30000/UDP 5d22h
service/jitsi-jitsi-meet-web ClusterIP 10.21.189.115 80/TCP 5d22h
service/jitsi-prosody ClusterIP 10.21.84.50 5280/TCP,5281/TCP,5347/TCP,5222/TCP,5269/TCP 5d22h
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/jitsi-jitsi-meet-web nginx-external meet.app-code.ru 80, 443 25h
Установка Mattermost
Самый простой вариант, на мой взгляд, при установке Mattermost это использовать operator.
Добавить helm репозиторий:
helm repo add mattermost https://helm.mattermost.com
Установить оператор:
helm -n mattermost-operator upgrade --install --create-namespace \
mattermost-operator \
mattermost/mattermost-operator
Данные для подключения к БД нужно сформировать в определенном формате, так же нужны данные для подключения к S3, для этого можно использовать небольшой скрипт:
#!/bin/bash
### БД
username="mostuser"
password="password"
database="mattermost"
db_url="postgres.host"
url="postgres://${username}:${password}@${db_url}:5432/${database}?connect_timeout=10&sslmode=disable"
pg_url_base64=$(echo -n "${url}" | base64 -w0)
echo "pg_url_base64: ${pg_url_base64}"
### S3
accesskey="accesskey"
secretkey="secretkey"
accesskey_base64=$(echo -n "${accesskey}" | base64 -w0)
secretkey_base64=$(echo -n "${secretkey}" | base64 -w0)
echo "accesskey_base64: ${accesskey_base64}"
echo "secretkey_base64: ${secretkey_base64}"
Создать secret с данными для подключения к БД most-postgres-connection.yaml:
apiVersion: v1
kind: Secret
metadata:
name: most-postgres-connection
type: Opaque
data:
DB_CONNECTION_CHECK_URL:
DB_CONNECTION_STRING:
MM_SQLSETTINGS_DATASOURCEREPLICAS:
Создать secret с данными для подключения к S3 mattermost-filestore-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: most-s3-sa-key
type: Opaque
data:
accesskey:
secretkey:
Создать yaml фаил с описанием mattermost.yaml:
apiVersion: installation.mattermost.com/v1beta1
kind: Mattermost
metadata:
name: mattermost
spec:
image: mattermost/mattermost-team-edition
version: 10.1.2
imagePullPolicy: Always
licenseSecret: ""
replicas: 1
ingress:
enabled: true
host: most.app-code.ru
annotations:
kubernetes.io/ingress.class: nginx-external
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-body-size: 500m
tlsSecret: most.app-code.ru-tls
database:
external:
secret: most-postgres-connection
fileStore:
external:
url: s3.yandexcloud.net
bucket: most-s3-bucket-test
secret: most-s3-sa-key
scheduling:
nodeSelector:
node-group: public
Установить все в кластер:
kubectl create ns mattermost
kubectl -n mattermost apply -f mattermost-filestore-secret.yaml
kubectl -n mattermost apply -f postgresql_conn_secret.yaml
kubectl -n mattermost apply -f mattermost.yaml
Проверить, что все запустилось:
$ kubectl -n mattermost get pods,ingress
NAME READY STATUS RESTARTS AGE
pod/mattermost-6788fb845-frmfl 1/1 Running 0 8m7s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/mattermost most.app-code.ru 80, 443 8m7s
Зайти через веб интерфейс, сделать начальные настройки.
Скачать архив с плагином Jitsi:
wget https://github.com/mattermost-community/mattermost-plugin-jitsi/releases/download/v2.0.1/jitsi-2.0.1.tar.gz
В системных настройках: System Console → Plugin Managment загрузить скачанный архив:
Включить плагин и перейти в его настройки:
Внести настройки для связи с Jitsi, которые указывали ранее, это App ID и JWT токен:
Перейти в любой канал или персональный чат, справа на панели появится кнопка Jitsi:
Либо в любом диалоге вызвать командой /jitsi
Перейти по созданной ссылке, присоединиться к видео встрече:
Важно, при переходе по этой ссылке все получают права Модератора. Если считаете, что так не надо делать — не публикуйте эту ссылку, а приглашайте к конференции через кнопку приглашения:
Удачного пользования! :-)