Configure Kubernetes Worker Nodes
1. 🧭 Scope Legend
Use these scope markers throughout this page and the wider Kubernetes CI/CD documentation.
maxRunners for every organization against the total CPU, RAM, disk, and container capacity available in each environment pool.2. 🧾 Worker Node Inputs
PROD Workers
QA Workers
DEV Workers
tmpl-ac-cicd-env-wk-00ac-cicd-api.aspireclan.com:443https://pkgs.k8s.io/core:/stable:/v1.35/deb/3. 📦 VM Specs
CPU: 8 vCPU
RAM: 32 GB
Disk: 200 GB
Clone: tmpl-ub-24-min4. 🧱 Prepare the Base Worker Template VM
Login to the VM and complete the base OS preparation.
lsblksudo growpart /dev/sda 3
sudo pvresize /dev/sda3
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
df -hHDD resize reference: Resize Ubuntu VM HDD
swapon --showsudo modprobe overlay
sudo modprobe br_netfiltercat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOFcat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOFsudo sysctl --systemsudo apt install -y containerdsudo mkdir -p /etc/containerdcontainerd config default | sudo tee /etc/containerd/config.toml >/dev/nullsudo nano /etc/containerd/config.tomlSystemdCgroup = falseSystemdCgroup = truesandbox_image = "registry.k8s.io/pause:3.8"sandbox_image = "registry.k8s.io/pause:3.10.1"sudo systemctl daemon-reload
sudo systemctl enable containerd
sudo systemctl restart containerdsudo ufw disable
sudo systemctl disable ufwsudo mkdir -p /etc/apt/keyringscurl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpgecho "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.listsudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable kubeletsudo kubeadm config images pullsudo systemctl status containerd --no-pager -lsudo systemctl status kubelet --no-pager -lswapon --showcat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOFsudo crictl infosudo swapoff -a
sudo sed -i.bak '/ swap / s/^/#/' /etc/fstabswapon --showkubeadm versionkubectl version --clientsudo apt update && sudo apt upgrade -y5. 🧹 Clean the VM Before Templating
sudo apt autoremove -y
sudo apt clean
sudo journalctl --vacuum-time=3d
sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-idOptional cleanup:
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*Then shut it down:
sudo shutdown -h now6. 📀 Create Template
tmpl-ac-cicd-env-wk-00Create the template only after all base configuration and cleanup steps are complete.
7. 🧬 Clone Template for Worker VMs
Clone the above template and configure each worker VM.
PROD Worker Nodes
192.168.8.71 ac-cicd-prod-wk-01192.168.8.72 ac-cicd-prod-wk-02192.168.8.73 ac-cicd-prod-wk-03192.168.8.74 ac-cicd-prod-wk-04QA Worker Nodes
192.168.8.81 ac-cicd-qa-wk-01192.168.8.82 ac-cicd-qa-wk-02192.168.8.83 ac-cicd-qa-wk-03192.168.8.84 ac-cicd-qa-wk-04DEV Worker Nodes
192.168.8.91 ac-cicd-dev-wk-01192.168.8.92 ac-cicd-dev-wk-02192.168.8.93 ac-cicd-dev-wk-03192.168.8.94 ac-cicd-dev-wk-04Complete configuration of the VM using: Configure VMs
8. 🚀 Join Worker Nodes to the Cluster
Run the following on each worker after hostname and IP configuration is complete.
kubeadm versionkubectl version --clientSet the hostname of the target worker first.
sudo hostnamectl set-hostname <<TARGET_WORKER_HOSTNAME>>
hostnamectlAvailable worker hostnames:
ac-cicd-prod-wk-01
ac-cicd-prod-wk-02
ac-cicd-prod-wk-03
ac-cicd-prod-wk-04
ac-cicd-qa-wk-01
ac-cicd-qa-wk-02
ac-cicd-qa-wk-03
ac-cicd-qa-wk-04
ac-cicd-dev-wk-01
ac-cicd-dev-wk-02
ac-cicd-dev-wk-03
ac-cicd-dev-wk-04sudo rebootswapon --showIf swap still shows anything, run:
sudo swapoff -a
sudo sed -i.bak '/ swap / s/^/#/' /etc/fstabswapon --showGenerate the join command on ac-cicd-cp-01:
kubeadm token create --print-join-commandJoin the worker to the cluster using the exact one-line command.
sudo kubeadm join ac-cicd-api.aspireclan.com:443 --token xxxxxx.xxxxxxxxxxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9. 🔥 Enable Firewall (Post-Bootstrap)
# kubelet API
sudo ufw allow 10250/tcp
# NodePort services (optional, but keep if you use NodePort)
sudo ufw allow 30000:32767/tcp
sudo ufw allow from 192.168.8.0/22
# Enable firewall
sudo ufw enable
sudo ufw status10. ✅ Verify from Control Plane
Run these on ac-cicd-cp-01.
kubectl get nodes -o widekubectl get pods -n kube-system -o wide11. 🏷️ Apply Labels and Taints to Newly Added Workers
Run these on ac-cicd-cp-01 while building the full worker pool so all worker nodes match the same ARC runner targeting pattern.
kubectl label node ac-cicd-dev-wk-01 workload=arc-runner --overwrite
kubectl label node ac-cicd-qa-wk-01 workload=arc-runner --overwrite
kubectl label node ac-cicd-prod-wk-01 workload=arc-runner --overwrite
kubectl label node ac-cicd-prod-wk-02 workload=arc-runner --overwrite
kubectl label node ac-cicd-dev-wk-02 env=dev workload=arc-runner --overwrite
kubectl label node ac-cicd-dev-wk-03 env=dev workload=arc-runner --overwrite
kubectl label node ac-cicd-dev-wk-04 env=dev workload=arc-runner --overwrite
kubectl label node ac-cicd-qa-wk-02 env=qa workload=arc-runner --overwrite
kubectl label node ac-cicd-qa-wk-03 env=qa workload=arc-runner --overwrite
kubectl label node ac-cicd-qa-wk-04 env=qa workload=arc-runner --overwrite
kubectl label node ac-cicd-prod-wk-03 env=prod workload=arc-runner --overwrite
kubectl label node ac-cicd-prod-wk-04 env=prod workload=arc-runner --overwritekubectl taint node ac-cicd-dev-wk-02 env=dev:NoSchedule --overwrite
kubectl taint node ac-cicd-dev-wk-03 env=dev:NoSchedule --overwrite
kubectl taint node ac-cicd-dev-wk-04 env=dev:NoSchedule --overwrite
kubectl taint node ac-cicd-qa-wk-02 env=qa:NoSchedule --overwrite
kubectl taint node ac-cicd-qa-wk-03 env=qa:NoSchedule --overwrite
kubectl taint node ac-cicd-qa-wk-04 env=qa:NoSchedule --overwrite
kubectl taint node ac-cicd-prod-wk-03 env=prod:NoSchedule --overwrite
kubectl taint node ac-cicd-prod-wk-04 env=prod:NoSchedule --overwrite12. 🔎 Verify Labels and Taints
Run these on ac-cicd-cp-01.
kubectl get nodes --show-labelskubectl describe nodes | egrep "Name:|Roles:|Taints:|env=|workload="kubectl get nodes -L env,workload13. 🔁 After Server Restart (Worker)
Run these on a worker node after a server restart.
sudo systemctl status kubelet --no-pager -lsudo systemctl status containerd --no-pager -lswapon --showsudo swapoff -a
sudo sed -i.bak '/ swap / s/^/#/' /etc/fstabswapon --showsudo systemctl daemon-reload
sudo systemctl restart containerd
sudo systemctl restart kubeletsudo systemctl status containerd --no-pager -lsudo systemctl status kubelet --no-pager -lRun this on ac-cicd-cp-01 to confirm the node is back.
kubectl get nodes -o wide14. 📋 Worker Inventory
PROD Worker Nodes
192.168.8.71 ac-cicd-prod-wk-01192.168.8.72 ac-cicd-prod-wk-02192.168.8.73 ac-cicd-prod-wk-03192.168.8.74 ac-cicd-prod-wk-04QA Worker Nodes
192.168.8.81 ac-cicd-qa-wk-01192.168.8.82 ac-cicd-qa-wk-02192.168.8.83 ac-cicd-qa-wk-03192.168.8.84 ac-cicd-qa-wk-04DEV Worker Nodes
192.168.8.91 ac-cicd-dev-wk-01192.168.8.92 ac-cicd-dev-wk-02192.168.8.93 ac-cicd-dev-wk-03192.168.8.94 ac-cicd-dev-wk-0415. 🧾 Flat Worker Inventory
192.168.8.71 ac-cicd-prod-wk-01
192.168.8.72 ac-cicd-prod-wk-02
192.168.8.73 ac-cicd-prod-wk-03
192.168.8.74 ac-cicd-prod-wk-04
192.168.8.81 ac-cicd-qa-wk-01
192.168.8.82 ac-cicd-qa-wk-02
192.168.8.83 ac-cicd-qa-wk-03
192.168.8.84 ac-cicd-qa-wk-04
192.168.8.91 ac-cicd-dev-wk-01
192.168.8.92 ac-cicd-dev-wk-02
192.168.8.93 ac-cicd-dev-wk-03
192.168.8.94 ac-cicd-dev-wk-04