NTP¶
Rôle¶
Service de synchronisation horaire interne pour l'ensemble de l'infrastructure Indio, en remplacement des pools NTP publics pour toute la flotte. Le paquet indio-baseline-config (RPM déployé fleet-wide, voir Baseline config) configure chaque VM pour utiliser exclusivement ces 3 serveurs internes comme sources de temps.
Architecture¶
- 3 nœuds chrony indépendants, sans VIP ni réplication entre eux (contrairement à PostgreSQL) :
INDSERV005(10.100.2.134),INDSERV006(10.100.2.135),INDSERV007(10.100.2.136), segmentseg-service(10.100.2.128/26). - Chaque serveur se synchronise sur le pool public
{0,1,2}.rocky.pool.ntp.org(3 sources amont,iburst) et sert le temps aux réseaux internes10.100.0.0/16et10.15.0.0/16. local stratum 10configuré : chaque serveur continue à servir l'heure à ses clients même si les sources amont publiques deviennent injoignables.makestep 1.0 3(correction brutale de l'horloge autorisée sur les 3 premières mesures si l'écart dépasse 1s — utile juste après un boot) etrtcsync(synchronise l'horloge matérielle depuis le système, pas l'inverse).- Consommateurs : toute la flotte, via le drop-in
/etc/chrony.d/indio-ntp.conflivré par le RPMindio-baseline-config(3 directivesserver ... iburstcodées en dur sur les IP.134/.135/.136), qui vient s'ajouter à/remplacer la configuration chrony par défaut du template.
Structure du dépôt¶
| Fichier | Contenu |
|---|---|
main.tf |
3 VM (for_each), clone du template, IP via NetBox |
variables.tf |
vsphere_network = "seg-service", nodes = [INDSERV005, INDSERV006, INDSERV007], vm_cpu = 1, vm_ram = 1024 |
versions.tf |
Providers hashicorp/vsphere (>= 2.6.0), e-breuninger/netbox (>= 5.0.0, < 6.0.0) |
ansible/site.yml |
Play unique, rôle chrony_server, groupe ntp |
ansible/group_vars/ntp.yml |
ntp_upstreams (pool public), ntp_allow_networks (réseaux internes) — aucun secret |
ansible/roles/chrony_server/ |
Installation chrony, template chrony.conf, ouverture du service ntp (123/udp) dans firewalld |
flowchart LR
subgraph UPSTREAM["Pool public"]
U0["0.rocky.pool.ntp.org"]
U1["1.rocky.pool.ntp.org"]
U2["2.rocky.pool.ntp.org"]
end
subgraph SEGSERVICE["seg-service — 10.100.2.128/26"]
N1["INDSERV005<br/>10.100.2.134<br/>chronyd"]
N2["INDSERV006<br/>10.100.2.135<br/>chronyd"]
N3["INDSERV007<br/>10.100.2.136<br/>chronyd"]
end
U0 & U1 & U2 -. "3 sources amont, iburst" .-> N1
U0 & U1 & U2 -. "3 sources amont, iburst" .-> N2
U0 & U1 & U2 -. "3 sources amont, iburst" .-> N3
N1 & N2 & N3 --> FLEET["Toute la flotte<br/>indio-ntp.conf (RPM indio-baseline-config)<br/>3 IP en dur, pas de VIP/round-robin"]
Provisioning Terraform¶
/root/ntp/main.tfclone 3 VM (for_eachsurvar.nodes) depuistmpl-rocky96-hardened, IP assignées par NetBox (data.netbox_ip_addresses, filtredns_nameen minuscules).- Variables (
variables.tf) :vsphere_network = "seg-service",vm_gateway = "10.100.2.190",vm_netmask = 26,nodes = [INDSERV005, INDSERV006, INDSERV007],vm_cpu = 1,vm_ram = 1024— le plus petit gabarit de l'infra, cohérent avec un simple relais chrony. lifecycle.ignore_changessurannotation,clone[0].template_uuid,clone[0].customize,disk[0].io_share_count(pattern identique à tous les projets vSphere de l'infra).- Providers :
hashicorp/vsphere(>= 2.6.0),e-breuninger/netbox(>= 5.0.0, < 6.0.0). - Identifiants vCenter/NetBox via
terraform.tfvars(non versionné) ; modèle dansterraform.tfvars.example.
Configuration Ansible¶
Playbook /root/ntp/ansible/site.yml, rôle unique chrony_server appliqué au groupe ntp (les 3 nœuds) :
- Installe le paquet
chrony. - Déploie
/etc/chrony.confdepuischrony.conf.j2: bouclepool {{ u }} iburstsurntp_upstreams, boucleallow {{ n }}surntp_allow_networks,driftfile,makestep 1.0 3,rtcsync,local stratum 10,logdir /var/log/chrony. - Ouvre le service
ntp(123/udp) dans firewalld (zonedrop). - Active et démarre
chronyd.
Aucun secret dans ce dépôt : ni group_vars/ntp.yml (upstreams et réseaux autorisés uniquement, en clair) ni ansible.cfg ne référencent de vault.
Procédure de déploiement¶
terraform apply(dans/root/ntp) : clone les 3 VM et attribue leurs IP via NetBox.ansible-playbook site.yml(dans/root/ntp/ansible) : installe et configure chrony sur les 3 nœuds — rôle idempotent, pas d'ordre particulier entre les nœuds (contrairement à PostgreSQL, aucune dépendance primaire/standby ici).
Contrôle de santé / Vérification¶
chronyc trackingsur un nœud :Reference ID/Stratumdoivent refléter une synchronisation active sur le pool public (stratum bas, typiquement 2-3) plutôt que le stratum local de secours (10).chronyc sources -v: les 3 sourcespooldoivent apparaître avec un état^*/^+(synchronisée / candidate), pas?(injoignable).- Côté client fleet-wide :
chronyc sourcesdoit lister les 3 IP10.100.2.134/135/136(pas le pool public par défaut) — confirme queindio-ntp.confa bien pris effet. firewall-cmd --list-servicessur un des 3 nœuds doit inclurentp.
Points d'attention¶
- Pas de haute disponibilité au sens VIP/failover : les 3 serveurs sont indépendants ; c'est aux clients de configurer les 3 IP comme sources (ce que fait le RPM
indio-baseline-config), pas un mécanisme de bascule automatique côté serveur — à la différence de PostgreSQL (VIP keepalived) ou de Zabbix (HA natif). - Round-robin DNS envisagé : un enregistrement DNS
ntp.infra.indioen round-robin sur les 3 IP est prévu côté AD pour simplifier la configuration client, mais n'est pas encore en place à ce jour. - Dépendance de toute la flotte : une panne simultanée des 3 nœuds dégraderait la synchronisation horaire de l'ensemble de l'infrastructure (chaque hôte reste toutefois capable de tenir l'heure localement un moment via son horloge système,
rtcsyncgardant l'horloge matérielle à jour). - Couplage avec le socle : le remplacement du pool public par les 3 IP internes est réalisé par le RPM
indio-baseline-config(hors de ce dépôt), pas par ce rôle Ansible — un hôte qui n'aurait pas ce RPM (VM hors baseline) continuerait à interroger le pool public par défaut.