Day-2 Operations: giữ cluster sống được nhiều năm
Bài 10 bạn dựng xong cluster. Chúc mừng — đó là Day 1.
Bài 10 bạn dựng xong cluster. Chúc mừng — đó là Day 1.
Nhưng cluster không sống trong ngày đầu tiên; nó sống trong ba năm tiếp theo. Và trong ba năm đó: node cần bảo trì, K8s ra bản mới mỗi ~4 tháng, đĩa đầy, node chết, ai đó xóa nhầm, và — thứ khiến nhiều người mất ngủ nhất — chứng chỉ control plane hết hạn sau đúng 1 năm kể từ lúc bạn gõ kubeadm init.
Đó là Day 2: mọi thứ xảy ra sau khi cluster chạy. Bài này dạy bốn kỹ năng sống còn:
- Bảo trì node không downtime —
cordon/drain/uncordon - Nâng cấp cluster —
kubeadm upgradeđúng cách, không phá cluster - Chứng chỉ — quả bom hẹn giờ 1 năm và cách tháo nó
- Khôi phục — restore etcd (Bài 10 mới dạy backup), và dựng HA control plane
Đây là bài phân biệt "người dựng được cluster" với "người vận hành được cluster".
Vấn đề: Day 1 xong không có nghĩa là xong
Ngày 1 ✅ kubeadm init, cluster Ready, app chạy. Ăn mừng.
Ngày 30 ⚠️ Cần thay RAM cho worker-01. Tắt máy = Pod trên đó chết?
Ngày 90 ⚠️ K8s 1.30 sắp hết hỗ trợ. Nâng cấp thế nào cho khỏi sập?
Ngày 180 ⚠️ etcd hỏng sau sự cố điện. Có snapshot — nhưng RESTORE kiểu gì?
Ngày 365 💥 CHỨNG CHỈ CONTROL PLANE HẾT HẠN.
kubectl báo "certificate has expired".
API Server từ chối mọi kết nối. Cluster "chết lâm sàng" —
app vẫn chạy nhưng bạn KHÔNG ĐIỀU KHIỂN ĐƯỢC GÌ NỮA.Cái ngày 365 đó là thứ khiến nhiều team hoảng loạn thật sự, vì không ai cảnh báo trước. Ta tháo bom đó ngay trong bài này.
1. Bảo trì node — cordon, drain, uncordon
Cần thay RAM cho worker-01. Tắt thẳng máy? Pod trên đó chết đột ngột (Bài 03: K8s sẽ tái tạo, nhưng có gián đoạn). Cách đúng: dời Pod đi trước, rồi mới tắt.
cordon "Đừng xếp Pod MỚI lên node này nữa"
→ node thành SchedulingDisabled. Pod đang chạy VẪN Ở LẠI.
drain "Dời hết Pod đang chạy đi nơi khác"
→ cordon + trục xuất Pod (tôn trọng PodDisruptionBudget — Bài 03!)
→ node sạch, an toàn để tắt máy.
uncordon "Xong việc rồi, nhận Pod trở lại"# 1. Chặn Pod mới + dời Pod cũ đi
kubectl drain worker-01 \
--ignore-daemonsets \ # DaemonSet (Bài 07) không dời được — bỏ qua
--delete-emptydir-data \ # Pod có emptyDir (Bài 05) sẽ MẤT dữ liệu tạm
--timeout=300s
kubectl get nodes
# worker-01 Ready,SchedulingDisabled ← đã cordon, Pod đã dời hết
# 2. Giờ tắt máy, thay RAM, bật lại...
sudo shutdown -h now
# 3. Máy lên lại → cho nhận Pod trở lại
kubectl uncordon worker-01
kubectl get nodes # Ready (không còn SchedulingDisabled)⚠️ drain sẽ TREO nếu PodDisruptionBudget không cho phép (Bài 03: minAvailable: 2 mà chỉ còn 2 Pod → không được xóa thêm). Đây là tính năng, không phải lỗi — PDB đang bảo vệ app của bạn. Muốn drain được: scale lên trước, hoặc sửa PDB.
⚠️ drain giết Pod trên node đó — kể cả bare Pod (Bài 02: Pod trần không ai hồi sinh). Đây lại thêm một lý do đừng chạy bare Pod ở production.
💡 Rút một node ra khỏi cluster hẳn:
kubectl drain→kubectl delete node worker-01→ trên chính máy đósudo kubeadm reset.
2. Nâng cấp cluster — kubeadm upgrade
K8s ra một minor version mỗi ~4 tháng, và mỗi bản chỉ được hỗ trợ khoảng 14 tháng. Cluster không nâng cấp = chạy bản không còn vá lỗi bảo mật.
Luật vàng: version skew
⛔ KHÔNG được nhảy cóc minor version.
1.30 → 1.32 là SAI. Phải đi từng bước: 1.30 → 1.31 → 1.32.
⛔ kubelet KHÔNG được mới hơn kube-apiserver.
→ Luôn nâng CONTROL PLANE trước, WORKER sau.
Thứ tự bất di bất dịch:
control plane (kubeadm → apiserver...) → kubelet ở master → worker từng cáiTrên master
# 1. Xem có thể lên bản nào
sudo apt update
sudo apt-cache madison kubeadm | head -5 # liệt kê version có sẵn
# 2. Gỡ ghim, nâng RIÊNG kubeadm trước
sudo apt-mark unhold kubeadm
sudo apt-get install -y kubeadm=1.31.x-*
sudo apt-mark hold kubeadm
# 3. XEM TRƯỚC kế hoạch nâng cấp (không đổi gì cả)
sudo kubeadm upgrade plan
# 4. Thực hiện nâng cấp control plane
sudo kubeadm upgrade apply v1.31.x
# 5. Drain chính master, rồi nâng kubelet + kubectl
kubectl drain master-01 --ignore-daemonsets
sudo apt-mark unhold kubelet kubectl
sudo apt-get install -y kubelet=1.31.x-* kubectl=1.31.x-*
sudo apt-mark hold kubelet kubectl
sudo systemctl daemon-reload && sudo systemctl restart kubelet
kubectl uncordon master-01Trên từng worker (LẦN LƯỢT, không đồng loạt!)
# --- trên MASTER: dời Pod khỏi worker sắp nâng ---
kubectl drain worker-01 --ignore-daemonsets --delete-emptydir-data
# --- trên WORKER-01 ---
sudo apt-mark unhold kubeadm && sudo apt-get install -y kubeadm=1.31.x-* && sudo apt-mark hold kubeadm
sudo kubeadm upgrade node # ← worker dùng "upgrade node"
sudo apt-mark unhold kubelet kubectl
sudo apt-get install -y kubelet=1.31.x-* kubectl=1.31.x-*
sudo apt-mark hold kubelet kubectl
sudo systemctl daemon-reload && sudo systemctl restart kubelet
# --- trên MASTER: cho worker nhận Pod lại ---
kubectl uncordon worker-01
kubectl get nodes # worker-01 đã v1.31.x
# → Lặp cho worker-02. TỪNG CÁI MỘT, để app luôn còn chỗ chạy.💡 Nhớ
apt-mark holdở Bài 10? Chính nó ngănapt upgradevô tình nâng K8s lúc bạn không để ý — và giờ bạn thấy vì sao: nâng cấp K8s phải có kế hoạch, đúng thứ tự, không bao giờ để xảy ra tình cờ.
3. Chứng chỉ — quả bom hẹn giờ 1 năm
Đây là phần tôi muốn bạn nhớ nhất cả bài.
kubeadm init tạo ra một loạt chứng chỉ TLS cho control plane (API Server, etcd, kubelet client...) — và chúng hết hạn sau đúng 1 năm.
# KIỂM TRA NGAY HÔM NAY — trên master
sudo kubeadm certs check-expiration CERTIFICATE EXPIRES RESIDUAL TIME
apiserver Jul 13, 2027 364d
apiserver-etcd-client Jul 13, 2027 364d
etcd-server Jul 13, 2027 364d
...
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME
ca Jul 11, 2036 9y ← CA sống 10 nămĐiều xảy ra khi hết hạn: API Server từ chối mọi kết nối. kubectl báo certificate has expired or is not yet valid. Nghịch lý tàn nhẫn: app của bạn vẫn chạy bình thường (Pod không cần API Server để tồn tại), nhưng bạn mất hoàn toàn quyền điều khiển — không deploy, không scale, không sửa được gì. Cluster "chết lâm sàng".
Gia hạn (làm trước khi hết hạn!)
# Trên master — gia hạn TẤT CẢ chứng chỉ, thêm 1 năm nữa
sudo kubeadm certs renew all
# Khởi động lại các Pod control plane để nạp cert mới
# (chúng là static Pod — di chuyển file manifest ra rồi trả lại là chúng restart)
sudo mv /etc/kubernetes/manifests /tmp/manifests && sleep 20
sudo mv /tmp/manifests /etc/kubernetes/manifests
# Cập nhật kubeconfig admin (nó cũng chứa cert!)
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
sudo kubeadm certs check-expiration # kiểm chứng: đã 364d trở lại💡 Tin vui ít người biết: mỗi lần
kubeadm upgrade, chứng chỉ được tự gia hạn. Nên cluster nâng cấp đều đặn (2–3 lần/năm) gần như không bao giờ dính vụ hết hạn. Cluster "để yên cho lành" mới là cluster chết ở ngày 365. Nghịch lý: không đụng vào cluster mới là cách chắc chắn nhất để giết nó.
⚠️ Đặt lịch nhắc 10 tháng ngay hôm nay, hoặc dựng alert cảnh báo (Bài Observability của chặng sau làm được điều này).
4. Khôi phục etcd — backup vô dụng nếu chưa thử restore
Bài 10 dạy etcdctl snapshot save. Nhưng một bản backup chưa từng được restore thử thì không phải backup — nó là niềm hy vọng. Giờ ta học phần còn lại.
# --- TRÊN MASTER ---
# 1. Dừng control plane (di chuyển static Pod manifest đi)
sudo mv /etc/kubernetes/manifests /tmp/manifests-backup
sudo systemctl stop kubelet
# Đợi container etcd/apiserver dừng hẳn:
sudo crictl ps # không còn etcd/kube-apiserver
# 2. Cất data-dir cũ (ĐỪNG XÓA — lỡ restore hỏng còn đường lui!)
sudo mv /var/lib/etcd /var/lib/etcd.old
# 3. Restore snapshot vào data-dir mới
sudo ETCDCTL_API=3 etcdctl snapshot restore /var/backups/etcd-2026-07-01.db \
--data-dir=/var/lib/etcd
# 4. Trả manifest về → kubelet tự dựng lại control plane với dữ liệu đã restore
sudo mv /tmp/manifests-backup /etc/kubernetes/manifests
sudo systemctl start kubelet
# 5. Kiểm chứng (đợi 1-2 phút)
kubectl get nodes
kubectl get pods -A # trạng thái quay về thời điểm snapshot⚠️ Restore đưa cluster về đúng thời điểm snapshot. Mọi thay đổi sau mốc đó (Deployment mới, Secret mới, namespace mới) biến mất. Đây chính là lý do backup phải chạy thường xuyên — và là lý do GitOps (chặng sau) là lưới an toàn tuyệt vời: nếu manifest nằm trong git, bạn dựng lại được mọi thứ ngay cả khi mất sạch etcd.
💡 Hãy tập restore trên cluster lab, hôm nay. Đừng để lần restore đầu tiên trong đời rơi vào lúc production đang cháy và sếp đứng sau lưng.
5. HA control plane — bỏ điểm chết duy nhất
Cluster ở Bài 10 có một master. Master chết = mất API Server, mất etcd = mất quyền điều khiển cluster (app vẫn chạy, nhưng mọi self-healing/scale/deploy đứng im).
1 master (Bài 10) 3 master (HA)
───────────────── ─────────────
master chết → mất control 1 master chết → 2 cái còn lại vẫn quorum
plane hoàn toàn → cluster tiếp tục hoạt động bình thường
etcd cần QUORUM = (N/2)+1:
3 node → chịu được 1 node chết ✅ khuyên dùng
5 node → chịu được 2 node chết
2 node → chịu được 0! (quorum = 2) ❌ TỆ HƠN 1 node — số CHẴN vô dụng⚠️ Luôn dùng số LẺ master (3 hoặc 5). 2 master không những không HA mà còn tệ hơn 1 master.
Điều kiện tiên quyết — thứ phải quyết định TỪ ĐẦU
┌──────────────────┐
Client/worker ──► │ VIP / LB │ ← keepalived+HAProxy, hoặc LB phần cứng
│ 192.168.200.79 │
└────────┬─────────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
master-01 master-02 master-03
(etcd) (etcd) (etcd) ← "stacked etcd"⚠️ Cạm bẫy lớn nhất của Bài 10 — đọc kỹ đoạn này. Ở capstone ta dùng:
--control-plane-endpoint=192.168.200.80 # ← IP THẬT của master-01Nếu sau này muốn thêm master, endpoint đó phải là VIP/LB, không phải IP một máy — vì mọi node đang trỏ vào 192.168.200.80; master-01 chết là tất cả chết theo, dù bạn có 3 master.
# ĐÚNG cho cluster định làm HA sau này:
sudo kubeadm init \
--control-plane-endpoint="192.168.200.79:6443" \ # ← VIP, không phải IP máy
--upload-certs \
--pod-network-cidr=10.244.0.0/16💡 Bài học kiến trúc: dùng VIP (hoặc một DNS name) làm
control-plane-endpointngay từkubeadm initđầu tiên, kể cả khi bạn chỉ có 1 master. Nó miễn phí lúc đó, và cho bạn đường lên HA sau này. Đổi endpoint trên cluster đang chạy thì rất đau.
Thêm master
# Trên master-01: lấy lệnh join dành cho CONTROL PLANE
sudo kubeadm init phase upload-certs --upload-certs # in ra certificate key
kubeadm token create --print-join-command # in ra lệnh join
# Trên master-02, master-03: thêm cờ --control-plane
sudo kubeadm join 192.168.200.79:6443 \
--token <token> --discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <certificate-key>
kubectl get nodes # 3 node control-plane
kubectl -n kube-system get pods | grep etcd # 3 etcd — quorum khỏe🚀 Lab — Day-2 trên cluster nhiều node
# Cluster kind 3 node để tập cordon/drain
cat <<EOF | kind create cluster --name ops --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes: [{role: control-plane}, {role: worker}, {role: worker}]
EOF1. Drain an toàn
kubectl create deployment web --image=nginx --replicas=4
kubectl get pods -o wide # Pod rải trên 2 worker
kubectl drain ops-worker --ignore-doesnotexist 2>/dev/null
kubectl drain ops-worker --ignore-daemonsets --delete-emptydir-data
kubectl get nodes # ops-worker: Ready,SchedulingDisabled
kubectl get pods -o wide # Pod đã DỜI hết sang worker2 — app không gián đoạn ✨
kubectl uncordon ops-worker
kubectl get nodes # Ready trở lại2. PDB chặn drain (tính năng, không phải lỗi!)
cat <<EOF | kubectl apply -f -
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: web-pdb }
spec:
minAvailable: 4 # đòi giữ CẢ 4 Pod — cố tình quá đáng
selector: { matchLabels: { app: web } }
EOF
kubectl drain ops-worker2 --ignore-daemonsets --timeout=30s
# → "Cannot evict pod ... violate the pod's disruption budget"
# → PDB đang BẢO VỆ app. Muốn drain: scale lên, hoặc hạ minAvailable.
kubectl delete pdb web-pdb3. Kiểm tra chứng chỉ (trên cluster kubeadm thật)
# Chạy trên master của cluster Bài 10:
sudo kubeadm certs check-expiration
# → Ghi lại ngày hết hạn. ĐẶT LỊCH NHẮC 10 THÁNG NGAY HÔM NAY.4. Dọn
kind delete cluster --name opsCâu chuyện thực tế
Ngày 366. Một cluster nội bộ chúng tôi dựng cho team data — dựng xong, chạy ngon, và rồi... không ai đụng vào nữa. Suốt một năm. Đúng tinh thần "đang chạy thì đừng sờ vào".
Một sáng thứ Hai, một bạn cần deploy job mới. kubectl get pods → Unable to connect to the server: x509: certificate has expired. Bạn ấy tưởng hỏng mạng. Rồi tưởng hỏng VPN. Rồi gọi tôi.
Nghịch lý làm mọi người bối rối: các job data vẫn đang chạy ngon lành (Pod không cần API Server để sống). Nhưng chúng tôi không điều khiển được gì — không deploy, không xem log qua kubectl, không scale. Cluster như một con tàu vẫn chạy nhưng buồng lái khóa chặt.
May là fix nhanh: kubeadm certs renew all + restart control plane + copy lại admin.conf. Mất 20 phút. Nhưng 20 phút đó đến sau 2 tiếng hoảng loạn đi tìm nguyên nhân, vì không ai trong team từng nghe nói chứng chỉ K8s có hạn 1 năm. Đau nhất: đây là sự cố hoàn toàn đoán trước được — nó ghi rõ ngày hết hạn từ giây phút cluster ra đời.
Từ đó tôi có hai luật: (1) ngày dựng xong cluster, việc đầu tiên là chạy kubeadm certs check-expiration và đặt lịch nhắc; (2) nâng cấp cluster ít nhất 2 lần/năm — vừa vá bảo mật, vừa tự động gia hạn cert, một mũi tên hai đích.
Cú tát thứ hai — drain không suy nghĩ. Bảo trì worker, tôi gõ kubectl drain worker-01 --ignore-daemonsets --force (thêm --force cho khỏi vướng). Trên node đó có một bare Pod ai đó tạo tay để chạy một tác vụ dài — --force xóa thẳng, và không ai tái tạo nó (Bài 02: bare Pod chết là chết luôn). Tác vụ chạy 6 tiếng bay sạch. Bài học: --force là để xóa Pod không có controller quản — nghĩa là những Pod sẽ không bao giờ quay lại. Hiểu rõ mình đang giết cái gì.
Bài học:
Không đụng vào cluster = cách chắc chắn nhất để giết nó. Chứng chỉ hết hạn ở ngày 365. Cluster được nâng cấp đều đặn thì cert tự gia hạn — nghịch lý đẹp: chăm sóc thường xuyên an toàn hơn để yên.
kubeadm certs check-expirationngay hôm nay. Rồi đặt lịch nhắc 10 tháng. Đây là 30 giây đổi lấy việc không bao giờ mất buồng lái.Backup chưa từng restore thử = niềm hy vọng, không phải backup. Tập restore trên lab, khi không ai đứng sau lưng bạn.
draintrước khi tắt node,uncordonsau khi xong. PDB chặn drain là nó đang bảo vệ bạn — đừng--forcecho qua chuyện.Dùng VIP làm
control-plane-endpointngay từ đầu, kể cả khi mới có 1 master. Miễn phí hôm nay, cứu bạn ngày muốn lên HA.Số master phải LẺ (3 hoặc 5). 2 master tệ hơn 1 — quorum không cho phép chết cái nào.
Pitfalls
Không biết chứng chỉ hết hạn sau 1 năm → ngày 365 mất quyền điều khiển cluster (app vẫn chạy — càng dễ nhầm là "lỗi mạng").
kubeadm certs check-expiration+ lịch nhắc.Nhảy cóc minor version (1.30 → 1.32) → hỏng. Phải đi từng bước một.
Nâng worker trước control plane → kubelet mới hơn API Server = vi phạm version skew, lỗi khó lường. Control plane luôn trước.
Drain đồng loạt nhiều worker → không còn chỗ cho Pod, app sập. Từng cái một.
Quên
uncordonsau bảo trì → node bị bỏ hoang, cluster mất công suất mà không ai hiểu vì sao Pod dồn hết vào node khác.drain --forcekhông suy nghĩ → xóa bare Pod vĩnh viễn (không controller nào tái tạo). Biết mình đang giết gì.Xóa
/var/lib/etcdtrước khi restore → mất đường lui nếu snapshot hỏng. Luônmvsang.old, đừngrm.Restore etcd rồi tưởng mọi thứ nguyên vẹn → mọi thay đổi sau mốc snapshot đã mất. Backup thường xuyên + giữ manifest trong git.
2 master "cho có HA" → quorum = 2, chết một cái là mất quorum. Tệ hơn 1 master. Dùng 3.
--control-plane-endpointtrỏ vào IP một máy → không lên HA được sau này (mọi node đang trỏ vào máy đó). Dùng VIP/DNS ngay từinit.Chỉ backup etcd mà không backup chứng chỉ/
/etc/kubernetes/pki→ restore etcd xong nhưng không dựng lại được control plane. Backup cả hai.Không có alert cho node NotReady / đĩa đầy → sự cố âm ỉ tới lúc bùng. (Chặng sau: Observability sẽ vá lỗ này.)
Tóm tắt
- Day 1 = dựng cluster. Day 2 = giữ nó sống nhiều năm — đây mới là phần dài nhất.
- Bảo trì node:
drain --ignore-daemonsets --delete-emptydir-data→ tắt máy →uncordon. PDB chặn drain là đang bảo vệ app (Bài 03), đừng--forcebừa. - Nâng cấp: không nhảy cóc minor; control plane trước, worker sau; worker từng cái một.
kubeadm upgrade plan→apply(master) →kubeadm upgrade node(worker). - ⭐ Chứng chỉ control plane hết hạn sau 1 NĂM.
kubeadm certs check-expirationngay hôm nay;kubeadm certs renew allđể gia hạn. Nâng cấp cluster định kỳ = cert tự gia hạn. - Restore etcd: dừng control plane →
mv /var/lib/etcd(đừng xóa!) →etcdctl snapshot restore→ trả manifest về. Backup chưa test restore = không phải backup. - HA control plane: số LẺ (3/5) vì quorum
(N/2)+1; cần VIP/LB làm--control-plane-endpoint— quyết định từ lúcinit, khó đổi sau. - Nghịch lý: cluster "để yên cho lành" chính là cluster chết ở ngày 365.
🎓 Kết thúc Chặng — Kubernetes
Đi qua 11 bài:
- Bài 01 — K8s là gì & Kiến trúc: vì sao vượt Compose, control plane + worker, luồng deploy, kubeadm, kubeconfig.
- Bài 02 — Pod & kubectl: đơn vị nhỏ nhất, declarative, lifecycle, 3 probe, debug khi đỏ.
- Bài 03 — ReplicaSet & Deployment: self-healing, rolling update, rollback, scale, HPA, scheduling (affinity/taint/PDB).
- Bài 04 — Service & Namespace: ClusterIP/NodePort/LoadBalancer/ExternalName, endpoints, DNS, vách ngăn, RBAC.
- Bài 05 — ConfigMap & Secret: tách cấu hình khỏi code, 12-factor, base64 ≠ mã hóa.
- Bài 06 — Lưu trữ & StatefulSet: PV/PVC/StorageClass, chạy database/app có trạng thái đúng cách.
- Bài 07 — Job & CronJob: workload chạy-rồi-xong, batch & định kỳ, DaemonSet.
- Bài 08 — Bảo mật & tài nguyên: SecurityContext, Pod Security, QoS, LimitRange, NetworkPolicy.
- Bài 09 — Ingress & TLS: định tuyến L7, HTTPS tự động với cert-manager.
- Bài 10 — Capstone: dựng cluster on-prem 3 node + migrate stack từ Compose lên K8s.
- Bài 11 — Day-2 Operations: bảo trì node, nâng cấp, chứng chỉ, restore etcd, HA control plane.
Từ câu hỏi "Compose sập khi server chết thì sao?" → một cụm nhiều máy tự co giãn, tự phục hồi, deploy không downtime, có HTTPS tự gia hạn, và bạn biết cách giữ nó sống nhiều năm.
Bạn đã sẵn sàng cho
- Helm — trình quản lý gói cho K8s: đóng cả stack manifest thành 1 chart, có version & rollback.
- GitOps (ArgoCD / Flux) — git là nguồn sự thật; cluster tự kéo về và tự sửa sai lệch. Tiến hóa tự nhiên của tư duy declarative.
- Rancher — quản trị nhiều cluster từ một bảng điều khiển, xác thực tập trung.
- Observability — Prometheus + Grafana + Loki: nhìn thấy sự cố trước khi khách hàng gọi (và cảnh báo trước khi cert hết hạn!).
- CI/CD lên K8s — build image → push registry → cập nhật manifest → GitOps lo phần còn lại.
- Service Mesh (Istio/Linkerd) — mTLS, traffic splitting, observability sâu giữa các service.
Lời khuyên đi tiếp
Phá cluster của bạn cho nát.
poweroffnode, xóa Pod, làm sai selector, drain khi có PDB, thử restore etcd. Học từ đống đổ vỡ tự tạo, an toàn hơn học từ sự cố production.Migrate một project thật. Lấy stack Compose cũ, đưa lên K8s end-to-end. Bạn sẽ gặp lại mọi pitfall trong chặng — và hiểu chúng tận xương.
Ngày đầu tiên cluster chạy:
kubeadm certs check-expiration+ đặt lịch nhắc. 30 giây hôm nay, cứu bạn khỏi một buổi sáng hoảng loạn sau 12 tháng.Tập restore etcd khi không ai đứng sau lưng. Lần restore đầu đời không nên rơi vào lúc production đang cháy.
Đừng vội Helm khi chưa thạo YAML thô. Viết tay manifest đủ nhiều để hiểu Helm đang sinh ra cái gì.
Quay lại nền tảng khi bí. Mọi sự cố K8s đều quy về vài thứ: Pod (Bài 02), label/selector (Bài 03), endpoints/DNS (Bài 04), kiến trúc ai-làm-gì (Bài 01). Nền chắc thì debug nhanh.
Hết chặng Docker bạn dựng được full stack qua 1 lệnh trên 1 máy. Hết chặng này bạn dựng được cụm tự sống sót trên nhiều máy, đưa stack lên đời, và giữ nó sống qua nhiều năm. Chặng tiếp — Helm, GitOps, Rancher, Observability, CI/CD — chỉ là xây cao hơn trên nền móng bạn vừa đổ.
Chúc bạn dựng được hệ thống mà lúc một con server cháy lúc 3 giờ sáng, bạn vẫn ngủ ngon — vì cluster đã tự lo. 🚀
— Minh Hưng