Kubernetes auf Arch Linux ARM
Auch wenn Arch Linux meist topaktuelle Pakete hat, so ist dies bei Projekten wie Kubernetes auf der ARM Architektur nicht der Fall. Auch im AUR, also dem von der Community gepflegten Bereich, finden sich für ARM 64 bit keine Kubernetes Pakete. Es ist jedoch relativ einfach, sich auf Basis des Quellcodes von Kubernetes einen eigenen Build zu erzeugen. Damit sind sowohl für ARM 32bit als auch ARM 64bit eigene Arch Linux Kubernetes Pakete in überschaubarer Zeit und mit nur wenigen Handgriffen gebaut.
Wie das geht, wird im folgenden Beitrag erklärt.
Zunächst wird ein PKGBUILD benötigt.
Das ist die Beschreibung, mit der ein Arch Linux Paket gebaut wird.
Arch Linux bringt dafür ein eigenes Werkzeug mit, makepkg
.
Als Vorlage für das Kubernetes-PKGBUILD kann das PKGBUILD aus dem AUR Paket dienen.
Nachdem die fehlenden Plattformen ergänzt wurden, sieht ein Kubernetes Version 1.11 PKGBUILD wie folgt aus:
#Maintainer: Thomas Kruse <[email protected]>
#Contributor: Iwan Timmer <[email protected]>
pkgname=kubernetes
pkgver=1.11.1
_contribver=f4ce29dd35b68f538a5845d7e294bbf056d5d215
pkgrel=1
pkgdesc="Production-Grade Container Scheduling and Management"
depends=('glibc' 'bash')
makedepends=('go' 'rsync' 'go-bindata')
optdepends=('etcd: etcd cluster required to run Kubernetes')
arch=('x86_64' 'i686' 'armv7h' 'aarch64')
source=("$pkgname-$pkgver.tar.gz::https://dl.k8s.io/v$pkgver/kubernetes-src.tar.gz"
"https://github.com/kubernetes/contrib/archive/$_contribver.tar.gz"
"kubernetes.install")
noextract=("$pkgname-$pkgver.tar.gz")
url="http://kubernetes.io/"
license=("APACHE")
backup=('etc/kubernetes/apiserver'
'etc/kubernetes/config'
'etc/kubernetes/controller-manager'
'etc/kubernetes/kubelet'
'etc/kubernetes/proxy'
'etc/kubernetes/scheduler')
install=kubernetes.install
sha256sums=('e597a3a73f4c4933e9fb145d398adfc4e245e4465bbea50b0e55c78d2b0e70ef'
'4bd2a2f4fc2a17b78dd53a8f7312760b4028d600d14006a3cdf5768b28b44b27'
'fb6fce3ef4b793863286dafb5856ce28027427005d6c6fd44162844921ab714b')
prepare() {
mkdir -p $srcdir/$pkgname-$pkgver
tar -xf $srcdir/$pkgname-$pkgver.tar.gz -C $srcdir/$pkgname-$pkgver
}
build() {
cd $srcdir/$pkgname-$pkgver
make -j1
hack/generate-docs.sh
}
package() {
cd $srcdir/$pkgname-$pkgver
[ "$CARCH" = 'i686' ] && _kubearch=386
[ "$CARCH" = 'x86_64' ] && _kubearch=amd64
[ "$CARCH" = 'aarch64' ] && _kubearch=arm64
[ "$CARCH" = 'armv7h' ] && _kubearch=arm
binaries=(apiextensions-apiserver cloud-controller-manager kube-proxy kube-apiserver kube-controller-manager kubelet kubeadm kubemark hyperkube kube-aggregator kube-scheduler kubectl kubemark)
for bin in "${binaries[@]}"; do
install -Dm755 _output/local/bin/linux/$_kubearch/$bin $pkgdir/usr/bin/$bin
done
# install manpages
install -d $pkgdir/usr/share/man/man1/
install -pm 644 docs/man/man1/* $pkgdir/usr/share/man/man1
# install the place the kubelet defaults to put volumes
install -d $pkgdir/var/lib/kubelet
cd $srcdir/contrib-$_contribver
# install config files
install -dm 755 $pkgdir/etc/kubernetes/
install -m 644 -t $pkgdir/etc/kubernetes/ init/systemd/environ/*
# install service files
install -dm 755 $pkgdir/usr/lib/systemd/system
install -m 644 -t $pkgdir/usr/lib/systemd/system init/systemd/*.service
install -dm 755 $pkgdir/usr/lib/tmpfiles.d
install -m 644 -t $pkgdir/usr/lib/tmpfiles.d init/systemd/tmpfiles.d/*.conf
}
Bei der eigentlichen Installation wird noch ein Systemuser angelegt und ein Verzeichnis, in dem kubelet
seine Daten ablegen kann.
Dazu wird ein kubernetes.install
Script verwendet, das im folgenden zu sehen ist.
post_install() {
getent group kube >/dev/null || groupadd -r kube
getent passwd kube >/dev/null || useradd -r -g kube -d / -s /sbin/nologin -c "Kubernetes user" kube
chown -R kube:kube /var/lib/kubelet
}
post_upgrade() {
post_install
}
Nun kann der eigentliche Build des Kubernetes ARM Paketes erfolgen.
Dies geschieht mit makepkg -s
, allerdings gibt es noch eine Sache zu beachten:
Für den Build werden erhebliche Mengen Hauptspeicher benötigt, sodass eine Maschine mit 2 GB zu wenig ist. Abhilfe kann da zram schaffen. Mit zram kann im Hauptspeicher ein Swap-Bereich angelegt werden, dessen Inhalt komprimiert ist. Auf diese Weise kann der Hauptspeicher effizienter genutzt werden, die CPU wird jedoch stärker belastet. Bei 2GB echtem RAM und einem Kompressionsverhältnis von 1:2 bis 1:3 sollten entsprechend auch 2 GB zram Speicher nutzbar sein.
$ sudo modprobe zram
$ sudo swapoff -a
$ sudo zramctl --reset /dev/zram0
$ sudo zramctl --find --size 2000M
$ sudo mkswap /dev/zram0
$ sudo swapon /dev/zram0
$ free -m
total used free shared buff/cache available
Mem: 1974 324 848 0 800 1628
Swap: 2047 0 2047
Falls das noch nicht reicht, kann zusätzlich eine Auslagerungsdatei angelegt werden, um darüber weiteren Swap Speicher bereitzustellen. Das geht natürlich mit entsprechenden Geschwindigkeitseinbußen einher, da so ein Swap Speicher auf dem relativ langsamen eMMC, SD oder SSD Sekundärspeicher angesiedelt ist.
$ sudo fallocate -l 1000M /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
Wichtig zu wissen ist, dass der Build von Kubernetes standardmäßig parallel mit allen CPU-Kernen abläuft. Damit multipliziert sich auch der Hauptspeicherbedarf mit der Anzahl paralleler Buildprozesse. Gerade bei sowieso knappem Speicher lohnt es sich also, die Parallelität einzuschränken.
Kubernetes ist in der Sprache go (golang) entwickelt und entsprechend muss die go-Option gesetzt werden, nicht alle Prozessoren zur Parallelisierung des Builds einzusetzen.
Dies geschieht mit der Option "-p 1".
Der Kubernetes Buildprozess hat für solche Parameter die Umgebungsvariable GOFLAGS
definiert, darin kann dann -p 1
hinterlegt werden.
[tkruse@c2-master0 kubernetes]$ export GOFLAGS="-p 1"
[tkruse@c2-master0 kubernetes]$ makepkg -si
==> Making package: kubernetes 1.11.0-1 (Sun Jul 22 13:50:37 2018)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Installing missing dependencies...
resolving dependencies...
looking for conflicting packages...
Packages (2) go-bindata-3.4.0-1 rsync-3.1.3-1
Total Download Size: 0.80 MiB
Total Installed Size: 2.91 MiB
:: Proceed with installation? [Y/n]
:: Retrieving packages...
rsync-3.1.3-1-aarch64 276.4 KiB 4.50M/s 00:00 [##############################################] 100%
go-bindata-3.4.0-1-aarch64 541.7 KiB 5.29M/s 00:00 [##############################################] 100%
(2/2) checking keys in keyring [##############################################] 100%
(2/2) checking package integrity [##############################################] 100%
(2/2) loading package files [##############################################] 100%
(2/2) checking for file conflicts [##############################################] 100%
(2/2) checking available disk space [##############################################] 100%
:: Processing package changes...
(1/2) installing rsync [##############################################] 100%
(2/2) installing go-bindata [##############################################] 100%
:: Running post-transaction hooks...
(1/2) Reloading system manager configuration...
(2/2) Arming ConditionNeedsUpdate...
==> Retrieving sources...
-> Downloading kubernetes-1.11.0.tar.gz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 161 100 161 0 0 288 0 --:--:-- --:--:-- --:--:-- 288
100 23.2M 100 23.2M 0 0 6513k 0 0:00:03 0:00:03 --:--:-- 8400k
-> Downloading f4ce29dd35b68f538a5845d7e294bbf056d5d215.tar.gz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 160 0 160 0 0 305 0 --:--:-- --:--:-- --:--:-- 304
100 15.9M 0 15.9M 0 0 3095k 0 --:--:-- 0:00:05 --:--:-- 4278k
-> Found kubernetes.install
==> Validating source files with sha256sums...
kubernetes-1.11.0.tar.gz ... Passed
f4ce29dd35b68f538a5845d7e294bbf056d5d215.tar.gz ... Passed
kubernetes.install ... Passed
==> Extracting sources...
-> Extracting f4ce29dd35b68f538a5845d7e294bbf056d5d215.tar.gz with bsdtar
==> Starting prepare()...
==> Starting build()...
+++ [0722 13:51:46] Building go targets for linux/arm64:
./vendor/k8s.io/code-generator/cmd/deepcopy-gen
+++ [0722 13:52:17] Building go targets for linux/arm64:
./vendor/k8s.io/code-generator/cmd/defaulter-gen
+++ [0722 13:52:38] Building go targets for linux/arm64:
./vendor/k8s.io/code-generator/cmd/conversion-gen
+++ [0722 13:53:02] Building go targets for linux/arm64:
./vendor/k8s.io/code-generator/cmd/openapi-gen
+++ [0722 13:53:33] Building go targets for linux/arm64:
./vendor/github.com/jteeuwen/go-bindata/go-bindata
+++ [0722 13:53:38] Building go targets for linux/arm64:
cmd/kube-proxy
cmd/kube-apiserver
cmd/kube-controller-manager
cmd/cloud-controller-manager
cmd/kubelet
cmd/kubeadm
cmd/hyperkube
cmd/kube-scheduler
vendor/k8s.io/kube-aggregator
vendor/k8s.io/apiextensions-apiserver
cluster/gce/gci/mounter
cmd/kubectl
cmd/gendocs
cmd/genkubedocs
cmd/genman
cmd/genyaml
cmd/genswaggertypedocs
cmd/linkcheck
vendor/github.com/onsi/ginkgo/ginkgo
test/e2e/e2e.test
cmd/kubemark
vendor/github.com/onsi/ginkgo/ginkgo
test/e2e_node/e2e_node.test
make: Entering directory '/home/tkruse/kubernetes/src/kubernetes-1.11.0'
make[1]: Entering directory '/home/tkruse/kubernetes/src/kubernetes-1.11.0'
make[1]: Leaving directory '/home/tkruse/kubernetes/src/kubernetes-1.11.0'
+++ [0722 16:35:53] Building go targets for linux/arm64:
cmd/gendocs
cmd/genkubedocs
cmd/genman
cmd/genyaml
make: Leaving directory '/home/tkruse/kubernetes/src/kubernetes-1.11.0'
==> Entering fakeroot environment...
==> Starting package()...
==> Tidying install...
-> Removing libtool files...
-> Purging unwanted files...
-> Removing static library files...
-> Stripping unneeded symbols from binaries and libraries...
-> Compressing man and info pages...
==> Checking for packaging issues...
==> WARNING: Package contains reference to $srcdir
usr/bin/kubemark
usr/bin/kubectl
usr/bin/apiextensions-apiserver
usr/bin/kube-aggregator
usr/bin/cloud-controller-manager
usr/bin/kubeadm
usr/bin/kube-controller-manager
usr/bin/hyperkube
usr/bin/kubelet
usr/bin/kube-proxy
usr/bin/kube-scheduler
usr/bin/kube-apiserver
==> Creating package "kubernetes"...
-> Generating .PKGINFO file...
-> Generating .BUILDINFO file...
-> Adding install file...
-> Generating .MTREE file...
-> Compressing package...
=> Leaving fakeroot environment.
==> Finished making: kubernetes 1.11.0-1 (Sun Jul 22 17:03:01 2018)
==> Installing package kubernetes with pacman -U...
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) kubernetes-1.11.0-1
Total Installed Size: 725.18 MiB
:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring [################################################] 100%
(1/1) checking package integrity [################################################] 100%
(1/1) loading package files [################################################] 100%
(1/1) checking for file conflicts [################################################] 100%
(1/1) checking available disk space [################################################] 100%
:: Processing package changes...
(1/1) installing kubernetes [################################################] 100%
Optional dependencies for kubernetes
etcd: etcd cluster required to run Kubernetes
:: Running post-transaction hooks...
(1/3) Reloading system manager configuration...
(2/3) Creating temporary files...
(3/3) Arming ConditionNeedsUpdate...
Als Buildergebnis wird die Datei kubernetes-1.11.0-1-aarch64.pkg.tar.xz
erzeugt.
Diese kann nun lokal installiert werden, oder auf andere Knoten verteilt und dort installiert werden.
$ sudo pacman -U kubernetes-1.11.0-1-aarch64.pkg.tar.xz
$ sudo pacman -U socat ethtool ebtables
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.