Zum Inhalt

Deployment von Knoten

Dieses How-to ist veraltet. Es wird bald aktualisiert.

Jeder Cluster erhält einen eigenen Deployment-Host. Dieser Host wird verwendet, um individuelle Images für jeden Knoten zu bauen. Gleichzeitig fungiert der Host als Ansible-Controller, der die Knotenkonfiguration mittels Ansible aktualisieren kann.

Es gibt nur eine zentrale Ansible-Konfiguration für jeden Host. Diese Konfiguration wird während des Build-Prozesses (OpenWrt Imagebuilder) verwendet, um die individuelle Host-Konfiguration in das Image zu integrieren. Sie wird auch verwendet, um aktualisierte Konfigurationen auf einen bereits deployten und laufenden Knoten auszuspielen.

Etwas konkreter: Die Ansible-Roles für OpenWrt können Konfigurationsdateien nicht nur direkt auf ein OpenWrt-System deployen, sondern auch in ein beliebiges Verzeichnis schreiben. Das ist besonders nützlich, wenn man mit dem Imagebuilder eigene Images bauen und die richtige Konfiguration für den jeweiligen Knoten direkt einbinden möchte.

Passen Sie die Release-Version nach Belieben an.

mkdir pplznetdraft
cd pplznetdraft
wget https://downloads.openwrt.org/releases/22.03.0-rc5/targets/x86/64/openwrt-imagebuilder-22.03.0-rc5-x86-64.Linux-x86_64.tar.xz
tar -xvf openwrt-imagebuilder-22.03.0-rc5-x86-64.Linux-x86_64.tar.xz
cd openwrt-imagebuilder-22.03.0-rc5-x86-64.Linux-x86_64
Speichern Sie dieses Script als build.sh. In diesem Beispiel erstelle ich 60 Images für n300–n359 mit OpenWrt 22.03 rc5.
#!/usr/bin/env bash
ansibledir="/pvedisk/ansible_pplznet"
workdir="/pvedisk/pplznetdraft"
imagebuilderdir="openwrt-imagebuilder-22.03.0-rc5-x86-64.Linux-x86_64"
imagepath="bin/targets/x86/64/openwrt-22.03.0-rc5-x86-64-generic-ext4-combined.img.gz"
PACKAGES="python3 bind-host luci-app-ddns ddns-scripts-services ddns-scripts-nsupdate ddns-scripts bind-client tcpdump babeld collectd collectd-mod-cpu collectd-mod-interface collectd-mod-iwinfo collectd-mod-load collectd-mod-memory collectd-mod-network collectd-mod-rrdtool e2fsprogs htop iftop luci luci-app-babeld luci-app-statistics luci-app-vnstat2 luci-app-wireguard mtr nmap-full prometheus-node-exporter-lua vim-fuller vnstat2 vnstati2 wg-installer-client wireguard-tools zlib"
FILES="files/"
oldindex=359
for index in {300..359}; do
        # delete old configs
        rm -rf ${workdir}/${imagebuilderdir}/files/*
        # run ansible to deploy host specific config
        cd ${ansibledir}
        ansible-playbook buildimage_n${index}.yml
        # build image
        cd ${workdir}/${imagebuilderdir}
        # if you want to build without packages:
        #make image FILES="${FILES}"
        make image PACKAGES="${PACKAGES}" FILES="${FILES}"
        # mv and extract
        cp ${imagepath} ../n${index}.img.gz
        gunzip -f ../n${index}.img.gz
        oldindex=${index}
done

Dieses Script führt Ansible aus, um die Konfigurationsdateien lokal zu deployen, damit sie in das jeweilige Image eingebaut werden.

Im Ansible-Pfad habe ich diese 60 Hosts konfiguriert. Für jeden Host gibt es ein Playbook, wie in diesem Beispiel für n300:

- hosts: n300.demo.junicast.de
  become: true
  gather_facts: false
  connection: local
  ignore_errors: yes
  vars:
    ansible_host: 127.0.0.1
    skip_handlers: true
    openwrt_deployroot: "/pvedisk/pplznetdraft/openwrt-imagebuilder-22.03.0-rc5-x86-64.Linux-x86_64/files/"
    openwrt_system_deployroot: "{{ openwrt_deployroot }}"
    openwrt_dropbear_deployroot: "{{ openwrt_deployroot }}"
    openwrt_network_deployroot: "{{ openwrt_deployroot }}"
    openwrt_firewall_deployroot: "{{ openwrt_deployroot }}"
    openwrt_babeld_deployroot: "{{ openwrt_deployroot }}"
    openwrt_dropbear_runimagebuilder: true
    openwrt_network_runimagebuilder: true
    openwrt_firewall_runimagebuilder: true
    openwrt_babeld_runimagebuilder: true
  roles:
    - imp1sh.ansible_pplznet.pplznet_node_deploy
    - imp1sh.ansible_openwrt.ansible_openwrtsystem
    - imp1sh.ansible_openwrt.ansible_openwrtdropbear
    - imp1sh.ansible_openwrt.ansible_openwrtnetwork
    - imp1sh.ansible_openwrt.ansible_openwrtfirewall
    - imp1sh.ansible_openwrt.ansible_openwrtbabeld

Am Ende entstehen einzelne img-Dateien, die ich mit folgendem Script in Proxmox importiere.

#!/usr/bin/python3
# difference to create_virtenv2 is that all interfaces on vmbbr1
import os
vlans = [
        {'guestid': 300,
        'vlanid': 1300,
        'nic': 'net0',
        'bridge': 'vmbr1'},
        {'guestid': 300,
        'vlanid': 71,
        'nic': 'net1',
        'bridge': 'vmbr1'},
        {'guestid': 300,
        'vlanid': 2300,
        'nic': 'net2',
        'bridge': 'vmbr1'
        {'guestid': 300,
        'vlanid': 3000,
        'nic': 'net3',
        'bridge': 'vmbr1'},
        {'guestid': 300,
        'vlanid': 2999,
        'nic': 'net4',
        'bridge': 'vmbr1'},
[...] define all your vlans
        ]

for index in range(300, 360):
#    print("qm create", index, "--agent 0 --autostart 0 --balloon 0 --cores 1 --cpu host --memory 128 --name node" + str(index))
    runcommandqm = "qm create " + str(index) + " --agent 0 --autostart 0 --balloon 0 --cores 1 --cpu host --memory 128 --name node" + str(index)
    print(runcommandqm)
    os.system(runcommandqm)
    runcommandimportdisk = "qm importdisk " + str(index) + " /pvedisk/pplznetdraft/n" + str(index) + ".img pvedisk"
    # this for zfs
    # runcommandactivatedisk = "qm set " + str(index) + " --scsihw virtio-scsi-pci --scsi0 pvedisk:vm-" + str(index) + "-disk-0"
    # this for raw eg btrfs
    runcommandactivatedisk = "qm set " + str(index) + " --scsihw virtio-scsi-pci --scsi0 pvedisk:" + str(index) + "/vm-" + str(index) + "-disk-0.raw"
    print(runcommandimportdisk)
    os.system(runcommandimportdisk)
    print(runcommandactivatedisk)
    os.system(runcommandactivatedisk)
#runcommandvlan = "qm set " + str(vlans[0]['guestid']) + " --" + str(vlans[0]['nic']) + " virtio,bridge=" + str(vlans[0]['bridge']) + ",tag=" + str(vlans[0]['vlanid'])
#print(runcommandvlan)
#os.system(runcommandvlan)
for vlan in vlans:
    runcommandvlan = "qm set " + str(vlan['guestid']) + " --" + str(vlan['nic']) + " virtio,bridge=" + str(vlan['bridge']) + ",tag=" + str(vlan['vlanid'])
    print(runcommandvlan)
    os.system(runcommandvlan)
for index in range(300, 360):
    runcommandstart ="qm start " + str(index)
    print(runcommandstart)
    os.system(runcommandstart)
Abhängig davon, wie Ihre Storage-Volumes heißen, könnten Anpassungen erforderlich sein. Auch die Bridge-Namen können abweichen und der Pfad, in dem die Disk liegt, kann anders sein. Es gibt ein Beispiel für ZFS und eines für Raw-Dateien.