Created: 2019-03-20 mer. 14:15
ifconfig/netstat/route/brctl
-> ip/ss/bridge
iptables
-> nftables
linux > 4.17systemd
=> maquettes à réaliser
demo up # work work work demo down
couches basses vers couches hautes:
Pour chaque: mes choix, et les alternatives survolées
bridge linux ~ switch
generate_mac(){ hexdump -vn3 -e '/3 "52:54:00"' -e '/1 ":%02x"' -e '"\n"'\ /dev/urandom } show_mac_address(){ ip -j link show $1 | jq '.[].address' } ip link add dummytest address `generate_mac` type dummy show_mac_address dummytest # "52:54:00:aa:68:d5" ip link add brtest type bridge show_mac_address brtest # "46:d9:2d:f0:68:9d" ip link set dev dummytest master brtest show_mac_address brtest # "52:54:00:aa:68:d5"
Problèmes spécifiques à iptables:
ACCEPT
ou REJECT
?ACCEPT
=> iptables-save/iptables-restore
LA partie à accuser quand rien ne marche …
--dhcp-hostfile
.Si un répertoire, prend en compte tous les fichiers.
kill -HUP
Format:
52:54:00:f8:2e:b3,192.168.100.200,test.dev #@MAC,@IP,dns
=> s'automatise très bien
Automatisation de tout ce qui précède:
Objectifs:
sudo DEBUG=true nvbr up debug: set vbr0 up, state in /var/run/nvbr/vbr0 debug: bridge=vbr0 debug: mac=52:54:00:f0:51:09 debug: dummyint=vbr0dummy debug: ipbr=192.168.100.1/24 debug: dnsdomain=.dev debug: generate dummy interface vbr0dummy debug: create bridge vbr0 debug: bridge up debug: activate routing debug: generate firewall rules debug: oldrules stored in /var/run/nvbr/vbr0/iptables_before_nvbr debug: new rules stored in /var/run/nvbr/vbr0/natrules debug: start dnsmasq # work work work
# work work work sudo DEBUG=1 nvbr down debug: stop dnsmasq debug: restore firewall state from /var/run/nvbr/vbr0/iptables_before_nvbr debug: put down bridge up vbr0 debug: bridge=vbr0 debug: dummyint=vbr0dummy debug: destroy /var/run/nvbr/vbr0
/var/run/nvbr/${bridge_name}
/var/run/nvbr/vbr0/ ├── dnsmasq.conf #configuration dnsmasq ├── dnsmasq_leases # baux dhcp ├── dnsmasq.pid ├── hosts.d # dhcp statique ├── iptables_before_nvbr # sauvegarde des règles └── natrules # règles appliquées
# nvbr addhost/delhost bridge_name machine_name @mac,@ip,dnsname sudo nvbr addhost vbr0 node1 52:54:00:f8:2e:b3,192.168.100.200,server.dev
crée dans hosts.d/node1
:
52:54:00:f8:2e:b3,192.168.100.200,server.dev
et fait prendre en compte par dnsmasq la nouvelle config.
netbase=192.168.123 sudo DEBUG=1 ipbr=${netbase}.1/24 \ dhcp_ipmin=${netbase}.2 dhcp_ipmax=${netbase}.100 / nvbr up
À creuser:
=> possibilités de passthrough (GPU, token usb …)
Partie réseau: une interface réseau d'une VM correspond à un périphérique tap ou macvtap
qemu-system-x86_64 # commande de base kvm # raccourci pour -enable-kvm -m 256 # fixe la mémoire de base disponible -smp 2 # 2 CPU disk.qcow2 # un fichier d'image disque
interface tap: permet à un programme de parler à un périphérique réseau géré par le noyau
# création de l'interface tap sudo ip tuntap add mod tap dev tap0 sudo ip link set dev tap0 up # ajout au bridge sudo ip link set dev tap0 master vbr0 # démarrer la VM kvm -netdev tap,br=vbr0,ifname=tap0,script=no,downscript=no,id=n1 \ -device virtio-net-pci,netdev=n1 disk.img # qemu 3.1+: nic fusionne netdev et device kvm -nic tap,br=vrb0,ifname=tap0,script=no,downscript=no disk.img
v1: script=/etc/qemu-ifup
downscript=/etc/qemu-ifdown
=> automatise l'ajout/la suppression de l'interface tap au bridge
# création de l'interface tap sudo ip tuntap add mod tap dev tap0 sudo ip link set dev tap0 up # ajout au bridge: fait par /etc/qemu-ifup # démarrer la VM kvm -nic tap,br=vrb0,ifname=tap0 disk.img
v2: automatisation de la création de l'interface tap
kvm -nic bridge,br=vbr0,model=virtio-net-pci disk_img.qcow2 # /usr/lib/qemu/qemu-bridge-helper crée une interface tap # et l'ajoute au bridge spécifié
Le bridge visé doit apparaître dans /etc/qemu/bridge.conf
:
allow vbr0
kvm
: groupe kvm
pour utiliser /dev/kvm
qemu-bridge-helper
: chmod +s
virt-manager
virsh
Pour facilement réutiliser le travail fait sur nvbr
, on utilise la session système.
qemu+ssh://root@localhost/system
Intérêt pour construire des maquettes:
GUI possible également.
export LIBVIRT_DEFAULT_URI=qemu+ssh://root@localhost/system cat > /tmp/vbr0.xml <<EOF <network> <name>nvbr_vbr0</name> <forward mode="bridge"/> <bridge name="vbr0"/> </network> EOF virsh net-define /tmp/vbr0.xml virsh net-list --all # Name State Autostart Persistent # nvbr_vbr0 inactive no yes virsh net-start nvbr_vbr0; virsh net-undefine nvbr_vbr0 virsh net-list --all # Name State Autostart Persistent # nvbr_vbr0 active no no
Création initiale à partir d'une image d'installation sur le réseau:
virt-install \ --name debian9 \ --ram 1024 \ --disk path=./debian9.qcow2,size=8 \ --vcpus 1 \ --os-type linux \ --os-variant debian9 \ --network network=nvbr_vbr0 \ --console pty,target_type=serial \ --location 'http://ftp.fr.debian.org/debian/dists/stretch/main/installer-amd64/' \
GUI
-> virsh dumpxml
-> virsh define maversion.xml
lvm
…qemu-img
qemu-img create -f qcow2 -b image_de_base.qcow2 overlay.qcow2
On démarre ensuite une VM avec overlay.qcow2
comme disque.
overlay.qcow2
overlay.qcow2
, puis sur image_de_base.qcow2
virsh snapshot-create domain snapshot.xml virsh snapsho-revert domain snapshot.xml
--live
: sauvegarde la mémoire égalementLes solutions bas-niveau m'imposent toujours d'installer une image de base.
libguestfs héberge des images disques minimales, correspondant à l'installation initiale.
virt-builder
permet de générer des images bootables à partir des images du
projet libguestfssudo apt install libguestfs-tools virt-builder debian-9 --format qcow2 --timezone "Europe/Paris" \ --ssh-inject root:file:$HOME/.ssh/id_ed25519.pub \ --install console-setup,keyboard-configuration,ifupdown,isc-dhcp-client,ssh \ --edit '/boot/grub/grub.cfg: s/\/dev\/vda1/\/dev\/sda1/g' \ --edit '/etc/network/interfaces: s/ens2/ens3/g' \ --hostname vmtest \ --root-password password:toto
=> bonne solution pour de l'intégration continu d'un produit à tester sur plusieurs distributions linux
solution intégrée:
gestion d'image
Vagrant.configure("2") do |config| config.vm.box = "debian/stretch64" config.vm.provider :libvirt do |libvirt| libvirt.default_prefix = "lab" libvirt.host = "localhost" libvirt.username = "root" libvirt.id_ssh_key_file = "id_ed25519" libvirt.connect_via_ssh = true end config.vm.hostname = "citron" config.vm.network "public_network", dev: "vbr0", type: "bridge", mode: "bridge" end
premier vagrant up -> download or update local box -> ask provider to run vm -> connect to running vm through management network -> run provisionner
La phase de provisionning n'est pas rejouée automatiquement ensuite.
vagrant up vagrant suspend vagrant resume # up can be used vagrant destroy
vagrant ssh # ssh with config given by vagrant ssh-config # Host default # HostName 192.168.121.13 # User vagrant # Port 22 # UserKnownHostsFile /dev/null # StrictHostKeyChecking no # PasswordAuthentication no # IdentityFile .../.vagrant/machines/default/libvirt/private_key # IdentitiesOnly yes # LogLevel FATAL # ProxyCommand ssh 'localhost' -l 'root' -i \ # '~/.ssh/id_ed25519' nc -q0 %h %p
config.vm.synced_folder ".", "/vagrant", type: "nfs", nfs_version: 4, nfs_udp: false config.vm.synced_folder ".", "/vagrant", type: "rsync", rsync_exclude: ".git/"
nodes = [ { name: "node1", mac: "52:54:00:f8:2e:b3", ip: "192.168.100.200", dnsname: "server.dev" }, { name: "node2", mac: "52:54:00:13:6d:6a", ip: "192.168.100.150", dnsname: "client.dev" } ]
nodes.each do |node| config.vm.define node[:name] do |n| n.vm.hostname = node[:dnsname] n.vm.network "public_network", dev: "vbr0", type: "bridge", mac: node[:mac], mode: "bridge" end end
config.vm.provision "install puppet agent", type: "shell", path: "script/install_puppet_6_agent.sh" config.vm.provision "test", type: "puppet", manifests_path: ["vm", "/vagrant"], manifest_file: "manifests/limesurvey.pp", options: "--modulepath=/vagrant/modules", environment_variables: { "LANG": "C" }
triggers: insérer des actions dans le cycle de vie.
# type: need last version of vagrant, #with VAGRANT_EXPERIMENTAL="typed_triggers" # run after all vms have been destroy config.trigger.after :destroy, type: :command do |t| t.info = "remove vagrant-libvirt network" t.run = {inline: "./script/del_vagrant-libvirt_net.sh"} end
config.trigger.before :up do |t| t.info = "adds dnsmasq static config" t.ruby do |env,machine| net = machine.config.vm.networks.select{|n| n[0]==:public_network and n[1][:mac] }[0][1] node = nodes.select{ |n| n[:mac] == net[:mac] }.first nvbr=`which nvbr`.chomp system "sudo #{nvbr} addhost '#{net[:dev]}' '#{node[:name]}' '#{node[:mac]},#{node[:ip]},#{node[:dnsname]}'" end end # run after each vm destruction config.trigger.before :destroy do |t| t.info = "deletes dnsmasq static config" t.ruby do |env,machine| net = machine.config.vm.networks.select{|n| n[0]==:public_network and n[1][:mac] }[0][1] node = nodes.select{ |n| n[:mac] == net[:mac] }.first nvbr=`which nvbr`.chomp system "sudo #{nvbr} delhost '#{net[:dev]}' '#{node[:name]}'" end end
plmlab/gamba/natbridge
: utilisable, manque doc et intégration libvirtplmlab/gamba/vagrantfiles
: partage de conf Vagrant basique: à faire !