Arch Linux got kubernetes packaged into the [community] repository the past
week with the hard work of David Runge. I contribute to testing the packages so
I thought it would be interesting to write up quickly the testing that was done.
Originally I did the testing with docker but with the dockershim deprecation
I rewrote the blog to utilize containerd instead.
David has reworked the kubernetes archwiki article as well. It currently doesn’t
cover all use cases and contributions welcome. I will try cover the containerd
parts of this page to the wiki.
Our goal in this post is to simply setup a one node “cluster” and test some
basic functionality. kubeadm is going to be used for bootstrapping the cluster
as it is an easy way to get started.
For the testing portion of kubernetes I utilized lxd as it’s a neat interface for managing virtual machines. They also provide Arch Linux images which makes things fairly easy to setup.
# lxc launch images:archlinux/current arch-vm-kubernetes-test --vm
# lxc exec arch-vm-kubernetes-test bashThis sets up an Arch Linux virtual machine we will setup kubernetes with. Next up we need to install the packges we will be using to setup kubernetes.
# pacman -S kubernetes-control-plane
# pacman -S containerd kubeadm kubectlWe have split up the kubernetes package in different components and then
construced 3 package groups for users. kubernetes-control-plane for the
control planes/master nodes. kubernetes-node for worker nodes, and then
kubernetes-tools for the tools like kubectl. We are also fetching
containerd for the container runtime.
Setup of the different container runtimes is explained at the container runtimes webpage. However, there are a few distro specifics which could be nice to document on the archwiki. Next part of the setup is to ensure the modules and kernel parameters are correct.
# cat <<EOF | tee /etc/modules-load.d/containerd.conf
br_netfilter
EOF
# modprobe br_netfilter
# cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# sysctl --system
# systemctl start containerdI have no clue why they br_netfilter are needed, but I guess docker solves
this itself where as containerd does not. It should be noted we don’t setup
the overlay module as the containerd service inserts it on its own. Rest of it
is fairly straight forward and verbatim from the kubernetes documentation.
# kubeadm init --pod-network-cidr=192.168.0.0/16 \
--upload-certs --ignore-preflight-errors=NumCPU,Mem
[init] Using Kubernetes version: v1.19.4
[preflight] Running pre-flight checks
[[...SNIP...]]
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
[[...SNIP...]]kubeadm sets up the kubernetes cluster. The pod network CIRD defines the IP
range the pods (read containers) are going to be using inside the cluster.
Because we are using the default lxd containers we need to ignore a few limits
kubernetes imposes on us. It expects more then 1 CPU code, and more then 1GB
RAM. However this doesn’t matter for the fairly small workload we have for the
testing.
In a real cluster you would hopefully have larger nodes!
Once the cluster has initialized we can copy the admin.conf and query for the
cluster nodes.
# mkdir ~/.kube
# cp -i /etc/kubernetes/admin.conf ~/.kube/config
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
archlinux NotReady master 18m v1.20.0Currently it says NotReady which is because there is no network configured on
the cluster. We will untaint the master node, which allows us to deploy pods on
the master, and then setup some network.
# kubectl taint nodes --all node-role.kubernetes.io/master-
node/archlinux untaintedWe will be using kube-router for the networking portion as it is what I have
been using personally, and it has been fairly straight forward to setup.
It can be fetched from their github repository which has the RBAC support
kubeadm setup. We can just apply this deployment fairly easily.
https://raw.githubusercontent.com/cloudnativelabs/kube-router/v1.1.0/daemonset/kubeadm-kuberouter.yaml
# kubectl apply -f kubeadm-kuberouter.yaml
# kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS
kube-system coredns-f9fd979d6-2wp2x 1/1 Running 0
kube-system coredns-f9fd979d6-522nz 1/1 Running 0
kube-system etcd-archlinux 1/1 Running 0
kube-system kube-apiserver-archlinux 1/1 Running 0
kube-system kube-controller-manager-archlinux 1/1 Running 0
kube-system kube-proxy-sjxvw 1/1 Running 0
kube-system kube-router-8fq2m 1/1 Running 0
kube-system kube-scheduler-archlinux 1/1 Running 0
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
archlinux Ready master 20m v1.20.0Now our cluster is ready for a workload! Personally I have sometimes queried the
docker for the running containerd, but we are currently using containerd
which provides ctr for interacting with the containers. It organizes all pods
related to kubernetes inside a k8s.io namespace, where you can list the pods.
# ctr -n k8s.io c list
CONTAINER IMAGE RUNTIME
0cf8a9c17 docker.io/cloudnativelabs/kube-router:latest io.containerd.runc.v2
2bda5427a k8s.gcr.io/pause:3.2 io.containerd.runc.v2
4dbdaea0d k8s.gcr.io/pause:3.2 io.containerd.runc.v2
5430728fc k8s.gcr.io/pause:3.2 io.containerd.runc.v2
546633029 k8s.gcr.io/pause:3.2 io.containerd.runc.v2
5593c7f09 k8s.gcr.io/kube-proxy:v1.20.0 io.containerd.runc.v2
7f4dd2ff4 k8s.gcr.io/pause:3.2 io.containerd.runc.v2
96dd370ec k8s.gcr.io/pause:3.2 io.containerd.runc.v2
aab09f1e1 docker.io/cloudnativelabs/kube-router:latest io.containerd.runc.v2
aba203048 k8s.gcr.io/pause:3.2 io.containerd.runc.v2
b1bd5082a sha256:0369cf4303ffdb467dc219990960a9baa8... io.containerd.runc.v2
dc02359d9 k8s.gcr.io/coredns:1.7.0 io.containerd.runc.v2
e42de4f65 k8s.gcr.io/kube-controller-manager:v1.20.0 io.containerd.runc.v2
fc943a990 k8s.gcr.io/kube-apiserver:v1.20.0 io.containerd.runc.v2
fe49fbf3f k8s.gcr.io/kube-scheduler:v1.20.0 io.containerd.runc.v2Now we have the basics cluster working. We will add an deployment on this cluster and expose it through a load balancer. It’s
The steps are taken from the “create a deployment” page in the kubernetes documentation.
# kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.10
# kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed
# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.96.177.87 <pending> 8080:31569/TCP 5s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22m
# curl 10.96.177.87:8080
Hostname: hello-node-59bffcc9fd-hs7mk
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.3 - lua: 10008
Request Information:
client_address=192.168.0.1
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://10.96.177.87:8080/
Request Headers:
accept=*/*
host=10.96.177.87:8080
user-agent=curl/7.73.0
Request Body:
-no body in request-This shows an fairly simple setup with one kubernetes node running a service and a pod. It can be expanded upon, but for the sake of keeping this short this works as an introduction I reckon.
Hopefully this was as a simple introduction to kubernetes on Arch Linux!