🎯 Lesson Objective
Understand how to set up a production-grade Kubernetes cluster in 2026: High Availability control plane, containerd 2.0, cgroup v2, nftables, etcd backup strategy, and disaster recovery with Velero.
1. Checklist Production Cluster 2026
- Control plane HA: 3 or 5 control plane nodes (odd number for etcd quorum)
- Container runtime: containerd 2.0 + cgroup v2 (systemd driver)
- CNI: Cilium 1.17+ (eBPF, no kube-proxy mode)
- kube-proxy mode: nftables (IPVS deprecated 1.35, iptables legacy)
- etcd: external etcd cluster or stacked, with automated backup
- OS Node: Ubuntu 24.04 LTS or Flatcar Linux (immutable)
- TLS everywhere: automatic cert rotation with kubeadm
2. Prepare Node
# Ubuntu 24.04 — chạy trên tất cả nodes # Disable swap (bắt buộc với K8s) swapoff -a sed -i '/swap/d' /etc/fstabEnable required kernel modules
cat <<EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter
Sysctl settings
cat <<EOF | 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 fs.inotify.max_user_watches = 524288 fs.inotify.max_user_instances = 512 EOF sysctl --system
Verify cgroup v2
stat -fc %T /sys/fs/cgroup
output: cgroup2fs ← cgroup v2 OK
Nếu là tmpfs → cần enable cgroup v2 trong kernel boot params
3. Install containerd 2.0
# Cài containerd 2.0 (released 2025) apt-get install -y apt-transport-https ca-certificates curl gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list apt-get update && apt-get install -y containerd.ioConfig containerd với systemd cgroup driver
mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml
Enable systemd cgroup (BẮT BUỘC với cgroup v2)
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
Verify sandbox image mới nhất
grep sandbox_image /etc/containerd/config.toml
sandbox_image = "registry.k8s.io/pause:3.10"
systemctl restart containerd systemctl enable containerd
Verify containerd 2.0
containerd --version
containerd containerd.io 2.0.x
ctr version
4. Install kubeadm, kubelet, kubectl
# K8s 1.32+ APT repository curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' > /etc/apt/sources.list.d/kubernetes.listapt-get update apt-get install -y kubelet kubeadm kubectl apt-mark hold kubelet kubeadm kubectl
kubelet --version && kubeadm version && kubectl version --client
5. Init Control Plane with kubeadm
# kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: "1.32.0"
controlPlaneEndpoint: "k8s-api.example.com:6443" # Load Balancer endpoint
networking:
podSubnet: "10.0.0.0/16" # Cilium pod CIDR
serviceSubnet: "10.96.0.0/12"
etcd:
local:
dataDir: /var/lib/etcd
# extraArgs để tuning etcd
extraArgs:
auto-compaction-retention: "8"
quota-backend-bytes: "8589934592" # 8Gi
apiServer:
extraArgs:
audit-log-path: /var/log/kubernetes/audit.log
audit-log-maxage: "30"
audit-log-maxbackup: "10"
audit-log-maxsize: "100"
event-ttl: "8h"
controllerManager:
extraArgs:
node-cidr-mask-size: "24"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
kubeletExtraArgs:
cgroup-driver: systemd
---
# Kube-proxy nftables mode (K8s 1.32+)
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: nftables # mới nhất, thay IPVS/iptables
nftables:
masqueradeAll: false
masqueradeBit: 14
minSyncPeriod: 0s
syncPeriod: 30s
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
serverTLSBootstrap: true # tự động cấp cert cho kubelet
# Init cluster (chạy trên control plane đầu tiên) kubeadm init --config kubeadm-config.yaml --upload-certsOutput quan trọng:
kubeadm join k8s-api.example.com:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx \
--control-plane --certificate-key xxx ← join control plane
kubeadm join k8s-api.example.com:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx ← join worker
Setup kubectl
mkdir -p $HOME/.kube cp /etc/kubernetes/admin.conf $HOME/.kube/config
Cài Cilium CNI (thay vì flannel/calico)
helm repo add cilium https://helm.cilium.io/ helm install cilium cilium/cilium
--namespace kube-system
--set kubeProxyReplacement=true \ # Cilium thay kube-proxy hoàn toàn --set k8sServiceHost=k8s-api.example.com
--set k8sServicePort=6443kubectl get nodes
NAME STATUS ROLES AGE
control-plane-1 Ready control-plane 2m
6. Join Control Plane Nodes (HA)
# Chạy trên control-plane-2 và control-plane-3 kubeadm join k8s-api.example.com:6443 \ --token [TOKEN] \ --discovery-token-ca-cert-hash sha256:[HASH] \ --control-plane \ --certificate-key [CERT_KEY]Join worker nodes
kubeadm join k8s-api.example.com:6443
--token [TOKEN]
--discovery-token-ca-cert-hash sha256:[HASH]Verify cluster
kubectl get nodes -o wide kubectl get pods -n kube-system
7. etcd Automatic Backup
# Snapshot etcd thủ công ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d-%H%M%S).db \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.keyVerify snapshot
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-latest.db --write-out=table
CronJob backup hàng ngày (tạo pod trên control plane)
cat <<'EOF' > /etc/cron.daily/etcd-backup #!/bin/bash BACKUP_DIR=/backup/etcd mkdir -p $BACKUP_DIR ETCDCTL_API=3 etcdctl snapshot save $BACKUP_DIR/etcd-$(date +%Y%m%d-%H%M%S).db
--endpoints=https://127.0.0.1:2379
--cacert=/etc/kubernetes/pki/etcd/ca.crt
--cert=/etc/kubernetes/pki/etcd/server.crt
--key=/etc/kubernetes/pki/etcd/server.keyGiữ 7 ngày
find $BACKUP_DIR -name "*.db" -mtime +7 -delete
Upload lên S3
aws s3 cp $BACKUP_DIR/ s3://my-cluster-backup/etcd/ --recursive EOF chmod +x /etc/cron.daily/etcd-backup
8. Velero — Disaster Recovery
# Cài Velero CLI curl -L https://github.com/vmware-tanzu/velero/releases/latest/download/velero-linux-amd64.tar.gz | tar xz mv velero-*/velero /usr/local/bin/Cài Velero với AWS S3 backend
velero install
--provider aws
--plugins velero/velero-plugin-for-aws:latest
--bucket my-velero-backups
--secret-file ./credentials-velero
--backup-location-config region=ap-southeast-1
--snapshot-location-config region=ap-southeast-1
--use-node-agent # cho PV backup với restic/kopiaTạo scheduled backup hàng ngày
velero schedule create daily-backup
--schedule="0 2 * * *"
--ttl 168h # giữ 7 ngàyBackup thủ công
velero backup create cluster-backup-$(date +%Y%m%d)
--include-namespaces production,stagingRestore từ backup
velero restore create --from-backup cluster-backup-20260130
Xem backup status
velero backup describe cluster-backup-20260130 velero backup logs cluster-backup-20260130
9. Certificate Management
# Xem expiry của tất cả certs kubeadm certs check-expirationOutput:
CERTIFICATE EXPIRES RESIDUAL TIME
admin.conf Mar 30, 2027 09:00 UTC 364d
apiserver Mar 30, 2027 09:00 UTC 364d
etcd-healthcheck-client Mar 30, 2027 09:00 UTC 364d
Renew tất cả certs (cần làm trước khi expire)
kubeadm certs renew all
Restart control plane components sau khi renew
systemctl restart kubelet
Hoặc kill static pods
crictl pods | grep -E "(kube-apiserver|kube-controller|kube-scheduler|etcd)" | awk '{print $1}' | xargs crictl stopp
10. Node Pools and Taints
# Label nodes theo role kubectl label node worker-1 node-role.kubernetes.io/worker= kubectl label node gpu-1 accelerator=nvidia-a100 kubectl label node spot-1 node.kubernetes.io/instance-type=spotTaint dedicated nodes
kubectl taint nodes gpu-1 dedicated=gpu:NoSchedule kubectl taint nodes spot-1 cloud.google.com/gke-spot=true:NoSchedule
WorkloadSelectorPolicy (K8s 1.32+): nodes chỉ nhận workloads phù hợp
Deployments chọn nodes với tolerations + nodeSelector
Summary
- Control plane HA: 3+ nodes + external load balancer
- containerd 2.0 + cgroup v2 + systemd driver: production standard 2026
- kube-proxy nftables mode: replace IPVS/iptables
- Cilium CNI with kubeProxyReplacement: a complete networking stack
- etcd automatic backup + Velero: disaster recovery strategy__HTMLTAG_131___
- cert rotation: kubeadm certs renew all before expire