1. Chuẩn bị môi trường và cài đặt Container Runtime (Containerd)
1.1. Vô hiệu hóa Swap trên tất cả các node
Kubernetes yêu cầu Swap phải bị tắt hoàn toàn để đảm bảo chính sách quản lý bộ nhớ (OOM killer) hoạt động đúng đắn. Nếu không, kubeadm sẽ báo lỗi và không cho khởi tạo cluster.
swapoff -a
Kết quả mong đợi: Không có đầu ra hoặc thông báo thành công. Kiểm tra lại bằng lệnh free -h thấy cột Swap bằng 0B.
Để đảm bảo Swap không tự bật lại sau khi restart, cần chỉnh sửa file /etc/fstab.
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
Kết quả mong đợi: Dòng chứa từ khóa "swap" trong file /etc/fstab đã bị comment (bắt đầu bằng dấu #).
1.2. Cài đặt Containerd và cấu hình
Docker Engine không còn được khuyến nghị cho Kubernetes mới (phiên bản 1.24+), chúng ta sẽ sử dụng containerd trực tiếp. Đây là runtime tiêu chuẩn cho K8s hiện đại.
apt-get update
apt-get install -y containerd.io
Kết quả mong đợi: Package containerd được cài đặt thành công.
Tạo file cấu hình mặc định cho containerd để K8s có thể tương thích.
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
Kết quả mong đợi: File cấu hình được tạo tại /etc/containerd/config.toml.
Chỉnh sửa file cấu hình để sử dụng Systemd Cgroup driver (bắt buộc cho K8s trên Linux mới) và bật Runc runtime.
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
Kết quả mong đợi: Dòng SystemdCgroup trong file cấu hình đã đổi thành true.
Khởi động lại dịch vụ containerd và đảm bảo nó tự động chạy khi boot.
systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd
Kết quả mong đợi: Dịch vụ containerd chạy ở trạng thái active (running).
2. Cài đặt Kubernetes components (Kubeadm, Kubelet, Kubectl)
2.1. Thêm repository Kubernetes chính thức
Package K8s trong kho mặc định của Debian/Ubuntu thường cũ. Cần thêm repo chính thức để lấy bản mới nhất (stable).
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat
Kết quả mong đợi: Repository Kubernetes được thêm vào hệ thống.
2.2. Cài đặt các package cần thiết
Cài đặt bộ công cụ quản lý K8s: kubeadm (khởi tạo cluster), kubelet (agent chạy trên node), và kubectl (CLI để điều khiển).
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
Kết quả mong đợi: Các package được cài đặt và khóa version (hold) để tránh bị tự động nâng cấp gây xung đột.
Chặn Kubernetes tự động nâng cấp bằng Systemd.
systemctl daemon-reload
Kết quả mong đợi: Systemd nhận diện các đơn vị dịch vụ mới.
3. Khởi tạo Control Plane (Master Node)
3.1. Xác định IP của Control Plane
Cần biết IP của node Master để các Worker Node kết nối vào. Thực hiện lệnh này trên node Master.
ip addr show | grep "inet " | grep -v "inet6" | head -n 1
Kết quả mong đợi: Hiển thị dòng IP của interface mạng chính (ví dụ: 192.168.1.10). Ghi nhớ IP này để thay thế vào bước tiếp theo.
3.2. Khởi tạo Cluster với CNI Calico
Thực hiện lệnh kubeadm init để tạo Control Plane. Chúng ta sẽ cấu hình Pod Network CIDR để tương thích với Calico CNI sau này.
Lưu ý: Thay thế 192.168.1.10 bằng IP thực tế của node Master của bạn.
kubeadm init \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=192.168.1.10 \
--node-name control-plane
Kết quả mong đợi:
1. Quá trình khởi tạo thành công.
2. Xuất hiện một đoạn mã lệnh bắt đầu bằng kubeadm join ... (đây là lệnh để Worker tham gia).
3. Xuất hiện thông báo về việc cấu hình kubeconfig.
3.3. Cấu hình Kubeconfig cho người dùng root
Để chạy lệnh kubectl ngay lập tức mà không cần copy file cấu hình, ta cần tạo thư mục và liên kết file.
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
Kết quả mong đợi: File config được tạo trong thư mục home của root.
4. Kết nối Worker Nodes vào Cluster
4.1. Chuẩn bị Worker Nodes
Trên các máy ảo Proxmox đóng vai trò là Worker, bạn cần thực hiện các bước 1 (tắt swap, cài containerd) giống hệt như Control Plane trước khi chạy lệnh join.
Đảm bảo các Worker Node đã cài đặt kubeadm, kubelet và containerd.
4.2. Tham gia vào Cluster
Sao chép lệnh kubeadm join ... được in ra ở bước 3.2 trên Control Plane và chạy trên từng Worker Node.
Lưu ý: Lệnh này có chứa Token và Hash cụ thể của cluster bạn vừa tạo. Không dùng lệnh mẫu.
kubeadm join 192.168.1.10:6443 --token \
--discovery-token-ca-cert-hash sha256:
Kết quả mong đợi: Thông báo This node control-plane has joined the cluster. hoặc This worker node has joined the cluster..
5. Cấu hình mạng Pod với Calico CNI
5.1. Cài đặt Calico
Kubernetes cần một mạng overlay để các Pod nói chuyện với nhau. Calico là lựa chọn phổ biến cho hạ tầng Proxmox vì hỗ trợ tốt BGP và IPIP.
Chạy lệnh này trên Control Plane Node.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
Kết quả mong đợi:
1. Xuất hiện dòng podsecuritypolicy created (hoặc tương tự).
2. Xuất hiện dòng daemonset.apps/calico-node created.
Đợi khoảng 1-2 phút để các Pod của Calico (calico-kube-controllers, calico-node) chuyển sang trạng thái Running.
kubectl get pods -n kube-system -o wide
Kết quả mong đợi:
1. Tất cả Pod trong namespace kube-system (bao gồm calico, coredns, etcd) có trạng thái Running.
2. Các Pod calico-node xuất hiện trên tất cả các Worker Node.
6. Kiểm tra và Verify kết quả
6.1. Kiểm tra trạng thái Node
Xác nhận tất cả các node đã tham gia và sẵn sàng (Ready).
kubectl get nodes
Kết quả mong đợi:
1. Hiển thị danh sách Control Plane và các Worker Nodes.
2. Trạng thái (STATUS) của tất cả node là Ready.
3. Không có node nào ở trạng thái NotReady.
6.2. Kiểm tra Pod Network
Triển khai một ứng dụng test nhỏ để đảm bảo mạng giữa các Pod hoạt động.
kubectl run test-pod --image=busybox --restart=Never --command -- sleep 3600
Kết quả mong đợi: Pod được tạo và chuyển sang trạng thái Running.
kubectl exec test-pod -- ping -c 3 8.8.8.8
Kết quả mong đợi: Ping thành công từ bên trong Pod ra internet (3 packets transmitted, 0 packet loss).
6.3. Kiểm tra kết nối nội bộ
Tạo 2 pod để test kết nối qua Service hoặc IP Pod.
kubectl run pod-a --image=busybox --restart=Never --command -- sleep 3600
kubectl run pod-b --image=busybox --restart=Never --command -- sleep 3600
Lấy IP của pod-b.
kubectl get pod pod-b -o jsonpath='{.status.podIP}'
Kết quả mong đợi: Trả về IP của pod-b (ví dụ: 192.168.x.x).
Ping từ pod-a sang pod-b bằng IP.
kubectl exec pod-a -- ping -c 3
Kết quả mong đợi: Ping thành công, chứng tỏ mạng Pod-to-Pod qua Calico đã hoạt động tốt.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng AI Training phân tán với DeepSpeed, Ray và Kubernetes trên hạ tầng Proxmox
« Phần 1: Chuẩn bị hạ tầng Proxmox và yêu cầu phần cứng
Phần 3: Cấu hình GPU passthrough và lập kế hoạch tài nguyên »