Skip to main content

10.1. Design and Install a Kubernetes Cluster - Architecture and Planning

Mục lục


1. Thiết kế Kubernetes cluster — những câu hỏi cần đặt ra trước

Giả sử được giao nhiệm vụ thiết kế Kubernetes cluster cho một dự án mới. Không phải bấm máy tính ngay — trước đó, cần trả lời một loạt câu hỏi nền tảng, vì mỗi câu trả lời sẽ định hình toàn bộ hướng đi. Đây không phải bài kiểm tra trí nhớ — đây là bài tập về tư duy hệ thống.

Câu hỏi cốt lõi: Cluster này phục vụ mục đích gì? Dùng cloud nào hoặc tự host? Chạy những workload nào? Traffic dự kiến ra sao?

1.1. Mục đích sử dụng cluster

Đây là câu hỏi quan trọng nhất, vì nó quyết định gần như mọi thứ còn lại.

  • Học tập: Chỉ cần single-node, nhẹ nhàng, dễ setup. Minikube là lựa chọn phổ biến.
  • Development/Testing: Cần multi-node để mô phỏng môi trường thật, nhưng không cần high availability.
  • Production: Đòi hỏi HA configuration, backup, monitoring, và rollback strategy. High availability (HA) nghĩa là nhân bản mọi thành phần quan trọng để không còn điểm chết đơn lẻ (single point of failure) — mất một node thì cluster vẫn vận hành bình thường; cách làm cụ thể sẽ được bàn ở Part 10.2.

💡 Hình dung: Chọn mục đích giống chọn loại nhà — nhà nghỉ 1 tầng cho chuyến đi chơi, penthouse cho gia đình ổn định. Cluster cũng vậy: dùng sai quy mô thì lãng phí tiền hoặc thiếu tài nguyên khi cần.

1.2. Cloud adoption — dùng cloud hay tự host?

Tổ chức đã có cloud provider chưa? Nếu có, tại sao phải tự quản lý hạ tầng khi đã có managed service?

  • Dùng cloud provider (GCP, AWS, Azure): Managed Kubernetes (GKE, EKS, AKS) giúp giảm operational overhead. Cluster được setup, upgrade, và scale tự động.
  • Tự host (on-premises): Cần bare metal hoặc VM, tự quản lý control plane. Phù hợp khi có yêu cầu compliance hoặc hạ tầng legacy.

1.3. Loại workload

Ứng dụng sẽ chạy trên cluster là gì? Câu trả lời ảnh hưởng tới node sizing và storage.

  • Một vài ứng dụng nhỏ: Node nhỏ, storage đơn giản.
  • Ứng dụng web có traffic vừa: Cần nhiều replicas, load balancer, persistent storage.
  • Big data, ML, analytics: Cần node lớn, GPU nodes, high-performance storage.
Loại WorkloadĐặc điểmYêu cầu Node
Web app nhỏCPU-bound, stateless2 vCPU, 4GB RAM
Database (PostgreSQL)I/O nặng, statefulSSD, nhiều RAM
ML trainingGPU-intensiveGPU node, nhiều CPU

1.4. Network traffic

Traffic liên tục hay burst? Điều này ảnh hưởng tới auto-scaling configuration.

  • Traffic liên tục: Quy mô node ổn định, scale dần theo growth.
  • Traffic burst: Cần auto-scaling linh hoạt, cluster có thể expand nhanh khi cần.

2. Các giải pháp triển khai Kubernetes

Sau khi trả lời các câu hỏi trên, chọn công cụ triển khai phù hợp. Có 2 nhóm chính: dùng cho local/dev, và dùng cho production.

2.1. Môi trường local — bắt đầu học Kubernetes

Minikube

Minikube deploy cluster bằng cách tạo VM (hoặc container) trên máy local, chạy toàn bộ Kubernetes components bên trong đó.

minikube start --driver=virtualbox
# minikube v1.34.0 on Ubuntu 22.04
# Automatically selected the virtualbox driver
# Starting local Kubernetes cluster...
# Kubectl has been configured to use the minikube cluster

Ưu điểm: tự động hoàn toàn, chỉ cần 1 lệnh. Mặc định Minikube dựng cluster single-node, nhưng từ phiên bản 1.10.1 trở đi nó đã hỗ trợ multi-node qua flag --nodes, và hỗ trợ cả multi-control-plane HA qua flag --ha. Hạn chế thật sự nằm ở chỗ mọi node đều chạy trên cùng một máy local, nên không mô phỏng được hạ tầng nhiều máy thật.

kubeadm

kubeadm là công cụ chính thức của dự án Kubernetes để bootstrap một cluster: nó sinh certificate, sinh manifest cho các control plane component, rồi cung cấp lệnh để các node khác join vào. kubeadm deploy cluster bằng cách join các node lại với nhau. Không tự động tạo VM — cần pre-provision hosts trước.

# Initialize control plane node
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# Output:
# Your Kubernetes control-plane has initialized successfully!
# You can now join any number of machines by running:
# kubeadm join 192.168.1.10:6443 --token abc123...

Ưu điểm: hỗ trợ multi-node cluster, chính là cách production dùng. Nhược điểm: cần tự provision hosts.

💡 Hình dung: Minikube như xe tập lái có giáo viên ngồi cạnh — tự động an toàn. kubeadm như lái thật trên đường — cần chuẩn bị đầy đủ nhưng linh hoạt hơn nhiều.

Giải phápTự động tạo VMMulti-nodeĐộ phức tạp
MinikubeCó (--nodes, nhưng gói gọn trên 1 máy local)Thấp
kubeadmKhôngCó (trên nhiều máy thật)Trung bình

💡 Lưu ý về Windows: Control plane của Kubernetes chỉ chạy được trên Linux. Windows chỉ được hỗ trợ ở vai trò worker node (Windows Server 2022 hoặc 2025). Vì vậy, muốn dựng cluster từ một máy Windows thì vẫn phải dùng VM (VirtualBox, Hyper-V, VMware Workstation) để chạy Linux VM, rồi cài Kubernetes bên trong — dù bản thân kubectl/kubeadm có sẵn binary cho Windows.

2.2. Môi trường production — chọn đúng công cụ

Turnkey solution — giải pháp tự quản lý

Turnkey solution là kiểu giải pháp "chìa khoá trao tay": công cụ lo phần dựng cluster cho sẵn, nhưng hạ tầng bên dưới và việc vận hành lâu dài vẫn thuộc về người dùng. Đây là các công cụ giúp setup Kubernetes cluster trên infrastructure tự có, không dùng managed service của cloud.

  • kubeadm: Công cụ chuẩn, dùng cho on-prem. Cần tự quản lý upgrade và maintenance.
  • kops: Chính thức hỗ trợ AWS và GCE; DigitalOcean, Hetzner và OpenStack ở mức beta, Azure còn ở mức alpha. Tự động tạo infrastructure (VPC, ELB, ASG) và deploy Kubernetes.
  • kubespray: Dùng Ansible để deploy Kubernetes trên bare metal hoặc cloud. Phù hợp cho hybrid environment.
  • OpenShift: Nền tảng enterprise từ Red Hat, build on top of Kubernetes với thêm CI/CD pipelines, web console, và security features.
  • VMware PKE: Giải pháp Kubernetes cho môi trường VMware vSphere, nay được đóng gói dưới tên VMware Tanzu Kubernetes Grid Integrated Edition (TKGI).

Managed solution — Kubernetes-as-a-Service

Cloud provider lo toàn bộ control plane, chỉ cần tập trung vào workloads.

ProviderDịch vụĐặc điểm nổi bật
Google CloudGKEOne-click upgrade, auto-pilot mode
Amazon Web ServicesEKSTích hợp IAM, Fargate integration
Microsoft AzureAKSAzure AD integration, Azure Monitor
Red HatOpenShift OnlineEnterprise-grade, có CI/CD built-in
# Ví dụ: Tạo GKE cluster
gcloud container clusters create my-cluster \
--zone us-central1-a \
--num-nodes=3

# Output:
# Creating cluster my-cluster in us-central1-a... Done.
# Created [https://container.googleapis.com/v1/projects/...].
# kubeconfig entry generated for my-cluster.

So sánh: managed vs self-managed

Tiêu chíManaged (GKE/EKS/AKS)Self-managed (kubeadm)
Control plane maintenanceProvider loTự quản lý
Upgrade control planeTự động hoặc manualTự thực hiện
CostTrả theo nodeTrả theo VM/node
CustomizationHạn chếToàn quyền kiểm soát
CompliancePhụ thuộc cloudTự kiểm soát hoàn toàn

3. Quy mô cluster và yêu cầu tài nguyên

3.1. Giới hạn về quy mô

Kubernetes cluster có những giới hạn được test và support. Không phải không thể vượt quá, nhưng vượt qua thì không còn được support chính thức. Một cluster được xem là "vừa cỡ" khi thoả đồng thời cả bốn điều kiện dưới đây.

Thông sốGiới hạn chính thức
Số nodeKhông quá 5.000 node
Tổng số podKhông quá 150.000 pod
Tổng số containerKhông quá 300.000 container
Pod trên mỗi nodeKhông quá 110 pod

💡 Hình dung: 5.000 node giống 5.000 tòa nhà trong một thành phố. Mỗi tòa nhà chứa tối đa 110 căn hộ (pod), mỗi căn hộ có thể có nhiều người ở (container). Kubernetes có thể quản lý cả một "thành phố" như vậy.

3.2. Yêu cầu tài nguyên cho node

Mỗi node cần đủ tài nguyên để chạy OS + kubelet + container runtime + workloads.

Yêu cầu tối thiểu theo tài liệu kubeadm:

  • 2 GB RAM trở lên cho mỗi máy (ít hơn thì gần như không còn chỗ cho ứng dụng).
  • 2 CPU trở lên cho máy làm control plane node.
  • Swap phải được tắt, hoặc được kubelet cấu hình để chấp nhận swap.
  • Đủ disk cho image và dữ liệu container — tài liệu chính thức không chốt con số, thực tế thường tính từ 20 GB trở lên.

Yêu cầu khuyến nghị cho production:

  • 4-8 CPU.
  • 8-16 GB RAM.
  • 50-100 GB SSD.
# Kiểm tra tài nguyên node
kubectl describe node node-1 | grep -A 5 "Allocated resources"

# Output (minh họa):
# Allocated resources:
# Resource Requests Limits
# cpu 800m (40%) 2 (100%)
# memory 1Gi (50%) 4Gi (100%)

3.3. Chọn giải pháp theo mục đích

Mục đíchGiải phápGhi chú
Học tậpMinikube, single-node kubeadm2CPU, 4GB RAM đủ
DevelopmentMulti-node kubeadm (1 master + 2-3 workers)Mô phỏng production nhẹ
Staging3 master HA + 3+ workersTest HA failover
Production3-5 master HA + N workersTuỳ quy mô app

4. Lưu trữ và cấu hình node

4.1. Chọn storage theo workload

Storage ảnh hưởng trực tiếp tới performance của ứng dụng.

Loại WorkloadLoại Storage phù hợpLý do
Database (I/O nặng)SSD-backedCần throughput cao, latency thấp
File storage trung bìnhHDDTiết kiệm chi phí
Distributed appNetwork storage (NFS, EBS)Chia sẻ data giữa pods
Stateful app cần persistPersistentVolumeDữ liệu không mất khi pod restart
# Ví dụ: khai báo một StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd

⚠️ Lưu ý: In-tree provisioner cũ kubernetes.io/gce-pd vẫn khai báo được, nhưng mọi thao tác của nó đã bị chuyển hướng bắt buộc (CSI migration) sang CSI driver pd.csi.storage.gke.io, nên nên khai báo thẳng CSI driver như trên.

4.2. Storage class

StorageClass là cách Kubernetes abstract việc provisioning storage. Thay vì tạo PV thủ công, pod có thể yêu cầu PVC, và StorageClass sẽ tự động provision đúng loại storage.

kubectl get storageclass

# Output (minh họa):
# NAME PROVISIONER RECLAIMPOLICY
# standard (default) kubernetes.io/gce-pd Delete
# fast kubernetes.io/gce-pd Delete
# managed-nfs cluster.local/nfs Retain

💡 Hình dung: StorageClass giống menu trong nhà hàng — không cần biết đầu bếp nấu gì, chỉ cần chọn món (Slow, Standard, Fast), và hệ thống tự chuẩn bị đúng nguyên liệu và cách nấu.

4.3. Node type — physical hay virtual?

Cả 2 đều hoạt động được với Kubernetes.

  • Virtual Machines (VMs): Phổ biến nhất, linh hoạt, dễ scale. Dùng trên cloud hoặc on-prem với VMware, Proxmox.
  • Bare Metal: Hiệu năng cao hơn, không có virtualization overhead. Phù hợp cho high-performance workloads.

Có thể mix: dùng VMs cho worker nodes (dễ scale), bare metal cho database nodes (performance).


5. Kiến trúc node master và worker

5.1. Vai trò của master và worker node

Đây là kiến trúc cơ bản của mọi Kubernetes cluster.

Kubernetes Cluster ArchitectureMaster NodeControl Planekube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-manager(optional)kubectl / API callsWorker NodeData Planekubeletkube-proxyContainer Runtime(containerd)PodsPod APod BMaster điều khiển, Worker chạy workload — hai vai trò tách biệt như bộ não và cơ bắp.

Master Node (Control Plane) chứa các components quản lý cluster:

  • kube-apiserver: Giao diện chính — tất cả kubectl commands và API calls đều đi qua đây.
  • etcd: Database lưu trữ toàn bộ cluster state.
  • kube-scheduler: Quyết định pod nào chạy trên node nào.
  • kube-controller-manager: Chạy các controller process (Node controller, Replication controller, Endpoints controller, Service Account controller).

Worker Node (Data Plane) chứa các components chạy workloads:

  • kubelet: Agent trên mỗi node, nhận instructions từ API server.
  • kube-proxy: Network proxy, quản lý network rules trên node.
  • Container Runtime: Chạy containers (thường là containerd).
  • Pods: Nơi containers thực sự chạy.

5.2. Best practice — dedicated master node

Đây là best practice được khuyến nghị, đặc biệt trong production.

⚠️ Lưu ý quan trọng: Mặc dù Kubernetes cho phép run workloads trên master node, KHÔNG nên làm vậy trong production.

  • Khi kubeadm initialize cluster, control plane node được đánh taint tự động — taint là một dấu hiệu gắn lên node để đẩy pod thường ra chỗ khác. Taint ở đây là node-role.kubernetes.io/control-plane:NoSchedule, nghĩa là pod thông thường không được schedule lên control plane node.
  • Lý do: nếu workload ngốn tài nguyên trên master, control plane có thể bị ảnh hưởng → nguy hiểm cho toàn cluster.
# Xem taints trên control plane node
kubectl describe node master-node | grep -A 3 Taints

# Output (minh họa):
# Taints: node-role.kubernetes.io/control-plane:NoSchedule

⚠️ Lưu ý: Taint cũ node-role.kubernetes.io/master:NoSchedule đã bị gỡ khỏi kubeadm từ Kubernetes v1.25 — trên cluster hiện hành chỉ còn taint node-role.kubernetes.io/control-plane.

5.3. Yêu cầu về hệ điều hành

  • Control plane: Bắt buộc chạy trên Linux 64-bit — không có lựa chọn nào khác.
  • Worker node: Linux, hoặc Windows Server 2022/2025 nếu cần chạy Windows container.
  • Phổ biến nhất: Ubuntu, CentOS, RHEL.
  • Container runtime: Hỗ trợ containerd, CRI-O, hoặc Docker (qua cri-dockerd).

5.4. etcd placement — stacked vs external

Trong large clusters, có 2 cách đặt etcd:

Stacked (default): etcd chạy trên cùng node với control plane components. Dễ setup, ít servers hơn. Nhưng nếu node down, mất cả control plane lẫn etcd — vì vậy tài liệu chính thức yêu cầu tối thiểu 3 stacked control plane node cho một cluster HA.

External etcd: etcd chạy trên dedicated nodes riêng. An toàn hơn, nhưng cần gấp đôi số host so với stacked — tối thiểu 3 host cho control plane và 3 host cho etcd. Phù hợp cho mission-critical deployments.

Chi tiết về HA setup và etcd topology sẽ được bàn ở Part 10.2.


6. Quy hoạch mạng cho cluster

Có một kịch bản rất hay gặp ở lần dựng cluster đầu tiên: mọi thứ trông như đã xong — kubectl get nodes báo Ready, pod lên Running — nhưng ứng dụng bên trong pod lại không gọi nổi database nội bộ của công ty đặt ở 10.244.7.20. Không phải lỗi firewall, cũng không phải lỗi DNS. Lỗi nằm ở chỗ dải IP đã cấp cho pod trùng đúng dải mạng nội bộ đó, nên node nhìn thấy 10.244.7.20 và tưởng đó là một pod trong chính cluster, giữ gói tin lại thay vì đẩy ra router.

Một biến thể khác còn khó truy hơn: chọn dải IP cho Service đè lên dải mà VPN của công ty đang cấp. Cluster chạy hoàn toàn bình thường cho tới ngày có người bật VPN lên và mất truy cập vào một nửa hạ tầng, vì máy của họ không còn biết nên định tuyến dải đó đi đâu.

Điểm chung của cả hai sự cố: chúng rất đắt để sửa. Đổi dải IP của pod hay của Service sau khi cluster đã chạy gần như đồng nghĩa với dựng lại cluster từ đầu. Vì vậy quy hoạch mạng thuộc về giai đoạn thiết kế, không phải giai đoạn vận hành — và đây là phần hay bị bỏ sót nhất trong toàn bộ quá trình chuẩn bị.

6.1. Ba dải IP không được chồng nhau

Trước hết cần thống nhất cách đọc ký hiệu. CIDR (Classless Inter-Domain Routing) là cách viết gọn một dải địa chỉ IP dưới dạng địa_chỉ/số_bit: phần /số_bit cho biết bao nhiêu bit đầu là phần cố định của dải, phần còn lại là chỗ để cấp phát. Ví dụ 10.244.0.0/16 cố định 16 bit đầu (10.244), để trống 16 bit sau — tức là chứa được khoảng 65.000 địa chỉ, từ 10.244.0.0 tới 10.244.255.255. Số sau dấu gạch càng nhỏ thì dải càng rộng.

Một Kubernetes cluster luôn có ba dải IP song song, hoàn toàn độc lập với nhau:

DảiCấp địa chỉ cho aiGiá trị mặc địnhĐặt ở đâu
Node networkIP thật của từng máy chạy nodeDo hạ tầng mạng quyết định, Kubernetes không can thiệpDHCP hoặc IP tĩnh của hạ tầng
Pod CIDRMỗi pod một IPKhông có mặc định — phụ thuộc CNI plugin đã chọnkubeadm init --pod-network-cidr=...
Service CIDRClusterIP ảo của mỗi Service10.96.0.0/12kubeadm init --service-cidr=...

Chi tiết đáng nhớ ở bảng trên: --service-cidr có mặc định sẵn là 10.96.0.0/12, còn --pod-network-cidr không có mặc định. Cờ này chỉ đơn giản khai báo "dải nào dành cho pod", và nếu được đặt thì control plane sẽ tự cắt dải đó thành từng khối con cấp cho mỗi node. Giá trị cụ thể phải lấy theo CNI plugin định dùng, vì mỗi plugin có dải quen thuộc riêng của nó.

Quy tắc bắt buộc: ba dải này không được giao nhau, và không dải nào trong số đó được giao với mạng vật lý đang dùng. Tài liệu kubeadm nói rất thẳng về điều này — dải pod không được chồng lấn với bất kỳ mạng host nào, có chồng lấn là chắc chắn gặp vấn đề. Lý do đơn giản: node quyết định gửi một gói tin đi đâu bằng cách tra bảng định tuyến. Nếu hai dải trùng nhau, cùng một địa chỉ đích lại khớp với hai đích đến khác nhau, và gói tin sẽ đi tới đúng một nơi — thường là nơi sai.

💡 Hình dung: ba dải IP giống ba khu phố trong cùng một thành phố, mỗi khu có hệ thống số nhà riêng. Chừng nào tên phố khác nhau thì bưu tá không bao giờ nhầm. Nhưng nếu khu mới xây lại lấy trùng tên phố với khu cũ, mọi lá thư gửi tới "số 20" đều rơi vào tình huống hai nhà cùng địa chỉ — và bưu tá chỉ giao được cho một nhà, thường là nhà gần hơn. Quy hoạch tên phố là việc làm trước khi xây, không phải sau khi dân đã dọn vào.

Quy hoạch ba dải IP của clusterNode network192.168.56.0/24Hạ tầng mạng cấp, Kubernetes không can thiệp.Máy thậtkhông giao nhauPod CIDR10.244.0.0/16Không có mặc định — chọn theo CNI plugin.Mỗi podkhông giao nhauService CIDR10.96.0.0/12Mặc định của kubeadm — IP ảo, không gắn máy nào.Mỗi ServiceChồng lấn dù chỉ một phần là gói tin đi lạc — và sửa thì phải dựng lại cluster.

Trên một cluster đang chạy, có thể đọc lại hai dải mà control plane đang dùng để đối chiếu với sơ đồ mạng của tổ chức:

kubectl cluster-info dump | grep -E "cluster-cidr|service-cluster-ip-range"

# Output minh họa
# "--cluster-cidr=10.244.0.0/16",
# "--service-cluster-ip-range=10.96.0.0/12",

Hai field cần nhìn là --cluster-cidr (dải cấp cho pod, do controller manager cắt nhỏ cho từng node) và --service-cluster-ip-range (dải cấp ClusterIP, do API server quản lý). Nếu một trong hai chạm vào dải đang dùng trong mạng nội bộ, đây là lúc phát hiện ra — trước khi đưa workload thật lên.

Để thấy rõ ba dải tách biệt như thế nào, có thể liệt kê khối pod CIDR mà mỗi node được cấp đặt cạnh IP thật của chính node đó:

kubectl get nodes -o custom-columns=NODE:.metadata.name,POD_CIDR:.spec.podCIDR,NODE_IP:.status.addresses[0].address

# Output minh họa
# NODE POD_CIDR NODE_IP
# controlplane 10.244.0.0/24 192.168.56.10
# node01 10.244.1.0/24 192.168.56.11
# node02 10.244.2.0/24 192.168.56.12

Cột POD_CIDR cho thấy control plane đã cắt dải tổng 10.244.0.0/16 thành từng khối /24 riêng cho mỗi node, mỗi khối khoảng 254 địa chỉ — đủ cho giới hạn 110 pod mỗi node đã nói ở mục 3.1. Cột NODE_IP nằm ở một dải hoàn toàn khác (192.168.56.x), đúng như thiết kế: địa chỉ của máy và địa chỉ của pod không bao giờ được lẫn vào nhau.

(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)

6.2. Các port phải mở giữa các node

Triệu chứng kinh điển thứ hai: kubeadm join chạy trên worker node rồi treo cứng ở bước kết nối tới control plane, hoặc node join được nhưng kubectl logskubectl exec luôn báo timeout trong khi kubectl get pods vẫn chạy bình thường. Hai lỗi này hầu như luôn cùng một nguyên nhân: firewall giữa các máy đang chặn đúng port mà thành phần đó cần.

Điều này liên hệ thẳng với kiến trúc ở mục 5: mỗi component trong danh sách đó đều lắng nghe trên một port riêng, nên danh sách port cần mở chính là danh sách component có mặt trên từng loại node.

Control plane node:

ProtocolChiềuPortDùng choAi gọi tới
TCPInbound6443Kubernetes API serverTất cả
TCPInbound2379-2380etcd server client APIkube-apiserver, etcd
TCPInbound10250Kubelet APIChính node đó, control plane
TCPInbound10259kube-schedulerChính node đó
TCPInbound10257kube-controller-managerChính node đó

Worker node:

ProtocolChiềuPortDùng choAi gọi tới
TCPInbound10250Kubelet APIChính node đó, control plane
TCPInbound10256kube-proxyChính node đó, load balancer
TCPInbound30000-32767NodePort ServicesTất cả
UDPInbound30000-32767NodePort ServicesTất cả

Vài điểm cần giải thích thêm:

  • 6443 là port duy nhất mà người dùng bên ngoài thực sự cần chạm tới. Mọi lệnh kubectl, mọi lần node join, mọi controller đều đi qua đây. Chặn port này là cluster coi như không tồn tại.
  • 2379-2380 phải mở giữa các control plane node với nhau trong cấu hình HA, vì các etcd member dùng 2380 để bầu leader và đồng bộ dữ liệu với nhau. Trên cluster một control plane thì hai port này chỉ dùng nội bộ trong máy.
  • 10250 là đường control plane gọi ngược xuống kubelet của từng node. Đây chính là đường mà kubectl logs, kubectl execkubectl top đi qua — nên khi chỉ riêng ba lệnh đó hỏng còn mọi thứ khác bình thường, gần như chắc chắn là 10250 bị chặn.
  • 30000-32767NodePort range — dải port mặc định mà Kubernetes dùng khi tạo Service kiểu NodePort, tức là kiểu Service mở một port trên mọi node để truy cập từ bên ngoài. Cần mở cả TCP lẫn UDP vì Service có thể khai báo một trong hai giao thức.

💡 Hình dung: mỗi node là một toà nhà có nhiều cửa, mỗi cửa mở đúng cho một loại khách. Cửa 6443 là sảnh chính, nơi mọi khách từ ngoài đi vào. Cửa 10250 là cửa sau chỉ dành cho ban quản lý toà nhà đi kiểm tra từng tầng. Cửa 2379-2380 là hành lang nối giữa các toà nhà quản lý với nhau, người ngoài không bao giờ dùng tới. Khoá nhầm một cửa thì toà nhà vẫn đứng đó, chỉ là có một loại khách vĩnh viễn không vào được — và nhìn từ bên ngoài rất khó đoán là cửa nào.

Mọi port ở trên đều có thể đổi sang giá trị khác; khi đổi thì mở đúng port mới thay cho port mặc định, và etcd còn có thể đặt hẳn ra cụm host riêng bên ngoài. Trước khi chạy kubeadm init, cách kiểm tra nhanh nhất là thử gõ cửa xem port đã thông chưa:

nc -zv 192.168.56.10 6443

# Output minh họa
# Connection to 192.168.56.10 6443 port [tcp/*] succeeded!

Dòng succeeded! nghĩa là đường tới API server đã thông từ máy đang đứng. Nếu nhận được Connection refused thì API server chưa chạy, còn nếu lệnh treo rồi báo timed out thì gần như chắc chắn có firewall hoặc security group đang chặn ở giữa — hai triệu chứng này dẫn tới hai hướng xử lý hoàn toàn khác nhau.

(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)

6.3. Chọn CNI plugin

Triệu chứng thứ ba, và là điều gần như ai cũng gặp ngay sau kubeadm init lần đầu: node ở trạng thái NotReady, pod kẹt vĩnh viễn ở ContainerCreating, và kubectl describe pod in ra dòng network plugin is not ready: cni config uninitialized. Đây không phải lỗi — đây là thiết kế. Kubernetes cố tình không kèm sẵn phần triển khai mạng cho pod; nó chỉ định nghĩa yêu cầu (mọi pod phải nói chuyện được với mọi pod khác mà không cần NAT) rồi giao việc thực hiện cho một CNI plugin (Container Network Interface) do người dựng cluster tự chọn và cài. Cluster chưa cài CNI là cluster chưa dùng được.

Vì đây là lựa chọn phải ra trong giai đoạn thiết kế — nó quyết định luôn giá trị --pod-network-cidr ở mục 6.1 — cần nắm vài khái niệm để so sánh cho có căn cứ:

  • Overlay network: cách cho gói tin của pod "đi nhờ" trên mạng vật lý bằng cách bọc nó trong một gói tin khác, thường dùng kỹ thuật VXLAN. Ưu điểm là không cần động gì tới router của hạ tầng — mạng bên dưới không cần biết pod tồn tại. Nhược điểm là mỗi gói tin phải bọc vào rồi bóc ra, tốn thêm CPU và làm giảm kích thước dữ liệu hữu ích trong mỗi gói.
  • Routing thuần: không bọc gói tin, mà báo cho hạ tầng mạng biết đường tới từng dải pod, thường qua BGP (Border Gateway Protocol) — giao thức mà chính Internet dùng để các mạng quảng bá cho nhau biết "dải địa chỉ này đi qua tôi". Nhanh hơn overlay vì không có lớp bọc, nhưng đòi hỏi hạ tầng mạng phải hợp tác, nên thường chỉ khả thi ở môi trường on-prem tự làm chủ router.
  • eBPF: cơ chế cho phép nạp chương trình nhỏ chạy thẳng trong nhân Linux để xử lý gói tin, thay cho chuỗi luật iptables dài dằng dặc. Khi số Service lên tới hàng nghìn, cách làm bằng iptables chậm dần rõ rệt còn eBPF thì gần như không đổi, nên đây là yếu tố đáng cân nhắc với cluster lớn.
  • NetworkPolicy: tài nguyên chuẩn của Kubernetes để giới hạn pod nào được nói chuyện với pod nào. Điểm mấu chốt: NetworkPolicy do CNI plugin thực thi, không phải do Kubernetes. Tạo NetworkPolicy trên một cluster mà plugin không hỗ trợ thì API server vẫn nhận, vẫn hiện ra trong kubectl get netpol, nhưng hoàn toàn không có tác dụng — một cái bẫy bảo mật rất nguy hiểm vì nó im lặng.
CNI pluginDataplaneThực thi NetworkPolicyPod CIDR quen dùngHợp với
FlannelOverlay VXLAN (và vài backend khác)Khôngflanneld không tự thực thi, phải bổ sung controller riêng hoặc ghép Calico/Cilium10.244.0.0/16Lab, học tập, dev cluster không cần phân quyền mạng
CalicoMặc định BGP full-mesh không đóng gói, có thể bật overlay; hỗ trợ dataplane eBPF — đầy đủ NetworkPolicy chuẩn, thêm GlobalNetworkPolicy riêng192.168.0.0/16Production on-prem, môi trường cần chính sách mạng chặt
CiliumeBPF — thêm chính sách ở tầng ứng dụng (L7)Tuỳ chế độ IPAMCluster lớn, cần quan sát luồng mạng và thay thế kube-proxy
Weave NetOverlayCó (khi còn phát triển)Không nên chọn mới — repo đã archive từ 20/06/2024, chỉ còn đọc

💡 Hình dung: chọn CNI giống chọn đơn vị chuyển phát cho khu đô thị vừa quy hoạch ở mục 6.1. Flannel là dịch vụ giao hàng giá rẻ: đưa thư tới đúng nhà, nhanh gọn, nhưng không kiểm tra xem ai được phép gửi cho ai. Calico là đơn vị có thêm bộ phận kiểm soát ra vào, đọc danh sách được phép trước khi giao. Cilium là đơn vị dùng hệ thống phân loại tự động ngay tại cổng, xử lý được lượng thư rất lớn và còn ghi lại nhật ký từng lá thư. Chọn dịch vụ nào là việc của lúc lập quy hoạch — đổi giữa chừng nghĩa là toàn khu phải ngừng nhận thư một thời gian.

Bốn câu hỏi quyết định lựa chọn, theo thứ tự ưu tiên thực tế:

  1. Có cần chặn luồng giữa các pod không? Nếu có — và mọi cluster production nhiều tenant đều có — thì loại Flannel thuần ra khỏi danh sách ngay từ đầu, vì thêm NetworkPolicy vào sau nghĩa là phải cài chồng thêm một lớp nữa.
  2. Hạ tầng mạng có cho phép routing thuần không? Nếu tự làm chủ router và chạy được BGP thì Calico ở chế độ không đóng gói cho hiệu năng tốt nhất. Nếu chạy trên cloud hoặc không động được vào router, buộc phải dùng overlay.
  3. Cluster dự kiến lớn tới đâu? Vài chục node thì gần như plugin nào cũng ổn. Từ vài trăm node và hàng nghìn Service trở lên, dataplane eBPF (Cilium, hoặc Calico bật chế độ eBPF) là khác biệt đo được chứ không còn là lý thuyết.
  4. Đội vận hành quen với cái gì? Một plugin mạnh nhưng không ai trong đội đọc nổi log của nó khi sự cố xảy ra lúc hai giờ sáng là lựa chọn tệ hơn một plugin đơn giản mà cả đội hiểu rõ.

⚠️ Lưu ý: giá trị --pod-network-cidr phải khớp với cấu hình của CNI đã chọn. Flannel mặc định đọc 10.244.0.0/16 từ manifest của nó, nên dùng dải khác thì phải sửa manifest cho khớp. Calico lấy sẵn dải 192.168.0.0/16 trong ví dụ cài đặt và tự phát hiện dải thật từ cấu hình kubeadm đang chạy, nhưng ở nền tảng không dùng kubeadm thì phải khai báo tay qua biến CALICO_IPV4POOL_CIDR. Lệch giữa hai bên là pod lên được nhưng không định tuyến được cho nhau.


7. Checklist thiết kế trước khi cài cluster

Toàn bộ các mục phía trên quy về một việc duy nhất: ra quyết định trước, rồi mới gõ lệnh. Phần này không nhắc lại lý thuyết — nó là danh sách những câu hỏi cần có câu trả lời bằng văn bản trước khi chạy dòng lệnh cài đặt đầu tiên. Câu nào chưa trả lời được thì chưa nên bắt đầu cài.

💡 Hình dung: đây là bản vẽ thiết kế phải được duyệt trước khi đổ móng. Sau khi móng đã đổ, mọi thay đổi trên bản vẽ đều quy ra đập đi xây lại — và với cluster, "đập đi xây lại" nghĩa là dựng lại từ đầu rồi di chuyển toàn bộ workload sang.

Mục đích và quy mô:

  • Cluster này phục vụ mục đích gì — học tập, dev, staging hay production? Tiêu chí: production thì mọi câu dưới đây đều bắt buộc trả lời, học tập thì Minikube một node là đủ.
  • Cần bao nhiêu worker node ở thời điểm khởi đầu, và dự kiến tăng tới đâu trong 12 tháng tới? Tiêu chí: lấy tổng số pod dự kiến chia cho 110 pod mỗi node, rồi cộng thêm dư địa cho lúc drain node đi bảo trì.
  • Mỗi node cấu hình bao nhiêu CPU và RAM? Tiêu chí: tối thiểu 2 CPU và 2 GB RAM cho control plane theo tài liệu kubeadm; production nên từ 4 CPU và 8 GB RAM trở lên.

Hạ tầng và công cụ:

  • Tự host hay dùng managed service? Tiêu chí: có yêu cầu compliance hoặc hạ tầng on-prem sẵn thì tự host; còn lại chọn managed để khỏi gánh việc vận hành control plane.
  • Nếu tự host, dùng công cụ nào — kubeadm, kops hay kubespray? Tiêu chí: kubeadm cho on-prem và cho người muốn hiểu từng bước; kops khi hạ tầng nằm trên AWS hoặc GCE và muốn tạo luôn cả VPC lẫn load balancer; kubespray khi đã có sẵn quy trình Ansible.
  • Node là VM hay bare metal? Tiêu chí: VM cho worker để dễ scale, bare metal cho node chạy database hoặc workload nhạy cảm với độ trễ.

Control plane và etcd:

  • Bao nhiêu control plane node? Tiêu chí: 1 cho dev; từ 3 trở lên và luôn là số lẻ cho production, để etcd còn bầu được leader khi mất một node.
  • etcd đặt stacked hay external? Tiêu chí: stacked cần tối thiểu 3 host và đủ cho đa số trường hợp; external cần 6 host nhưng tách được rủi ro mất đồng thời cả control plane lẫn dữ liệu.
  • Control plane node có nhận workload thường không? Tiêu chí: production thì giữ nguyên taint node-role.kubernetes.io/control-plane:NoSchedule, đừng gỡ.

Mạng — phần đắt nhất nếu chọn sai:

  • Dải IP thật của các node là gì? Tiêu chí: hỏi đội hạ tầng mạng và ghi lại chính xác, vì hai câu dưới phụ thuộc vào câu này.
  • Pod CIDR chọn dải nào? Tiêu chí: đủ rộng cho tổng số pod tối đa nhân hệ số dự phòng, không giao với mạng node, không giao với bất kỳ dải nào công ty đang dùng — kể cả dải VPN và dải của các site khác.
  • Service CIDR giữ mặc định 10.96.0.0/12 hay đổi? Tiêu chí: giữ mặc định nếu dải 10.96.x.x10.111.x.x đang trống; đổi nếu hạ tầng đã dùng dải đó.
  • CNI plugin nào? Tiêu chí: cần NetworkPolicy thì Calico hoặc Cilium; cluster rất lớn thì ưu tiên dataplane eBPF; chỉ làm lab thì Flannel là đủ.
  • Danh sách port đã mở giữa các node chưa? Tiêu chí: đối chiếu đúng hai bảng ở mục 6.2, và kiểm tra thật bằng nc chứ không tin vào tài liệu cấu hình firewall.

Lưu trữ:

  • Workload nào cần lưu trữ bền vững? Tiêu chí: database và message queue thì cần; ứng dụng web stateless thì không.
  • Dùng StorageClass nào làm mặc định? Tiêu chí: khai báo thẳng CSI driver, đừng dùng in-tree provisioner cũ.
  • Có cần tách riêng node cho workload nặng I/O không? Tiêu chí: có, nếu database dùng chung node với workload khác đang gây tranh chấp đĩa.

Vận hành:

  • Backup etcd theo lịch nào, và lưu ở đâu ngoài cluster? Tiêu chí: quy trình chi tiết ở Part 6; điều cần chốt ở giai đoạn thiết kế là nơi lưu bản backup phải nằm ngoài cluster.
  • Chính sách upgrade ra sao — bao lâu nâng một lần, nâng trong khung giờ nào? Tiêu chí: Kubernetes ra bản mới đều đặn, nên chốt trước khung bảo trì sẽ đỡ phải tranh luận về sau.
  • Ai được quyền truy cập cluster, ở mức nào? Tiêu chí: thiết kế RBAC trước khi có người dùng thật, vì siết quyền sau khi mọi người đã quen dùng quyền admin là việc rất khó.

Nguồn tham khảo

Nguồn gốc: Khóa "Certified Kubernetes Administrator (CKA)" — phần "Design and Install a Kubernetes Cluster" (Thiết kế cluster: mục đích, cloud adoption, workload và traffic; Các giải pháp triển khai: Minikube, kubeadm, turnkey và managed solution; Quy mô cluster và yêu cầu tài nguyên; Lưu trữ và cấu hình node; Kiến trúc node master và worker), nền tảng KodeKloud. Giảng viên: Mumshad Mannambeth.

Repo ghi chú, link tài liệu, và đáp án các practice question của toàn bộ khóa học: kodekloudhub/certified-kubernetes-administrator-course.

Fact-check:

  • Giới hạn quy mô chính thức của Kubernetes: không quá 110 pod trên mỗi node, không quá 5.000 node, không quá 150.000 pod và không quá 300.000 container trên toàn cluster — một cluster phải thoả đồng thời cả bốn điều kiện — 2026-09-23, Kubernetes Docs — Considerations for large clusters
  • Yêu cầu tối thiểu theo tài liệu kubeadm: 2 GB RAM trở lên mỗi máy, 2 CPU trở lên cho máy làm control plane, kết nối mạng thông suốt giữa các máy, và swap phải tắt hoặc được kubelet cấu hình để chấp nhận — 2026-09-23, Kubernetes Docs — Installing kubeadm
  • Minikube hỗ trợ multi-node cluster qua flag --nodes (từ minikube v1.10.1) và multi-control-plane HA qua flag --ha, không còn giới hạn ở single-node — 2026-09-23, minikube — Using Multi-Node Clusters
  • Control plane của Kubernetes chỉ chạy được trên Linux; Windows chỉ được hỗ trợ ở vai trò worker node, với Windows Server 2022 hoặc Windows Server 2025 — 2026-09-23, Kubernetes Docs — Windows containers in Kubernetes
  • kubeadm gắn cho control plane node taint node-role.kubernetes.io/control-plane:NoSchedule; taint cũ node-role.kubernetes.io/master đã bị gỡ khỏi kubeadm từ v1.25 — 2026-09-23, Kubernetes Docs — Creating a cluster with kubeadm
  • kOps hỗ trợ chính thức AWS và GCE; DigitalOcean, Hetzner và OpenStack ở mức beta; Azure ở mức alpha — không còn là công cụ chỉ dành cho AWS — 2026-09-23, kOps — Welcome
  • In-tree provisioner kubernetes.io/gce-pd vẫn còn trong core nhưng mọi thao tác đã bị chuyển hướng bắt buộc (CSI migration, không thể tắt) sang CSI driver pd.csi.storage.gke.io — 2026-09-23, Kubernetes Docs — Volumes
  • Topology stacked etcd cần tối thiểu 3 control plane node cho cluster HA; topology external etcd cần gấp đôi số host — tối thiểu 3 host control plane và 3 host etcd — 2026-09-23, Kubernetes Docs — Options for Highly Available Topology
  • Cờ --service-cidr của kubeadm init có giá trị mặc định 10.96.0.0/12; cờ --pod-network-cidr không có giá trị mặc định, chỉ khai báo dải IP cho pod và khi được đặt thì control plane tự cấp CIDR con cho mỗi node — 2026-09-23, Kubernetes Docs — kubeadm init
  • Dải mạng cấp cho pod không được chồng lấn với bất kỳ mạng host nào; có chồng lấn thì gần như chắc chắn gặp sự cố, và giá trị --pod-network-cidr phụ thuộc vào CNI provider được chọn — 2026-09-23, Kubernetes Docs — Creating a cluster with kubeadm
  • Port inbound trên control plane node: TCP 6443 (API server), 2379-2380 (etcd server client API), 10250 (Kubelet API), 10259 (kube-scheduler), 10257 (kube-controller-manager); trên worker node: TCP 10250 (Kubelet API), 10256 (kube-proxy), và TCP lẫn UDP 30000-32767 (NodePort Services, là dải mặc định); mọi port đều có thể đổi sang giá trị khác — 2026-09-23, Kubernetes Docs — Ports and Protocols
  • NetworkPolicy do network plugin thực thi; tạo một NetworkPolicy trên cluster dùng giải pháp mạng không hỗ trợ sẽ không có tác dụng gì — 2026-09-23, Kubernetes Docs — Network Policies
  • Flannel dùng mặc định dải 10.244.0.0/16 và chuyển tiếp gói tin qua các backend trong đó có VXLAN; binary flanneld không tự thực thi NetworkPolicy, muốn có thì phải bổ sung controller riêng hoặc dùng kèm Calico/Cilium — 2026-09-23, flannel-io/flannel
  • Calico dùng 192.168.0.0/16 làm pod CIDR trong hướng dẫn cài đặt, mặc định chạy BGP full-mesh node-to-node không đóng gói và có tuỳ chọn bật overlay; ở nền tảng không dùng kubeadm phải khai báo dải qua biến CALICO_IPV4POOL_CIDR — 2026-09-23, Calico Docs — Install on on-premises deployments
  • Cilium dùng dataplane eBPF và có thể thay thế hoàn toàn kube-proxy, xử lý Service kiểu ClusterIP, NodePort, LoadBalancer, externalIPs và HostPort — 2026-09-23, Cilium Docs — Kubernetes Without kube-proxy
  • Repository Weave Net đã được archive ngày 20/06/2024 và chuyển sang trạng thái chỉ đọc — 2026-09-23, weaveworks/weave