We now have a Kubernetes master node setup with proper network configuration.
This is part 1 of the 3 parts article, links to part 2 and 3 below:
- Part 1 - Basic OS setup and master node.
- Part 2 - Worker node and creating a new service.
- Part 3 - Make your service stateful via persistent volume.
However, you cannot run anything on it without a worker node. if you try to "deploy a pod" (i.e. running some programs) in the cluster, there is no place to run it.
You will need a worker node.
Setting up a worker node
You will need to setup your machine (in my case, a Raspberry Pi) according to the setup guide in part 1. Follow the instructions there and stop just before the session about setting up the master node.
Basically you will have OS configured, all needed softwares installed and updated.
Remember when you initiated the master node, some output were generated that provides the instruction on how to setup a worker node:
kubeadm join <some IP>:6443 --token <some token> \ --discovery-token-ca-cert-hash sha256:<some long sha256 hash>
Just run it as root and you're done.
You can check the nodes status by:
kubectl get nodes
Running simple softwares
In Kubernetes, software is run on the worker nodes by either defining a pod, or a deployment. A deployment is defined by a manifest like below, which illustrates how to run the popular BitTorrent software, transmission, in a Kubernetes cluster.
Since it is a BitTorrent software, it needs to store information somewhere. Hence, this example below also contains a Persistent Volume and Persistent Volume Claim that will allow the software to store information.
Otherwise the deployment, when deleted (stopped), will lost all information in it, and thus you wasted a couple of hours downloading something and you will not be able to find it anywhere.
# transmission.yaml apiVersion: apps/v1 kind: Deployment metadata: name: transmission spec: selector: matchLabels: app: jasworks department: transmission replicas: 1 template: metadata: labels: app: jasworks department: transmission spec: volumes: - name: pv-transmission-config persistentVolumeClaim: claimName: pvc-transmission-config - name: pv-transmission-downloads persistentVolumeClaim: claimName: pvc-transmission-downloads hostNetwork: true containers: - name: transmission image: ghcr.io/linuxserver/transmission imagePullPolicy: IfNotPresent ports: - containerPort: 9091 - containerPort: 51413 - containerPort: 51413 protocol: UDP env: - name: name value: "transmission" - name: PUID value: "10997" - name: PGID value: "10997" - name: TRANSMISSION_WEB_HOME value: "/combustion-release/" - name: WHITELIST value: "192.168.0.0/24" volumeMounts: - mountPath: "/config" name: pv-transmission-config - mountPath: "/downloads" name: pv-transmission-downloads
How do we find the software?
The section below (extracted from above), tells the Kubernetes controller, which in turn tells the Docker, to download the container image for transmission from ghcr.io/linuxserver/transmission.
containers: - name: transmission image: ghcr.io/linuxserver/transmission imagePullPolicy: IfNotPresent
How to store information?
The following sections defines 2 required paths for this container image to work. Normally in the docker repository (like the one above), they will provide documentation on how to configure the container image. In this case, they require at minimum, 2 storage folders (one for configuration, one for downloads) in order for the software to work.
This is the section that defines the volume.
volumes: - name: pv-transmission-config persistentVolumeClaim: claimName: pvc-transmission-config - name: pv-transmission-downloads persistentVolumeClaim: claimName: pvc-transmission-downloads
And this is how you tell the container to mount the folders according to the volumes definition.
volumeMounts: - mountPath: "/config" name: pv-transmission-config - mountPath: "/downloads" name: pv-transmission-downloads
The definitions of pv-transmission-config and pv-transmission-downloads are covered in additional manifest files, which will be explained in part 3. You can also refer to the Persistent Volumes documentation (from Kubernetes website) to create one.
And once you have created the necessary manifest files (in the above case, 3), use the following command to apply the manifest into your cluster.
kubectl apply -f <manifest file name> # There are 3 of them in this example.
You can check the running status by:
kubectl get deployments
Something like below will show up:
NAME READY UP-TO-DATE AVAILABLE AGE ghost 1/1 1 1 22h transmission 1/1 1 1 99s
In the above example, I have 2 applications running, one is ghost and the other one is transmission. You can get pods (pods are the places where the applications really run) by running:
kubectl get pods
Results will be similar to below:
NAME READY STATUS RESTARTS AGE ghost-548587c976-zlhmm 1/1 Running 0 3h47m transmission-67bcdb6f6c-tq94m 1/1 Running 0 3m43s
And you can review the logs for the transmission pod by:
kubectl logs transmission-67bcdb6f6c-tq94m
That concludes part 2. I'll explain more details of Persistent Volumes and Persistent Volume Claims in part 3.