SEANK.H.LIAO

kubelet standalone mode with containerd

why use systemd when you can use kubelet?

kubelet standalone

kubelet is the agent that runs on every node in kubernetes. It also has a standalone mode where it just manages pods based on manifests on the filesystem.

There are not many guides out there, and most of them outdated with the deprecation of docker, like kelseyhightower/standalone-kubelet-tutorial, povilasv.me/raspberrypi-kubelet, with the closest being ops.tips but it doesn't actually list out all the configs.

Anyway, I want kubelet and I want containerd.

setup

I'm on Arch Linux, so getting sou is an easy:

1$ pacman -S containerd kubelet

There are some necessary settings:

 1$ cat << EOF > /etc/modules-load.d/br_netfilter.conf
 2br_netfilter
 3EOF
 4
 5cat << EOF > /etc/sysctl.d/30-ipforward.conf
 6net.ipv4.ip_forward=1
 7net.ipv4.conf.lxc*.rp_filter=0
 8net.ipv6.conf.default.forwarding=1
 9net.ipv6.conf.all.forwarding=1
10EOF

containerd

containerd is our container runtime of choice, and it needs some configuring:

 1$ cat << EOF > /etc/containerd/config.toml
 2
 3# importart or else it defaults to v1
 4version = 2
 5
 6[plugins."io.containerd.grpc.v1.cri".cni]
 7
 8    # archlinux default
 9    bin_dir = "/usr/lib/cni"
10
11    # how to configure pod networking
12    conf_template = "/etc/cni/cni.template"
13EOF

So cni config.. There's a spec which defines the config format. And there's the default plugins repo with the online docs.

You could drop the full config (with subnet already set) into the container cni conf_dir, or you could have kubelet trigger its generation via conf_template. Note, changing things won't force containerd to regenerate the config, delete it manually.

Basically, use ptp, add host-local as ipam and chain a portmap after. I couldn't get bridge to work.

note: kubernetes us currently on v0.4.0 of CNI spec, so some old style config (subnet) is needed

 1$ cat << EOF > /etc/cni/cni.template
 2{
 3  "name": "containerd",
 4  "cniVersion": "0.4.0",
 5  "plugins": [{
 6    "type": "ptp",
 7    "ipMasq": true,
 8    "ipam": {
 9      "type": "host-local",
10      "subnet": "{{.PodCIDR}}",
11      "routes": [
12        {"dst": "0.0.0.0/0"}
13      ]
14    }
15  },{
16    "type": "portmap",
17    "capabilities": {
18      "portMappings": true
19    }
20  }]
21}
22EOF

kubelet

Currently on kubelet v1.21.3

Arch provides a systemd unit file for kubelet where args are passed via env defined in:

1$ cat << EOF > /etc/kubernetes/kubelet.env
2KUBELET_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --config /etc/kubernetes/kubelet.yaml
3EOF

I'm going to not use deprecated flags and use a config file instead:

 1$ cat << EOF > /etc/kubernetes/kubelet.yaml
 2apiVersion: kubelet.config.k8s.io/v1beta1
 3kind: KubeletConfiguration
 4authentication:
 5  webhook:
 6    enabled: false
 7authorization:
 8  mode: AlwaysAllow
 9enableServer: false
10logging:
11  format: text
12  sanitization: false
13podCIDR: 10.241.1.0/24
14staticPodPath: /etc/kubernetes/manifests
15EOF

Now we can put a pod definition in /etc/kubernertes/manifests/foo.yaml and watch it run:

 1$ cat << EOF > /etc/kubernetes/manifests/httpbin.yaml
 2apiVersion: v1
 3kind: Pod
 4metadata:
 5  name: httpbin
 6spec:
 7  containers:
 8    - name: httpbin
 9      image: kennethreitz/httpbin
10      ports:
11        - name: http
12          containerPort: 80
13          hostPort: 45678
14EOF