Neuigkeiten von trion.
Immer gut informiert.

CRI-O Kubernetes Worker Setup auf Arch Linux ARM

CRI-O

Nachdem im vorherigen Beitrag zu Kubernetes gezeigt wurde, wie mittels CRI-O ein Kubernetes Master Node eingerichtet wird, folgt nun eine Worker Node. Das besondere auch hier: Es wird Arch Linux auf ARM 64bit Architektur verwendet.

Für das Setup wird kubeadm verwendet, daher wird auch die Ausgabe von einem Kubernetes-Master Setup benötigt, da dort das erforderliche Token ausgeben wird.

Beispiel für kubeadm Setup Ausgabe auf Kubernetes Master Node
You can now join any number of machines by running the following on each node
as root:

  kubeadm join 10.23.15.110:6443 --token nnnxv2.2p7n2zwuddqedg25 --discovery-token-ca-cert-hash sha256:7563bc0dcf826a37e96f820725147a61d9970a094e1428832283f803aad91cd3

Auf den Worker Nodes werden jeweils die folgenden Pakete installiert:

  • runc

    • runc-1.0.0rc5-1-aarch64.pkg.tar.xz

  • CRI-O

    • crictl-bin-1.11.1-1-aarch64.pkg.tar.xz

    • cri-o-1.11-1-aarch64.pkg.tar.xz

  • CNI

    • cni-0.6.0-2-aarch64.pkg.tar.xz

    • cni-plugins-0.6.0-1-aarch64.pkg.tar.xz

  • Kubernetes

    • kubernetes-1.11.1-1-aarch64.pkg.tar.xz

  • socat, ethtool, ebtables

Installation der CRI-O und Kubernetes Pakete
$ sudo pacman -U *xz
loading packages...
resolving dependencies...
looking for conflicting packages...

Packages (6) cni-0.6.0-2  cni-plugins-0.6.0-1  cri-o-1.11-1  crictl-bin-1.11.1-1  kubernetes-1.11.1-1  runc-1.0.0rc5-1

Total Installed Size:  808.83 MiB
Net Upgrade Size:       83.65 MiB

:: Proceed with installation? [Y/n]
...
:: Running post-transaction hooks...
(1/3) Reloading system manager configuration...
(2/3) Creating temporary files...
(3/3) Arming ConditionNeedsUpdate...

Für Kubernetes werden noch weitere Pakete benötigt:

Installation von socat, ethtool und ebtables
$ sudo pacman -S socat ethtool ebtables
resolving dependencies...
looking for conflicting packages...

Packages (3) ebtables-2.0.10_4-6  ethtool-1:4.17-1  socat-1.7.3.2-2

Total Download Size:   0.30 MiB
Total Installed Size:  1.11 MiB

:: Proceed with installation? [Y/n]
...

Danach wird zunächst die CRI-O Konfiguration vorgenommen, anschließend kann dann kubelet eingerichtet werden.

Als nächstes wird danach kubelet konfiguriert und aktiviert.

CRI-O Konfiguration

Zuerst die CRI-O Konfiguration: CRI-O verhält sich in einigen Punkten anders, als Docker. So muss zwingend konfiguriert werden, von wo CRI-O nicht signierte Images beziehen darf. Um das Standardverhalten von Docker nachzubilden, kann die folgende Image-Policy verwendet werden.

Image Policy Konfiguration in /etc/containers/policy.json
$ mkdir /etc/containers
$ echo '
{
    "default": [{"type": "insecureAcceptAnything"}]
}' > /etc/containers/policy.json

Weitere Einstellungen werden in der /etc/crio/crio.conf vorgenommen:

  • CRI-O kann flexibel mit mehreren Registries konfiguriert werden, die verwendet werden, falls ein unqualifizierter Image-Nanme verwendet wird. Analog zum Verhalten von Docker soll docker.io verwendet werden.

  • Für die Netzwerkkonfiguration wird CNI verwendet, der richtige Pfad für die Binaries ist /opt/cni/bin.

  • Durch CRI-O sollen keine Mounts angelegt werden, dies wird fallweise durch kubelet später durchgeführt

Die CRI-O Settings sehen dann wie folgt aus:

Konfiguration in /etc/crio/crio.conf
registries = ['docker.io']
plugin_dir = "/opt/cni/bin"

#default_mounts = [
#       "/run/secrets",
#]

Nachdem die CRI-O Konfiguration vollständig ist, kann der CRI-O Dienst aktiviert und gestartet werden.

Aktivierung des CRI-O Dienstes
$ sudo systemctl enable crio
Created symlink /etc/systemd/system/multi-user.target.wants/crio.service -> /usr/lib/systemd/system/crio.service.
$ sudo systemctl start crio

kubelet Konfiguration

Die reguläre systemd-Unit für kubelet deklariert eine Abhängigkeit auf Docker. Diese wird entsprechend auf CRI-O geändert. Damit während der Bootstrap-Phase der kubelet Dienst nicht von systemd als fehlerhaft markiert wird, soll systemd lediglich im Abstand einer Minute einen Neustart versuchen. Nach einigen Versuchen wird kubeadm die erforderliche kubelet Konfiguration erzeugt haben, so dass ein Start gelingt. Mit systemctl edit --full kubelet kann die Konfiguration angepasst werden.

Anpassung kubelet systemd-Unit
[Unit]
After=crio.service
Requires=crio.service

[Service]
RestartSec=60

Für den kube-proxy werden privilegierte Container erzeugt. Damit kubelet mit --allow-privileged=true startet, muss dies in der /etc/kubernetes/config eingestellt werden. An dieser Stelle wird auf die Konfiguration der API-Server-URL verzichtet, dies wird kubeadm später in einer generierten Konfigurationsdatei mitteilen.

Konfiguration in /etc/kubernetes/config
KUBE_ALLOW_PRIV="--allow-privileged=true"
KUBE_MASTER=""

Weitere Einstellungen werden in der /etc/kubernetes/kubelet Konfigurationsdatei vorgenommen:

  • Der Hostname des Knotens soll automatisch bestimmt werden, darum wird der entsprechende Parameter leer gelassen

  • Als Konfiguration für kubelet wird die Datei /etc/kubernetes/kubelet.conf angegeben, außerdem wird der Pfad zur Bootstrap-Konfiguration gesetzt (kubeadm wird diese dann später erzeugen).

  • Damit CRI-O verwendet wird, muss noch die Container-Runtime auf remote und der entsprechende Socket-Pfad gesetzt werden

Konfiguration in /etc/kubernetes/kubelet
KUBELET_HOSTNAME=""
KUBELET_KUBECONFIG="--kubeconfig=/etc/kubernetes/kubelet.conf --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf"
KUBELET_ARGS="--cluster-domain=cluster.local --cluster-dns=10.96.0.10 --cgroup-driver=systemd --fail-swap-on=false --network-plugin=kubenet --container-runtime=remote --container-runtime-endpoint=unix:///var/run/crio/crio.sock"

Die kubelet Konfiguration ist abgeschlossen, sodass der Dienst aktiviert werden kann. Gestartet wird kubelet noch nicht, das übernimmt kubeadm später.

Aktivierung des Kubelet Dienstes
$ sudo systemctl enable kubelet.service
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service -> /usr/lib/systemd/system/kubelet.service.

Bevor es losgehen kann, wird im Kernel noch IP-Forwarding aktiviert. Das ist wichtig, damit die Netzwerkkommunikation der Pods später funktioniert.

Konfiguration von IP Forwarding in /etc/sysctl.d/30-ipforward.conf
$ echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/30-ipforward.conf

Nun muss der Rechner entweder neu gestartet werden, oder durch ein manuelles sudo sysctl net.ipv4.ip_forward=1 das IP-Forwarding aktiviert werden.

Kubernetes Cluster Beitritt

Auf den Cluster-Nodes ist Swapspeicher aktiviert, daher wird kubeadm angewiesen, diesen bei der Verifizierung der Umgebung zu akzeptieren. Damit statt Docker CRI-O als Container Engine verwendet wird, muss der Pfad zum CRI-Socket auch bei kubeadm spezifiziert werden.

Kubernetes Cluster Beitritt mit CRI-O
$ sudo kubeadm join 10.23.15.110:6443 --ignore-preflight-errors Swap --cri-socket=/var/run/crio/crio.sock --token nnnxv2.2p7n2zwuddqedg25 --discovery-token-ca-cert-hash sha256:7563bc0dcf826a37e96f820725147a61d9970a094e1428832283f803aad91cd3

	[WARNING Swap]: running with swap on is not supported. Please disable swap
I0729 18:37:32.057489     595 kernel_validator.go:81] Validating kernel version
I0729 18:37:32.057981     595 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.23.15.110:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.23.15.110:6443"
[discovery] Requesting info from "https://10.23.15.110:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.23.15.110:6443"
[discovery] Successfully established connection with API Server "10.23.15.110:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/crio/crio.sock" to the Node API object "c2-worker2" as an annotation

This node has joined the cluster:
* Certificate signing request was sent to master and a response
  was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.

Kubernetes Overlay Network

Damit ein virtuelles Netzwerk für die Pods zur Verfügung steht, fehlt lediglich noch ein entsprechendes Overlay-Network. Auf dem Master kann dazu folgendes Kommando ausgeführt werden, um Weave als Container-Netzwerk zu installieren:

$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.WEAVE_NO_FASTDP=1"
serviceaccount/weave-net configured
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.extensions/weave-net created

Hier wird der Fast-Data-Path bei Weave deaktiviert, da dies auf einigen ARM Maschinen zu einer Kernel-Panic führt. In neueren Linux-Kernelversionen soll der Fehler behoben werden, dann ist mit weniger CPU-Belastung eine höhere Geschwindigkeit mit Weave zu erzielen.




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Los geht's!

Bitte teilen Sie uns mit, wie wir Sie am besten erreichen können.