Tài liệu này hướng dẫn tạo một cluster LKE đầu tiên cho ứng dụng web như Website AI: những lựa chọn trên form tạo cluster LKE, cách chia node pool theo vai trò, cách tính cỡ node theo request, và cách giữ an toàn file kubeconfig. Sau phần lý thuyết về pod, Service, ConfigMap, volume và Ingress, đây là lúc cần một cluster thật để chạy thử.
1. Cluster LKE gồm những gì
LKE (Linode Kubernetes Engine) là dịch vụ Kubernetes được quản lý của Linode. Như đã nói trong bài Kubernetes là gì: control plane, node và pod, một cluster có hai nửa. Với cluster LKE, trách nhiệm giữa hai nửa được chia rõ ràng:
| Phần | Ai vận hành | Gồm những gì |
|---|---|---|
| Control plane | Linode | API server, etcd, scheduler, controller manager, cùng các thành phần riêng của Linode như Cloud Controller Manager (tạo NodeBalancer) và CSI driver (tạo Block Storage) |
| Worker node | Bạn chọn, Linode dựng | Các máy Linode chạy kubelet, container runtime, kube-proxy và CNI. Đây là nơi pod thật sự chạy |
| Tài nguyên đi kèm | Cluster tự tạo khi cần | NodeBalancer cho Service LoadBalancer, Block Storage volume cho PVC |
Bạn không SSH được vào control plane, cũng không phải lo sao lưu etcd hay vá API server; mọi thao tác đều đi qua API và kubeconfig. Chi phí của cluster LKE nằm ở worker node, NodeBalancer và volume, nên mỗi lựa chọn bên dưới cũng là lựa chọn về tiền.
Worker node được nhóm thành node pool: các node cùng loại máy, tăng giảm số lượng hoặc thêm pool mới bất cứ lúc nào mà không phải tạo lại cluster. Mỗi node được gắn sẵn label lke.linode.com/pool-id cho biết nó thuộc pool nào.
2. Các lựa chọn khi tạo cluster LKE
Form tạo cluster LKE trên Cloud Manager rất ngắn, nhưng mỗi ô đều có hệ quả lâu dài:
- Label: đặt tên nói rõ cluster phục vụ sản phẩm nào và chừa hậu tố số cho cluster sau, ví dụ
app-prod-01. Nhìn tên là biết vai trò, giống cách đặt tên máy trên Cloud VPS. - Region: chọn region gần người dùng nhất để giảm độ trễ. Với khách hàng ở Việt Nam, Singapore (
ap-south) thường là lựa chọn hợp lý. Region không đổi được sau khi tạo: muốn chuyển region là phải dựng cluster mới và di chuyển workload. - Phiên bản Kubernetes: LKE thường chỉ cung cấp vài nhánh minor gần nhất. Chọn phiên bản cũng là cam kết nâng cấp định kỳ, và trên LKE nâng cấp nghĩa là các node lần lượt bị thay bằng node mới, nên workload phải chịu được việc pod bị dời đi.
- Control plane có HA hay không: LKE có tuỳ chọn control plane nhiều bản sao, tính phí thêm. Pod đang chạy không chết khi control plane chập chờn, chỉ việc deploy, scale và các controller bị ảnh hưởng.
Có một thứ bạn không phải chọn: CNI. LKE tự cài Calico ngay khi tạo cluster, các CRD của Calico xuất hiện gần như cùng lúc với namespace default. Calico lo mạng giữa các pod trên nhiều node và hỗ trợ NetworkPolicy nếu sau này cần khoanh vùng traffic.
Tài liệu chính thức về các tuỳ chọn này nằm ở trang Linode Kubernetes Engine.
3. Node pool: chia node theo vai trò
Một cluster LKE nhỏ có thể chỉ cần một pool, nhưng nên tách pool theo vai trò ngay từ đầu vì các nhóm workload hành xử rất khác nhau:
| Pool | Chạy gì | Đặc điểm |
|---|---|---|
| Pool hệ thống | Ingress controller, cert-manager, monitoring | Ít pod, ổn định, nhưng là cổng chung: chết là mọi website cùng chết |
| Pool website | Pod ứng dụng của từng site | Số pod tăng theo số khách, tải lên xuống theo traffic từng site, deploy liên tục |
Tách pool giúp một site bị bot cào hết CPU không kéo theo ingress controller. Nhưng scheduler vẫn tự do đặt pod lên bất kỳ node nào còn chỗ; muốn pod hệ thống chỉ chạy ở pool hệ thống, bạn phải khai báo nodeAffinity theo label lke.linode.com/pool-id (có bài riêng trong series).
4. Chọn kích thước node cho cluster LKE
Node của cluster LKE là các gói máy Linode thông thường. Ở nhóm Shared CPU, ba cỡ hay gặp là g6-standard-1 (1 vCPU, 2 GB RAM), g6-standard-2 (2 vCPU, 4 GB) và g6-standard-4 (4 vCPU, 8 GB). Khi chọn, hãy xét ba điều sau.
Allocatable nhỏ hơn con số trên bảng giá
Một node 4 GB không cho pod dùng đủ 4 GB. kubelet giữ lại một phần cho hệ điều hành và chính nó, phần còn lại gọi là allocatable. Trong phần allocatable đó, mỗi node còn phải chạy các DaemonSet hệ thống của LKE như calico-node, kube-proxy và CSI node driver. Xem con số thật bằng:
kubectl describe node <tên-node> | grep -A 6 Allocatable
kubectl describe node <tên-node> | grep -A 10 "Allocated resources"Phần hao hụt này gần như cố định theo node, nên node càng nhỏ thì tỷ lệ bị "ăn mất" càng lớn.
Đếm pod theo request, không theo cảm giác
Scheduler xếp pod dựa trên requests, không dựa trên mức dùng thực tế. Giả sử container web đặt request 150m CPU và 300Mi RAM. Công thức ước lượng:
số pod tối đa theo RAM = (allocatable RAM − request của DaemonSet hệ thống) / request RAM mỗi pod
số pod tối đa theo CPU = (allocatable CPU − request của DaemonSet hệ thống) / request CPU mỗi pod
→ lấy số nhỏ hơn, rồi chừa khoảng trống cho lúc deploy (RollingUpdate tạo pod mới trước khi xoá pod cũ)Với website PHP, RAM thường hết trước CPU, nên ưu tiên gói có tỷ lệ RAM trên CPU cao.
Ít node to hay nhiều node nhỏ
Nhiều node nhỏ thì một node chết chỉ kéo theo ít pod, nhưng hao hụt cho DaemonSet bị nhân lên. Ít node to tận dụng tài nguyên tốt hơn, nhưng mỗi sự cố node làm nhiều website bị dời đi cùng lúc. Với cluster LKE, đổi ý không tốn kém: thêm pool cỡ khác, dời workload sang, rồi xoá pool cũ.
5. Kubeconfig: chìa khoá vào cluster LKE
Khi cluster LKE sẵn sàng, Cloud Manager cho tải về một file kubeconfig. Đây là file YAML mà kubectl dùng để biết gọi API server nào và xưng danh bằng gì. Cấu trúc của nó (giá trị đã thay bằng <...>):
apiVersion: v1
kind: Config
clusters:
- name: lke<id>
cluster:
server: https://<api-server-endpoint>:443
certificate-authority-data: <...>
users:
- name: lke<id>-admin
user:
token: <...> # token quản trị: ai có nó là có toàn quyền
contexts:
- name: lke<id>-ctx
context:
cluster: lke<id>
user: lke<id>-admin
namespace: default
current-context: lke<id>-ctxDòng token là toàn bộ vấn đề: kubeconfig mặc định của cluster LKE mang quyền quản trị cao nhất, không có lớp xác thực thứ hai. File lọt ra ngoài nghĩa là cluster LKE lọt ra ngoài. Cách dùng an toàn hằng ngày:
# mỗi cluster một file, chỉ chủ sở hữu đọc được
chmod 600 ~/.kube/app-prod-01.yaml
export KUBECONFIG=~/.kube/app-prod-01.yaml
kubectl config get-contexts # chắc chắn đang trỏ đúng cluster
kubectl get nodes -o wide # các node của mọi node pool
kubectl get pods -n kube-system # calico, coredns, csi-linode, kube-proxy...
kubectl get storageclass # linode-block-storage và linode-block-storage-retainThói quen gõ kubectl config get-contexts trước một lệnh nguy hiểm trở nên cần thiết ngay khi có cluster LKE thứ hai. Kubernetes giải thích cơ chế gộp nhiều kubeconfig trong trang Organizing Cluster Access Using kubeconfig Files.
6. Quyền truy cập: ai được cầm chìa khoá
Với cluster LKE, nên đặt ra mấy nguyên tắc tương đương quản lý SSH key trên Cloud VPS:
- Kubeconfig quản trị chỉ nằm trong tay người vận hành cluster: không gửi qua chat, không commit vào Git, không dán vào ticket. Kiểm tra
.gitignorevà.dockerignoređể file không lọt vào Git hay image. - Lộ thì thu hồi ngay. Cloud Manager có thao tác reset kubeconfig: token cũ mất hiệu lực, mọi người phải tải file mới.
- Dev và hệ thống CI không dùng kubeconfig quản trị. Hướng đúng là tạo ServiceAccount riêng, gắn
RolevàRoleBindingchỉ trong namespace cần thiết, rồi sinh kubeconfig từ token của ServiceAccount đó. Cơ chế phân quyền được mô tả trong tài liệu RBAC của Kubernetes. - Token Linode API là một chìa khoá khác. Token này tạo và xoá được cả cluster, node pool lẫn NodeBalancer. Chỉ cấp đúng phạm vi cần dùng và đặt thời hạn.
Ví dụ tối thiểu cho một ServiceAccount chỉ được deploy trong một namespace:
kubectl create namespace site-a
kubectl -n site-a create serviceaccount deployer
kubectl -n site-a create rolebinding deployer-edit \
--clusterrole=edit --serviceaccount=site-a:deployer
kubectl -n site-a create token deployer --duration=24h7. Lỗi thường gặp với cluster LKE mới
- Gõ lệnh vào nhầm cluster: biến
KUBECONFIGtrong một tab terminal cũ vẫn trỏ cluster thử nghiệm. Đặt tên file, context rõ ràng và kiểm tra context trước mọi lệnhapplyhaydelete. Unable to connect to the serversau khi reset kubeconfig: token cũ đã bị thu hồi. Tải lại file và cập nhật mọi nơi đang dùng file cũ.- Pod
Pendingdù node còn "trống":kubectl topcho thấy node đang rảnh, nhưng tổngrequestsđã chạm allocatable. Xem mục "Allocated resources" thay vì nhìn mức dùng thực tế. - Quên rằng node có thể bị thay bất cứ lúc nào: nâng cấp phiên bản hoặc recycle node sẽ tạo node mới với tên mới, IP mới. Không viết cấu hình nào phụ thuộc tên node hay IP node cụ thể. Một dòng comment hay
nodeNametrỏ tới node của cluster thử nghiệm cũ, sót lại trong manifest, là lỗi rất dễ mắc.
8. Checklist trước khi đưa workload lên cluster LKE
- Tên cluster nói rõ vai trò, region gần người dùng, phiên bản Kubernetes còn được hỗ trợ.
- Node pool tách theo vai trò (hệ thống, website), cỡ node tính từ allocatable và request.
- Kubeconfig quản trị có quyền
600, không nằm trong repo hay image, đã biết cách reset. - CI và dev dùng ServiceAccount có quyền hẹp theo namespace.
- Token Linode API có phạm vi và thời hạn rõ ràng.
- Không manifest nào phụ thuộc tên node hay IP node.
Tạo một cluster LKE chỉ mất vài phút; phần tốn thời gian là quyết định workload nào chạy ở đâu, mỗi pod cần bao nhiêu tài nguyên, ai được quyền làm gì. Cách traffic đi vào cluster đã có ở bài Ingress và NodeBalancer, còn cách volume được cấp phát nằm ở bài PersistentVolume, PVC và StorageClass.
Bài tiếp theo
Manifest Kubernetes đầu tiên: namespace, Deployment và MySQL StatefulSet. Đọc từng file YAML của một ứng dụng Laravel trên Kubernetes, vì sao MySQL dùng StatefulSet thay vì Deployment, và những lỗi hay gặp ở phiên bản đầu.
