Test Umgebung mit K3s aufsetzten

Hallo ich möchte zwecks Evaluation eine Testinstanz mit K3s wie im Blog Artikel Vorteile von Open-Source-Softwarelösungen mit Self-Hosting beschrieben aufsetzten. Leider scheitert der apply reproduzierbar beim nubus Service.

Kann mir da jemand einen Tipp geben was da schief geht ?

FAILED RELEASES:
NAME NAMESPACE CHART VERSION DURATION
ums opendesk nubus/nubus 8s

in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[3]: in helmfile/apps/nubus/helmfile-child.yaml.gotmpl: failed processing release ums: command „/usr/local/bin/helm“ exited with non-zero status:

PATH:
/usr/local/bin/helm

ARGS:
0: helm (4 bytes)
1: upgrade (7 bytes)
2: --install (9 bytes)
3: ums (3 bytes)
4: /root/.cache/helmfile/nubus/nubus/1.18.1/nubus (46 bytes)
5: --version (9 bytes)
6: 1.18.1 (6 bytes)
7: --timeout (9 bytes)
8: 900s (4 bytes)
9: --create-namespace (18 bytes)
10: --namespace (11 bytes)
11: opendesk (8 bytes)
12: --values (8 bytes)
13: /tmp/helmfile146685300/opendesk-ums-values-56946644b (52 bytes)
14: --reset-values (14 bytes)
15: --history-max (13 bytes)
16: 10 (2 bytes)

ERROR:
exit status 1

EXIT STATUS
1

STDERR:
level=INFO msg=„warning: cannot overwrite table with non table for keycloak.postgresql.auth.existingSecret (map[keyMapping:map[password:] name:])“
level=INFO msg=„warning: cannot overwrite table with non table for nubusKeycloakExtensions.postgresql.auth.existingSecret (map[keyMapping:map[password:] name:])“
I0323 16:29:41.262576 265602 warnings.go:107] „Warning: path /$ cannot be used with pathType Exact“
Error: failed to create typed patch object (opendesk/ums-portal-consumer; apps/v1, Kind=StatefulSet): errors:
.spec.template.spec.initContainers[name=„wait-for-ldap“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-udm“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-object-storage“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-provisioning-api“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„univention-compatibility“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
admission webhook „validate.nginx.ingress.kubernetes.io“ denied the request: host „portal.desk.simpego.ch“ and path „/favicon.ico“ is already defined in ingress opendesk/opendesk-static-files-portal

COMBINED OUTPUT:
Release „ums“ does not exist. Installing it now.
level=INFO msg=„warning: cannot overwrite table with non table for keycloak.postgresql.auth.existingSecret (map[keyMapping:map[password:] name:])“
level=INFO msg=„warning: cannot overwrite table with non table for nubusKeycloakExtensions.postgresql.auth.existingSecret (map[keyMapping:map[password:] name:])“
I0323 16:29:41.262576 265602 warnings.go:107] „Warning: path /$ cannot be used with pathType Exact“
Error: failed to create typed patch object (opendesk/ums-portal-consumer; apps/v1, Kind=StatefulSet): errors:
.spec.template.spec.initContainers[name=„wait-for-ldap“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-udm“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-object-storage“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„wait-for-provisioning-api“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]
.spec.template.spec.initContainers[name=„univention-compatibility“].env: duplicate entries for key [name=„AWS_DEFAULT_REGION“]

Die beiden existingSecret-Warnings sind vermutlich nicht der eigentliche Blocker. Relevant sind hier drei andere Punkte:

  1. duplicate entries for key [name=„AWS_DEFAULT_REGION“]
    Das ist ein echter Fehler. In den generierten Manifests wird AWS_DEFAULT_REGION für mehrere initContainers doppelt gesetzt. Das kommt typischerweise daher, dass die Region sowohl über die openDesk-Values als auch noch einmal über eigene Overrides/extraEnv gesetzt wird.Bitte einmal vor dem apply rendern und prüfen:

helmfile template --environment dev --namespace opendesk > /tmp/opendesk-rendered.yaml rg -n "AWS_DEFAULT_REGION|ums-portal-consumer|wait-for-object-storage|wait-for-ldap|wait-for-udm" /tmp/opendesk-rendered.yaml

Wenn AWS_DEFAULT_REGION dort in denselben initContainers doppelt vorkommt, muss eine der beiden Quellen raus. Wenn du das gebündelte MinIO/S3-Setup nutzt, würde ich zuerst eigene zusätzliche AWS_*-Overrides entfernen.
2. host „portal.desk.simpego.ch“ and path „/favicon.ico“ is already defined
Das sieht nach einer nicht sauberen vorherigen Installation oder nach kollidierenden Ingress-Ressourcen aus. Für eine Evaluation würde ich nicht „drüberinstallieren“, sondern sauber neu anfangen:

kubectl get ingress -n opendesk kubectl delete namespace opendesk

Danach warten, bis der Namespace wirklich weg ist, und erst dann neu deployen. Alternativ direkt auf einem frischen K3s-Cluster testen.
3. Warning: path /$ cannot be used with pathType Exact
Das ist ein Hinweis darauf, dass der Ingress-NGINX bei dir vermutlich noch mit den neuen strikten Defaults läuft. Im offiziellen K3s-Blogartikel zu openDesk steht dafür explizit, dass bei Ingress-NGINX die folgenden Einstellungen nötig sind:

  • controller.config.annotations-risk-level=Critical
  • controller.config.strict-validate-path-type=falseAußerdem sollte Traefik in K3s deaktiviert sein und eine passende NGINX-Ingress-Version verwendet werden.

Mein Vorschlag wäre also in dieser Reihenfolge:

  1. K3s/Namespace bereinigen
  2. prüfen, ob Traefik wirklich aus ist
  3. Ingress-NGINX wie im Blog konfigurieren
  4. helmfile template laufen lassen und gezielt nach doppeltem AWS_DEFAULT_REGION suchen
  5. erst danach wieder helmfile apply

Wenn es dann immer noch scheitert, wäre der nächste sinnvolle Schritt, die eigene helmfile/environments/dev/values.yaml.gotmpl bzw. alle Custom-Overrides zu prüfen, die Objekt-Storage/S3-Settings setzen.

Danke für deine schnelle und detailierte Antwort. Ist sehr geschätzt.

1-3 Kann ich eigentlich ausschliessen da ich mich kanonisch an die Anleitung halte, der nginx proxy ist ja nicht im opendesk namespace und bleibt daher erhalten. Ich installiere aber um diese Probleme möglichst zu vermeiden auf einer frischen Debian 13 VM

FAILED RELEASES:
NAME   NAMESPACE   CHART         VERSION   DURATION
ums    opendesk    nubus/nubus                   5s

in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[3]: in helmfile/apps/nubus/helmfile-child.yaml.gotmpl: failed processing release ums: command "/usr/local/bin/helm" exited with non-zero status:

PATH:
  /usr/local/bin/helm

ARGS:
  0: helm (4 bytes)
  1: upgrade (7 bytes)
  2: --install (9 bytes)
  3: ums (3 bytes)
  4: /root/.cache/helmfile/nubus/nubus/1.18.1/nubus (46 bytes)
  5: --version (9 bytes)
  6: 1.18.1 (6 bytes)
  7: --timeout (9 bytes)
  8: 900s (4 bytes)
  9: --create-namespace (18 bytes)
  10: --namespace (11 bytes)
  11: opendesk (8 bytes)
  12: --values (8 bytes)
  13: /tmp/helmfile2949786645/opendesk-ums-values-85ff6cd859 (54 bytes)
  14: --reset-values (14 bytes)
  15: --history-max (13 bytes)
  16: 10 (2 bytes)

ERROR:
  exit status 1

EXIT STATUS
  1

STDERR:
  level=INFO msg="warning: cannot overwrite table with non table for keycloak.postgresql.auth.existingSecret (map[keyMapping:map[password:<nil>] name:<nil>])"
  level=INFO msg="warning: cannot overwrite table with non table for nubusKeycloakExtensions.postgresql.auth.existingSecret (map[keyMapping:map[password:<nil>] name:])"
  I0324 12:33:09.228059   27717 warnings.go:107] "Warning: path /$ cannot be used with pathType Exact"
  Error: failed to create typed patch object (opendesk/ums-portal-consumer; apps/v1, Kind=StatefulSet): errors:
    .spec.template.spec.initContainers[name="wait-for-ldap"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-udm"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-object-storage"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-provisioning-api"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="univention-compatibility"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]

COMBINED OUTPUT:
  Release "ums" does not exist. Installing it now.
  level=INFO msg="warning: cannot overwrite table with non table for keycloak.postgresql.auth.existingSecret (map[keyMapping:map[password:<nil>] name:<nil>])"
  level=INFO msg="warning: cannot overwrite table with non table for nubusKeycloakExtensions.postgresql.auth.existingSecret (map[keyMapping:map[password:<nil>] name:])"
  I0324 12:33:09.228059   27717 warnings.go:107] "Warning: path /$ cannot be used with pathType Exact"
  Error: failed to create typed patch object (opendesk/ums-portal-consumer; apps/v1, Kind=StatefulSet): errors:
    .spec.template.spec.initContainers[name="wait-for-ldap"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-udm"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-object-storage"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="wait-for-provisioning-api"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]
    .spec.template.spec.initContainers[name="univention-compatibility"].env: duplicate entries for key [name="AWS_DEFAULT_REGION"]

dein helmfile template command spuckt auch einen Fehler:

Templating release=open-xchange, chart=/root/.cache/helmfile/open-xchange-repo/appsuite-public-sector/2.28.18/appsuite-public-sector
in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[4]: in helmfile/apps/open-xchange/helmfile-child.yaml.gotmpl: command "/usr/local/bin/helm" exited with non-zero status:

PATH:
  /usr/local/bin/helm

ARGS:
  0: helm (4 bytes)
  1: template (8 bytes)
  2: open-xchange (12 bytes)
  3: /root/.cache/helmfile/open-xchange-repo/appsuite-public-sector/2.28.18/appsuite-public-sector (93 bytes)
  4: --version (9 bytes)
  5: 2.28.18 (7 bytes)
  6: --post-renderer (15 bytes)
  7: post-renderer-openxchange-HAPROXY (33 bytes)
  8: --namespace (11 bytes)
  9: AWS_DEFAULT_REGION|ums-portal-consumer|wait-for-object-storage|wait-for-ldap|wait-for-udm (89 bytes)
  10: --values (8 bytes)
  11: /tmp/helmfile3001126411/AWS_DEFAULT_REGION|ums-portal-consumer|wait-for-object-storage|wait-for-ldap|wait-for-udm-open-xchange-values-588c78f65f (144 bytes)
  12: --values (8 bytes)
  13: /tmp/helmfile3972646574/AWS_DEFAULT_REGION|ums-portal-consumer|wait-for-object-storage|wait-for-ldap|wait-for-udm-open-xchange-values-6f97749f8c (144 bytes)

ERROR:
  exit status 1

EXIT STATUS
  1

STDERR:
  Error: invalid argument "post-renderer-openxchange-HAPROXY" for "--post-renderer" flag: plugin: {Name:post-renderer-openxchange-HAPROXY Type:postrenderer/v1} not found

COMBINED OUTPUT:
  Error: invalid argument "post-renderer-openxchange-HAPROXY" for "--post-renderer" flag: plugin: {Name:post-renderer-openxchange-HAPROXY Type:postrenderer/v1} not found

der Output von rg auf dem vor dem Fehler geschriebenen Content

7593:  name: ums-portal-consumer
7839:  name: "ums-portal-consumer-object-storage"
7856:  name: "ums-portal-consumer-provisioning-api"
7904:  name: ums-portal-consumer-common
9544:  name: ums-portal-consumer-scripts
9581:  wait-for-ldap.sh: |
9591:  wait-for-udm.sh: |
9628:  name: ums-portal-consumer-ucr
9649:  name: ums-portal-consumer
13326:            - name: AWS_DEFAULT_REGION
13368:            - name: AWS_DEFAULT_REGION
13790:        - name: wait-for-udm
13804:          command: ["wait-for-udm.sh"]
14016:        - name: wait-for-udm
14030:          command: ["wait-for-udm.sh"]
16339:  name: ums-portal-consumer
16348:  serviceName: ums-portal-consumer
16360:        intents.otterize.com/service-name: ums-portal-consumer
16375:      serviceAccountName: ums-portal-consumer
16377:        - name: wait-for-ldap
16391:          command: ["/bin/bash", "/scripts/wait-for-ldap.sh"]
16395:            - name: AWS_DEFAULT_REGION
16397:            - name: AWS_DEFAULT_REGION
16401:                name: ums-portal-consumer
16423:        - name: wait-for-udm
16437:          command: ["/bin/bash", "/scripts/wait-for-udm.sh"]
16441:            - name: AWS_DEFAULT_REGION
16443:            - name: AWS_DEFAULT_REGION
16447:                name: ums-portal-consumer
16469:        - name: wait-for-object-storage
16488:                name: ums-portal-consumer
16493:                  name: ums-portal-consumer-object-storage
16498:                  name: ums-portal-consumer-object-storage
16500:            - name: AWS_DEFAULT_REGION
16502:            - name: AWS_DEFAULT_REGION
16538:                  name: ums-portal-consumer-provisioning-api
16540:            - name: AWS_DEFAULT_REGION
16542:            - name: AWS_DEFAULT_REGION
16546:                name: ums-portal-consumer
16572:                name: ums-portal-consumer
16579:                  name: ums-portal-consumer-object-storage
16584:                  name: ums-portal-consumer-object-storage
16589:                  name: ums-portal-consumer-provisioning-api
16591:            - name: AWS_DEFAULT_REGION
16593:            - name: AWS_DEFAULT_REGION
16663:                name: ums-portal-consumer
16670:                  name: ums-portal-consumer-object-storage
16675:                  name: ums-portal-consumer-object-storage
16680:                  name: ums-portal-consumer-provisioning-api
16682:            - name: AWS_DEFAULT_REGION
16721:            name: ums-portal-consumer-ucr
16725:            name: ums-portal-consumer-scripts
17975:                  name: ums-portal-consumer-provisioning-api
18033:          command: ["wait-for-udm.sh"]
18291:      - name: wait-for-udm-rest-api
18292:        command: ["/bin/sh", "-c", "/usr/local/bin/wait-for-udm-rest-api.py"]
18416:      - name: "wait-for-ldap"
18430:        command: ["wait-for-ldap.sh"]

Hier noch mein Setup Skript

#!/bin/bash

export ENV_DOMAIN=""
export ENV_EMAIL=""
export MASTER_PASSWORD=""
export OPENDESK_RELEASE="v1.13.1"

apt -y update
apt -y dist-upgrade
apt -y autoremove
apt -y autoclean
apt -y clean

apt -y install git

wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
chmod +x /usr/local/bin/yq

sysctl -w fs.inotify.max_user_instances=10000000

curl -sfL https://get.k3s.io | sh -s -- --disable=traefik
export OPENDESK_NAMESPACE="opendesk"
#curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

wget https://get.helm.sh/helm-v3.20.1-linux-amd64.tar.gz -O helm.tar.gz
tar -xf helm.tar.gz
cp linux-amd64/helm /usr/local/bin/
chmod +x /usr/local/bin/helm

wget https://github.com/helmfile/helmfile/releases/download/v1.4.3/helmfile_1.4.3_linux_amd64.tar.gz -O helmfile.tar.gz
tar -xf helmfile.tar.gz
cp helmfile /usr/local/bin/
chmod +x /usr/local/bin/helmfile
helmfile init

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--create-namespace \
--namespace ingress-nginx \
--set controller.allowSnippetAnnotations=true \
--set controller.admissionWebhooks.allowSnippetAnnotations=true \
--set controller.config.annotations-risk-level=Critical \
--set controller.config.strict-validate-path-type=false

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml
cat << 'EOF' > clusterissuer-tmp.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer # I'm using ClusterIssuer here
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: $ENV_EMAIL
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
EOF
envsubst < clusterissuer-tmp.yaml > clusterissuer.yaml
rm clusterissuer-tmp.yaml
kubectl apply -f clusterissuer.yaml

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.32/deploy/local-path-storage.yaml
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

git clone https://gitlab.opencode.de/bmi/opendesk/deployment/opendesk.git
cd opendesk
git checkout -b $OPENDESK_RELEASE

cat << 'EOF' > helmfile/environments/dev/values-tmp.yaml.gotmpl
global:
  domain: "$ENV_DOMAIN"

cluster:
  service:
    type: "NodePort"

ingress:
  ingressClassName: "nginx"

certificate:
  issuerRef:
    name: "letsencrypt-prod"
EOF
envsubst < helmfile/environments/dev/values-tmp.yaml.gotmpl > helmfile/environments/dev/values.yaml.gotmpl
rm helmfile/environments/dev/values-tmp.yaml.gotmpl

export OPENDESK_NAMESPACE="opendesk"
kubectl create namespace ${OPENDESK_NAMESPACE}
kubectl config set-context --current --namespace=${OPENDESK_NAMESPACE}

helmfile apply --environment dev --namespace ${OPENDESK_NAMESPACE} --timeout 1200


Das Problem duplicate entries for key [name="AWS_DEFAULT_REGION"] ist auf die helm Version zurückzuführen siehe https://github.com/helm/helm/issues/31529 das Manual sagt helm >= 3.9.0 sei OK (ohne v3.18) gilt das wohl nicht für helm 4 daher auf die getestete v3.17.3 mit helmfile v1.0.0 und helmDiff v3.11.0 gewechselt.

Neben git muss auch yq auf dem server verfügbar sein.

Führt aber zu einem Fehler im Modul openexchange

in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[4]: in helmfile/apps/open-xchange/helmfile-child.yaml.gotmpl: command "/usr/local/bin/helm" exited with non-zero status:

PATH:
  /usr/local/bin/helm

ARGS:
  0: helm (4 bytes)
  1: diff (4 bytes)
  2: upgrade (7 bytes)
  3: --allow-unreleased (18 bytes)
  4: open-xchange (12 bytes)
  5: /tmp/helmfile2501130435/opendesk/open-xchange/appsuite-public-sector/2.28.18/appsuite-public-sector (99 bytes)
  6: --version (9 bytes)
  7: 2.28.18 (7 bytes)
  8: --post-renderer (15 bytes)
  9: ./post-renderer-openxchange-HAPROXY.sh (38 bytes)
  10: --namespace (11 bytes)
  11: opendesk (8 bytes)
  12: --values (8 bytes)
  13: /tmp/helmfile3867778798/opendesk-open-xchange-values-7fd9d679ff (63 bytes)
  14: --values (8 bytes)
  15: /tmp/helmfile3227894008/opendesk-open-xchange-values-865bc4b867 (63 bytes)
  16: --reset-values (14 bytes)
  17: --detailed-exitcode (19 bytes)
  18: --color (7 bytes)

ERROR:
  exit status 1

EXIT STATUS
  1

STDERR:
  Error: Failed to render chart: exit status 1: coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/exchange-interop:e43f77b956c8fa0bb49f8ed4d075e3c3de8f1351 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/nextcloud-integration:8cf1b742aff361973f638204afcb05eb59e53dcc commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/public-sector:16d74ae6675d97f3077dbb266e98dc3da8b0f5c6 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.ingress.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.serviceAccount.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/exchange-interop:e43f77b956c8fa0bb49f8ed4d075e3c3de8f1351 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/nextcloud-integration:8cf1b742aff361973f638204afcb05eb59e53dcc commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/public-sector:16d74ae6675d97f3077dbb266e98dc3da8b0f5c6 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.serviceAccount.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  Error: error while running post render on files: error while running command /root/opendesk/helmfile/apps/open-xchange/post-renderer-openxchange-HAPROXY.sh. error output:
  usage: yq [-h] [--yaml-output] [--yaml-roundtrip]
            [--yaml-output-grammar-version {1.1,1.2}] [--width WIDTH]
            [--indentless-lists] [--explicit-start] [--explicit-end]
            [--in-place] [--version]
            [jq_filter] [files ...]
  yq: error: argument files: can't open '
    (. | select(.kind == "Ingress") | select(.metadata.name == "open-xchange-appsuite-http-api-routes-appsuite-api") | .spec.rules[].http.paths[].path) |=
      (select(. == "/appsuite/api(.*)") | "/appsuite/api") // .
  ': [Errno 2] No such file or directory: '\n  (. | select(.kind == "Ingress") | select(.metadata.name == "open-xchange-appsuite-http-api-routes-appsuite-api") | .spec.rules[].http.paths[].path) |=\n    (select(. == "/appsuite/api(.*)") | "/appsuite/api") // .\n'
  : exit status 2
  Use --debug flag to render out invalid YAML
  Error: plugin "diff" exited with error

COMBINED OUTPUT:
  ********************
  	Release was not present in Helm.  Diff will show entire contents as new.
  ********************
  Error: Failed to render chart: exit status 1: coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/exchange-interop:e43f77b956c8fa0bb49f8ed4d075e3c3de8f1351 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/nextcloud-integration:8cf1b742aff361973f638204afcb05eb59e53dcc commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/public-sector:16d74ae6675d97f3077dbb266e98dc3da8b0f5c6 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.ingress.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.serviceAccount.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/exchange-interop:e43f77b956c8fa0bb49f8ed4d075e3c3de8f1351 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/nextcloud-integration:8cf1b742aff361973f638204afcb05eb59e53dcc commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/public-sector:16d74ae6675d97f3077dbb266e98dc3da8b0f5c6 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.serviceAccount.annotations (map[])
  coalesce.go:298: warning: cannot overwrite table with non table for appsuite-public-sector.appsuite.core-mw.update.podAnnotations (map[commit.open-xchange.com/core:a1e874a6e51bdedab4e2c768fd037159c943aeb6 commit.open-xchange.com/guard:8a07217bd94a34442d2e0b15d98cd70f7e8b9a85 commit.open-xchange.com/office:4b1a916d403e8cd71318c2d0e528ac0d20892624 commit.open-xchange.com/weakforced:7a3d63dfece8ba3fbfec8b9f2e0e60e47567d4bf])
  Error: error while running post render on files: error while running command /root/opendesk/helmfile/apps/open-xchange/post-renderer-openxchange-HAPROXY.sh. error output:
  usage: yq [-h] [--yaml-output] [--yaml-roundtrip]
            [--yaml-output-grammar-version {1.1,1.2}] [--width WIDTH]
            [--indentless-lists] [--explicit-start] [--explicit-end]
            [--in-place] [--version]
            [jq_filter] [files ...]
  yq: error: argument files: can't open '
    (. | select(.kind == "Ingress") | select(.metadata.name == "open-xchange-appsuite-http-api-routes-appsuite-api") | .spec.rules[].http.paths[].path) |=
      (select(. == "/appsuite/api(.*)") | "/appsuite/api") // .
  ': [Errno 2] No such file or directory: '\n  (. | select(.kind == "Ingress") | select(.metadata.name == "open-xchange-appsuite-http-api-routes-appsuite-api") | .spec.rules[].http.paths[].path) |=\n    (select(. == "/appsuite/api(.*)") | "/appsuite/api") // .\n'
  : exit status 2
  Use --debug flag to render out invalid YAML
  Error: plugin "diff" exited with error

Ein Schritt weiter: Es gibt offenbar zwei yq Tools die sich leicht unterscheiden. Benötigt wird die Go Version nicht die Python sonst tritt obiger Fehler auf. Leider installiert der Paketmanager von Debian 13 standardmässig die Python Version.

Führt leider zum nächsten Fehler

Upgrading release=opendesk-nextcloud-management, chart=/tmp/helmfile3322734551/opendesk/opendesk-nextcloud-management/opendesk-nextcloud-management/4.9.1/opendesk-nextcloud-management, namespace=opendesk
Release "opendesk-nextcloud-management" does not exist. Installing it now.


FAILED RELEASES:
NAME                            NAMESPACE   CHART                                          VERSION   DURATION
opendesk-nextcloud-management   opendesk    nextcloud-repo/opendesk-nextcloud-management                7m55s

in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[5]: in helmfile/apps/nextcloud/helmfile-child.yaml.gotmpl: failed processing release opendesk-nextcloud-management: command "/usr/local/bin/helm" exited with non-zero status:

PATH:
  /usr/local/bin/helm

ARGS:
  0: helm (4 bytes)
  1: upgrade (7 bytes)
  2: --install (9 bytes)
  3: opendesk-nextcloud-management (29 bytes)
  4: /tmp/helmfile3322734551/opendesk/opendesk-nextcloud-management/opendesk-nextcloud-management/4.9.1/opendesk-nextcloud-management (128 bytes)
  5: --version (9 bytes)
  6: 4.9.1 (5 bytes)
  7: --wait (6 bytes)
  8: --wait-for-jobs (15 bytes)
  9: --timeout (9 bytes)
  10: 1800s (5 bytes)
  11: --create-namespace (18 bytes)
  12: --namespace (11 bytes)
  13: opendesk (8 bytes)
  14: --values (8 bytes)
  15: /tmp/helmfile1070563665/opendesk-opendesk-nextcloud-management-values-c5d8b5699 (79 bytes)
  16: --reset-values (14 bytes)
  17: --history-max (13 bytes)
  18: 10 (2 bytes)

ERROR:
  exit status 1

EXIT STATUS
  1

STDERR:
  Error: jobs.batch "opendesk-nextcloud-management-1" not found

COMBINED OUTPUT:
  Release "opendesk-nextcloud-management" does not exist. Installing it now.
  Error: jobs.batch "opendesk-nextcloud-management-1" not found

Update auf helm 3.20.1 helmfile 1.4.3 und opendesk 13.1 hat nichts gebracht, gleicher Fehler

scheint ein generelles Problem zu sein Deployment fails at opendesk-nextcloud-management (#311) · Issues · BMI / openDesk / Deployment / openDesk · GitLab

Hallo, bist du bei deiner Installation weiter gekommen? Stehe vor dem selben Fehler…

Hi leider nein, habe noch folgende Dinge versucht:
→ Grösste mögliche Cloud Instanz bei Hetzner gebucht um Performance auszuschliessen
→ Wechsel auf Longhorn als Storrage Provider
→ Habe auch mal die Authorin des Blog Beitrags angeschrieben ob sie den Beitrag mal redigieren könnte, leider keine Antwort
Hat leider nichts gebracht, habe aber gesehen, dass jemand auf den Bug reagiert hat. Muss ich mal ausprobieren ob da was drin ist. Zumindest bin ich nicht mehr alleine…

Ok, schade. Schade auch, dass es so ein Krampf ist, sich eine OpenDesk Testumgebung aufzusetzen. So wird das nichts in unseren Verwaltungen, liebes BMI. :smiley:

Mit Hilfe des Log Commands konnte ich den Fehler bei mir weiter einschränken:

Running occ theming:config logo /var/nextcloud/data/nextcloud_data/logo_f0557cdf951d35a183aa77d3d93e013a98277e333170307f39ddcd3ae06df52b2bdfdd5f5a65526227c1949a5decafc21dc40408e1a446364f6ce35a38509272.png…FAIL.
Got exit code 1. Exiting now.
Command output:

In ObjectStoreStorage.php line 546:

Error while writing stream to object store

In S3ConnectionTrait.php line 177:

Creation of bucket „nextcloud“ failed. Error executing „CreateBucket“ on „h
ttps://objectstore.svm.cloud/nextcloud“; AWS HTTP error: cURL error 60: SSL
certificate problem: self-signed certificate (see https://curl.haxx.se/lib
curl/c/libcurl-errors.html) for https://objectstore.svm.cloud/nextcloud

Demnach meckert er in diesem Moment das Zertifikat an.
Vermutlich funktioniert schon der certmanager gar nicht, sodass keine Zertifikate für die eingetragene Domain ausgesetllt werden. Gehe ich auf unsere Testdomain „svm.cloud“, erhalte ich ein Zertifkat vom Ingress Controller:

Allgemeiner Name (CN) Kubernetes Ingress Controller Fake Certificate
Organisation (O) Acme Co
Organisationseinheit (OU) <Gehört nicht zum Zertifikat>

Keine Ahnung, wie ich das beheben soll. Warum braucht es für eine Testinstanz überhaupt öffentliche Zertifikate? :roll_eyes:

Das neue Log grenzt es ziemlich gut ein: Der Fehler passiert nicht primär bei Nextcloud-Theming selbst, sondern beim Schreiben in den konfigurierten S3/ObjectStore.

Entscheidend ist diese Stelle:

Error while writing stream to object store
Creation of bucket "nextcloud" failed
cURL error 60: SSL certificate problem: self-signed certificate
for https://objectstore.svm.cloud/nextcloud

Das heißt: Der Nextcloud-Pod versucht per HTTPS auf objectstore.svm.cloud zuzugreifen, vertraut dem dort präsentierten Zertifikat aber nicht.

Der Hinweis

Kubernetes Ingress Controller Fake Certificate

bedeutet meistens: Für diesen Host liegt dem Ingress kein gültiges TLS-Secret vor, oder cert-manager hat noch kein Zertifikat ausgestellt. Dann liefert ingress-nginx sein Default/Fake-Zertifikat aus.

Ich würde zwei Dinge getrennt prüfen.

1. Ist das ObjectStore-Zertifikat gültig?

Vom Cluster aus testen:

kubectl -n opendesk run curl-debug --rm -it --restart=Never \
  --image=curlimages/curl -- \
  curl -v https://objectstore.svm.cloud/nextcloud

Wenn dort ebenfalls self-signed certificate kommt, ist genau das die Ursache.

Dann prüfen:

kubectl -n opendesk get ingress
kubectl -n opendesk get certificate
kubectl -n opendesk describe certificate
kubectl get clusterissuer,issuer -A
kubectl get certificaterequest,order,challenge -A

Wichtig ist auch, ob DNS wirklich auf den Ingress zeigt:

dig objectstore.svm.cloud
dig portal.svm.cloud

und ob Port 80/443 von außen erreichbar ist. Für Let’s Encrypt HTTP-01 muss der Host öffentlich erreichbar sein.

2. Ist objectstore.svm.cloud für eine Testinstanz überhaupt die richtige URL?

Wenn der ObjectStore innerhalb des Clusters läuft, würde ich für eine Testinstanz möglichst nicht über den öffentlichen Ingress gehen, sondern über den internen Kubernetes-Service, zum Beispiel sinngemäß:

http://<minio-service>.<namespace>.svc.cluster.local:<port>

Dann hat man dieses TLS-/Ingress-/Let’s-Encrypt-Problem auf dem internen Pfad nicht. Ob und wie das bei openDesk/Nubus/Nextcloud konfigurierbar ist, hängt von den Values ab.

Wenn ihr bewusst einen externen HTTPS-Endpunkt nutzt, gibt es drei saubere Optionen:

  1. Ein öffentlich gültiges Zertifikat für objectstore.svm.cloud ausstellen lassen.
  2. Eine interne CA verwenden und diese CA in den Nextcloud-Container bzw. die beteiligten Pods einbauen.
  3. Für eine reine Testumgebung HTTP oder einen internen Service-Endpunkt nutzen, falls die Charts/Values das zulassen.

Unsicher wäre, TLS-Verifikation einfach abzuschalten, falls es dafür irgendwo einen Schalter gibt. Das kann zum Testen kurzfristig helfen, kaschiert aber genau die Art Problem, die später im Betrieb wiederkommt.

Warum braucht eine Testinstanz öffentliche Zertifikate?

Eigentlich braucht sie nicht zwingend öffentliche Zertifikate. Aber sobald ein Dienst per https://... angesprochen wird, validiert der Client das Zertifikat. In diesem Fall ist der Client Nextcloud/PHP/cURL im Pod. Der kennt euer selbstsigniertes Zertifikat nicht und bricht deshalb korrekt ab.

Für Browser-Zugriff kann man ein Self-Signed-Zertifikat noch manuell wegklicken. Für Pods, Jobs und Init-Container geht das nicht ohne Trust-Konfiguration.

Kurz gesagt: Nicht openDesk “braucht” zwingend öffentliche Zertifikate, sondern eure aktuelle ObjectStore-Konfiguration verwendet HTTPS mit einem Zertifikat, dem die Workloads nicht vertrauen.

Praktische Tipps aus unserer Erfahrung

Für Testumgebungen würde ich Let’s Encrypt trotzdem nicht komplett umgehen, wenn die Instanz über echte Hostnames erreichbar sein soll. Viele Probleme tauchen sonst erst später auf, weil Browser, Pods, Jobs, Webhooks und externe Clients Zertifikate unterschiedlich streng prüfen.

Was bei uns geholfen hat:

  • Für öffentlich erreichbare Testinstanzen echte DNS-Namen verwenden.
  • cert-manager früh separat prüfen, bevor man den ganzen openDesk-Stack debuggt.
  • Erst mit Let’s Encrypt Staging testen, damit man nicht versehentlich Rate Limits trifft.
  • Danach auf Let’s Encrypt Production wechseln.
  • Certificate-/Challenge-Status immer separat prüfen:
kubectl get clusterissuer,issuer -A
kubectl get certificate -A
kubectl get certificaterequest,order,challenge -A

Wenn dort schon etwas hängt, ist der openDesk-Fehler oft nur ein Folgefehler.

Für Kostenkontrolle haben wir gelernt: Helm allein löst den Betrieb nicht. Gerade bei Testinstanzen lohnt es sich, Infrastruktur und Applikation getrennt zu denken.

Ein paar Punkte, die bei uns wichtig wurden:

  • Kleine Testcluster bewusst klein halten und Ressourcenlimits setzen.
  • Retained State, also Daten, die wirklich bleiben müssen, klar von wegwerfbarer Runtime trennen.
  • Wenn möglich, teure Runtime-Ressourcen geplant schlafen legen.
  • Vor dem Abschalten Snapshots oder Retained Disks sauber sichern.
  • Beim Wiederhochfahren nicht nur “Helm install war erfolgreich” prüfen, sondern echte Smoke Checks laufen lassen.
  • Früh Monitoring/Logs einbauen, sonst weiß man beim nächsten Fehler nur “failed”, aber nicht warum.

Gerade ObjectStore, PVCs, Ingress, TLS und Mail sind Bereiche, in denen ein Chart zwar Ressourcen erzeugt, aber nicht automatisch garantiert, dass die gesamte Betriebsumgebung valide ist.

Ich würde als nächsten Schritt die relevanten anonymisierten Values für ObjectStore/S3, Ingress und cert-manager posten. Besonders interessant wären:

  • ObjectStore/S3 endpoint
  • bucket name
  • TLS/SSL flags
  • Ingress hostnames
  • cert-manager issuer/clusterIssuer
  • ob MinIO/ObjectStore intern im Cluster läuft oder extern bereitgestellt wird

Hallo,

viele Dank für deine detaillierte Antwort.

Ich konnte den cert-manager nun dazu bewegen, die LE-Zertifikate korrekt auszustellen.
War wohl eine Kombination aus Fehlern im öffentlichen und internen DNS.

sles-k3s:~ # kubectl get certificate -A
NAMESPACE   NAME                    READY   SECRET                      AGE
opendesk2   opendesk-certificates   True    opendesk-certificates-tls   164m
opendesk3   opendesk-certificates   True    opendesk-certificates-tls   13m
sles-k3s:~ # kubectl get certificaterequest,order,challenge -A
NAMESPACE   NAME                                                         APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
opendesk2   certificaterequest.cert-manager.io/opendesk-certificates-1   True                True    letsencrypt-prod   system:serviceaccount:cert-manager:cert-manager   164m
opendesk3   certificaterequest.cert-manager.io/opendesk-certificates-1   True                True    letsencrypt-prod   system:serviceaccount:cert-manager:cert-manager   13m

NAMESPACE   NAME                                                            STATE   AGE
opendesk2   order.acme.cert-manager.io/opendesk-certificates-1-3403108310   valid   164m
opendesk3   order.acme.cert-manager.io/opendesk-certificates-1-3403108310   valid   13m

Sieht mMn gut aus. Aber eine Frage dazu habe ich:

Muss die gewünschte Domain im internen Netz (also auf meiner K3S-VM selbst) auf die öffentliche oder interne IP-Adresse des Servers aufgelöst werden? Aktuell habe ich es im internen Netz so (Beispiel):

*.meine-domain.cloud > 192.168.0.1 (= SLES Server mit K3S)
meine-domain.cloud > 192.168.0.1
192.168.0.1 = SLES mit K3S
Extern werden die zwei Records zur public IP-Adresse aufgelöst.

Das Deployen vom Nextcloud-Management lief damit dann auch durch:

Listing releases matching ^opendesk-nextcloud$
opendesk-nextcloud      opendesk3       1               2026-05-12 18:23:32.443473838 +0200 CEST        deployed        opendesk-nextcloud-4.9.4

Nun hängt die Installation aber gleich beim nächsten Schritt:

Upgrading release=opendesk-nextcloud-notifypush, chart=/root/.cache/helmfile/nextcloud-repo/opendesk-nextcloud-notifypush/4.9.4/opendesk-nextcloud-notifypush, namespace=opendesk3

Ich würde ja zu gern wissen, was da überhaupt im Hintergrund gemacht wird, aber Logs bekomme ich keine ausgespuckt:

kubectl logs opendesk-nextcloud-notifypush-65979b7b58-bjvzp -f

Die Installation bricht dann irgendwann hiermit ab:

Release "opendesk-nextcloud-notifypush" does not exist. Installing it now.


UPDATED RELEASES:
NAME                            NAMESPACE   CHART                                          VERSION   DURATION
opendesk-nextcloud-management   opendesk3   nextcloud-repo/opendesk-nextcloud-management   4.9.4         7m9s
opendesk-nextcloud              opendesk3   nextcloud-repo/opendesk-nextcloud              4.9.4           1s


FAILED RELEASES:
NAME                            NAMESPACE   CHART                                          VERSION   DURATION
opendesk-nextcloud-notifypush   opendesk3   nextcloud-repo/opendesk-nextcloud-notifypush                30m1s

in ./helmfile.yaml.gotmpl: in .helmfiles[0]: in ./helmfile_generic.yaml.gotmpl: in .helmfiles[5]: in helmfile/apps/nextcloud/helmfile-child.yaml.gotmpl: failed processing release opendesk-nextcloud-notifypush: command "/usr/bin/helm" exited with non-zero status:

PATH:
  /usr/bin/helm

ARGS:
  0: helm (4 bytes)
  1: upgrade (7 bytes)
  2: --install (9 bytes)
  3: opendesk-nextcloud-notifypush (29 bytes)
  4: /root/.cache/helmfile/nextcloud-repo/opendesk-nextcloud-notifypush/4.9.4/opendesk-nextcloud-notifypush (102 bytes)
  5: --version (9 bytes)
  6: 4.9.4 (5 bytes)
  7: --wait (6 bytes)
  8: --timeout (9 bytes)
  9: 1800s (5 bytes)
  10: --create-namespace (18 bytes)
  11: --namespace (11 bytes)
  12: opendesk3 (9 bytes)
  13: --values (8 bytes)
  14: /tmp/helmfile2240622117/opendesk3-opendesk-nextcloud-notifypush-values-54ff4cfdf5 (81 bytes)
  15: --reset-values (14 bytes)
  16: --history-max (13 bytes)
  17: 10 (2 bytes)

ERROR:
  exit status 1

EXIT STATUS
  1

STDERR:
  Error: context deadline exceeded

COMBINED OUTPUT:
  Release "opendesk-nextcloud-notifypush" does not exist. Installing it now.
  Error: context deadline exceeded

Beim Einrichten habe ich mich soweit an die Anleitung des erwähnten Blogs gehalten.

Die Zertifikate sehen jetzt gut aus. Zur DNS-Frage: Bei uns ist die wichtige Regel, dass alle browserseitigen openDesk-Hosts immer auf die IP zeigen müssen, auf der der Ingress für diese Hostnames terminiert. Ob das intern die private LAN-IP oder extern die öffentliche IP ist, ist zweitrangig.

Für dein Setup klingt Split-DNS also plausibel:

intern: *.meine-domain.cloud -> 192.168.0.1 extern: *.meine-domain.cloud -> public IP

Das ist sogar oft besser als intern auf die Public-IP zu zeigen, wenn der Router kein Hairpin-NAT sauber kann. Entscheidend ist: Von der K3s-VM und aus Pods heraus muss https://drive.meine-domain.cloud, https://portal… usw. den Ingress erreichen und das LE-Zertifikat für den Namen sehen.

Zum neuen Fehler: context deadline exceeded bei opendesk-nextcloud-notifypush heißt sehr wahrscheinlich nicht mehr DNS/Cert-Problem, sondern Helm wartet 30 Minuten auf ein Kubernetes-Objekt, das nicht Ready wird. Wichtig: opendesk-nextcloud deployed … 1s bedeutet nicht zwingend, dass Nextcloud schon betriebsbereit ist. In der openDesk-Helmfile wartet der eigentliche Nextcloud-Release nicht hart auf Readiness; notifypush ist dann oft der erste Release, bei dem der noch nicht fertige Nextcloud-/Redis-/Postgres-Pfad sichtbar wird.

Ich würde als Nächstes nicht bei kubectl logs -f anfangen, sondern bei Status/Events:

NS=opendesk3 kubectl -n $NS get deploy,rs,pod,svc,endpoints,ingress | grep -E 'nextcloud|notifypush|redis|postgresql' kubectl -n $NS describe deploy opendesk-nextcloud-notifypush kubectl -n $NS describe pod -l app.kubernetes.io/instance=opendesk-nextcloud-notifypush kubectl -n $NS get events --sort-by=.lastTimestamp | tail -n 100 kubectl -n $NS logs deploy/opendesk-nextcloud-notifypush --all-containers --prefix --tail=-1 kubectl -n $NS logs deploy/opendesk-nextcloud-notifypush --all-containers --prefix --previous --tail=-1

Besonders interessant wären ImagePullBackOff, CrashLoopBackOff, fehlende Endpoints für opendesk-nextcloud-aio, redis-headless oder postgresql, sowie Readiness-Probe-Fehler.

Wenn es nur um eine Evaluationsinstanz geht, kann man notifypush auch testweise deaktivieren und später separat debuggen:

replicas: nextcloudNotifyPush: 0

Dann sollte der Release opendesk-nextcloud-notifypush nicht installiert werden. Das nimmt nur die Push-Benachrichtigungen raus, nicht Nextcloud selbst.

Oh man, vielen Dank für deine Antwort und Hilfe!

Die Events zeigten mir die Ursache:

kubectl -n opendesk3 get events --sort-by=.lastTimestamp | tail -n 100
42m         Warning   FailedScheduling   pod/opendesk-nextcloud-aio-cron-29644250-tq5hb                 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
13m         Warning   FailedScheduling   pod/opendesk-nextcloud-aio-cron-29644455-n6vfc                 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
8m4s        Warning   FailedScheduling   pod/opendesk-nextcloud-aio-cron-29644450-6fh7f                 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
37m         Warning   FailedScheduling   pod/opendesk-nextcloud-aio-cron-29644255-t826g                 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
18m         Warning   FailedScheduling   pod/opendesk-nextcloud-aio-cron-29644450-6fh7f                 0/1 nodes are available: 1 Insufficient cpu. no new claims to deallocate, preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
...

Ich hatte die Test-VM mehrfach neu aufgesetzt, um eine saubere Installation zu garantieren. Dabei habe ich beim letzten mal aus Versehen nur 4 Cores vergeben und nicht die empfohlenen 12.

Somit lief die Nextcloud-Installation durch und es hängt beim nächsten Release „openproject“, weil da wieder pods nicht starten wollen:

sles-k3s:~ # kubectl -n opendesk3 get events --sort-by=.lastTimestamp | tail -n 100 | grep openproject
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-seeder-1-jwfzt-app-tmp                   waiting for pod openproject-seeder-1-jwfzt to be scheduled
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-web-c5687577f-5z75h-tmp                  External provisioner is provisioning volume for claim "opendesk3/openproject-web-c5687577f-5z75h-tmp"
11m         Normal    SuccessfulCreate               replicaset/openproject-web-c5687577f                                       Created pod: openproject-web-c5687577f-5z75h
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-app-tmp   waiting for pod openproject-worker-default-9c4f6955b-vc57q to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-app-tmp   Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-seeder-1-jwfzt-tmp                       waiting for pod openproject-seeder-1-jwfzt to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-seeder-1-jwfzt-tmp                       Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-tmp       waiting for pod openproject-worker-default-9c4f6955b-vc57q to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-tmp       Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-tmp       External provisioner is provisioning volume for claim "opendesk3/openproject-worker-default-9c4f6955b-vc57q-tmp"
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-seeder-1-jwfzt-tmp                       External provisioner is provisioning volume for claim "opendesk3/openproject-seeder-1-jwfzt-tmp"
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-app-tmp      waiting for pod openproject-hocuspocus-64857ccd96-xgnnb to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-app-tmp      Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    ScalingReplicaSet              deployment/openproject-hocuspocus                                          Scaled up replica set openproject-hocuspocus-64857ccd96 from 0 to 1
11m         Normal    SuccessfulCreate               replicaset/openproject-hocuspocus-64857ccd96                               Created pod: openproject-hocuspocus-64857ccd96-xgnnb
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-tmp          waiting for pod openproject-hocuspocus-64857ccd96-xgnnb to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-tmp          Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    SuccessfulCreate               replicaset/openproject-worker-default-9c4f6955b                            Created pod: openproject-worker-default-9c4f6955b-vc57q
11m         Normal    ScalingReplicaSet              deployment/openproject-worker-default                                      Scaled up replica set openproject-worker-default-9c4f6955b from 0 to 1
11m         Normal    ScalingReplicaSet              deployment/openproject-web                                                 Scaled up replica set openproject-web-c5687577f from 0 to 1
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-tmp          External provisioner is provisioning volume for claim "opendesk3/openproject-hocuspocus-64857ccd96-xgnnb-tmp"
11m         Normal    SuccessfulCreate               job/openproject-seeder-1                                                   Created pod: openproject-seeder-1-jwfzt
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-web-c5687577f-5z75h-app-tmp              waiting for pod openproject-web-c5687577f-5z75h to be scheduled
11m         Normal    WaitForPodScheduled            persistentvolumeclaim/openproject-web-c5687577f-5z75h-tmp                  waiting for pod openproject-web-c5687577f-5z75h to be scheduled
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-web-c5687577f-5z75h-tmp                  Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-seeder-1-jwfzt-tmp                       Successfully provisioned volume pvc-d320fc7c-b15f-4dd4-88bf-29f6c1999435
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-app-tmp   External provisioner is provisioning volume for claim "opendesk3/openproject-worker-default-9c4f6955b-vc57q-app-tmp"
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-web-c5687577f-5z75h-tmp                  Successfully provisioned volume pvc-11ee0553-0891-4d5d-aabc-3764ea10661d
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-tmp          Successfully provisioned volume pvc-ded20756-62b6-4a1d-8296-bf94494342ca
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-web-c5687577f-5z75h-app-tmp              External provisioner is provisioning volume for claim "opendesk3/openproject-web-c5687577f-5z75h-app-tmp"
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-seeder-1-jwfzt-app-tmp                   External provisioner is provisioning volume for claim "opendesk3/openproject-seeder-1-jwfzt-app-tmp"
11m         Normal    Provisioning                   persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-app-tmp      External provisioner is provisioning volume for claim "opendesk3/openproject-hocuspocus-64857ccd96-xgnnb-app-tmp"
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-tmp       Successfully provisioned volume pvc-a5ed3b63-754a-48c2-9a42-cff909c6068f
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-worker-default-9c4f6955b-vc57q-app-tmp   Successfully provisioned volume pvc-d81f3373-0103-4f41-a78c-678eae082115
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-hocuspocus-64857ccd96-xgnnb-app-tmp      Successfully provisioned volume pvc-06fd8240-d11f-48b1-9ba0-29b56a564f53
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-seeder-1-jwfzt-app-tmp                   Successfully provisioned volume pvc-b7d5f792-9cf4-42de-86cd-7035cacb6f7e
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-seeder-1-jwfzt-app-tmp                   Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    ExternalProvisioning           persistentvolumeclaim/openproject-web-c5687577f-5z75h-app-tmp              Waiting for a volume to be created either by the external provisioner 'rancher.io/local-path' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
11m         Normal    Pulled                         pod/openproject-hocuspocus-64857ccd96-xgnnb                                Container image "registry.opencode.de/bmi/opendesk/components/supplier/openproject/images-mirror/hocuspocus:release-338001b2@sha256:59c725d05136445dcf542ef20f1881e0cd3e7f90c897b9339758349c21c1ef77" already present on machine and can be accessed by the pod
11m         Normal    Started                        pod/openproject-hocuspocus-64857ccd96-xgnnb                                Container started
11m         Normal    Created                        pod/openproject-hocuspocus-64857ccd96-xgnnb                                Container created
11m         Normal    ProvisioningSucceeded          persistentvolumeclaim/openproject-web-c5687577f-5z75h-app-tmp              Successfully provisioned volume pvc-7bfa9d2b-26b4-4b50-ba0e-dfc63a304ce1
11m         Normal    Created                        pod/openproject-seeder-1-jwfzt                                             Container created
11m         Normal    Pulled                         pod/openproject-seeder-1-jwfzt                                             Container image "registry-1.docker.io/library/postgres:16.9-alpine3.20@sha256:e5507c984377515b8c9922b0eb19f55aba2063fdc7bccf268cefd53133f97054" already present on machine and can be accessed by the pod
11m         Normal    Started                        pod/openproject-seeder-1-jwfzt                                             Container started
10m         Normal    Sync                           ingress/openproject                                                        Scheduled for sync
5m34s       Warning   BackOff                        pod/openproject-seeder-1-jwfzt                                             Back-off restarting failed container seeder in pod openproject-seeder-1-jwfzt_opendesk3(3b47a6c1-cb00-44c7-a24e-f441f7c7d97b)
5m12s       Normal    Created                        pod/openproject-seeder-1-jwfzt                                             Container created
5m12s       Normal    Started                        pod/openproject-seeder-1-jwfzt                                             Container started
5m12s       Normal    Pulled                         pod/openproject-seeder-1-jwfzt                                             Container image "registry.opencode.de/bmi/opendesk/components/supplier/openproject/images-mirror/open_desk:17.3.1@sha256:7efa81e2771234e9bb618d6266c4c5e8f0ba16afa9b3bb203c87a7f6b49050fb" already present on machine and can be accessed by the pod
5m10s       Normal    Killing                        pod/openproject-seeder-1-jwfzt                                             Stopping container seeder
5m10s       Normal    SuccessfulDelete               job/openproject-seeder-1                                                   Deleted pod: openproject-seeder-1-jwfzt
5m3s        Warning   BackoffLimitExceeded           job/openproject-seeder-1                                                   Job has reached the specified backoff limit
58s         Warning   BackOff                        pod/openproject-web-c5687577f-5z75h                                        Back-off restarting failed container wait-for-db in pod openproject-web-c5687577f-5z75h_opendesk3(d4d78706-68a5-4005-9a70-cd0e4e7189d4)
19s         Normal    Pulled                         pod/openproject-worker-default-9c4f6955b-vc57q                             Container image "registry.opencode.de/bmi/opendesk/components/supplier/openproject/images-mirror/open_desk:17.3.1@sha256:7efa81e2771234e9bb618d6266c4c5e8f0ba16afa9b3bb203c87a7f6b49050fb" already present on machine and can be accessed by the pod
19s         Normal    Created                        pod/openproject-worker-default-9c4f6955b-vc57q                             Container created
19s         Normal    Started                        pod/openproject-worker-default-9c4f6955b-vc57q                             Container started
13s         Warning   BackOff                        pod/openproject-worker-default-9c4f6955b-vc57q                             Back-off restarting failed container wait-for-db in pod openproject-worker-default-9c4f6955b-vc57q_opendesk3(a23f8a14-4af5-4eec-a3dc-600b7ea1d929)
5s          Normal    Started                        pod/openproject-web-c5687577f-5z75h                                        Container started
5s          Normal    Created                        pod/openproject-web-c5687577f-5z75h                                        Container created
5s          Normal    Pulled                         pod/openproject-web-c5687577f-5z75h                                        Container image "registry.opencode.de/bmi/opendesk/components/supplier/openproject/images-mirror/open_desk:17.3.1@sha256:7efa81e2771234e9bb618d6266c4c5e8f0ba16afa9b3bb203c87a7f6b49050fb" already present on machine and can be accessed by the pod
sles-k3s:~ # kubectl -n opendesk3 logs openproject-web-c5687577f-5z75h --all-containers --prefix --tail=-1
[pod/openproject-web-c5687577f-5z75h/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:40:in 'block in Dir.tmpdir': system temporary path is world-writable: /tmp (StructuredWarnings::StandardWarning)
[pod/openproject-web-c5687577f-5z75h/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:40:in 'block in Dir.tmpdir': /tmp is world-writable: /tmp (StructuredWarnings::StandardWarning)
[pod/openproject-web-c5687577f-5z75h/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:38:in 'block in Dir.tmpdir': . is not writable: /app (StructuredWarnings::StandardWarning)
[pod/openproject-web-c5687577f-5z75h/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:44:in 'Dir.tmpdir': could not find a temporary directory (ArgumentError)
[pod/openproject-web-c5687577f-5z75h/wait-for-db]
[pod/openproject-web-c5687577f-5z75h/wait-for-db]     end or raise ArgumentError, "could not find a temporary directory"
[pod/openproject-web-c5687577f-5z75h/wait-for-db]                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick/configuration.rb:81:in 'MiniMagick::Configuration.extended'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:13:in 'Kernel#extend'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:13:in '<module:MiniMagick>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:7:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/analyzer/image_analyzer/image_magick.rb:5:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:28:in '<class:Engine>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:23:in '<module:ActiveStorage>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:22:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:18:in 'block in <top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:16:in 'Array#each'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:16:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/config/application.rb:33:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/actions.rb:15:in 'Rails::Command::Actions#require_application!'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/environment_argument.rb:30:in 'Rails::Command::EnvironmentArgument#require_application!'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/actions.rb:19:in 'Rails::Command::Actions#boot_application!'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/commands/runner/runner_command.rb:30:in 'Rails::Command::RunnerCommand#perform'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor/command.rb:28:in 'Thor::Command#run'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor/invocation.rb:127:in 'Thor::Invocation#invoke_command'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/base.rb:176:in 'Rails::Command::Base#invoke_command'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor.rb:538:in 'Thor.dispatch'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/base.rb:71:in 'Rails::Command::Base.perform'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:65:in 'block in Rails::Command.invoke'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:143:in 'Rails::Command.with_argv'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:63:in 'Rails::Command.invoke'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/commands.rb:18:in '<top (required)>'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-web-c5687577f-5z75h/wait-for-db]       from bin/rails:4:in '<main>'
sles-k3s:~ # kubectl -n opendesk3 logs openproject-worker-default-9c4f6955b-vc57q --all-containers --prefix --tail=-1
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:40:in 'block in Dir.tmpdir': system temporary path is world-writable: /tmp (StructuredWarnings::StandardWarning)
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:40:in 'block in Dir.tmpdir': /tmp is world-writable: /tmp (StructuredWarnings::StandardWarning)
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:38:in 'block in Dir.tmpdir': . is not writable: /app (StructuredWarnings::StandardWarning)
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db] /usr/local/lib/ruby/4.0.0/tmpdir.rb:44:in 'Dir.tmpdir': could not find a temporary directory (ArgumentError)
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]     end or raise ArgumentError, "could not find a temporary directory"
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick/configuration.rb:81:in 'MiniMagick::Configuration.extended'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:13:in 'Kernel#extend'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:13:in '<module:MiniMagick>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/mini_magick-5.3.1/lib/mini_magick.rb:7:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/analyzer/image_analyzer/image_magick.rb:5:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:28:in '<class:Engine>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:23:in '<module:ActiveStorage>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/activestorage-8.1.2.1/lib/active_storage/engine.rb:22:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:18:in 'block in <top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:16:in 'Array#each'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/all.rb:16:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/config/application.rb:33:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/actions.rb:15:in 'Rails::Command::Actions#require_application!'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/environment_argument.rb:30:in 'Rails::Command::EnvironmentArgument#require_application!'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/actions.rb:19:in 'Rails::Command::Actions#boot_application!'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/commands/runner/runner_command.rb:30:in 'Rails::Command::RunnerCommand#perform'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor/command.rb:28:in 'Thor::Command#run'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor/invocation.rb:127:in 'Thor::Invocation#invoke_command'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/base.rb:176:in 'Rails::Command::Base#invoke_command'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/thor-1.5.0/lib/thor.rb:538:in 'Thor.dispatch'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command/base.rb:71:in 'Rails::Command::Base.perform'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:65:in 'block in Rails::Command.invoke'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:143:in 'Rails::Command.with_argv'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/command.rb:63:in 'Rails::Command.invoke'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /app/vendor/bundle/ruby/4.0.0/gems/railties-8.1.2.1/lib/rails/commands.rb:18:in '<top (required)>'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'Kernel.require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from /usr/local/lib/ruby/4.0.0/bundled_gems.rb:60:in 'block (2 levels) in Kernel#replace_require'
[pod/openproject-worker-default-9c4f6955b-vc57q/wait-for-db]    from bin/rails:4:in '<main>'
Error from server (BadRequest): container "openproject" in pod "openproject-worker-default-9c4f6955b-vc57q" is waiting to start: PodInitializing

Scheint ein Problem mit dem Filesystem zu sein. Im Event-Log sieht man ja aber, dass der Provisioner die Volumes erfolgreich erstellt hat - auch für openproject-web und openproject-worker.

Dennoch bricht der Start beider Pods mit could not find a temporary directory ab.

Es gibt aber auch etwas positives zu berichten. Mir ist es nun schon einmal möglich, mich am Portal mit dem Administrator-Account anzumelden.

Für eine reine Evaluation würde ich es deutlich einfacher machen und nicht versuchen, sofort die komplette Suite produktionsnah zum Laufen zu bekommen.

Mein Vorschlag:

  1. Auf den aktuellen Patch-Stand gehen
    Stand 14.05.2026 ist im openDesk-Repo v1.14.2 der neueste Tag. Den würde ich für einen frischen Test nehmen, weil dort schon einige der früheren Nubus-/Ingress-Themen entschärft sind.

Wichtig: Nicht auf Helm 4 gehen. Laut openDesk-Doku: Helm >= 3.17.3, aber nicht 3.18.0, nicht 3.20.1 und nicht 4.x.

  1. Für K3s/local-path OpenProject erst einmal abklemmen
    Der aktuelle Fehler ist kein DNS- oder CPU-Thema mehr. Die openDesk-Doku weist explizit darauf hin, dass der local-path-provisioner kein Sticky-Bit-Support für die OpenProject-Tmp-Volumes bietet. Genau dazu passt dein Fehler:

Dir.tmpdir: could not find a temporary directory

Für eine Evaluation würde ich OpenProject daher erst einmal deaktivieren, statt daran weiter zu debuggen.

  1. Nicht alles auf einmal installieren
    Wenn du nur Portal/Login/Nextcloud testen willst, würde ich mit einem kleineren Profil starten:

helmfile/environments/dev/values.yaml.gotmpl

global:
domain: „meine-domain.cloud“

persistence:
storageClassNames:
RWO: „local-path“

apps:
openproject:
enabled: false
jitsi:
enabled: false
element:
enabled: false
collabora:
enabled: false
cryptpad:
enabled: false
xwiki:
enabled: false

replicas:
nextcloudNotifyPush: 0

Damit lässt du die größten bzw. fehleranfälligsten Zusatzkomponenten erst einmal weg:

  • OpenProject wegen local-path/tmp-Volume-Problem
  • Jitsi wegen zusätzlicher UDP-/Netzwerk-Themen
  • Element/Matrix wegen zusätzlicher Komplexität
  • Collabora/CryptPad/XWiki, falls du erst einmal nur die Kerninstallation prüfen willst
  • Nextcloud Notify Push, weil Nextcloud auch ohne Push-Benachrichtigungen evaluierbar ist
  1. Frisch starten
    Für eine Wegwerf-Testinstanz würde ich keine halb fehlgeschlagenen Releases weiterpflegen:

kubectl delete ns opendesk3 --ignore-not-found

Dann frisch mit dem kleineren Profil ausrollen:

git fetch --tags
git checkout v1.14.2
helmfile apply -e dev -n opendesk3

Wenn das läuft, würde ich die Komponenten einzeln wieder zuschalten, z. B. erst Collabora, dann XWiki, dann ggf. OX/Mail, und OpenProject zuletzt nur mit anderer StorageClass oder mit dem bekannten Workaround:

containerSecurityContext:
readOnlyRootFilesystem: false

openproject:
useTmpVolumes: false

Kurz gesagt: Für Evaluation lieber weniger konfigurieren, aktuellen Patch-Stand nutzen, frischer Namespace, und optionale Apps schrittweise aktivieren. Mit 4 Cores ist die komplette Suite ohnehin nicht realistisch; die Doku nennt für die initiale Evaluation 12 Cores und 32 GB RAM.

1 „Gefällt mir“

Nochmals vielen Dank für deine ausführliche Hilfestellung.

Nach Anwendung des Workarounds für OpenProject hat das OpenDesk-Deployment nun komplett funktioniert - alle Pods und Dienste laufen.

Wunderbar.
Vielleicht sollte es nocheinmal ein Refresh von Vorteile von Open-Source-Softwarelösungen mit Self-Hosting geben.

Worauf hast Du nun am Ende gehostet? Hetzner, welche Maschine?

Ja, eine Überarbeitung des Blog-Eintrages wäre wohl nicht schlecht.

Für den ersten Einblick in Opendesk läuft es auf einem lokalen Server bei uns selbst. Ist eine SLES VM über Proxmox.

Noch eine Frage:

Die OX AppSuite bzw. „Groupware“ sollte normalerweise ohne weitere Konfiguration out-of-the-box funktionieren (also das UI), richtig?

Die Seite lädt zwar, aber das UI nicht.

Die Browser-Konsole verrät:

„Server is down“

Die Pods sind aber alle im Status „Running“ bzw. „Completed“.

Ja, die OX AppSuite / Groupware-UI sollte bei einer vollständigen openDesk-Installation grundsätzlich ohne separate Handkonfiguration funktionieren. Es gibt aber eine wichtige Einschränkung: Dass alle Pods Running oder Completed sind, reicht bei OX nicht als Gesundheitscheck.

Aus unserem Deployment: Die AppSuite besteht grob aus statischem UI plus OX-Middleware/API. Es kann also passieren, dass /appsuite/ lädt, aber die API dahinter nicht erreichbar oder nicht gesund ist. Dann sieht man im Browser nur generische Meldungen wie „Server is down“.

Ich würde als Nächstes gezielt prüfen, ob die AppSuite-API funktioniert und ob open-xchange-core-mw Fehler loggt:

NS=opendesk3
HOST=webmail.meine-domain.cloud # ggf. anpassen: mail/meine-domain je nach global.hosts.openxchange

kubectl -n $NS get pods | grep -E ‚open-xchange|mariadb|redis|minio|ums‘
kubectl -n $NS get deploy,svc,endpoints | grep -E ‚open-xchange|mariadb|redis|minio‘

curl -k -I https://$HOST/appsuite/
curl -k -i https://$HOST/appsuite/api/login?action=autologin
curl -k -i https://$HOST/appsuite/api/capabilities?action=all

kubectl -n $NS logs deploy/open-xchange-core-mw --all-containers --tail=300
kubectl -n $NS logs deploy/open-xchange-core-ui --all-containers --tail=100

Falls die Deployment-Namen anders heißen:

kubectl -n $NS get deploy | grep open-xchange
kubectl -n $NS logs -l app.kubernetes.io/instance=open-xchange --all-containers --tail=300

In unserem Setup waren bei AppSuite vor allem diese Punkte relevant:

  1. OX darf für den internen Filestore nicht von der öffentlichen Objectstore-URL abhängen.
    Wir haben OX auf den internen MinIO-Service gezwungen:

objectstores:
openxchange:
endpoint: „http://minio:9000

Sonst kann OX je nach DNS/Ingress/TLS-Situation scheinbar laufen, aber beim Start oder bei API-Aufrufen hängen.

  1. AppSuite-Login/API-Fehler sieht man meistens in open-xchange-core-mw, nicht im UI-Pod.
    Interessante Suchbegriffe:

kubectl -n $NS logs deploy/open-xchange-core-mw --all-containers --tail=500
| grep -Ei ‚error|exception|oidc|ldap|contactsLdapClient|Invalid Credentials|filestore|s3|minio|mariadb|mysql|redis‘

  1. Wenn Mail-Verschlüsselung/OX Guard nicht sauber läuft, würde ich sie für eine Evaluation abschalten.
    Das ist bei uns im Pilot bewusst deaktiviert:

functional:
groupware:
mail:
encryption:
enabled: false

Das sollte zwar eher Warnbanner als „Server is down“ verursachen, nimmt aber eine Fehlerquelle raus.

  1. Prüfe in der Browser-Network-Ansicht die erste rote Anfrage.
    Die Konsolenmeldung „Server is down“ ist sehr generisch. Entscheidend ist, ob z. B. /appsuite/api/... mit 404, 502, 503 oder 500 antwortet. Diese URL plus Statuscode wäre der nächste gute Hinweis.

Kurz: Ja, das UI sollte out-of-the-box funktionieren. Wenn nur die Seite lädt, aber die AppSuite „Server is down“ meldet, würde ich zuerst OX-Middleware/API, Ingress-Routing für /appsuite/api/ und die interne MinIO/Objectstore-Konfiguration prüfen.

1 „Gefällt mir“

Während eines Client-Zugriffs wird für das deployment open-xchange-core-mw-groupware folgendes geloggt:

{"timestamp":1779188103707,"level":4,"file":"org.glassfish.jersey.servlet.WebComponent","line":595,"method":"filterFormParameters","msg":"A servlet request to the URI https://webmail.my-domain.cloud:80/appsuite/api?action=config&version=8.46.4 contains form parameters in the requ
est body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.","details":{"com
.openexchange.grizzly.requestURI":"/appsuite/api","com.openexchange.grizzly.serverName":"webmail.my-domain.cloud","com.openexchange.grizzly.userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36","com.openexchan
ge.grizzly.pathInfo":"/appsuite/api","thread":"OXWorker-0000009","com.openexchange.grizzly.remoteAddress":"10.42.0.1","com.openexchange.grizzly.threadName":"OXWorker-0000009","com.openexchange.localhost.version":"8.46.92","com.openexchange.grizzly.remotePort":"443","com.openexchan
ge.localhost.ipAddress":"10.42.0.193","com.openexchange.grizzly.servletPath":"","com.openexchange.grizzly.queryString":"action=config&version=8.46.4","com.openexchange.grizzly.method":"GET","com.openexchange.http.requestwatcher.marker":"true"},"requestId":"1008237541-17678"}

Die erste Browser-Konsolenmeldung ist „Server is down“, die zweite Meldung ist

meta.js:28 Uncaught (in promise) 
{xhr: {…}, error: '404 An unknown error occurred', code: 'NOSERVER'}

die dritte:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'pgettext')
    at Object.<anonymous> (main.js:107:70)
    at Je (backbone.js:336:57)
    at J (backbone.js:322:19)
    at ue (backbone.js:110:16)
    at M.trigger (backbone.js:312:5)
    at m (gettext.js:39:6)
    at async Object.change (locale.js:37:5)
    at async Promise.all (appsuite/index 1)

ausgegeben von https://webmail.my-domain.cloud/src/io.ox/core/locale/meta.js.

Curl:

Ein curl auf /appsuite/ antwortet mit HTTP 200.
Curl auf /appsuite/api/… allerdings mit 404, also not found.

Ein curl auf das interne MinIO (curl -k -i http://10.42.0.143:9000) antwortet mit 403 Forbidden.

Ich nehme an, ein 403 soll auch bei der API so passieren, weshalb es für mich erstmal nach dem von dir erwähnten Fehler ausschaut:

Das (bzw. die IP-Adresse, denn „minio“ löst der Server nicht auf) trage ich in der ./helmfile/environments/default/objectstores.yaml.gotmpl ein und wende es mit kubectl apply -f FILE an?

Sorry für die grundsätzlichen Fragen zum Handling eines Kubernetes-Clusters…

Edit:

Folgende Errors tauchen auch im Log auf:

{"timestamp":1779190634636,"level":4,"file":"org.glassfish.jersey.internal.Errors","line":191,"method":"logErrors","msg":"The following warnings have been detected: WARNING: Parameter 1 of type com.openexchange.redis.internal.BasicRedisConnector<?, ?> from public com.openexchange redis.internal.rest.RedisConnectorRESTService(com.openexchange.redis.internal.BasicRedisConnector<?, ?>,com.openexchange.server.ServiceLookup) is not resolvable to a concrete type.\n","details":{"thread":"ResourcePublisher"}}