· Kubernetes · 8 Min. Lesezeit
Mattermost auf Kubernetes: Operator, Datenbank und SSO
Ein selbst gehosteter Team-Chat als Slack-Alternative, betrieben über den Mattermost-Operator. Voraussetzungen, externe Datenbank und Filestore, die Mattermost-Ressource, Login über OpenID Connect und die drei folgenreichsten Fallen.

Bevor Sie den ersten Befehl absetzen, lohnt die Frage, ob der Operator-Weg zu Ihrem Fall passt. Er bringt Bausteine mit, die Sie dauerhaft pflegen: den Operator selbst, eine externe Datenbank, einen Objektspeicher, einen Ingress Controller und optional einen Identity-Provider. Für ein Team, das ohnehin auf Kubernetes fährt und Chat als regulären Workload behandeln will, ist das der richtige Zuschnitt. Für eine Handvoll Leute ohne Cluster ist es Überbau.
Zwei Randbedingungen sollten Sie kennen, bevor Sie planen.
Die Release-Kadenz ist eng. Mattermost veröffentlicht jeden Monat am 16. eine neue Server-Version. Wer nicht monatlich nachziehen will, fährt auf einem Extended Support Release.
| Zweig | Stand Juli 2026 | Supportende |
|---|---|---|
| Aktuelles Release | v11.9, veröffentlicht am 16.07.2026 | 15.10.2026 |
| Aktuelles ESR | v11.7 | 15.05.2027 |
| Auslaufendes ESR | v10.11 | 15.08.2026 |
Mehr als ein Server kostet Lizenz. Für Deployments mit mehreren Servern ist laut Doku eine Enterprise-Lizenz nötig. Ohne Lizenz gehört replicas: 1 ausdrücklich in den spec-Block. Auch OpenID Connect ist keine Funktion der Team Edition, dazu unten mehr.
Die Bausteine und ihre dokumentierten Alternativen
Datenbank und Dateiablage gehören nicht in den Mattermost-Pod. Die Doku ist bei der Empfehlung deutlich, lässt aber Spielraum.
| Baustein | Empfehlung der Doku | Gültige Alternative | Nicht für Produktion |
|---|---|---|---|
| Datenbank | Managed PostgreSQL außerhalb des Clusters | CloudNativePG im Cluster, bei vorhandener Expertise | keine Angabe |
| Dateiablage | Managed S3-kompatibler Speicher | selbst betriebener S3-kompatibler Speicher | PVC-basierter lokaler Filestore |
| Ingress | NGINX Ingress Controller, eigener Schritt | keine Angabe | keine Angabe |
Die Alternativen stammen aus dem Deployment Guide, die Einstufung der lokalen Ablage aus dem Operator-Quellcode. Ich halte die letzte Spalte für die wichtigste Weichenstellung des Setups: Wer den lokalen Filestore nimmt, weil er in fünf Minuten steht, baut sich eine Instanz, die keine zweite Replica verträgt.
Schritt 0: Voraussetzungen prüfen
Prüfen Sie diese vier Punkte, bevor Sie etwas anlegen.
Helm-Version. Der Deployment Guide verlangt Helm 3.13.0 oder neuer.
helm version --shortPostgreSQL-Version. Die Doku nennt PostgreSQL 14.0+ als Minimum, angehoben mit v11.0 im Oktober 2025. MySQL ist seit v11.0 raus.
psql -h mattermost-db.lab.rz.jabi-it.de -U mattermost -d mattermost -c 'SELECT version();'Ingress Controller. Der NGINX Ingress Controller ist ein eigener, vorgelagerter Installationsschritt und nicht Teil des Operators.
kubectl get pods -A -l app.kubernetes.io/name=ingress-nginxLizenz. Klären Sie vorab, ob eine Enterprise-Lizenz vorliegt. Davon hängen Replica-Zahl und OpenID Connect ab.
Schritt 1: Operator installieren
Der Operator kommt aus dem offiziellen Helm-Repo und bekommt einen eigenen Namespace. Das jüngste Release ist v1.25.7 vom 21.05.2026. Die Doku empfiehlt, stets die neueste Operator-Version mit einer unterstützten Server-Version zu kombinieren.
helm repo add mattermost https://helm.mattermost.com
helm repo update
kubectl create ns mattermost-operator
helm install mattermost-operator mattermost/mattermost-operator -n mattermost-operatorPrüfung:
helm list -n mattermost-operator
kubectl -n mattermost-operator get podsDer Operator-Pod muss Running sein. Solange er nicht läuft, wird eine angelegte Mattermost-Ressource schlicht ignoriert.
Schritt 2: Datenbank-Secret anlegen
Die externe Datenbank wird über ein Secret angebunden. Die Doku nennt drei Schlüssel: DB_CONNECTION_STRING, DB_CONNECTION_CHECK_URL und MM_SQLSETTINGS_DATASOURCEREPLICAS.
kubectl create ns mattermost
kubectl -n mattermost create secret generic mattermost-db-connection \
--from-literal=DB_CONNECTION_STRING='postgres://mattermost:PASSWORT@mattermost-db.lab.rz.jabi-it.de:5432/mattermost?connect_timeout=10' \
--from-literal=DB_CONNECTION_CHECK_URL='postgres://mattermost:PASSWORT@mattermost-db.lab.rz.jabi-it.de:5432/mattermost?connect_timeout=10' \
--from-literal=MM_SQLSETTINGS_DATASOURCEREPLICAS=''DB_CONNECTION_CHECK_URL wertet der Legacy-Readiness-Init-Container aus. Für neue Deployments empfiehlt die Doku stattdessen spec.database.readinessCheck.mode: builtin. Über ein YAML-Manifest angelegt, gehören unter data base64-kodierte Werte hinein.
Prüfung:
kubectl -n mattermost get secret mattermost-db-connection \
-o jsonpath='{.data.DB_CONNECTION_STRING}' | base64 -d; echoSteht dort Base64-Salat statt einer lesbaren postgres://-URL, ist der Wert doppelt kodiert. Zum versionierten und trotzdem verschlüsselten Ablegen solcher Secrets siehe SOPS in der Praxis.
Schritt 3: Filestore-Secret anlegen
Für den S3-kompatiblen Speicher verlangt die Doku ein Secret mit accesskey und secretkey, im Feld data beide base64-kodiert. Überlassen Sie das Kodieren kubectl, dann entfällt diese Fehlerquelle.
kubectl -n mattermost create secret generic mattermost-filestore \
--from-literal=accesskey='AKIA...' \
--from-literal=secretkey='...'Prüfung: Denselben base64 -d-Abgleich wie in Schritt 2 auf .data.accesskey anwenden.
Schritt 4: Die Mattermost-Ressource anlegen
Jetzt beschreiben Sie die Installation als eine einzige Ressource.
apiVersion: installation.mattermost.com/v1beta1
kind: Mattermost
metadata:
name: mattermost-lab
namespace: mattermost
spec:
size: 1000users
replicas: 1
version: "11.9"
licenseSecret: ""
ingress:
enabled: true
host: chat.lab.rz.jabi-it.de
annotations:
kubernetes.io/ingress.class: nginx
tlsSecret: chat-lab-tls
database:
external:
secret: mattermost-db-connection
readinessCheck:
mode: builtin
fileStore:
external:
url: s3.lab.rz.jabi-it.de
bucket: mattermost
secret: mattermost-filestoreFür spec.size sind laut Typdefinition des Operators exakt fünf Werte zulässig: 100users, 1000users, 5000users, 10000users und 250000users. replicas: 1 steht hier bewusst, denn ohne Enterprise-Lizenz ist ein Mehrserver-Betrieb nicht vorgesehen. TLS gehört in spec.ingress.tlsSecret, die älteren Felder ingressName, ingressAnnotations und useIngressTLS sind deprecated.
Anwenden:
kubectl apply -f mattermost-installation.yamlPrüfung:
kubectl -n mattermost get mattermost
kubectl -n mattermost get pods
kubectl -n mattermost logs -f <pod-name>Hängt ein Pod, liefert kubectl -n mattermost describe pod <pod-name> die Ereignisse und die Liste der Init-Container samt Images. Letztere brauchen Sie für Stolperstein 1.
Schritt 5: Erreichbarkeit prüfen, erst intern, dann außen
Testen Sie zuerst am Ingress vorbei. Das trennt die Frage “läuft die Anwendung” von der Frage “stimmt der Weg von außen”.
kubectl -n mattermost port-forward svc/mattermost-lab 8065:8065
kubectl -n mattermost get ingressAntwortet die Instanz unter http://localhost:8065, ist der Server in Ordnung. Bleibt in der Ingress-Ausgabe die Spalte ADDRESS leer, deutet das auf einen fehlenden Ingress Controller aus Schritt 0 hin.
Schritt 6: Login über OpenID Connect
Statt einer eigenen Nutzerverwaltung binden Sie Mattermost an einen zentralen Identity-Provider an. Keycloak ist in der Doku zu OpenID Connect als unterstützter Provider genannt, neben Okta, OneLogin, Azure AD und weiteren. Zwei Punkte entscheiden vorab: OpenID Connect ist kostenpflichtig und in der Team Edition nicht enthalten, und LDAP-Daten sind laut Doku nicht mit OpenID kompatibel. Wer LDAP-Attribute und Gruppen braucht, konfiguriert SAML oder LDAP als Login-Provider, nicht OIDC.
Beim Identity-Provider hinterlegen Sie die Redirect-URI im festen Format {your-mattermost-url}/signup/openid/complete, für die Beispielinstanz also https://chat.lab.rz.jabi-it.de/signup/openid/complete. Nach dem Speichern verlangt die Doku einen Neustart des Servers. Auf Kubernetes ist das ein Rollout-Restart:
kubectl -n mattermost rollout restart deploy mattermost-lab
kubectl -n mattermost rollout status deploy mattermost-labPrüfung: Die Anmeldeseite aufrufen. Der SSO-Knopf steht dann neben Benutzername und Passwort. Fehlt er, ist das Stolperstein 13 der Sammlung.

Werte, die über spec.mattermostEnv als Umgebungsvariable gesetzt sind, lassen sich in der System Console nicht mehr ändern. Entweder Sie führen die Konfiguration in der Ressource, oder Sie lassen sie in der Oberfläche. Wie dieselbe Keycloak-Anbindung für ein anderes Werkzeug aussieht, steht im Beitrag ArgoCD an Keycloak hängen.
Schritt 7: Upgrade
Die Reihenfolge ist festgelegt. Datenbank und Dateiablage sichern, danach den Operator aktualisieren, erst dann den Server. Stellen Sie zuerst die laufende Version fest:
kubectl -n mattermost get mattermost -o jsonpath='{.items[*].spec.version}'; echoDiese Zahl brauchen Sie, um die richtigen Upgrade-Hinweise zu lesen. Die Important Upgrade Notes im v11-Changelog sind verkettet, jede Version verweist auf die Notes der vorherigen.
Operator zuerst:
helm repo update
helm upgrade mattermost-operator mattermost/mattermost-operator -n mattermost-operator
kubectl -n mattermost-operator get podsDanach spec.version in der Mattermost-Ressource anheben, erneut anwenden und die Prüfbefehle aus Schritt 4 wiederholen:
kubectl apply -f mattermost-installation.yaml
kubectl -n mattermost get podsDer Operator validiert vor der Änderung. Schlägt die Prüfung fehl, nimmt er keine Änderungen vor.
Die drei folgenreichsten Stolpersteine
1. Der Pod hängt im Init-Status und zieht ein postgres:13-Image
Symptom: Der Mattermost-Pod kommt nicht über Init hinaus. Im Cluster taucht ein Pull für postgres:13 auf, den niemand angefordert hat.
Ursache: Der Readiness-Modus external ist der Default. Er startet einen Init-Container mit postgres:13 und pg_isready. In Umgebungen ohne freien Zugang zur Docker-Registry scheitert dieser Pull.
Prüfung:
kubectl -n mattermost describe pod <pod-name> | grep -A2 'Init Containers'Lösung: spec.database.readinessCheck.mode: builtin setzen. Dann läuft der Check im Mattermost-Image selbst über mattermost db ping. Eine konkrete Mindestversion für diesen Befehl nennt die Doku nicht.
2. Dateien verschwinden nach einem Pod-Neustart
Symptom: Angehängte Dateien sind nach einem Neustart nicht mehr abrufbar, oder nur für einen Teil der Nutzer.
Ursache: Der lokale PVC-basierte Filestore ist im Operator-Quellcode ausdrücklich als nicht für Produktionsumgebungen empfohlen gekennzeichnet.
Prüfung:
kubectl -n mattermost get mattermost mattermost-lab -o jsonpath='{.spec.fileStore}'; echoLösung: Einen externen S3-kompatiblen Filestore über spec.fileStore.external mit url, bucket und secret anbinden.
3. Nach dem Upgrade auf v11 startet der Server nicht mehr
Symptom: Der Pod läuft in einen Fehler, die Datenbank wird nicht akzeptiert.
Ursache: Mit v11.0 im Oktober 2025 endete die MySQL-Unterstützung vollständig, und PostgreSQL v13 fiel aus der Unterstützung. Das Minimum ist PostgreSQL 14.
Prüfung:
SELECT version();Lösung: Vor dem Sprung auf v11 auf PostgreSQL migrieren beziehungsweise die Postgres-Instanz auf mindestens Version 14 heben. Beides gehört in ein eigenes Wartungsfenster, nicht in das des Server-Upgrades.
Die vollständige Sammlung der Stolpersteine
Die drei oben behandelten Fälle sind die folgenreichsten, aber nicht die einzigen. Die vollständige Sammlung aller fünfzehn Stolpersteine steht im Beitrag Mattermost auf Kubernetes: die vollständige Stolperstein-Sammlung, jeweils im gleichen Schema aus Symptom, Ursache, Prüfung und Lösung. Dort stehen unter anderem das Write-Only-Verhalten von spec.size, der deprecated TLS-Block, die lange Datenmigration in v11.9 und der fehlende SSO-Knopf. Legen Sie sich diese Seite neben die Konsole, wenn Sie ein Upgrade oder eine Erstinstallation begleiten.
Grenzen
Der Operator nimmt Ihnen das Schreiben von Deployment, Service und Ingress ab. Er nimmt Ihnen nicht die Verantwortung für Datenbank, Objektspeicher, Zertifikate und Identity-Provider ab. Das sind vier eigenständige Systeme, und drei davon können Mattermost lahmlegen, ohne dass an Mattermost selbst etwas falsch wäre.
Zur Planung: Ohne Enterprise-Lizenz bekommen Sie keinen Mehrserver-Betrieb und kein OpenID Connect. Wer den Chat wegen des zentralen Logins einführt, sollte das früh in der Kalkulation haben. Und wenn Ihr Team nicht monatlich upgraden kann, planen Sie von Anfang an auf einem ESR-Zweig und legen Sie den Wechseltermin fest, bevor der laufende Zweig ausläuft.
Ob ein selbst gehosteter Chat für Ihren Fall überhaupt die richtige Antwort ist, ordnet der Beitrag DSGVO-konforme Alternativen für die Team-Kommunikation ein.
Sie wollen Team-Kommunikation self-hosted, mit einem zentralen Login? Ich betreibe Chat, Identity und die Datenbank als zusammenhängendes, dokumentiertes System. Mehr unter Sichere Kommunikation, das Erstgespräch ist unverbindlich.

Alex Jabi
Ich betreue IT, Informationssicherheit und Datenschutz für KMU und Praxen an der Bergstraße und im Odenwald, persönlich, dokumentiert und ohne Cloud-Zwang.
Mehr über mich

