CérénIT

Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)

Web, Ops, IoT et Time Series - Janvier 2024

reverse-proxy caddy traefik docker cron lora lorawan duckdb mysql postgres sqlite

Après presque 2 ans de silence et le remplacement de Hugo et Bootstrap par Zola et Tailwind/daisyUI l’été dernier pour générer le site, je vous souhaite une bonne année à tous et la résolution de publier plus régulièrement mes trouvailles…

Data

TL;DR: DuckDB can attach MySQL, Postgres, and SQLite databases in addition to databases stored in its own format. This allows data to be read into DuckDB and moved between these systems in a convenient manner.

IoT

Ops

  • DKron via Dkron pilote vos crontab : un gestionnaire de cron distribué, avec une jolie interface et uen API - que demander de plus ? Sur un modèle agent/serveur, le serveur dRkon distribue les tâches aux agents dKron concernés. les agents dKron étant déployés sur les serveurs sur lesquels les jobs doivent s’exécuter.

Reverse Proxy

  • Caddy : si vous avez besoin d’un reverse-proxy avec gestion automatique des certificats et redirection HTTP > HTTPS et plein d’autres choses encore mais sans nécessité d’intégration avec Docker comme Traefik, alors jetez un coup d’oeil à Caddy. Il permet également d’avoir un certificat sur localhost. Comme Traefik, il est écrit en Go.

J’avoue que la concision de Caddy vs Traefik et le provider file est bien appréciable:

# Caddyfile
xxx.cerenit.fr {
	reverse_proxy 127.0.0.1:3000
}
# Traefik
http:
  middlewares:
    redirectToHttps:
      redirectScheme:
        permanent: true
        scheme: https
  routers:
    grafana:
      entryPoints:
        - websecure
        - web
      middlewares:
        - redirectToHttps
      rule: Host(`xxx.cerenit.fr`)
      service: grafana@file
      tls:
        certResolver: le
  services:
    grafana:
      loadBalancer:
        servers:
        - url: http://127.0.0.1:3000/

Pour un serveur, la migration de Traefik vers Caddy fait passer le fichier de configuration de 172 lignes à 27 - soit presque 6 fois moins ! 😏

  • Caddy-Docker-Proxy via Caddy Docker Proxy, Like Traefik But Better? : si vous souhaitez aller plus loin dans l’intégration Caddy/Docker dans l’objectif de remplacer Traefik, cela semble être une bonne piste. C’est une version modifiée de Caddy pour s’interfacer avec Docker. L’intégration se fait notamment via les labels, comme pour Traefik. A voir si on peut déployer la version standalone en dehors d’un conteneur comme on peut le faire avec Traefik. Cela éviterit ainsi que chaque container à exposer via Caddy-Docker-Proxy rejoigne le réseau ad-hoc.

Exemple:

services:
  whoami:
    image: traefik/whoami
    networks:
      - caddy
    labels:
      caddy: whoami.example.com
      caddy.reverse_proxy: "{{upstreams 80}}"

networks:
  caddy:
    external: true

Systemd timer pour les Cro(o)ners

cron crontab systemd timer unit

Cron et Crontab sont dans un bateau…

Il fut un temps où pour programmer le lancement des actions, notre meilleur ami était “cron” et la “crontab”. Outre la syntaxe et l’organisation de la crontab peu mémorisable, les tâches cron restaient complexes à déployer et à monitorer dans leur exécution. Si le fait d’avoir des répertoires plus génériques comme /etc/cron.{d,hourly,daily,weekly,monthly} ont un peu amélioré la partie exploitabilité/déployabilité, ils offraient assez peu de souplesses pour une plannification fine des tâches. De nombreux serveurs ont donc eu un mix de crontab classique et de ce format pendant des années.

Debian 9.0 (mais d’autres aussi comme Archlinux par ex) a fait le choix dans le cadre de son adoption de systemd de ne plus proposer un logiciel de type cron mais de s’appuyer sur l’implémentation interne à systemd, à savoir les “timers”. C’est une unité (unit) spéciale de systemd qui est controllée et supervisée par systemd et qui s’exécute selon une configuration temporelle donnée.

Voyons comment passer de cette crontab :

0 4 * * * /path/to/scripts/backup.sh >> /var/log/backup.log 2>&1

… ou de /etc/cron.daily/mybackup.sh appelant le même script à son équivalent sous un timer systemd.

Implémentation d’un timer systemd.

Si vous gérez déjà vos services via systemd, vous avez déjà utilisé des “unit” systemd de type “service”. Ces “unit” permettent de définir un process et son mode d’éxécution.

Pour implémenter un “timer” sous systemd, il va nous falloir un fichier “service”.

Pour notre tâche à planifier, nous allons avoir au final 3 fichiers :

  • Le script à exécuter ; c’est votre script /path/to/scripts/backup.sh ; il est inchangé par rapport à précédemment.
  • Le fichier “service” qui va dire quel script exécuter
  • Le fichier “timer” qui va indiquer quand il doit être exécuté.

A noter que par convention, les fichiers service et timer doivent avoir le même nom (foo.service, foo.timer).

Pour le fichier service, une base simple est la suivante :

/etc/systemd/system/mybackup.service :

[Unit]
Description=My Daily Backup

[Service]
Type=simple
ExecStart=/path/to/scripts/backup.sh
StandardError=journal

Je fournis une description à mon service, indique que c’est un process de type simple, le chemin vers mon script et je rajoute que le flux d’erreur est envoyé dans le journal. Pour plus d’information, se reporter à la doc des services et des exécutions.

Attention néanmoins, il ne faut pas de section [Install] car le script va être piloté par le fichier timer.

Ensuite, il nous faut un fichier “timer” :

/etc/systemd/system/mybackup.timer :

[Unit]
Description=My Daily Backup

[Timer]
# Define a calendar event (see `man systemd.time`)
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Au-delà de la description, les lignes importantes sont la section [Timer] et [Install] :

  • OnCalendar permet d’indiquer l’occurrence et la fréquence d’exécution du script. Il y a les abréviations classiques (daily, weekly, etc) mais vous pouvez avoir des choses plus complexes comme "Mon,Tue *-*-01..04 12:00:00" - voir systemd.time
  • Persistent va forcer l’exécution du script si la dernière exécution a été manquée suite à un reboot de serveur ou autre événement.
  • Enfin, la section Install va créer la dépendance pour que votre “timer” soit bien exécuté et pris en compte par systemd.

Il ne reste plus qu’à activer le timer et le démarrer :

systemctl enable mybackup.timer
systemctl start mybackup.timer

Gestion et suivi d’un timer

Pour voir la liste des “timers” actifs sur votre serveur, la date de leur dernière et prochaine exécution :

systemctl list-timers
NEXT                         LEFT          LAST                         PASSED       UNIT                         ACTIVATES
Mon 2018-01-29 17:25:59 CET  2h 27min left Sun 2018-01-28 22:20:35 CET  16h ago      apt-daily.timer              apt-daily.service
Tue 2018-01-30 06:36:33 CET  15h left      Mon 2018-01-29 06:37:35 CET  8h ago       apt-daily-upgrade.timer      apt-daily-upgrade.service
Tue 2018-01-30 09:25:48 CET  18h left      Mon 2018-01-29 09:25:48 CET  5h 33min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service

et accéder aux logs de vos “timers” :

journalctl -f -u apt-daily
-- Logs begin at Tue 2018-01-23 13:50:12 CET. --
Jan 28 22:20:35 codb2d9 systemd[1]: Starting Daily apt download activities...
Jan 28 22:20:35 codb2d9 systemd[1]: Started Daily apt download activities.

En cas de modification du .timer ou du .service, ne pas oublier de faire un system daemon-reload pour que la version actualisée de vos fichiers soit prise en compte par systemd.

Passé la petite prise en main de ce nouveau cadre d’exécution, elle me semble plus simple et surtout plus facile à intégrer dans des chaines de déploiements pilotées par Ansible ou autre.