blog-image

BorgWarehouse® avec Kubernetes

  • dHENRY
  • 03/11/2023
  • (Durée de lecture : 4 mn)

Benjamin (Raven) membre de l’équipe MytinyDC, à l’origine du projet BorgWareHouse, a fait évoluer son application en container. Il est donc temps de l’installer dans le cluster Kubernetes.

Quelle usage avec MytinyDC ?

Remplacer BackupPC, chargé de sauvegarder localement, la configuration des serveurs.
BackupPC est un excellent outil, m’ayant rendu de fiers services, mais devenu trop complexe à installer et configurer.

Avec ce nouveau système, je dispose d’un container chargé de stocker les données, et un script qui opère les sauvegardes quotidiennes de tous les serveurs.

Besoins

  • des volumes pour stocker la configuration et les données de sauvegardes envoyées par les clients Borg.
  • des accès réseaux : ssh et https
  • ATTENTION : Pour des raisons techniques liées à l’utilisation du service openssh-server, le container ne peut pas être exécuté en READ-ONLY (Openshift).

Les volumes

Comme indiqué dans sa documentation très détaillée (issu du fichier docker-compose) :

  • /home/borgwarehouse/app/config
  • /home/borgwarehouse/.ssh
  • /ssh_host:/etc/ssh
  • /repos:/home/borgwarehouse/repos

4 volumes Persistants, sont nécessaires, dont certains ne serviront qu’a stocker un seul fichier en mode “read-write” (oubliez les ConfigMap). L’idée reste de conserver toutes les données d’une instance à l’autre.

Les services réseaux

Pour être utilisable, ce déploiement devra exposer 2 ports :

  • ssh/tcp redirigé vers le port 22 du container
  • http/tcp redirigé vers le port 3000 du container

Utilisez un reverse proxy pour basculer en “http S”. Si vous souhaitez utiliser vos propres certificats, au sein du container, adaptez la configuration de vos “Services”/“Ingress”.

graph TD U(user) A(admin) subgraph container HTTP(Http server) SSHS(Ssh server) end A-->|administration http|container U-->|borg backup process ssh|container

Les manifests

Si il y a des volontaires pour fournir une distribution Helm, contacter Raven.

Les composants YAML

apiVersion: "v1"
kind: "Namespace"
metadata:
  name: "borgwarehouse"
  labels:
    name: "borgwarehouse"
---
# only if you need credential to pull image
apiVersion: 'v1'
kind: 'Secret'
metadata:
  name: 'dockerregistry'
  namespace: 'borgwarehouse'
type: 'kubernetes.io/dockerconfigjson'
data:
  .dockerconfigjson : your-secret-as-base64-encoded
---
apiVersion: v1
kind: "Secret"
metadata:
  name: "borgwarehouse-secret-envvars"
  namespace: "borgwarehouse"
type: "Opaque"
stringData:
  # Url to reach the IHM service
  NEXTAUTH_URL: "https://your.domain.com"
  NEXTAUTH_SECRET: "your-secret"
  CRONJOB_KEY: your-other-secret
  FQDN: "your.domain.com"
  # Port to reach ssh service
  SSH_SERVER_PORT: "your-exposed-ssh-port"
---
apiVersion: "v1"
kind: "PersistentVolumeClaim"
# in regards your cloud configuration

# 4 volumes - for config, /etc/ssh & ~/.ssh you could set to 1Mi
#             && repos set to (WyW)Gi
#  accessModes:
#    - "ReadWriteOnce"
#  resources:
#    requests:
#      storage: "1Mi"
---
# Adapt to your needs
apiVersion: "v1"
kind: "LimitRange"
metadata:
  name: "limitrange-borgwarehouse"
  namespace: "borgwarehouse"
spec:
  limits:
    - default:
        cpu: "1500m"
        memory: "800Mi"
      defaultRequest:
        cpu: "10m"
        memory: "50Mi"
      max:
        cpu: "1500m"
        memory: "800Mi"
      min:
        cpu: "10m"
        memory: "50Mi"
      type: Container
---
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: "borgwarehouse"
  namespace: "borgwarehouse"
spec:
  # Adapt to your needs
  revisionHistoryLimit: 1
  strategy:
    type: "Recreate" # | rollingUpdate
  selector:
    matchLabels:
      app: "borgwarehouse"
  replicas: 1
  template:
    metadata:
      labels:
        app: "borgwarehouse"
    spec:
      imagePullSecrets:
        - name: "dockerregistry" # If you need secret to pull image
      securityContext:
        runAsUser: 1001
        runAsGroup: 1001
        fsGroup: 1001
        runAsNonRoot: true
      containers:
        - name: "borgwarehouse"
      containers:
      - name: 'borgwarehouse'
        env:
          - name: 'NEXTAUTH_URL'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'NEXTAUTH_URL'
                optional: false
          - name: 'NEXTAUTH_SECRET'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'NEXTAUTH_SECRET'
                optional: false
          - name: 'CRONJOB_KEY'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'CRONJOB_KEY'
                optional: false
          - name: 'FQDN'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'FQDN'
                optional: false
          - name: 'SSH_SERVER_PORT'
            valueFrom :
              secretKeyRef:
                name: 'borgwarehouse-secret-envvars'
                key: 'SSH_SERVER_PORT'
          image: "borgwarehouse/borgwarehouse:latest" # lastest is a bad practise...
          # Adapt to your needs
          imagePullPolicy: "Always"
          readinessProbe:
            httpGet:
              path: "/"
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
            timeoutSeconds: 3
          startupProbe:
            httpGet:
              path: "/"
              port: 3000
            periodSeconds: 10
            failureThreshold: 30
          livenessProbe:
            httpGet:
              path: "/"
              port: 3000
            periodSeconds: 120
            timeoutSeconds: 3
          securityContext:
          ports:
            - containerPort: 22
              protocol: "TCP"
              name: "port-22"
            - containerPort: 3000
              protocol: "TCP"
              name: "port-3000"
          volumeMounts:
            - mountPath: "/home/borgwarehouse/app/config"
              name: "xxxxx-borgwarehouse-config"
            - mountPath: "/home/borgwarehouse/repos"
              name: "xxxxx-borgwarehouse-repos"
            - mountPath: "/home/borgwarehouse/.ssh"
              name: "xxxxx-borgwarehouse-homedirssh"
            - mountPath: "/etc/ssh"
              name: "xxxxx-borgwarehouse-etcssh"
      volumes:
        - name: "xxxxx-borgwarehouse-config"
          persistentVolumeClaim:
            # because only this claimref is able to use final volumes
            claimName: "claimref-xxxxx-borgwarehouse-config"
        - name: "xxxxx-borgwarehouse-repos"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-repos"
        - name: "xxxxx-borgwarehouse-homedirssh"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-homedirssh"
        - name: "xxxxx-borgwarehouse-etcssh"
          persistentVolumeClaim:
            claimName: "claimref-xxxxx-borgwarehouse-etcssh"
---
apiVersion: "v1"
kind: "Service"
metadata:
  name: "borgwarehouse-app-port-22"
  namespace: "borgwarehouse"
spec:
  # Adapt to your cluster configuration
  type: "NodePort"
  ports:
    - port: 22
      protocol: "TCP"
      targetPort: 22
      name: "port-borgwarehouse-22"
  selector:
    app: "borgwarehouse"
---
apiVersion: "v1"
kind: "Service"
metadata:
  name: "borgwarehouse-app-port-3000"
  namespace: "borgwarehouse"
spec:
  # Adapt to your cluster configuration
  type: "NodePort"
  ports:
    - port: 3000
      protocol: "TCP"
      targetPort: 3000
      name: "port-borgwarehouse-3000"
  selector:
    app: "borgwarehouse"
---
## Your ingress definitions...
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "borgwarehouse-app-port-3000"
  namespace: "borgwarehouse"
[...]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "borgwarehouse-app-port-22"
  namespace: "borgwarehouse"

Après intégration et démarrage de l’application, vérifier les accès réseaux.
Pour vous connecter, je vous renvoi à la documentation originale

+++

(*) Image Rendering Powered by