ajoute le réseau pour OpenStack : dummy0, paire veth, NAT restreint au réseau externe

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-10-07 11:40:34 +02:00
parent e879a214a9
commit 87c8aac5f5
14 changed files with 247 additions and 0 deletions

View file

@ -0,0 +1,21 @@
---
# Étape 4 du déploiement Syllabus : réseau pour OpenStack (dummy0, paire veth,
# NAT). Touche le réseau et le pare-feu — à exécuter uniquement après accord
# explicite d'Adam (règle 3). Se termine par un redémarrage, lui aussi
# soumis à son accord explicite.
#
# `reseau-openstack` tourne avant `durcissement` : ce dernier re-rend le
# pare-feu (nftables.conf.j2) en tenant compte du nouveau sous-réseau externe
# OpenStack (variables ci-dessous), et son filet de sécurité anti-coupure
# protège donc aussi ce changement-ci.
- name: Réseau pour OpenStack
hosts: syllabus
become: true
gather_facts: true
vars:
reseau_veth_gw: veth-ext-gw
reseau_veth_gw_subnet: 172.24.4.0/24
reseau_interface_publique: eno1
roles:
- reseau-openstack
- durcissement

View file

@ -55,6 +55,14 @@
mode: "0644"
notify: redémarrer fail2ban
- name: créer le répertoire des règles nftables additionnelles
ansible.builtin.file:
path: /etc/nftables.d
state: directory
owner: root
group: root
mode: "0750"
- name: déployer le script de retour à l'état d'avant durcissement
ansible.builtin.template:
src: durcissement-rollback.sh.j2

View file

@ -21,9 +21,22 @@ table inet filter {
chain forward {
type filter hook forward priority 0; policy drop;
{% if reseau_veth_gw_subnet is defined %}
# Un seul sens autorisé : réseau externe OpenStack -> Internet (NAT),
# plus les réponses à ce trafic. Rien n'entre depuis Internet vers les
# réseaux internes ; tout le reste est refusé par la politique drop.
iifname "{{ reseau_veth_gw }}" oifname "{{ reseau_interface_publique }}" ip saddr {{ reseau_veth_gw_subnet }} accept
iifname "{{ reseau_interface_publique }}" oifname "{{ reseau_veth_gw }}" ct state established,related accept
{% endif %}
}
chain output {
type filter hook output priority 0; policy accept;
}
}
# Autres règles (NAT, etc.), déposées par d'autres rôles. Un glob sans fichier
# correspondant n'est pas une erreur pour nft : cette ligne ne casse rien tant
# que /etc/nftables.d/ est vide.
include "/etc/nftables.d/*.conf"

View file

@ -0,0 +1,16 @@
---
# Réseau privé pour Kolla (interface de management / VIP interne, pas de HAProxy).
reseau_dummy_nom: dummy0
reseau_dummy_ip: 10.10.0.1/24
# Paire veth : un bout ira à Neutron (neutron_external_interface, étape 5),
# l'autre reste dans le réseau racine et porte la passerelle du réseau
# "externe" OpenStack (celui des routeurs de VM, pas les VM elles-mêmes).
reseau_veth_ovs: veth-ext-ovs
reseau_veth_gw: veth-ext-gw
reseau_veth_gw_ip: 172.24.4.1/24
reseau_veth_gw_subnet: 172.24.4.0/24
reseau_interface_publique: eno1
durcissement_delai_filet_secondes: 300

View file

@ -0,0 +1,6 @@
---
- name: redémarrer systemd-networkd
ansible.builtin.systemd:
name: systemd-networkd
state: restarted
enabled: true

View file

@ -0,0 +1,88 @@
---
# Étape 4 : réseau pour OpenStack. N'est jamais exécuté seul : ce rôle tourne
# dans le même play que `durcissement` (voir ansible/reseau-openstack.yml),
# pour que le pare-feu soit re-rendu avec la règle qui autorise ce nouveau
# sous-réseau — et pour réutiliser son filet de sécurité anti-coupure.
- name: charger le module noyau dummy au démarrage
ansible.builtin.copy:
content: "dummy\n"
dest: /etc/modules-load.d/reseau-openstack.conf
mode: "0644"
- name: charger le module dummy maintenant (sans attendre le prochain redémarrage)
community.general.modprobe:
name: dummy
state: present
- name: déployer l'interface dummy0 (management interne Kolla)
ansible.builtin.template:
src: 10-dummy0.netdev.j2
dest: /etc/systemd/network/10-dummy0.netdev
mode: "0644"
notify: redémarrer systemd-networkd
- name: déployer le réseau de dummy0
ansible.builtin.template:
src: 10-dummy0.network.j2
dest: /etc/systemd/network/10-dummy0.network
mode: "0644"
notify: redémarrer systemd-networkd
- name: déployer la paire veth (externe OpenStack)
ansible.builtin.template:
src: 20-veth-ext.netdev.j2
dest: /etc/systemd/network/20-veth-ext.netdev
mode: "0644"
notify: redémarrer systemd-networkd
- name: déployer le réseau du bout OVS de la paire veth (pas d'IP, pour Neutron)
ansible.builtin.template:
src: 21-veth-ext-ovs.network.j2
dest: /etc/systemd/network/21-veth-ext-ovs.network
mode: "0644"
notify: redémarrer systemd-networkd
- name: déployer le réseau du bout passerelle de la paire veth
ansible.builtin.template:
src: 22-veth-ext-gw.network.j2
dest: /etc/systemd/network/22-veth-ext-gw.network
mode: "0644"
notify: redémarrer systemd-networkd
- name: "activer systemd-networkd (ne gère que les interfaces déclarées, eno1 reste sous ifupdown)"
ansible.builtin.systemd:
name: systemd-networkd
enabled: true
# Pas de state ici : le handler s'occupe du (re)démarrage une fois tous les
# fichiers en place, pour n'appliquer qu'une seule fois.
- name: appliquer les nouvelles interfaces réseau
ansible.builtin.meta: flush_handlers
- name: activer le routage IPv4 (nécessaire au NAT)
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: "1"
sysctl_file: /etc/sysctl.d/99-reseau-openstack.conf
state: present
reload: true
- name: créer le répertoire des règles nftables additionnelles
ansible.builtin.file:
path: /etc/nftables.d
state: directory
owner: root
group: root
mode: "0750"
- name: déployer le NAT masquerade pour le réseau externe OpenStack
ansible.builtin.template:
src: 10-nat-openstack.conf.j2
dest: /etc/nftables.d/10-nat-openstack.conf
mode: "0640"
owner: root
group: root
# Handler défini dans le rôle durcissement (même play) : nft relit le fichier
# principal ET ses inclusions en une seule recharge.
notify: recharger nftables

View file

@ -0,0 +1,3 @@
[NetDev]
Name={{ reseau_dummy_nom }}
Kind=dummy

View file

@ -0,0 +1,8 @@
[Match]
Name={{ reseau_dummy_nom }}
[Network]
Address={{ reseau_dummy_ip }}
# Pas de route par défaut ni de DNS ici : cette interface sert uniquement de
# point d'ancrage interne pour Kolla (network_interface, kolla_internal_vip_address).
DHCP=no

View file

@ -0,0 +1,11 @@
# Géré par Ansible (rôle reseau-openstack) — ne pas modifier à la main.
# NAT masquerade : seul le sous-réseau "externe" OpenStack ({{ reseau_veth_gw_subnet }},
# utilisé par les routeurs de VM qui en ont explicitement besoin, jamais les
# VM de lab elles-mêmes — voir étape 10 du prompt de déploiement) sort vers
# Internet via {{ reseau_interface_publique }}.
table ip nat {
chain postrouting {
type nat hook postrouting priority 100;
ip saddr {{ reseau_veth_gw_subnet }} oifname "{{ reseau_interface_publique }}" masquerade
}
}

View file

@ -0,0 +1,6 @@
[NetDev]
Name={{ reseau_veth_ovs }}
Kind=veth
[Peer]
Name={{ reseau_veth_gw }}

View file

@ -0,0 +1,10 @@
[Match]
Name={{ reseau_veth_ovs }}
[Network]
# Pas d'IP : ce bout sera donné à Neutron (neutron_external_interface) à
# l'étape 5, qui l'attachera lui-même à son bridge OVS/OVN. On se contente de
# le faire monter et de le laisser persister au redémarrage.
DHCP=no
LinkLocalAddressing=no
ConfigureWithoutCarrier=yes

View file

@ -0,0 +1,10 @@
[Match]
Name={{ reseau_veth_gw }}
[Network]
Address={{ reseau_veth_gw_ip }}
DHCP=no
# Passerelle du réseau "externe" OpenStack (celui des routeurs de VM). Pas de
# route par défaut ajoutée ici : c'est le NAT masquerade nftables qui fait
# sortir ce sous-réseau vers Internet via {{ reseau_interface_publique }},
# pas une route système.

View file

@ -0,0 +1,3 @@
# Géré par Ansible (rôle reseau-openstack) — ne pas modifier à la main.
# Nécessaire pour que le NAT masquerade du réseau externe OpenStack fonctionne.
net.ipv4.ip_forward = 1