Da ich zu Testzwecken einen Kubernetes-Cluster brauche, habe ich versucht den Cluster mit k3s auf Fedora CoreOS auf zu bauen. Das ganze läuft in VMs auf einem KVM-Server.

Disk-Images erstellen

Im ersten Schritt muss dafür das Fedora CoreOS Qcow2 Image herunter geladen werden. Aus diesem kann man dann mit qemu-img create die Disk-Images für die einzelnen VMs ableiten.

qemu-img create -f qcow2 \
  -b /srv/virt/images/qcow2/fedora-coreos-37.20221127.3.0-qemu.x86_64.qcow2 \
  /srv/virt/vms/k3splain/k3sfl-master01_disk0.qcow2 10G
qemu-img create -f qcow2 \
  -b /srv/virt/images/qcow2/fedora-coreos-37.20221127.3.0-qemu.x86_64.qcow2 \
  /srv/virt/vms/k3splain/k3sfl-master02_disk0.qcow2 10G
qemu-img create -f qcow2 \
  -b /srv/virt/images/qcow2/fedora-coreos-37.20221127.3.0-qemu.x86_64.qcow2 \
  /srv/virt/vms/k3splain/k3sfl-master03_disk0.qcow2 10G
qemu-img create -f qcow2 \
  -b /srv/virt/images/qcow2/fedora-coreos-37.20221127.3.0-qemu.x86_64.qcow2 \
  /srv/virt/vms/k3splain/k3sfl-worker01_disk0.qcow2 10G
qemu-img create -f qcow2 \
  -b /srv/virt/images/qcow2/fedora-coreos-37.20221127.3.0-qemu.x86_64.qcow2 \
  /srv/virt/vms/k3splain/k3sfl-worker02_disk0.qcow2 10G

Ignition-File erstellen

Zur initialen Konfiguration verwendet Fedora CoreOS sogenannte Ignition-Files. Mit dem nachfolgenden Beispiel habe ich den Hostname gesetzt, ein paar sysctl-Parameter gesetzt, ein Modul geladen, dem NetworkManager eine statische IPv4-Konfiguration verpasst und einen SSH-Key hinterlegt, mit dem man sich bei der fertigen VM per SSH und dem User core einloggen kann.

variant: fcos
version: 1.4.0
storage:
  files:
    # CRI-O DNF module
    - path: /etc/modules-load.d/br_netfilter.conf
      mode: 0644
      overwrite: true
      contents:
        inline: br_netfilter
    # setting kernel parameters required by kubelet
    - path: /etc/sysctl.d/kubernetes.conf
      mode: 0644
      overwrite: true
      contents:
        inline: |
          net.bridge.bridge-nf-call-iptables=1
          net.ipv4.ip_forward=1
          net.ipv6.conf.all.forwarding=1
    - path: /etc/hostname
      mode: 0644
      contents:
        inline: |
          k3sfl-master01
    - path: /etc/NetworkManager/system-connections/enp1s0.nmconnection
      mode: 0600
      contents:
        inline: |
          [connection]
          id=enp1s0
          type=ethernet
          interface-name=enp1s0
          [ipv4]
          address1=10.200.181.71/24,10.200.181.1
          dns=10.200.181.1;
          dns-search=
          may-fail=false
          method=manual
          [ipv6]
          method=auto
passwd: # setting login credentials
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa A...

Aus dieser Config kann mit

docker run --interactive --rm quay.io/coreos/butane:release --pretty --strict < k3sfl-master01.bu > k3sfl-master01.ign

das finale Ignition-File erzeugt werden.

Installation der VM

Wenn die Vorbereitungen abgeschlossen sind, kann per virt-install die VM installiert werden.

virt-install --virt-type kvm \
    --name k3sfl-master01 \
    --vcpus=2 \
    --ram 4096 \
    --disk /srv/virt/vms/k3splain/k3sfl-master01_disk0.qcow2,bus=scsi,discard='unmap',format=qcow2 \
    --controller type=scsi,model=virtio-scsi \
    --cpu host \
    --network bridge=vbr0 \
    --import \
    --graphics=none \
    --os-type=linux \
    --os-variant="fedora-coreos-stable" \
    --channel unix,target.type=virtio,target.name='org.qemu.guest_agent.0' \
    --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/srv/virt/images/k3sfl-master01.ign"

k3s Cluster

Wenn alle 5 VMs erstellt sind, kann man sich daran machen, den k3s Cluster zu erstellen. Dafür wird das Binary von der offiziellen Website geladen und ausgeführt. Der K3S_TOKEN für die drei Master-Server ist ein selbst generierter zufälliger String. Der K3S_TOKEN für die Worker, auf denen der K3s-Agent läuft, kann auf dem Master-Server unter /var/lib/rancher/k3s/server/node-token gefunden werden.

#master01
curl -sfL https://get.k3s.io | K3S_TOKEN=XXXXXXXXXXXXXXXXXXX sh -s - server \
  --cluster-init --cluster-cidr=10.42.0.0/16,fd42::/56 \
  --service-cidr=10.43.0.0/16,fd43::/112 \
  --node-ip=10.200.181.71,fd01:4f8:201:a6:2fff:c018:f6c2:ad21
#master02
curl -sfL https://get.k3s.io | K3S_TOKEN=XXXXXXXXXXXXXXXXXXX sh -s - server \
  --server https://10.222.181.71:6443 \
  --cluster-cidr=10.42.0.0/16,fd42::/56 \
  --service-cidr=10.43.0.0/16,fd43::/112 \
  --node-ip=10.200.181.72,fd01:4f8:201:a6:2fff:d2f7:76ad:f4ec
#master03
curl -sfL https://get.k3s.io | K3S_TOKEN=XXXXXXXXXXXXXXXXXXX sh -s - server \
  --server https://10.222.181.71:6443 \
  --cluster-cidr=10.42.0.0/16,fd42::/56 \
  --service-cidr=10.43.0.0/16,fd43::/112 \
  --node-ip=10.200.181.73,fd01:4f8:201:a6:2fff:9357:8546:d361
#worker01
curl -sfL https://get.k3s.io | K3S_URL=https://10.222.181.71:6443 K3S_TOKEN=XXXXX::server:XXXXXX sh -s - agent \
  --node-ip=10.200.181.81,fd01:4f8:201:a6:2fff:e82a:d0a1:b838
#worker02
curl -sfL https://get.k3s.io | K3S_URL=https://10.222.181.71:6443 K3S_TOKEN=XXXXX::server:XXXXXX sh -s - agent \
  --node-ip=10.200.181.82,fd01:4f8:201:a6:2fff:c475:3afb:9acf

Wenn man will, kann man zum Abschluss noch die Master Nodes mittels

kubectl taint nodes k3sfl-master01 node-role.kubernetes.io/control-plane:NoSchedule

tainten, sodass die Workloads nur auf den Worker Nodes ausgeführt werden.