Kubernetes on Linux: Step-by-Step Guide to Orchestrating Containers

Introduction

Kubernetes has become the de facto standard for container orchestration, and its integration with Linux provides a robust and scalable platform for modern workloads. In this article we will walk through step‑by‑step how to deploy a Kubernetes cluster on a Linux server, from system preparation to deploying your first application.

Prerequisites

Before you begin, you need a recent Linux distribution (Ubuntu 22.04 LTS, CentOS Stream 9, or Rocky Linux 9) with at least 2 GB of RAM and 2 CPUs per node. Additionally, you must have access to a sudo‑enabled user account and a stable internet connection to download the required packages.

Installing Kubernetes Tools

The core components are kubeadm, kubelet, and kubectl. On Debian/Ubuntu‑based distributions you can add them via the official Kubernetes repository:

  • Update the package index: sudo apt-get update
  • Install dependencies: sudo apt-get install -y apt-transport-https ca-certificates curl
  • Add the GPG key: sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
  • Add the repository: echo 'deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main' | sudo tee /etc/apt/sources.list.d/kubernetes.list
  • Install the binaries: sudo apt-get update followed by sudo apt-get install -y kubelet kubeadm kubectl
  • Mark them on hold to prevent automatic upgrades: sudo apt-mark hold kubelet kubeadm kubectl

Initializing the Master Node

With the tools installed, initialize the control plane using kubeadm. Choose a pod network CIDR (for example, 10.244.0.0/16) and run:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

After completion, copy the configuration for your user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Installing a Pod Network (CNI)

Kubernetes requires a network plugin for pod communication. A popular choice is Flannel:

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Verify that all nodes are ready with kubectl get nodes.

Joining Worker Nodes to the Cluster

On each worker machine, run the join command that kubeadm init displayed at the end, something like:

sudo kubeadm join :6443 --token --discovery-token-ca-cert-hash sha256:

After joining, verify from the master: kubectl get nodes should show all nodes in the Ready state.

Deploying a Sample Application

To validate the cluster, we’ll deploy a simple web server using NGINX:

  • Create a deployment: kubectl create deployment nginx --image=nginx
  • Expose the deployment as a service: kubectl expose deployment nginx --port=80 --type=NodePort
  • Get the assigned port: kubectl get svc nginx
  • Access via http://: in your browser.

Scaling and Updates

Kubernetes lets you scale applications with a single command:

kubectl scale deployment nginx --replicas=5

To update the image, for example to a specific NGINX version:

kubectl set image deployment/nginx nginx=nginx:1.25

The control plane will perform a rolling update, ensuring that replicas remain available.

Best Practices and Troubleshooting

  • Keep the operating system up to date and apply security patches regularly.
  • Use descriptive node names and labels to organize workloads.
  • Monitor resource usage with kubectl top nodes and kubectl top pods.
  • Check the logs of kubelet and containers with journalctl -u kubelet and kubectl logs.
  • If a node fails to join, verify connectivity to port 6443 and the validity of the token.

Persistent Storage with Volumes

For stateful applications, Kubernetes offers PersistentVolumes and PersistentVolumeClaims. In a local Linux environment you can use the hostPath driver for testing:

  • Create a PV: cat < pv-hostpath.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
    name: task-pv-volume
    spec:
    storageClassName: manual
    capacity:
    storage: 1Gi
    accessModes:
    - ReadWriteOnce
    hostPath:
    path: /mnt/data
    EOF
  • Apply it: kubectl apply -f pv-hostpath.yaml
  • Create a PVC that consumes it: cat < pvc-hostpath.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: task-pvc-claim
    spec:
    storageClassName: manual
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 500Mi
    EOF
  • Apply the PVC: kubectl apply -f pvc-hostpath.yaml

You can then mount the claim in a pod:

cat < pod-with-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: task-pod
spec:
volumes:
- name: task-storage
persistentVolumeClaim:
claimName: task-pvc-claim
containers:
- name: task-container
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: task-storage
EOF

kubectl apply -f pod-with-volume.yaml

Conclusion

Deploying Kubernetes on Linux is an accessible process that provides great flexibility for managing containers at scale. By following the steps outlined, you will have a functional cluster ready for development, testing, or production workloads. Continue exploring the Helm ecosystem, Operators, and service meshes to further enhance your infrastructure.