Labkey@JSI

Resources

Labkey at JSI

Asked Dejan Lesjak (F9) to create a VM running Debian 13.1.

Users

Tasks:

  • Installed sudo,
  • Created user studen as part of sudo group.
  • Created user labkey to manage resources (not sudo, but probably docker, see how it works out with Kubernetes)

Disks

Workspace

  • Assign space to labkey user:
    studen@labkey:~$ sudo mkdir /data0/labkey
    studen@labkey:~$ sudo mkdir /data1/labkey
    studen@labkey:~$ sudo chown labkey:labkey /data0/labkey
    studen@labkey:~$ sudo chown labkey:labkey /data1/labkey
    
    

Docker

Follow installation instructions. Specifically:

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done;
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable
sudo apt-get install ca-certificates curl
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo vi /etc/apt/sources.list.d/docker.list
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian trixie stable
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Add labkey to docker

sudo usermod -G docker labkey

Now labkey can start docker:

studen@labkey:~$ sudo su labkey
labkey@labkey:~$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Kubernetes

The idea is to run a single Node with three Pods - a disk server (/data1/labkey), database server (/data0/labkey) and a labkey service.

Start with installing kubeadm. Made sure we are running an LTS kernel:

studen@labkey:~$ uname -r 
6.12.48+deb13-amd64

Add repository:

studen@labkey:~$ sudo apt-get install -y apt-transport-https ca-certificates curl gpg
studen@labkey:~$ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
studen@labkey:~$ cat /etc/apt/sources.list.d/kubernets.list
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /

Install kubelet kubeadm kubectl:

studen@labkey:~$ sudo apt-get install -y kubelet kubeadm kubectl
studen@labkey:~$ sudo apt-mark hold kubelet kubeadm kubectl

From apt: hold is used to mark a package as held back, which will prevent the package from being automatically installed, upgraded or removed.

Kubernets abstracts docker service at the containerd level. The service containerd is part of the docker bundle, it gets managed by systemd,
so status of containerd is checked by:

studen@labkey:~$ systemctl status containerd

Docker actually ships containerd.io package which contains both containerd daemon as well as runc, an injector service to start a container.
The configuration file /etc/containerd/config.toml is docker centric. To fit better with the instructions on container runtime,
it is better to regenerate a default containerd configuration:

studen@labkey:~$ sudo /bin/bash -c 'containerd config default > /etc/containerd/config.toml'

Change configuration of containerd to use systemd driver, since Trixie is recent enough to use cgroup v2 API. Bellow we check for version of cgroup
and highlight SystemdCgroup setting to true, whereas it was set to false originally.

studen@labkey:~$ stat -fc %T /sys/fs/cgroup/
cgroup2fs
studen@labkey:~$ grep SystemdCgroup /etc/containerd/config.toml 
            SystemdCgroup = true

Restarting containerd service runs OK, just complains that there is no CNI at init, which apparently is OK since we didn't start a cluster yet:

studen@labkey:~$ sudo systemctl restart containerd
studen@labkey:~$ sudo systemctl status containerd
[...]
Sep 30 11:25:57 labkey containerd[12742]: time=[...] level=error msg="failed to load cni during init, please check CRI plugin status ..."

While selecting CNI seems to be a crucial point, it is done with kubectl which won't work until we have the control plane up and running.
To start, disable swap and start the control plane with default parameters.

studen@labkey:~$ sudo swapofff -a
#studen@labkey:~$ sudo kubeadm init
#option to specify IP of the pods
studen@labkey:~$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16

This sets swap off temporarily, at reboot, the same command should be run prior to starting kubeadm.

Now we can start managing the cluster with kubectl. Delegate manegement to a temporary user to prevent admin certificate corruption. First, assign cluster-admin rights to user studen (see how the second command uses admin.conf created by kubeadm). Then, create a kubeconfig for studen and move it to default directory for kubeconfig, ie. ~/.kube/config. A configuration file clusterConfig.xml contains basic data of the cluster, which can be extracted using kubectl and admin.conf

# this is only done once, even after cert in admin/studen.conf expires
studen@labkey:~$ sudo kubectl --kubeconfig /etc/kubernetes/admin.conf create clusterrolebinding studen --clusterrole=cluster-admin --user=studen
# check cluster configuration to generate clusterConfig.yaml
studen@labkey:~$ sudo kubectl --kubeconfig /etc/kubernetes/admin.conf get cm kubeadm-config -n kube-system -o=jsonpath="{.data.ClusterConfiguration}"
# create a temoporary certificate for studen
studen@labkey:~$ sudo kubeadm kubeconfig user --config admin/clusterConfig.yaml --client-name studen --validity-period 24h > admin/studen.conf
# make it the default config for kubectl
# from this point onwards we don't need root
studen@labkey:~$ cp admin/studen.conf .kube/config
#now studen can do administration
studen@labkey:~$ kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
labkey   NotReady    control-plane   13d   v1.34.1

So there is at least the control node that is available. It seems the configuration is not complete, but at least it is there.
We can also look at config:

studen@labkey:~$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://178.172.43.129:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: studen
  name: studen@kubernetes
current-context: studen@kubernetes
kind: Config
users:
- name: studen
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

We can add CNI, which toggles Status to Ready. Some advice on selection of CNI, Flannel seems like a good candidate.
The yml file used is the one copied from git

studen@labkey:~$ mkdir cni && cd cni
studen@labkey:~$ wget https://github.com/antrea-io/antrea/releases/download/v2.4.3/antrea.yml 
# Flannel failed
# studen@labkey:~$ curl https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
#studen@labkey:~$ kubectl apply -f cni/kube-flannel.yml 
studen@labkey:~$ cd
studen@labkey:~$ kubectl apply -f cni/antrea.yml
[..]
#Equivalent to docker ps -A
studen@labkey:~$ kubectl get pods -A
NAME     STATUS   ROLES           AGE   VERSION
labkey   Ready    control-plane   15m   v1.34.1

Once CNI is applied, all pods should go to Running stage.

Allow scheduling of pods on control-plane node (since it is a single PC setup):

studen@labkey:~$ kubectl taint nodes --all node-role.kubernetes.io/control-plane-
node/labkey untainted

Test using a sample image:

studen@labkey:~$ kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
deployment.apps/kubernetes-bootcamp created
studen@labkey:~$ kubectl get pods -A
[..]
#after a while
NAMESPACE     NAME                                   READY   STATUS    RESTARTS   AGE
default       kubernetes-bootcamp-658f6cbd58-sthch   1/1     Running   0          28s
kube-system   antrea-agent-b8nfb                     2/2     Running   0          4m48s
kube-system   antrea-controller-547dbb7586-r6gnv     1/1     Running   0          4m48s
kube-system   coredns-66bc5c9577-6r6sw               1/1     Running   0          7m9s
kube-system   coredns-66bc5c9577-rfltb               1/1     Running   0          7m9s
kube-system   etcd-labkey                            1/1     Running   4          7m14s
kube-system   kube-apiserver-labkey                  1/1     Running   4          7m14s
kube-system   kube-controller-manager-labkey         1/1     Running   0          7m15s
kube-system   kube-proxy-lqhw6                       1/1     Running   0          7m9s
kube-system   kube-scheduler-labkey                  1/1     Running   14         7m14s

Further details on pod (docker inspect, docker logs):

studen@labkey:~$ kubectl describe pod kubernetes-bootcamp-658f6cbd58-sthch
[..]
studen@labkey:~$ kubectl logs kubernetes-bootcamp-658f6cbd58-sthch
Kubernetes Bootcamp App Started At: 2025-10-15T14:18:10.545Z | Running On:  kubernetes-bootcamp-658f6cbd58-sthch 

Running On: kubernetes-bootcamp-658f6cbd58-sthch | Total Requests: 1 | App Uptime: 77.342 seconds | Log Time: 2025-10-15T14:19:27.887Z

Also, if running kubectl proxy in a separate shell, one can access ports of image directly:

studen@labkey:~$ curl http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-658f6cbd58-sthch:8080/proxy/

Delete sample deployment:

studen@labkey:~$ kubectl delete deployment kubernetes-bootcamp

Discussion