Inhaltsverzeichnis

cloud-init

De-facto-standard für die Initialisierung cloud - alle wichtigen Linux Distributionen + FreeBSD.

Merkmale

Images

datasource

configdrive / nocloud data source

openstack/latest/
meta_data.json
network_data.json
user_data
vendor_data.json

Dual-Stack

Der YAML-parser wirft bei doppelter v4/v6 (inet/inet6)-Konfiguration den folgenden parsing-Fehler aus: cloudinit.net.ParserError interface can only be defined once

Der „Trick“ ist das gleiche Interface nochmal mit „:0“ anzugeben, das wird dann als verschiedenes interface interpretiert.

network-interfaces: |
  iface eth0 inet static
  address 1.2.3.4/24
  gateway 1.2.3.1
 
  iface eth0:0 inet6 static
  address 2a00:1:2:3::4/64
  gateway 2a00:1:2:3::1

Die Netzwerkkonfiguration landet dann in:

weitere Partitionen

Standardmäßig vergrößert cloud-init das root-Dateisystem auf die maximale Größe des virtuellen Datenträgers („ephemeral disk“).

Beispiel: zwei zusätzliche Partitionen mit 10G und 30G Größe:

#cloud-config
growpart:
  mode: off
runcmd:
# Parted asks whether to fix /dev/vda to use all available space, we reply "Fix" and continue
# Resize primary partition to 10GB
- "printf 'Fix\n1\nyes\n10GB\n' | parted ---pretend-input-tty /dev/vda resizepart"
# Prepare partitions
- "parted -s /dev/vda mkpart DATA ext4 10GB 20GB"
- "parted -s /dev/vda mkpart DATA ext4 20GB 50GB"
# Configure new partitions
- "echo $(parted /dev/vda -s print|grep DATA |awk '/^\ *[0-9]+/{print $1}') > /partition_nums.txt"
- "for i in $(cat /partition_nums.txt); do mkfs.ext4 /dev/vda${i}; done"
- "for i in $(cat /partition_nums.txt); do e2label /dev/vda${i} DATA${i}; done"
- "for i in $(cat /partition_nums.txt); do mkdir -p /mnt/disks/data${i}; done"
- "for i in $(cat /partition_nums.txt); do mount -t ext4 /dev/vda${i} /mnt/disks/data${i}; done"
- "for i in $(cat /partition_nums.txt); do echo LABEL=DATA${i} /mnt/disks/data${i} ext4 defaults 0 0 | sudo tee -a /etc/fstab; done"
# System is not aware of new space on main partition. Needs refresh.
- "resize2fs /dev/vda1"

https://docs.syseleven.de/syseleven-stack/de/howtos/repartition-vm-disk

Code

https://github.com/stefanux/cloud-init-example

Problembehandung

Passwort aus user-config setzen

Die Passwörter für root und den Standardbenutzer will man nicht als Klartext auf einem Server rumliegen haben. Daher RANDOM benutzen oder einen hash. Leider werden nicht alle hashes erkannt (z.B. der Standardmäßig bei Debian11 verwendet yescrypt mit $y nicht) weil die Unterscheidung zwischen Klartext und Hash mit einem regex vorgenommen wird (r'\$(1|2a|2y|5|6)(\$.+){2}').

Daher am besten ein bcrypt-hash für cloud-init hinterlegen und ggf. später mit ansible neu setzen.

Mögliche Konfiguration https://cloudinit.readthedocs.io/en/latest/topics/modules.html

chpasswd:
  list:
    - root:{{ baserole_root_password_hash }}

Kernel panic nach resize

Nach disk-resize kommt es zu einer kernel-panic. Grund ist ein fehlendes serielles Gerät wenn das Image Konsolenparameter (wie hier Debian11) von „console=tty0 console=ttyS0,115200“ hat.

Hier der Fix für libvirt: „The problem is „fixed“, if you remove '-serial none' from the kvm cmdline, and thus get the default serial device that kvm appends.

The original test.xml can be fixed in a similar manner by simply adding:

  <console type='pty'>
    <target type='serial' port='0'/>
  </console>

It can also be fixed by mounting the image and removing 'console=ttyS0' from the kernel command lines in /boot/grub/grub.cfg.

Its hard to see, because observing it makes it work. But, I suspect that the root of the problem is that cloud-initramfs-growpart is writing to stdout, which is redirected to /dev/console, and /dev/console writes are going to the non-existant device 'ttyS0' (as told to by the command line).“

Quelle

FQDN in /etc/hosts zeigt auf 127.0.1.1

Default is:

127.0.1.1 $FQDN $Hostname

Lösungsweg:

Debugging von cloud-init

auf dem host: /var/log/cloud-init-output.log

cloud-init aufräumen

cloud-init reset und logs entfernen:

cloud-init clean -l