ADD: implement migration and backup configurations for Nextcloud with Longhorn support

This commit is contained in:
2026-04-15 19:51:29 +02:00
parent 2ea9f3973f
commit be9329d313
15 changed files with 326 additions and 27 deletions
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Pod
metadata:
name: mariadb-backup
namespace: nextcloud
spec:
nodeName: knode0 # <-- FIXED ON node0
containers:
- name: backup
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: old
mountPath: /old
volumes:
- name: old
persistentVolumeClaim:
claimName: nextcloud-mariadb-pvc
@@ -0,0 +1,34 @@
apiVersion: v1
kind: Pod
metadata:
name: config-migration
namespace: nextcloud
spec:
volumes:
- name: old-config
persistentVolumeClaim:
claimName: nextcloud-config-pvc
- name: new-config
persistentVolumeClaim:
claimName: nextcloud-config-pvc-longhorn
containers:
- name: migrator
image: alpine:3.18
volumeMounts:
- name: old-config
mountPath: /old
- name: new-config
mountPath: /new
command: ['sh']
args:
- -c
- |
echo "Copying config data..."
if [ "$(ls -A /old)" ]; then
cp -rv /old/* /new/ 2>/dev/null || true
echo "Config migration completed"
else
echo "Old config is empty"
fi
sleep infinity
restartPolicy: Never
@@ -0,0 +1,34 @@
apiVersion: v1
kind: Pod
metadata:
name: apps-migration
namespace: nextcloud
spec:
volumes:
- name: old-apps
persistentVolumeClaim:
claimName: nextcloud-apps-pvc
- name: new-apps
persistentVolumeClaim:
claimName: nextcloud-apps-pvc-longhorn
containers:
- name: migrator
image: alpine:3.18
volumeMounts:
- name: old-apps
mountPath: /old
- name: new-apps
mountPath: /new
command: ['sh']
args:
- -c
- |
echo "Copying apps data..."
if [ "$(ls -A /old)" ]; then
cp -rv /old/* /new/ 2>/dev/null || true
echo "Apps migration completed"
else
echo "Old apps is empty"
fi
sleep infinity
restartPolicy: Never
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-mariadb-pvc-longhorn
namespace: nextcloud
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 10Gi
@@ -0,0 +1,24 @@
apiVersion: v1
kind: Pod
metadata:
name: mariadb-restore
namespace: nextcloud
spec:
nodeName: knode0
containers:
- name: restore
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: new
mountPath: /new
- name: oldbackup
mountPath: /backup
volumes:
- name: new
persistentVolumeClaim:
claimName: nextcloud-mariadb-pvc-longhorn
- name: oldbackup
hostPath:
path: /var/lib/nextcloud/mariadb-backup
type: DirectoryOrCreate
@@ -28,6 +28,11 @@ spec:
value: nextcloud value: nextcloud
ports: ports:
- containerPort: 3306 - containerPort: 3306
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 5
periodSeconds: 10
resources: resources:
requests: requests:
memory: "256Mi" memory: "256Mi"
@@ -41,4 +46,4 @@ spec:
volumes: volumes:
- name: mariadb-data - name: mariadb-data
persistentVolumeClaim: persistentVolumeClaim:
claimName: nextcloud-mariadb-pvc claimName: nextcloud-mariadb-pvc-longhorn
@@ -9,24 +9,4 @@ spec:
resources: resources:
requests: requests:
storage: 10Gi storage: 10Gi
storageClassName: local-path # <-- explicit default StorageClass storageClassName: longhorn
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nextcloud-mariadb-pv
labels:
app: mariadb
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-path
claimRef:
namespace: nextcloud
name: nextcloud-mariadb-pvc
hostPath:
path: /var/lib/nextcloud/mariadb-data
type: DirectoryOrCreate
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-apps-pvc-longhorn
namespace: nextcloud
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi
@@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nextcloud-config-pvc-longhorn
namespace: nextcloud
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 5Gi
@@ -16,12 +16,19 @@ spec:
# fsGroup sorgt dafür, dass gemountete Volumes die Gruppe www-data (33) bekommen # fsGroup sorgt dafür, dass gemountete Volumes die Gruppe www-data (33) bekommen
securityContext: securityContext:
fsGroup: 33 fsGroup: 33
# Auf knode0 zwingen (hat Kernel 6.1 mit NFS - Kompatibilität)
nodeSelector:
kubernetes.io/hostname: knode0
# hostAliases mappt die öffentliche Domain intern auf die Service-ClusterIP, # hostAliases mappt die öffentliche Domain intern auf die Service-ClusterIP,
# damit der Pod henryathome.home64.de direkt intern erreicht (vermeidet externe Loopback/Firewall/403) # damit der Pod henryathome.home64.de direkt intern erreicht (vermeidet externe Loopback/Firewall/403)
hostAliases: hostAliases:
- ip: "10.43.107.87" - ip: "10.43.107.87"
hostnames: hostnames:
- "henryathome.home64.de" - "henryathome.home64.de"
initContainers:
- name: wait-for-mariadb
image: busybox:1.34
command: ['sh', '-c', 'until nc -z mariadb.nextcloud.svc.cluster.local 3306; do echo waiting for mariadb; sleep 2; done;']
containers: containers:
- name: nextcloud - name: nextcloud
image: nextcloud:33-apache image: nextcloud:33-apache
@@ -73,7 +80,7 @@ spec:
claimName: nextcloud-data-pvc claimName: nextcloud-data-pvc
- name: config - name: config
persistentVolumeClaim: persistentVolumeClaim:
claimName: nextcloud-config-pvc claimName: nextcloud-config-pvc-longhorn
- name: apps - name: apps
persistentVolumeClaim: persistentVolumeClaim:
claimName: nextcloud-apps-pvc claimName: nextcloud-apps-pvc-longhorn
@@ -10,10 +10,13 @@ spec:
persistentVolumeReclaimPolicy: Retain persistentVolumeReclaimPolicy: Retain
storageClassName: nfs storageClassName: nfs
mountOptions: mountOptions:
- vers=4 - vers=3
- rsize=65536 - rsize=65536
- wsize=65536 - wsize=65536
- noatime - noatime
- soft
- timeo=20
- retrans=2
nfs: nfs:
server: 192.168.178.186 # <-- ERSETZEN: IP oder Hostname deiner NAS server: 192.168.178.186 # <-- ERSETZEN: IP oder Hostname deiner NAS
path: /volume1/Nextcloud/data # <-- ERSETZEN: Pfad zum Share auf der NAS (z.B. /volume1/nextcloud) path: /volume1/Nextcloud/data # <-- ERSETZEN: Pfad zum Share auf der NAS (z.B. /volume1/nextcloud)
+139
View File
@@ -0,0 +1,139 @@
# ─── ServiceAccount ───────────────────────────────────────────────
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-runner
namespace: gitlab
---
# ─── Role ─────────────────────────────────────────────────────────
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: gitlab-runner
namespace: gitlab
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/attach", "pods/log", "secrets", "configmaps", "services"]
verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]
---
# ─── RoleBinding ──────────────────────────────────────────────────
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: gitlab-runner
namespace: gitlab
subjects:
- kind: ServiceAccount
name: gitlab-runner
namespace: gitlab
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: gitlab-runner
---
# ─── Secret (Runner Authentication Token, GitLab 16+) ────────────
apiVersion: v1
kind: Secret
metadata:
name: gitlab-runner-secret
namespace: gitlab
type: Opaque
stringData:
runner-token: "glrt-3nNma_nEvL1Bq2zc8m5Zu286MQpwOjIKdDozCnU6MTAQ.01.181jg6jja"
---
# ─── ConfigMap (config.toml) ──────────────────────────────────────
apiVersion: v1
kind: ConfigMap
metadata:
name: gitlab-runner-config
namespace: gitlab
data:
config.toml: |
concurrent = 4
check_interval = 10
log_level = "info"
[session_server]
session_timeout = 1800
---
# ─── Deployment ───────────────────────────────────────────────────
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab-runner
namespace: gitlab
labels:
app: gitlab-runner
spec:
replicas: 1
selector:
matchLabels:
app: gitlab-runner
template:
metadata:
labels:
app: gitlab-runner
spec:
serviceAccountName: gitlab-runner
initContainers:
- name: register-runner
image: gitlab/gitlab-runner:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
gitlab-runner register \
--non-interactive \
--url "$CI_SERVER_URL" \
--token "$RUNNER_TOKEN" \
--executor kubernetes \
--kubernetes-namespace gitlab \
--kubernetes-service-account gitlab-runner \
--kubernetes-pull-policy if-not-present \
--kubernetes-privileged true \
--output-limit 4096 \
--kubernetes-cpu-request "100m" \
--kubernetes-cpu-limit "500m" \
--kubernetes-memory-request "256Mi" \
--kubernetes-memory-limit "4Gi"
env:
- name: CI_SERVER_URL
value: "https://gitlab.henryathome.home64.de"
- name: RUNNER_TOKEN
valueFrom:
secretKeyRef:
name: gitlab-runner-secret
key: runner-token
volumeMounts:
- name: runner-config
mountPath: /etc/gitlab-runner
containers:
- name: gitlab-runner
image: gitlab/gitlab-runner:latest
imagePullPolicy: IfNotPresent
command: ["gitlab-runner", "run", "--user=gitlab-runner", "--working-directory=/home/gitlab-runner"]
env:
- name: CI_SERVER_URL
value: "https://gitlab.henryathome.home64.de"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "1000m"
volumeMounts:
- name: runner-config
mountPath: /etc/gitlab-runner
volumes:
- name: runner-config
emptyDir: {}
+4
View File
@@ -18,6 +18,10 @@ stringData:
} }
prometheus_monitoring['enable'] = false prometheus_monitoring['enable'] = false
registry_external_url 'https://registry.henryathome.home64.de'
registry_nginx['listen_port'] = 5050
registry_nginx['listen_https'] = false
# Authentik SSO (OpenID Connect) # Authentik SSO (OpenID Connect)
gitlab_rails['omniauth_enabled'] = true gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect'] gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect']
+6 -2
View File
@@ -17,9 +17,13 @@ spec:
targetPort: 443 targetPort: 443
nodePort: 31443 nodePort: 31443
- name: ssh - name: ssh
port: 31022 port: 22
targetPort: 31022 targetPort: 22
nodePort: 31022 nodePort: 31022
- name: registry
port: 5050
targetPort: 5050
nodePort: 31050
type: NodePort type: NodePort
# --- # ---
+11
View File
@@ -0,0 +1,11 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-2replicas
provisioner: driver.longhorn.io
parameters:
numberOfReplicas: "2"
staleReplicaTimeout: "30"
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true