Deploying a Local Kubernetes Cluster with Kubeadm on CentOS

Infrastructure Requirements

A stable three-node architecture is recommended: one control-plane host and two compute nodes. Each virtual machine must meet baseline specifications including minimum 2 GB RAM, dual-core processors, unique MAC addresses, and unrestricted internal networking. Swap partitions must be disabled prior to component deployment.

Node Synchronization & DNS Resolusion

Apply consistant hostnames across all instances and establish static IP mappings to prevent resolution delays during bootstrap.

# Execute on every node
sudo hostnamectl set-hostname $(echo $HOSTNAME | tr '[:upper:]' '[:lower:]')

# Update /etc/hosts on all machines
sudo tee -a /etc/hosts >< EOF
192.168.1.18 control-plane
192.168.1.17 worker-alpha
192.168.1.19 worker-beta
EOF

OS Hardening & Kernel Tuning

Disable packet filtering restrictions, enforce permissive security contexts, and configure bridge forwarding parameters to satisfy kubelet expectations.

#!/bin/bash
set -euo pipefail

# Disable firewall & SELinux
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# Disable swap & persist configuration
swapoff -a
sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab

# Flush NAT & routing tables
iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X && iptables -P FORWARD ACCEPT

# Apply network kernel parameters
cat >< EOF > /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
EOF

sysctl --system

Container Runtime & Cgroup Alignment

Install the cnotainer engine and align its execution driver with systemd to prevent orchestration conflicts.

sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >< EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": ["https://your-docker-mirror.endpoint"]
}
EOF

sudo yum install -y docker-ce-18.09.0 docker-ce-cli-18.09.0 containerd.io
sudo systemctl enable --now docker
sudo systemctl daemon-reload

Kubernetes Component Deployment

Register the package repository and install CLI tools along with the runtime service.

sudo tee /etc/yum.repos.d/kubernetes.repo >< EOF
[kubernetes]
name=Kubernetes Packages
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

sudo yum install -y kubeadm-1.14.0-0 kubelet-1.14.0-0 kubectl-1.14.0-0

# Align kubelet cgroup driver
sudo sed -i 's/cgroup-driver=systemd/cgroup-driver=cgroupfs/g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

sudo systemctl enable --now kubelet

Control Plane Image Mirroring

Since official registries may be inaccessible, pre-fetch required manifests, apply local aliases, and purge upstream duplicates.

#!/usr/bin/env bash
set -euo pipefail

declare -A COMPONENT_VERS=(
  ["kube-proxy"]="v1.14.0"
  ["kube-controller-manager"]="v1.14.0"
  ["kube-scheduler"]="v1.14.0"
  ["kube-apiserver"]="v1.14.0"
  ["pause"]="3.1"
  ["etcd"]="3.3.10"
  ["coredns"]="1.3.1"
)

ALTERNATE_REG="registry.cn-hangzhou.aliyuncs.com/snail-gao"
DEFAULT_REG="k8s.gcr.io"

alias_and_cache_images() {
  for comp in "${!COMPONENT_VERS[@]}"; do
    local ver="${COMPONENT_VERS[$comp]}"
    echo "Pulling & aliasing ${comp}:${ver}"
    docker pull "${ALTERNATE_REG}/${comp}:${ver}"
    docker tag "${ALTERNATE_REG}/${comp}:${ver}" "${DEFAULT_REG}/${comp}:${ver}"
    docker rmi "${ALTERNATE_REG}/${comp}:${ver}"
  done
}

alias_and_cache_images
docker images | grep -E '(k8s\.gcr\.io/pause|k8s\.gcr\.io/etcd|k8s\.gcr\.io/coredns)'

Master Node Bootstrap

Initialize the control plane by validating prerequisites, generating cryptographic artifacts, and spawning static pod manifests.

kubeadm init \
  --kubernetes-version=1.14.0 \
  --apiserver-advertise-address=192.168.1.18 \
  --pod-network-cidr=10.244.0.0/16

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

Pod Network Interface Initialization

Deploy a Container Network Interface plugin to enable cross-node communication before attaching workers.

kubectl apply -f https://docs.projectcalico.org/v3.9/manifests/calico.yaml
kubectl get pods -n kube-system -w

Compute Node Registration

Execute the join directive retrieved from the master bootstrap output on each worker instance.

sudo kubeadm join 192.168.1.18:6443 \
  --token <generated-token> \
  --discovery-token-ca-cert-hash sha256:<certificate-hash>

Verify topology convergence on the control plane:

NAME            STATUS   ROLES    AGE   VERSION
worker-alpha    NotReady   <none>   45s   v1.14.0
worker-beta     NotReady   <none>   40s   v1.14.0
control-plane   Ready      master   18m   v1.14.0

Workload Provisioning & Scaling Validation

Define a replication controller manifest to validate scheduling, networking, and horizontal expansion capabilities.

cat >< YAML_EOF > test-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: web-backend
  labels:
    app: nginx-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-service
  template:
    metadata:
      name: web-backend
      labels:
        app: nginx-service
    spec:
      containers:
      - name: nginx-container
        image: nginx:alpine
        ports:
        - containerPort: 80
YAML_EOF

kubectl apply -f test-rs.yaml
kubectl get pods -o wide
kubectl describe rs web-backend
kubectl scale rs web-backend --replicas=5
kubectl delete -f test-rs.yaml

Tags: kubernetes kubeadm Calico CNI containerd

Posted on Sat, 26 Sep 2026 16:48:52 +0000 by adamp1