Host einrichten

Mit OpenSuse Kubic lässt sich schnell ein Kubernetes Server einrichten. An dieser Stelle geht es nur um die Einrichtung des Betriebssystemes, so dass dort eine Kubernetes Control-Plane oder ein Worker eingerichtet werden kann. Zunächst wird Kubic mit dem Installer eingerichtet. Die Default Einstellungen sind hier duchaus sinnvoll, so dass man sich hier einfach durchklicken kann. Das Netzwerk sollte über DHCP konfiguriert werden, so dass die IP-Adressen leicht zentral gepflegt werden können.

Nach einem Reboot hat man nun auch grundsätzlich lauffähiges System. Bevor nun Kubernetes konfiguriert wird, sollten in Hinblick auf die Sicherheit noch weitere Schritte durchgeführt werden.

Hardware

Sowohl Control Planes, als auch Worker stellen an die Hardware keine all zu hohen Anforderungen. Bei den Workern sollte Wert auf eine solide Server-Hardware, CPU und (ECC)RAM gelegt werden. Ansonsten reicht eine 20GB SSD als lokaler Storage. So ist immer sichergestellt, dass möglichst viele Nodes starten können. Ein zentraler Storage für das System bildet immer einen Single-Point-Of-Failure. Es sollte weiterhin auf alles Nodes die gleiche CPU Architektur verwendet werden. Ein Mix von z.B. x86 und ARM ist nicht zu empfehlen. Bei den Workern gilt die Regel "mehr CPU Cores und mehr RAM" ohne Einschränkung. Bei den Control Planes sollten mindestens 4 CPU Cores und 16 GByte RAM vorhanden sein.

Raspberry: Man kann zu Demozwecken auch einen Raspberry PI 4 mit mind. 4 GByte oder besser 8 GByte RAM nutzen. Mit kleineren Raspis lohnt sich der Versuch nicht.

Netzwerk

Sowohl Worker, als auch Control Planes sollten jeweils redundant angebunden werden. Grundsätzlich sollten immer zwei Ethernet Ports mit 802.1ad verwendet werden. Weniger als 1GBit/s pro Port sollten es nicht sein, bei größeren Installationen können auch 100GBit/s pro Port sinnvoll sein.

Selinux

Mit Selinux werden auf dem Host Role Based Access Lists (RBAC) aktiviert, die den Zugriff auf Systemfunktionen durch Prozesse einschränken. Das geht mit transactional-update setup-selinux sehr einfach, danach ist ein Reboot fällig. Mit sestatus kann man das Ergebnis sehen:

SELinux status:                 enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Memory protection checking: requested (insecure)
Max kernel policy version: 33

Jetzt kann man noch im Notfall mit setenforce 0 in den permissive Mode wechseln, was aber auf einem produktiven System unterbunden werden sollte.

Härtung

Damit die Selinux Einstellung nicht während der Laufzeit auf permissive umgestellt werden kann, müssen noch Flags gesetzt werden. Die zuständigen Flags kann man sich mit

getsebool -a | grep secure
secure_mode --> off
secure_mode_insmod --> off
secure_mode_policyload --> off

ansehen. Mit transactional-update run setsebool -P secure_mode_policyload=1 kann man verhindern, dass vom Enforcing wieder auf den Permissive Mode umgeschaltet werden kann. Der Parameter -P macht die Änderung permanent. Das lässt sich ohne Reboot auch nicht mehr ändern. Bei Kubic kommen da ein paar Fehlermeldungen, aber es funktioniert trotzdem. Nach einem Reboot sollten die Flags wie folgt aussehen:

getsebool -a | grep secure
secure_mode --> off
secure_mode_insmod --> off
secure_mode_policyload --> on

Jetzt kann man den enforcing Mode von Selinux nicht mehr zur Laufzeit ändern.

Zurücksetzen

Falls man den Enforcing Mode nach der Härtung doch einmal abschalten muss, dann müssen folgende Schritte durchgeführt werden:

  • Reboot
  • Im Bootmenü den Kernelparameter enforcing=0 setzen
  • Boot fortsetzen

Nun kann man mit transactional-update run setsebool -P secure_mode_policyload=0 das Flag zurücksetzen. Nach einem Reboot ist das Flag wieder gelöscht.

iptables

Kubernetes kümmert sich sehr gut um das Firewalling seiner eigenen Prozesse. Die Network Policies gelten allerdings nur für die Kubernetes Infrastruktur und Pods. Services, die auf dem Host laufen, bleiben erreichbar, was unter Umständen einen Ausbruch auf den Host erlaubt. Bei einem Preset von iptables muss man sehr vorsichtig vorgehen, damit Kubernetes auch weiterhin funktioniert. Auf dem Host sollte neben Kubernetes maximal noch ein sshd laufen. Mit dem folgenden iptables Ruleset in /etc/sysconfig/iptables kann man den Zugriff von Pods auf sshd unterbinden:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i enp0s3 -s 192.168.56.0/24 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j REJECT

COMMIT

Damit das Ruleset beim Boot auch geladen wird, muss noch ein Systemd Service eingerichtet werden, dazu wird die Datei /etc/systemd/system/iptables.service erstellt:

[Unit]
Description=Restore iptables rules on boot
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/sbin/iptables-restore /etc/sysconfig/iptables

[Install]
WantedBy=multi-user.target

Mit systemctl daemon-reload && systemctl enable iptables wird das aktiviert. Nach einem Reboot wird das Ruleset aktiviert und Kubernetes kann ungestört seine eigenen Rulesets ergänzen.

Virtualisierung

Sollte man Kubernetes Nodes virtualisieren?

Bei dieser Frage gehen die Meiungen z.T. sehr auseinander - wie so oft ist die Antwort "Es kommt darauf an" zutreffend. Befürworter von Virtualisierung führen gerne die Snapshotmöglichkeit an, die meist dann hilfreich ist, wenn ein Update nicht geklappt hat. Bei Kubic zieht dieses Argument allerdings nicht mehr, weil Kubic selbst über Snaphotmöglichkeiten verfügt, die bei Updates angewendet werden. Gegen die Virtualisierung spricht die Tatsache, dass man noch mehr Abhängigkeiten und Sicherheitsrisiken durch die Virtualisierung hat.

Die Mischung macht es

Im Falle von Kubic hat sich in einer Beispielinstallation folgende Architektur als sinnvoll erwiesen:

  • 2 Control-Planes virtualisiert, z.B. libvirt/kvm
  • 3 Control Planes als Hardware
  • 4 Worker virtualisiert wegen Zugriff auf Storage der VM Lösung
  • 10 Worker als Hardware

Alle Komponenten werden mit mindestens 2 Ethernet Ports mit dem Netzwerk verbunden. An der Stelle soll noch der Hinweis erlaubt sein, dass Kubic auch Infiniband unterstützt.

Links

https://wiki.centos.org/HowTos/SELinux

https://en.opensuse.org/Portal:MicroOS/SELinux