De Docker Compose à Kubernetes via Podman

Rédigé par Nicolas Sulek Aucun commentaire
Classé dans : Système Mots clés : aucun
Voici un petit guide pour migrer du couple Docker et Docker compose vers Podman et Kubernetes.

Plusieurs possibilités pour migrer vers Podman :
  • remplacer le moteur d'exécution de conteneur Docker par Podman et continuer à utiliser Docker Compose
  • utiliser podman-compose
  • utiliser les services systemd pour retranscrire les dépendances entre conteneurs
  • passer à Quadlet
  • réécrire les fichiers docker-compose.yml en fichier YAML pour Kubernetes
C'est cette dernière solution que j'ai choisie.

Déploiement via docker-compose

Prenons comme exemple un déploiement basique de VaultWarden avec Nginx en reverse-proxy :
services:
  nginx:
    image: nginx:alpine
    container_name: nginx
    environment:
      - TZ=Europe/Paris
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /home/vaultwarden/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      -  443:443
    restart: always

    image: vaultwarden/server:alpine
    container_name: vaultwarden
    environment:
      TZ: Europe/Paris
      DOMAIN: "https://toto.example.org/"
      SIGNUPS_ALLOWED: "false"
      INVITATIONS_ALLOWED: "false"
      SHOW_PASSWORD_HINT: "false"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /home/vaultwarden/vaultwarden:/data
    restart: always
    depends_on:
      - nginx

Docker Compose et Podman

Installons docker-compose et podman :
apt install docker-compose podman
Sous Debian, le paquet docker-compose installera également Docker, ce qui n'est clairement pas utile pour la suite.
Nous allons donc le désactiver :
systemctl stop docker.service docker.socket
systemctl disable docker.service docker.socket
et le remplacer par Podman :
rm /run/docker.sock
ln -s /run/podman/podman.sock /run/docker.sock
On peut maintenant instancier nos conteneurs en utilisant docker-compose et podman :
docker-compose up -d
On vérifie avec podman ps :
CONTAINER ID  IMAGE                                COMMAND               CREATED             STATUS                 PORTS                 NAMES
6e6899c44175  docker.io/library/nginx:alpine       nginx -g daemon o...  About a minute ago  Up About a minute ago  0.0.0.0:443->443/tcp  nginx
1b4f1698f547  docker.io/vaultwarden/server:alpine  /start.sh             About a minute ago  Up About a minute ago                        vaultwarden

Conversion en YAML pour Kubernetes

On va maintenant pouvoir utiliser podman pour générer un fichier YAML pour Kubernetes en lui spécifiant les conteneurs à récupérer :
podman kube generate nginx vaultwarden > vaultwarden.yaml
Il peut y avoir des Warning relatifs à des annotations tronquées :
WARN[0000] Truncation Annotation: "https://github.com/nginxinc/docker-nginx.git#cffeb933620093bc0c08c0b28c3d5cbaec79d729:mainline/alpine" to "https://github.com/nginxinc/docker-nginx.git#cffeb933620093bc0c": Kubernetes only allows 63 characters
Mais rien de grave, ce ne sont que des annotations que l'on pourra corriger voire supprimer.

On obtient le fichier résultat suivant :
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.3.1

# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    com.docker.official-images.bashbrew.arch/nginx: amd64
    io.kubernetes.cri-o.TTY/nginx: "false"
    io.kubernetes.cri-o.TTY/vaultwarden: "false"
    io.podman.annotations.autoremove/nginx: "FALSE"
    io.podman.annotations.autoremove/vaultwarden: "FALSE"
    io.podman.annotations.init/nginx: "FALSE"
    io.podman.annotations.init/vaultwarden: "FALSE"
    io.podman.annotations.privileged/nginx: "FALSE"
    io.podman.annotations.privileged/vaultwarden: "FALSE"
    io.podman.annotations.publish-all/nginx: "FALSE"
    io.podman.annotations.publish-all/vaultwarden: "FALSE"
    org.opencontainers.image.base.digest/nginx: sha256:0d0ef5c914d3ea700147da1bd050c59edb8bb12ca312f3800b29d7c8
    org.opencontainers.image.base.name/nginx: nginx:1.27.4-alpine-slim
    org.opencontainers.image.created/nginx: "2025-02-05T21:27:16Z"
    org.opencontainers.image.revision/nginx: cffeb933620093bc0c08c0b28c3d5cbaec79d729
    org.opencontainers.image.source/nginx: https://github.com/nginxinc/docker-nginx.git#cffeb933620093bc0c
    org.opencontainers.image.url/nginx: https://hub.docker.com/_/nginx
    org.opencontainers.image.version/nginx: 1.27.4-alpine
  creationTimestamp: "2025-02-18T10:10:21Z"
  labels:
    app: nginx-pod
  name: nginx-pod
spec:
  automountServiceAccountToken: false
  containers:
  - args:
    - nginx
    - -g
    - daemon off;
    env:
    - name: TZ
      value: Europe/Paris
    image: docker.io/library/nginx:alpine
    name: nginx
    ports:
    - containerPort: 443
      hostPort: 443
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /etc/localtime
      name: etc-localtime-host-0
      readOnly: true
  - env:
    - name: DOMAIN
      value: https://toto.example.org/
    - name: SIGNUPS_ALLOWED
      value: "false"
    - name: INVITATIONS_ALLOWED
      value: "false"
    - name: TZ
      value: Europe/Paris
    - name: SHOW_PASSWORD_HINT
      value: "false"
    image: docker.io/vaultwarden/server:alpine
    name: vaultwarden
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /etc/localtime
      name: etc-localtime-host-1
      readOnly: true
    - mountPath: /data
      name: home-vaultwarden-vaultwarden-host-2
  enableServiceLinks: false
  volumes:
  - hostPath:
      path: /etc/localtime
      type: File
    name: etc-localtime-host-0
  - hostPath:
      path: /etc/localtime
      type: File
    name: etc-localtime-host-1
  - hostPath:
      path: /home/vaultwarden/vaultwarden
      type: Directory
    name: home-vaultwarden-vaultwarden-host-2
Nettement plus verbeux et long que notre docker-compose.yml d'origine. On constate que podman va générer :
  • 1 pod (nginx-pod)
avec 2 conteneurs :
  • 1 nginx
  • 1 vaultwarden
On retrouve bien nos volumes et nos variables d'environnement.

Il ne restera plus qu'à modifier ce joli fichier pour le mettre à notre convenance, mais il est normalement déjà fonctionnel.
Après avoir arrêter les conteneurs lancés via docker-compose, on peut instancier les nouveaux avec :
podman kube play vaultwarden.yaml

Exposition des conteneurs

Un léger détail mais qui a son importance, les conteneurs ne sont plus directement exposés sur l'adresse IP publique de l'hôte, la faute à Kubernetes et au pod.
Il faudra, par exemple, rajouter un reverse proxy sur l'hôte redirigeant vers nos conteneurs, et sans doute supprimer le conteneur nginx n'ayant plus de raison d'être.

On obtiendrait ainsi le fichier vaultwarden.yaml suivant :
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2025-02-18T10:10:21Z"
  labels:
    app: vaultwarden-pod
  name: vaultwarden-pod
spec:
  ports:
  - name: "80"
    nodePort: 31849
    port: 80
    targetPort: 80
  selector:
    app: vaultwarden-pod
  type: NodePort
---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2025-02-18T10:10:21Z"
  labels:
    app: vaultwarden-pod
  name: vaultwarden-pod
spec:
  automountServiceAccountToken: false
  containers:
  - env:
    - name: TZ
      value: Europe/Paris
    - name: DOMAIN
      value: https://toto.example.org/
    - name: INVITATIONS_ALLOWED
      value: "false"
    - name: SHOW_PASSWORD_HINT
      value: "false"
    - name: SIGNUPS_ALLOWED
      value: "false"
    image: docker.io/vaultwarden/server:alpine
    name: vaultwarden
    ports:
    - containerPort: 80
      hostIP: 127.0.0.1
      hostPort: 80
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /data
      name: home-vaultwarden-vaultwarden-host-2
    - mountPath: /etc/localtime
      name: etc-localtime-host-2
      readOnly: true
  enableServiceLinks: false
  volumes:
  - hostPath:
      path: /home/vaultwarden/vaultwarden
      type: Directory
    name: home-vaultwarden-vaultwarden-host-2
  - hostPath:
      path: /etc/localtime
      type: File
    name: etc-localtime-host-2

Les commentaires sont fermés.