Mises à jour OTA¶
Une mise à jour OTA (Over-The-Air) qui échoue à 3h du matin sur 200 gateways de terrain est le cauchemar de tout ingénieur IoT — les stratégies robustes éliminent ce scénario.
Pourquoi l'OTA est critique¶
Dans un parc de devices IoT, le firmware n'est jamais "terminé". Les patches de sécurité sont inévitables — les CVE touchant le kernel Linux, OpenSSL, ou BusyBox affectent toutes les gateways déployées. Les correctifs de bugs émergent après les premières semaines d'usage terrain. Les nouvelles fonctionnalités doivent être déployées sans intervention physique.
Sur un parc de 500 devices, une mise à jour manuelle nécessitant 15 minutes par device représente 125 heures de travail. Hors de question. L'OTA n'est pas un luxe — c'est une nécessité opérationnelle.
La contrainte absolue : un device qui ne démarre plus après une mise à jour ratée est un device perdu jusqu'à intervention physique. Sur un capteur installé à 6 mètres de hauteur dans une usine, cette intervention peut coûter des centaines d'euros. Sur une bouée offshore, elle peut être impossible pendant des semaines.
Stratégies de mise à jour¶
Mise à jour full image¶
La stratégie la plus simple : télécharger une image système complète et remplacer intégralement la partition système. Simple à implémenter, garantit un état connu après mise à jour.
Avantages : Pas de gestion de dépendances, état final prévisible. Inconvénients : Taille de téléchargement élevée (souvent 100 MB à 1 GB), temps de mise à jour long, usage de bande passante important.
Mise à jour delta (différentielle)¶
Plutôt que de transmettre l'image complète, on calcule et transmet uniquement le différentiel entre la version courante et la version cible. Sur un delta de 500 MB vers 510 MB, la mise à jour peut peser 5 à 20 MB.
Outils : bsdiff/bspatch, xdelta3, courgette (Chrome). Le serveur OTA précalcule les deltas pour toutes les paires de versions (N-1→N, N-2→N, N-3→N). Le device télécharge le delta depuis sa version courante.
Avantages : Réduction drastique de la bande passante (÷10 à ÷50 typiquement). Inconvénients : Complexité de génération et de gestion des deltas, impossible si la version source est inconnue ou corrompue.
Partitionnement A/B¶
La stratégie A/B est le standard de facto pour les systèmes Linux embarqués et Android. Le système maintient deux partitions racine identiques (slot A et slot B). Le système actif tourne sur le slot A. La mise à jour s'installe sur le slot B pendant que le système continue de fonctionner normalement. Au redémarrage, le bootloader bascule sur le slot B.
flowchart LR
subgraph BEFORE ["Avant mise à jour"]
A1[Slot A\nv2.3.0\n✓ ACTIF]
B1[Slot B\nv2.3.0\nvide / ancienne version]
BL1[Bootloader\n→ boot sur A]
end
subgraph UPDATE ["Pendant la mise à jour"]
A2[Slot A\nv2.3.0\n✓ ACTIF en cours d'exécution]
B2[Slot B\nv2.4.0\n⬇ Installation en arrière-plan]
BL2[Bootloader\n→ toujours A]
end
subgraph AFTER ["Après redémarrage"]
A3[Slot A\nv2.3.0\nen attente]
B3[Slot B\nv2.4.0\n✓ ACTIF nouveau]
BL3[Bootloader\n→ boot sur B\nsi B valide]
end
subgraph ROLLBACK ["Rollback si échec"]
A4[Slot A\nv2.3.0\n✓ ACTIF restauré]
B4[Slot B\nv2.4.0\n✗ MARQUÉ INVALIDE]
BL4[Bootloader\n→ retour sur A\naprès N échecs]
end
BEFORE --> UPDATE --> AFTER
AFTER -. échec de boot .-> ROLLBACK Avantages : Rollback instantané et fiable, mise à jour sans coupure de service. Inconvénients : Nécessite deux fois la taille de la partition système en stockage flash.
Rollback automatique¶
Le rollback automatique est la protection fondamentale contre les mises à jour défaillantes. Il s'appuie sur une coopération entre le bootloader et le système.
Mécanisme watchdog au boot¶
Au premier démarrage après une mise à jour A/B, le bootloader marque le slot nouvellement activé comme "en période d'essai" (tries_remaining = 3). À chaque tentative de boot échouée, le compteur décrémente. À zéro, le bootloader rebascule sur l'ancien slot.
# Exemple : gestion des slots avec u-boot + libubootenv
# Vérifier l'état des slots
fw_printenv upgrade_available
# → upgrade_available=1 (mise à jour en attente de validation)
fw_printenv bootcount
# → bootcount=1 (premier boot post-mise à jour)
# Valider la mise à jour depuis userspace (à appeler après checks applicatifs)
fw_setenv upgrade_available 0
fw_setenv bootcount 0
# Si non validée dans les 3 boots → retour automatique sur l'ancien slot
Validation applicative avant confirmation¶
La validation ne doit pas se contenter de vérifier que le système a booté. Elle doit tester les fonctions critiques de l'application :
import sys
import subprocess
import paho.mqtt.client as mqtt
import time
def validate_update() -> bool:
"""
Vérifie que tous les composants critiques fonctionnent
après une mise à jour. Retourne True si le système est sain.
"""
checks = []
# 1. Services système démarrés
for service in ["mosquitto", "zigbee2mqtt", "nodered"]:
result = subprocess.run(["systemctl", "is-active", service],
capture_output=True, text=True)
ok = result.stdout.strip() == "active"
checks.append(("service:" + service, ok))
# 2. Broker MQTT joignable
try:
client = mqtt.Client()
client.connect("127.0.0.1", 1883, keepalive=5)
client.disconnect()
checks.append(("mqtt:local", True))
except Exception:
checks.append(("mqtt:local", False))
# 3. Connectivité northbound
try:
result = subprocess.run(
["ping", "-c", "1", "-W", "3", "mqtt-prod.industrial.local"],
capture_output=True
)
checks.append(("network:northbound", result.returncode == 0))
except Exception:
checks.append(("network:northbound", False))
# Rapport
all_ok = all(ok for _, ok in checks)
for name, ok in checks:
status = "OK" if ok else "FAIL"
print(f" [{status}] {name}")
return all_ok
if validate_update():
# Confirmer la mise à jour — le bootloader ne rollback plus
subprocess.run(["fw_setenv", "upgrade_available", "0"])
print("Mise à jour validée.")
else:
print("Validation échouée — rollback au prochain redémarrage.")
sys.exit(1)
Déploiement canary¶
Le déploiement canary consiste à exposer la nouvelle version à un petit pourcentage de la flotte avant un rollout complet. Cela permet de détecter les régressions sur une base restreinte avant qu'elles ne touchent toute la flotte.
Progression typique¶
| Étape | Pourcentage | Durée d'observation | Critères de passage |
|---|---|---|---|
| Canary initial | 1 % | 24 h | Taux d'erreur < 0,1 %, pas de rollback automatique |
| Groupe pilote | 10 % | 48 h | Taux d'erreur < 0,5 %, métriques stables |
| Déploiement partiel | 30 % | 24 h | Pas de régression observée |
| Déploiement général | 100 % | — | — |
La sélection du groupe canary doit être représentative : mélanger différents sites, différentes révisions hardware, différentes conditions réseau. Un canary constitué uniquement des devices les plus récents de l'usine pilote ne représente pas la diversité réelle de la flotte.
Outils OTA¶
Mender¶
Mender est la solution open-source la plus utilisée pour les mises à jour OTA sur systèmes Linux embarqués. Il supporte les stratégies A/B (Mender block device update) et les mises à jour d'artefacts individuels (fichiers de configuration, conteneurs Docker).
# Génération d'un artefact Mender depuis une image Yocto/BuildRoot
mender-artifact write rootfs-image \
--artifact-name "gateway-firmware-2.4.0" \
--device-type "raspberry-pi-4" \
--file rootfs.ext4 \
--output gateway-firmware-2.4.0.mender
# Déploiement via CLI Mender Server
mender-cli artifacts upload gateway-firmware-2.4.0.mender
mender-cli deployments create \
--name "Deploy 2.4.0 — Canary Usine Nord" \
--artifact "gateway-firmware-2.4.0" \
--device-group "canary-usine-nord"
L'interface web Mender Server affiche en temps réel la progression du déploiement : nombre de devices downloading, installing, rebooting, success, failure.
RAUC (Robust Auto-Update Controller)¶
RAUC est une alternative à Mender, davantage orientée systèmes Yocto. Il s'intègre profondément avec u-boot et barebox pour la gestion des slots A/B, et supporte la signature cryptographique des bundles de mise à jour.
# /etc/rauc/system.conf — configuration RAUC sur la gateway
[system]
compatible=raspberry-pi-4-industrial
bootloader=uboot
bundle-formats=plain verity
[keyring]
path=/etc/rauc/keyring.pem
[slot.rootfs.0]
device=/dev/mmcblk0p2
type=ext4
bootname=A
[slot.rootfs.1]
device=/dev/mmcblk0p3
type=ext4
bootname=B
SWUpdate¶
SWUpdate cible davantage les systèmes embarqués "bare metal" ou RTOS légers. Il supporte Hawkbit comme serveur de management OTA, et peut mettre à jour des partitions flash, des fichiers de configuration, des noyaux et des device trees indépendamment.
Comparatif¶
| Outil | Cible principale | Stratégie A/B | Delta update | Interface web | Licence |
|---|---|---|---|---|---|
| Mender | Linux embarqué | Natif | Oui (v3+) | Oui | Apache 2 / Mender Enterprise |
| RAUC | Linux + Yocto | Natif | Via plugin | Non (tiers) | LGPL |
| SWUpdate | Linux + bare metal | Oui | Non natif | Non (Hawkbit) | GPL v2 |
| Balena | Conteneurs Linux | Via resin | Non | Oui | Propriétaire |
| Android OTA | Android / AOSP | Natif (A/B) | Oui | Via MDM | Apache 2 |
Flux OTA complet¶
sequenceDiagram
participant DEV as Device terrain
participant MGR as Fleet Manager
participant STORE as Artefact Store
participant OPS as Opérateur
OPS->>STORE: Upload firmware 2.4.0
OPS->>MGR: Créer déploiement — canary 1 %
MGR->>DEV: Notification OTA disponible (MQTT)
DEV->>MGR: Accusé de réception
DEV->>STORE: Téléchargement artefact (HTTPS + TLS)
STORE-->>DEV: Firmware chiffré + signé
DEV->>DEV: Vérification signature (Ed25519)
DEV->>DEV: Installation sur slot B
DEV->>MGR: Status: installed, rebooting
DEV->>DEV: Redémarrage sur slot B
DEV->>DEV: Tests de validation (30 s)
alt Validation OK
DEV->>DEV: fw_setenv upgrade_available 0
DEV->>MGR: Status: success, version 2.4.0
MGR->>OPS: Canary OK — rollout à 10 % ?
else Validation échouée
DEV->>DEV: Redémarrage sur slot A (rollback)
DEV->>MGR: Status: failure, rolled back to 2.3.0
MGR->>OPS: ALERTE — rollback détecté sur device xyz
end Ce qu'il faut retenir¶
- Le partitionnement A/B avec rollback automatique est le seul mécanisme qui garantit qu'une mise à jour ratée ne laisse pas un device inutilisable.
- La validation applicative (pas seulement le boot) doit être effectuée avant de confirmer la mise à jour au bootloader.
- Le déploiement canary (1 % → 10 % → 100 %) limite l'impact des régressions à une fraction de la flotte.
- Mender, RAUC et SWUpdate sont les trois outils open-source de référence selon le type de système cible.
Chapitre suivant : Monitoring de flotte — superviser la santé de centaines de devices depuis un dashboard centralisé.