

Hướng dẫn cài đặt Kubernetes Cluster cho môi trường production bằng Script
Xây dựng Kubernetes HA cho production trên Ubuntu 24.04 LTS
Hướng dẫn triển khai mới bằng kubeadm: 3 control plane với stacked etcd, 3 worker, 2 load balancer, Cilium và persistent storage. Ví dụ dùng IPv4 trên VM/bare metal có mạng private. Cập nhật tài liệu: 22/10/2026.
Đây là cấu hình tham chiếu để triển khai và nghiệm thu. Bộ lệnh trong tài liệu chưa được chạy trên hạ tầng của bạn; chỉ đưa workload thật vào sau khi các bài kiểm tra ở cuối tài liệu đạt yêu cầu.
1. Kiến trúc và phạm vi
| Máy | IP private ví dụ | Vai trò | Cấu hình khởi điểm đề xuất |
|---|---|---|---|
k8s-lb-1 | 192.168.76.5 | HAProxy + Keepalived | 2 vCPU, 2 GB RAM |
k8s-lb-2 | 192.168.76.6 | HAProxy + Keepalived | 2 vCPU, 2 GB RAM |
| VIP | 192.168.76.9 | Endpoint HA | IP dành riêng, không cấp qua DHCP |
k8s-cp-1 | 192.168.76.10 | Control plane + etcd | 4 vCPU, 8 GB RAM, SSD 100 GB |
k8s-cp-2 | 192.168.76.11 | Control plane + etcd | 4 vCPU, 8 GB RAM, SSD 100 GB |
k8s-cp-3 | 192.168.76.12 | Control plane + etcd | 4 vCPU, 8 GB RAM, SSD 100 GB |
k8s-worker-1 | 192.168.76.21 | Ứng dụng + storage | 8 vCPU, 16 GB RAM; SSD dữ liệu riêng |
k8s-worker-2 | 192.168.76.22 | Ứng dụng + storage | Như worker 1 |
k8s-worker-3 | 192.168.76.23 | Ứng dụng + storage | Như worker 1 |
Các con số tài nguyên là điểm bắt đầu cho ví dụ, không phải cam kết capacity. Đo tải CPU/RAM, IOPS, độ trễ etcd và lượng storage trước khi chốt sizing.
- API endpoint:
k8s-api.example.internal:6443→ VIP. - Pod CIDR:
10.244.0.0/16; Service CIDR:10.96.0.0/12. - Domain ứng dụng ví dụ:
app.example.com→ VIP nếu truy cập nội bộ; nếu public, DNS trỏ public load balancer/NAT chỉ chuyển tiếp cổng ứng dụng. - Control plane giữ taint mặc định; workload chạy trên worker.
- Các control plane phải ở các failure domain khác nhau khi hạ tầng cho phép. Ba VM trên cùng một hypervisor không bảo vệ trước việc hypervisor đó hỏng.
- etcd có 3 member, chịu được mất 1 member. Không bảo trì đồng thời 2 control plane.
Điều kiện VIP: hai load balancer cùng mạng L2, hạ tầng cho phép di chuyển VIP, gratuitous ARP và VRRP unicast. Ví dụ này không cung cấp HA xuyên subnet/AZ bằng Keepalived. Với cloud không hỗ trợ cơ chế trên, dùng TCP load balancer HA của nhà cung cấp và giữ nguyên DNS API; bỏ phần Keepalived. Không áp dụng VIP kiểu này trực tiếp trên AWS VPC.
VIP là endpoint chung trong ví dụ gọn này. Hệ thống lớn nên tách API LB private và application LB theo nhu cầu tải, quyền truy cập và failure domain.
2. Phiên bản và quy ước thao tác
| Thành phần | Nhánh/bản tham chiếu | Cách kiểm soát |
|---|---|---|
| Ubuntu | 24.04 LTS, đã cập nhật bản vá | Không yêu cầu cố định ở point release 24.04.2 |
| Kubernetes | v1.36.5 | Pin cùng bản package trên 6 node |
| containerd | 2.3.x từ Docker APT | Chọn và lưu đúng Debian package version một lần |
| Cilium | Helm chart 1.20.3 | Pin chart, VXLAN, Kubernetes IPAM |
| Gateway API | v1.6.3 | Pin CRD theo tài liệu Cilium 1.20 |
| Helm CLI | v4.3.1 | Kiểm tra checksum trước khi cài |
| Longhorn | Helm chart 1.13.0, V1 data engine | Áp dụng khi dùng storage ở phần 12 |
Đây là bộ phiên bản tham chiếu, không phải chỉ dẫn luôn dùng bản mới nhất. Trước mỗi đợt triển khai, đối chiếu release notes, cảnh báo bảo mật và compatibility matrix; chọn bản vá còn được hỗ trợ rồi cập nhật đồng bộ tài liệu và file khóa phiên bản. Không tự động đổi minor version khi chạy lại script.
Quy ước: SSH bằng tài khoản vận hành có sudo. Chạy sudo -i để vào root shell cho các khối cài đặt host, backup và kubeadm. Các khối kubectl/helm chạy từ k8s-cp-1 trong root shell với kubeconfig chỉ rõ ở phần 8. Không ghi token, private key, file encryption hay kubeconfig quản trị lên Git hoặc bài blog.
Thứ tự: chuẩn bị mạng → LB → cài 6 node → bảo mật control plane → init CP1 → join CP2/CP3 và worker → Cilium → storage/HTTPS → backup/monitoring → nghiệm thu.
3. Chuẩn bị host và kết nối
3.1. Kiểm tra trên 8 máy
bash
- IP tĩnh/DHCP reservation và hostname duy nhất; VM clone không trùng MAC, product UUID hoặc machine identity.
- Đồng bộ giờ bằng chrony/NTP; kiểm tra
chronyc trackingsau khi cài chrony. - SSD local có độ trễ thấp cho
/var/lib/etcd; tránh volume mạng có latency không ổn định. - Node tới được DNS/NTP, Ubuntu/Docker/Kubernetes APT, Helm repo và image registry cần dùng; môi trường hạn chế internet phải mirror các dependency trước.
- Host network, Pod CIDR, Service CIDR và mạng VPN không chồng lấn.
- Dùng kernel Ubuntu được hỗ trợ, cgroup v2; Cilium yêu cầu kernel và eBPF/netfilter phù hợp. Ví dụ chỉ nhắm Linux amd64.
Đặt hostname đúng từng máy, ví dụ trên CP1:
bash
Dùng DNS nội bộ ổn định. Nếu chưa có DNS cho bootstrap, thêm cùng mapping vào /etc/hosts trên các máy liên quan, không xóa nội dung hiện hữu:
text
Kiểm tra trên cả 6 node và máy quản trị:
bash
3.2. Firewall
Giữ AppArmor và firewall. Mô hình này dùng firewall/ACL ở lớp mạng để kiểm soát north-south; 6 Kubernetes node nằm trong một vùng mạng tin cậy dành riêng cho cluster. Cho phép lưu lượng host và Pod cần thiết giữa chính các node đó. Không mở cả subnet nếu trong subnet có máy không thuộc cluster.
| Nguồn → đích | Giao thức/cổng | Mục đích |
|---|---|---|
| Bastion/VPN quản trị → host | TCP 22 | SSH |
| 6 node + quản trị → VIP/LB | TCP 6443 | API server |
| LB + 6 node + quản trị cần thiết → control plane | TCP 6443 | Backend API và kết nối nội bộ |
| Control plane ↔ control plane | TCP 2379–2380 | etcd, chỉ nội bộ |
| Control plane → 6 node | TCP 10250 | Kubelet API |
| 6 node ↔ 6 node | UDP 8472 | Cilium VXLAN |
| 6 node ↔ 6 node | TCP 4240 + ICMP | Cilium health checking |
| LB1 ↔ LB2 | IP protocol 112 | VRRP; đây không phải TCP/UDP port 112 |
| Client được phép → VIP/LB | TCP 80/443 | Ứng dụng, bật sau phần 13 |
| LB → 3 worker | TCP 8080/8443 | Gateway host network, phần 13 |
| Host → DNS/NTP/repo/registry/backup | Theo dependency thực tế | Bootstrap và vận hành |
Không mở scheduler/controller-manager, etcd, kubelet hoặc dashboard ra internet. Mô hình Cilium thay kube-proxy này không cần mở cả dải NodePort.
Nếu host có UFW, giữ lại chính sách quản trị nhưng phải thiết kế thêm rule cho forwarding, Pod CIDR và datapath Cilium. Các rule ufw allow <port> đơn lẻ không đủ; không bật UFW mặc định rồi giả định cluster sẽ chạy. Với mô hình này, thống nhất chính sách host firewall với đội mạng và kiểm chứng Cilium connectivity trước khi nghiệm thu. Không dùng ufw disable hay flush iptables như một bước cài đặt mặc định.
4. Load balancer HA
Chỉ thực hiện trên k8s-lb-1 và k8s-lb-2. Không cài kubeadm/containerd lên hai máy này.
4.1. HAProxy
bash
Tạo /etc/haproxy/haproxy.cfg giống nhau trên cả hai LB:
haproxy
bash
Các backend chưa có API server sẽ DOWN trước khi init; đây là trạng thái dự kiến. TCP check chỉ xác nhận listener; phải giám sát thêm API /readyz có xác thực sau khi cluster lên.
4.2. Keepalived
Chạy ip -br address để xác định interface private; ví dụ dưới dùng ens18. Thay đúng tên interface trên từng LB.
Trên cả hai LB, tạo /usr/local/sbin/check-haproxy:
bash
bash
Tạo /etc/keepalived/keepalived.conf trên LB1:
text
Trên LB2, dùng cùng cấu hình nhưng đổi:
| Thuộc tính | LB2 |
|---|---|
router_id | K8S_LB_2 |
priority | 100 |
unicast_src_ip | 192.168.76.6 |
IP trong unicast_peer | 192.168.76.5 |
VIP, virtual_router_id và subnet mask giữ giống nhau. Chọn VRID không trùng instance khác trong mạng. Script không đặt weight nên lỗi kiểm tra sẽ đưa instance vào FAULT, thay vì chỉ giảm một lượng priority không đủ để failover.
Trên mỗi LB:
bash
VIP chỉ xuất hiện trên một LB. Nếu cả hai cùng giữ VIP, dừng bootstrap và sửa VRRP/ACL/ARP; không tiếp tục khi mạng đang split-brain.
5. Chuẩn bị chung trên 6 Kubernetes node
5.1. Hệ điều hành, swap và kernel
Trên cả 6 node, root shell:
bash
Nếu swap đến từ systemd swap unit/zram, vô hiệu hóa đúng unit/generator tương ứng. Sau reboot, swapon --show phải rỗng. Tài liệu chủ động dùng mô hình không swap; Kubernetes có chế độ hỗ trợ swap nhưng không bật trong cấu hình này.
bash
Kỳ vọng cgroup2fs. Giữ AppArmor bật. Cập nhật bản vá OS và reboot trong cửa sổ triển khai trước khi init; về sau dùng lịch bảo trì có drain, không tự reboot đồng loạt các node.
5.2. Thêm APT repository
Thực hiện trên cả 6 node:
bash
5.3. Khóa phiên bản một lần, rồi dùng cùng file trên 6 node
Chỉ trên CP1, chọn phiên bản từ repository đã xác thực:
bash
Nếu không tìm thấy package, dừng để chọn bản vá hợp lệ và cập nhật bộ phiên bản; không bỏ pin rồi cài tùy ý. Chuyển chính file /root/k8s-versions.env bằng kênh quản trị tới 5 node còn lại. Lưu package đã chọn trong artifact mirror để tái dựng được về sau.
5.4. Cài runtime và công cụ Kubernetes
Trên cả 6 node, chạy nguyên khối sau trong root shell. Chỉ dùng cho node mới; không ghi đè runtime của node đang có workload.
bash
Kubelet có thể restart khi chưa có cấu hình từ kubeadm; kiểm tra lại sau init/join. Reboot 6 node trước bước tiếp theo và xác nhận swap vẫn tắt, thời gian đồng bộ, containerd hoạt động.
6. Chuẩn bị encryption và audit trước khi init
Chỉ trên CP1, root shell:
bash
Chuyển hai file trên bằng kênh quản trị bảo mật tới cùng đường dẫn trên CP2 và CP3 trước khi join. Trên hai máy đó cũng tạo các thư mục với mode tương ứng. Ba bản encryption config phải có cùng checksum; không tự sinh key riêng cho mỗi control plane.
bash
Encryption ở đây bảo vệ Secrets trong etcd. Key nằm trên host nên cần backup mã hóa, phân quyền host và quy trình xoay key; đây không thay thế KMS hoặc mã hóa ổ đĩa. Audit chỉ ghi Metadata để không ghi payload Secrets vào log. Gửi audit log từ cả ba control plane tới hệ thống log ngoài cluster và giám sát dung lượng.
7. Khởi tạo control plane đầu tiên
Trên CP1 tạo /root/kubeadm-init.yaml:
yaml
Reservation áp dụng cho cả 6 node; điều chỉnh theo sizing thực tế trước bootstrap. Cilium thay kube-proxy trong mô hình này; không cài thêm Flannel/Calico hoặc chạy lại phase addon kube-proxy.
Kiểm tra cấu hình, tải image và init:
bash
Lưu join command và certificate key trong nơi quản trị bảo mật, không tee ra file log có thể đọc rộng. Chỉ CP1 chạy init; mọi máy khác dùng join.
8. Join hai control plane còn lại và worker
8.1. Kubeconfig quản trị
Trên CP1, root shell:
bash
Khi mở root shell mới trên CP1, đặt lại biến trên. Nếu dùng user vận hành thông thường, chép kubeconfig vào ~/.kube/config của đúng user và đặt mode 0600. Đây là quyền cluster-admin dành cho bootstrap/break-glass; người dùng hằng ngày cần identity và RBAC riêng.
8.2. Join CP2 và CP3, từng máy một
Trước join, xác nhận hai file encryption/audit đã có và đúng quyền. Với host nhiều interface, cấu hình kubelet chọn đúng InternalIP; ví dụ chỉ trên CP2:
bash
CP3/worker thay bằng IP của chính máy đó. Dùng lệnh join control plane kubeadm vừa in. Ví dụ trên CP2, điền token/hash/key thật:
bash
CP3 đổi IP thành 192.168.76.12 và node name thành k8s-cp-3.
Trên CP1 kiểm tra API/etcd static Pods của node vừa join trước khi join control plane tiếp theo. NotReady do chưa có CNI là dự kiến ở giai đoạn này.
8.3. Join 3 worker
Lấy command mới trên CP1 khi cần:
bash
Trên mỗi worker, chạy command nhận được và thêm node name/runtime; ví dụ worker 1:
bash
Worker nhiều interface cũng đặt KUBELET_EXTRA_ARGS với IP riêng trước join. Worker không nhận certificate key, encryption key hay admin kubeconfig.
Certificate upload cho control-plane join mặc định chỉ tồn tại khoảng 2 giờ. Nếu hết hạn, trên CP1 chạy kubeadm init phase upload-certs --upload-certs để tạo lại; không chạy lại toàn bộ init. Token join thông thường cũng có hạn; dùng --ttl ngắn và xóa token không còn dùng sau bootstrap.
9. Cài Helm, Gateway CRD và Cilium
Trên CP1 trong root shell đã đặt KUBECONFIG.
9.1. Helm CLI
bash
9.2. Gateway CRD
Chỉ cài CRD từ tag cố định phù hợp với Cilium. Các dependency bên dưới gồm TLSRoute theo yêu cầu bản Cilium tham chiếu:
bash
9.3. Cilium
Tạo /root/cilium-values.yaml:
yaml
Kubernetes cấp PodCIDR theo từng node; không cấu hình thêm cluster-pool IPAM với CIDR khác. k8sServiceHost là endpoint HA để Cilium bootstrap khi chưa có kube-proxy. Host network cho phép Gateway dùng worker IP, không cần cài MetalLB chỉ để có external IP.
bash
Lệnh cuối phải báo không tìm thấy kube-proxy trong mô hình này. Kiểm tra thêm cilium status bằng Cilium CLI khi có; cài CLI theo release cố định từ nguồn chính thức, không dùng CLI chưa rõ phiên bản.
10. Xác nhận HA và DNS hệ thống
bash
Kỳ vọng: 3 etcd, 3 API server, 6 node Ready; ít nhất 2 CoreDNS replica nằm trên các worker khác nhau. Nếu CoreDNS dồn một node, chỉnh affinity/topology spread trong manifest quản lý của bạn và lưu thay đổi để áp dụng lại sau upgrade. Không coi Running là đã đạt mọi tiêu chí mạng.
Trên mỗi control plane kiểm tra local etcd bằng binary trong container cùng phiên bản:
bash
Giữ RBAC và NodeRestriction do kubeadm thiết lập mặc định. Kiểm tra taint control plane vẫn còn:
bash
11. Chính sách workload và kiểm thử mạng
11.1. Namespace production và quyền truy cập
bash
Chỉ áp dụng restricted cho namespace ứng dụng. Cilium/CSI có nhu cầu đặc quyền nên không áp chính sách này hàng loạt vào namespace hệ thống. Dùng OIDC với identity provider của tổ chức cho người dùng; bind group vào Role/ClusterRole theo nhu cầu. Ví dụ quyền đọc workload trong một namespace, không cấp đọc Secrets:
yaml
Lưu thành /root/workload-rbac.yaml, rồi kubectl apply -f /root/workload-rbac.yaml. Group chỉ có tác dụng khi hệ thống xác thực thực sự phát hành group developers; manifest không tự tạo tài khoản. Không phân phối admin.conf cho developer/CI.
Kiểm tra Secrets thực sự được mã hóa, dùng một marker thử không nhạy cảm. Từ CP1 tạo Secret rồi đọc trực tiếp record etcd bằng TLS client quản trị:
bash
Kỳ vọng prefix dạng k8s:enc:aescbc:v1:; kiểm tra đọc Secret qua API của cả ba control plane cũng thành công. Không dùng Secret nghiệp vụ làm marker test. Khi thay key, cần kiểm tra lại với snapshot cũ còn trong retention.
11.2. Ứng dụng nghiệm thu
Tạo /root/smoke.yaml. Image là ví dụ có tag cố định; trước workload thật phải duyệt image, quét lỗ hổng và khóa digest trong registry của tổ chức.
yaml
bash
Tạo /root/network-policy.yaml:
yaml
bash
Tạo /root/network-clients.yaml với hai Pod đặt trên worker 2 để kiểm thử từ xa:
yaml
bash
Hai lệnh đầu thành công; lệnh cuối phải bị chặn/timeout. Lấy Pod IP của một web Pod trên worker 1 hoặc 3 rồi gọi http://POD_IP:8080 từ allowed-client để kiểm chứng cross-node, không chỉ Service trên cùng node. Nếu có Cilium CLI, chạy thêm cilium connectivity test trong namespace riêng và dọn tài nguyên test sau đó.
12. Persistent storage với Longhorn
Phần này cung cấp lựa chọn storage cụ thể cho mô hình VM/bare metal. Nếu tổ chức đã có CSI cho SAN/Ceph hoặc cloud block storage, dùng CSI đó và StorageClass tương ứng; không cài chồng Longhorn chỉ để theo ví dụ.
12.1. Chuẩn bị 3 worker
Mỗi worker cần SSD dữ liệu riêng đã format ext4/XFS, mount bền vững bằng UUID tại /var/lib/longhorn. Provision disk theo quy trình hạ tầng của bạn; xác nhận đúng thiết bị trước thao tác format. Không dùng disk OS làm nơi lưu replica trong mô hình này. Dành thêm capacity cho replica, snapshot và rebuild; dung lượng khả dụng nhỏ hơn tổng dung lượng raw.
Trên từng worker, root shell:
bash
Không tiếp tục nếu findmnt không xác nhận mount riêng hoặc mount không còn sau reboot. Longhorn cảnh báo không dùng open-iscsi 2.1.12; kiểm tra bản host và dùng bản không bị ảnh hưởng. Nếu host dùng multipath, áp dụng cấu hình loại trừ thiết bị Longhorn theo tài liệu hãng trước khi attach volume.
Trên CP1:
bash
Namespace đặc quyền chỉ dành cho CSI/Longhorn; giới hạn ai được tạo Pod trong namespace này.
12.2. Cài đặt
Tạo /root/longhorn-values.yaml:
yaml
bash
Tạo /root/storage-class.yaml:
yaml
bash
Workload phải khai báo storageClassName: longhorn-retain. Retain giữ PV sau khi xóa PVC, không thay thế backup; đội vận hành phải có quy trình reclaim/xóa dữ liệu chủ động.
12.3. Nghiệm thu dữ liệu qua việc tạo lại Pod
Tạo /root/storage-smoke.yaml:
yaml
bash
Kỳ vọng persistent-ok và volume Healthy với 3 replica trên 3 worker khác nhau. Đây mới kiểm tra persistence qua Pod replacement; phải làm thêm bài attach lại trên worker khác và phục hồi từ offsite backup trước workload có dữ liệu thật. Không force-detach khi chưa fence được node cũ đang có khả năng ghi volume.
13. HTTPS qua Gateway API
13.1. Certificate
Thay app.example.com bằng domain thật trong toàn bộ phần này. Chuẩn bị certificate chain và private key do CA được client tin cậy cấp. Với public service dùng public CA; với nội bộ có thể dùng CA doanh nghiệp. Ví dụ tạo Secret từ hai file đã có:
bash
Certificate phải có SAN đúng domain và còn hạn. Cần tự động hóa renewal bằng cert-manager/tích hợp PKI của tổ chức hoặc có lịch thay cert đã kiểm chứng; không dùng certificate tự ký tạm thời để nghiệm thu production public.
13.2. Gateway và route
Tạo /root/gateway.yaml:
yaml
bash
Gateway phải Accepted=True, Programmed=True; HTTPRoute Accepted=True, ResolvedRefs=True. Cilium policy cho phép identity ingress tới web, không mở toàn bộ internet tới backend Pod. Các listener host network dùng 8080/8443 để không cần cấp thêm quyền bind cổng thấp cho Envoy. Dùng Gateway chung và chia route khi thêm domain; không tạo các Gateway host-network cạnh tranh cùng port trên cùng node.
13.3. Thêm frontend ứng dụng vào hai LB
Thêm cùng đoạn sau vào /etc/haproxy/haproxy.cfg trên cả hai LB:
haproxy
bash
Ở đây TLS kết thúc tại Cilium Envoy; HAProxy chuyển TCP nguyên trạng, không dùng PROXY protocol. Ứng dụng sẽ không tự nhận được IP client thật chỉ nhờ cấu hình này; nếu cần, phải thiết kế thêm cơ chế truyền IP, giới hạn trusted proxy và kiểm tra chống giả mạo header.
Từ máy client có đường tới VIP:
bash
Kỳ vọng HTTP chuyển sang HTTPS, HTTPS trả ok ... và certificate được xác minh. Với CA nội bộ, cài CA tin cậy hoặc truyền --cacert; không dùng -k để coi bài kiểm tra TLS đã đạt.
14. Backup etcd, PKI và cấu hình ra ngoài cluster
Backup có ba lớp độc lập:
| Lớp | Nội dung cần giữ | Cách phục hồi |
|---|---|---|
| Trạng thái cluster | Snapshot etcd | Khôi phục control plane/metadata Kubernetes |
| Danh tính và cấu hình | PKI, encryption key, kubeadm config, cấu hình từng node/LB | Phục hồi đúng trust và khả năng giải mã |
| Dữ liệu ứng dụng | Volume backup + database-native backup/PITR | Phục hồi dữ liệu thực tế |
Snapshot etcd không chứa dữ liệu PVC. Replica của Longhorn cũng không bảo vệ trước xóa nhầm hoặc mất cả site.
14.1. Kho backup mã hóa ngoài cluster
Ví dụ dùng restic với S3-compatible object storage độc lập. Trên cả 3 control plane, root shell:
bash
Tạo /etc/restic/k8s.env bằng thông tin thật, mode 0600:
bash
Không dùng nguyên placeholder. Chỉ cấp quyền bucket cần thiết; lưu mật khẩu restic trong secret manager ngoài cluster. Dùng retention/Object Lock theo quy định của tổ chức; không giữ credential có quyền phá toàn bộ backup trên host nếu có thể tách quyền ghi và retention.
Khởi tạo repository một lần trên một control plane:
bash
Nếu repository đã tồn tại, bỏ init, dùng restic snapshots để xác nhận kết nối.
14.2. Script backup
Trên mỗi control plane, tạo /usr/local/sbin/backup-kubernetes:
bash
Script dùng binary etcdctl/etcdutl trong etcd image thực tế, tránh trộn client khác phiên bản. Kiểm tra image cung cấp hai binary này trước khi bật timer. Mỗi control plane backup cả PKI/config của chính node đó. Đường dẫn backup cố định giúp retention theo host/path hoạt động nhất quán; flock ngăn hai job trên cùng máy ghi chồng nhau. Nếu upload lỗi, thư mục làm việc được giữ để điều tra và lần chạy sau sẽ cập nhật lại; giám sát dung lượng disk.
bash
14.3. Lịch chạy
Trên mỗi control plane, tạo /etc/systemd/system/backup-kubernetes.service:
ini
Tạo /etc/systemd/system/backup-kubernetes.timer:
ini
bash
Lịch này cho RPO tham chiếu xấp xỉ một giờ cộng thời gian thực thi khi backup thành công; đặt lịch ngắn hơn nếu nghiệp vụ yêu cầu. Bắt buộc alert khi job lỗi hoặc không có backup thành công trong hơn 2 giờ. Chạy restic check, retention và prune bằng job quản trị riêng đã kiểm thử; không để repository tăng vô hạn. Lưu thêm cấu hình LB, Helm values và manifest ứng dụng trong Git riêng không chứa secret.
14.4. Restore drill
Trước production, phục hồi thử trên mạng cô lập với RPO/RTO đã thống nhất:
- Dùng credential ngoài cluster để
restic restore <SNAPSHOT_ID> --target <RESTORE_DIR>. Chọn một snapshot etcd tốt làm nguồn cho cả ba member; kiểm tra metadata/hash bằng etcdutl cùng phiên bản etcd ghi trong backup. - Fencing/cô lập các member cũ để chúng không tham gia mạng của cụm phục hồi. Dừng API server và etcd cũ; di chuyển static Pod manifest ra ngoài
/etc/kubernetes/manifestskhi kubelet còn chạy, xác nhận container đã dừng rồi mới dừng kubelet. Không chỉ dừng kubelet và giả định container đã dừng. - Khôi phục PKI/config đúng node, encryption key tương ứng snapshot, DNS/VIP và quyền file. Không sao chép certificate riêng của CP1 lên mọi control plane. Nếu thay IP/name, phải lập lại membership và cấp certificate có SAN phù hợp.
- Trên từng control plane, dùng
etcdutl snapshot restorevới cùng snapshot và initial-cluster, nhưng--name,--initial-advertise-peer-urls, data directory riêng của node. Với etcd 3.6 cho Kubernetes, áp dụng revision bump và--mark-compactedtheo tài liệu etcd để tránh informer dùng cache cũ. Giá trị bump phải bao phủ số write kể từ snapshot. - Gắn data directory mới vào static etcd manifest theo runbook; khởi động lại etcd rồi API server trên cả ba control plane. Xác nhận quorum/endpoint health, Secrets đọc được, node và controller phục hồi.
- Khôi phục PVC/database từ backup riêng; chạy lại DNS, policy, HTTPS và bài kiểm tra dữ liệu. Ghi thời gian phục hồi đo được và các bước cần sửa.
Không dùng kubeadm reset, xóa etcd directory hoặc --force-new-cluster như một cách sửa lỗi thông thường. Mất một member khi quorum còn khỏe là bài thay member, không phải restore toàn bộ cluster.
15. Backup volume và database
Trong Longhorn, cấu hình Backup Target tới object storage ngoài cluster, dùng credential riêng với etcd backup. Chỉ truy cập UI qua VPN/port-forward hoặc ingress có xác thực:
bash
Port-forward mặc định bind loopback của máy chạy lệnh; khi chạy trên server, dùng SSH tunnel từ máy quản trị. Không đổi sang --address 0.0.0.0 để mở UI công khai.
Sau khi target kết nối thành công:
- Tạo recurring backup job, ví dụ mỗi ngày, retain tối thiểu 14 bản hoặc theo RPO/retention nghiệp vụ.
- Gán job/group vào tất cả volume cần bảo vệ, không chỉ tạo job mà quên gán volume.
- Xác nhận có bản backup trong object storage; restore sang PVC mới và kiểm tra dữ liệu.
- Với PostgreSQL/MySQL, triển khai thêm backup/PITR và quy trình quiesce phù hợp; snapshot volume không tự bảo đảm tính nhất quán cấp nghiệp vụ.
Nếu chọn CSI khác, làm bài tương đương theo hệ thống storage đó. Định kỳ diễn tập mất một worker, storage rebuild và mất toàn bộ site; kiểm chứng giới hạn thời gian detach/attach và fencing.
16. Giám sát, cảnh báo và log
Cài monitoring sau storage để metrics có persistent volume. Ví dụ dùng kube-prometheus-stack chart cố định 92.10.1; kiểm tra release notes/schema và helm template trước khi áp dụng nếu chọn bản khác.
Trên CP1 tạo /root/monitoring-values.yaml:
yaml
bash
Hai Prometheus có dữ liệu riêng; đây không tự tạo một TSDB gộp/deduplicate. Khi cần truy vấn HA tập trung, cấu hình thêm remote-write/Thanos hoặc nền tảng metrics của tổ chức. Có thể dùng Grafana hiện hữu; ví dụ không mở dashboard mặc định.
Chưa hoàn tất monitoring chỉ bằng cài chart. Cấu hình receiver thật trong Alertmanager, lưu credential bằng Secret và gửi test alert tới người trực. Receiver mặc định có thể không gửi thông báo. Xác nhận scrape target và bổ sung endpoint/TLS/RBAC cho etcd, scheduler/controller-manager nếu các metrics mặc định chỉ bind loopback; không mở cổng metrics công khai chỉ để hết cảnh báo.
Tối thiểu phải có các cảnh báo sau:
| Phạm vi | Cần theo dõi |
|---|---|
| Ngoài cluster | DNS/VIP, HTTPS ứng dụng, API readyz, chứng chỉ; alert vẫn chạy khi cả cluster hỏng |
| HA | Member etcd/quorum, API server, Cilium agent/operator/Envoy, CoreDNS và LB/VRRP |
| Tài nguyên | Disk/inode, etcd WAL/fsync latency, memory, CPU, Pod Pending/CrashLoopBackOff |
| Storage | Replica/volume degraded, disk pressure, capacity phục vụ rebuild, attach/detach thất bại |
| Backup | Thời điểm backup thành công cuối, lỗi job, repository/volume backup, restore drill |
| Bảo mật | Certificate sắp hết hạn, API audit, RBAC thay đổi bất thường |
Cài agent log theo nền tảng của tổ chức trên mọi host/node; gửi container log, kubelet/containerd, HAProxy/Keepalived và audit log ra nơi lưu trữ có retention ngoài cluster. Đặt giới hạn dung lượng và alert cho log/audit. Metrics-server là thành phần riêng nếu ứng dụng cần HPA dựa trên resource metrics; kube-prometheus-stack không thay thế metrics-server.
17. Nghiệm thu trước khi nhận traffic thật
Thực hiện trên staging tương đương trước, sau đó trên cụm mới khi chưa có dữ liệu thật. Lưu kết quả từng bài, thời gian gián đoạn và giới hạn quan sát được.
| Bài kiểm tra | Kết quả cần đạt |
|---|---|
| Bootstrap | 6 node Ready, 3 etcd/3 API server healthy, không có Pod hệ thống lỗi kéo dài |
| Network | DNS, ClusterIP, cross-node Pod traffic hoạt động; policy allow thành công và deny bị chặn |
| TLS | Redirect đúng; chứng chỉ/SAN/chain hợp lệ; có renewal và cảnh báo hạn |
| LB failover | Tắt Keepalived trên LB đang giữ VIP; VIP chuyển sang LB còn lại, API/HTTPS hoạt động lại trong ngưỡng đã chốt |
| HAProxy failure | Dừng HAProxy trên LB giữ VIP; health script làm VIP chuyển sang LB còn lại |
| Một control plane mất | Tắt VM hoặc dừng dịch vụ theo runbook; 2 etcd còn quorum, API qua VIP vẫn dùng được |
| Worker mất/drain | App còn phục vụ từ replica khác; kiểm tra reschedule và storage attach theo RTO |
| Storage | Ghi/đọc qua Pod replacement và đổi worker; volume không dồn replica cùng một máy |
| Backup | Có backup ngoài cluster, kiểm tra integrity; restore etcd và PVC/database thử thành công |
| Vận hành | Alert test đến đúng người, log được lưu, có runbook và lịch patch/cert/backup |
Ví dụ kiểm thử VIP sau khi cluster hoàn chỉnh: từ CP1 giữ lệnh kubectl get nodes và từ máy client gọi HTTPS, trên LB đang active chạy systemctl stop keepalived, đo gián đoạn, sau đó systemctl start keepalived. Các TCP session hiện hữu có thể phải reconnect; HA không đồng nghĩa không rớt một request nào.
Không kiểm thử mất hai control plane cùng lúc. Nếu việc bảo trì gặp PDB chặn hoặc volume chưa an toàn để detach, điều tra capacity/replica trước; không mặc định force-delete để vượt qua bài kiểm tra.
18. Vận hành sau triển khai
18.1. Bảo trì từng node
Từ máy quản trị, ví dụ worker 1:
bash
Nếu drain bị chặn bởi PDB, bare Pod nghiệm thu hoặc emptyDir, xem nguyên nhân và kế hoạch dữ liệu trước khi tiếp tục. Không thêm --force, --disable-eviction hoặc xóa emptyDir một cách mặc định. Dọn bare Pod test trước lịch bảo trì; theo quy trình Longhorn cho replica/engine đang ở node đó.
Sau cập nhật/reboot, chờ node, Cilium và storage khỏe rồi:
bash
Với control plane, cập nhật từng máy và xác nhận etcd quorum khỏe sau mỗi máy. Không bật tự động reboot đồng thời.
18.2. Upgrade và certificate
- Backup và restore drill trước đợt upgrade lớn; xem compatibility Cilium/Gateway API/CSI/monitoring trước khi đổi Kubernetes minor.
- Theo quy trình kubeadm chính thức; không nhảy qua minor. Control plane trước, worker sau; unhold/install/hold có kiểm soát từng node.
- Giữ việc skip kube-proxy trong cấu hình/quy trình upgrade vì Cilium đang thay thế nó; kiểm tra không sinh lại addon kube-proxy.
- Kiểm tra
kubeadm certs check-expiration, lập lịch renew theo chính sách PKI; certificate kubeadm và certificate HTTPS ứng dụng là hai vòng đời khác nhau. - Xoay encryption key đồng bộ trên mọi API server: thêm key mới, rolling restart, rewrite Secrets, xác minh giải mã, giữ key cũ cho snapshot còn retention. Không xóa key cũ chỉ vì đã đổi key ghi mới.
- Theo dõi capacity N+1: sau mất/bảo trì một worker vẫn đủ tài nguyên cho workload quan trọng và storage rebuild. Ba worker với ba volume replica sẽ bị degraded khi mất một worker và cần node thay thế để trở lại đủ ba replica.
- Workload thật cần probes, requests/limits, PDB, topology spread, quota, policy egress và image digest phù hợp; không dùng giá trị của app nghiệm thu làm sizing production.
18.3. Thay node và gỡ cụm
Thay node theo runbook drain → xử lý volume/etcd membership → xóa Node object → reprovision host → join lại. Gỡ cluster là quy trình riêng sau khi đã xác nhận backup/retention và di chuyển workload. Hướng dẫn này không chứa phần flush toàn bộ iptables, xóa hàng loạt PKI hoặc xóa etcd để tránh trộn thao tác phá hủy vào luồng dựng production.
Sau nghiệm thu, xóa riêng các tài nguyên smoke test nếu không dùng nữa; giữ lại và chỉnh sửa policy/namespace/storage theo ứng dụng thật. Do StorageClass dùng Retain, xóa PVC không tự xóa dữ liệu PV; ghi nhận và xử lý volume test theo quy trình reclaim.
19. Xử lý lỗi theo lớp
| Hiện tượng | Kiểm tra trước |
|---|---|
| API qua VIP không truy cập được | DNS, VIP trên đúng một LB, VRRP/ARP, HAProxy backend, firewall TCP 6443 |
| API container không lên | crictl ps -a, log container; đường dẫn/mode encryption/audit; certificate; etcd |
| Node NotReady | journalctl -u kubelet -n 100, crictl info, Cilium DaemonSet, swap/cgroup |
| Cross-node timeout | UDP 8472, MTU sau encapsulation, IP/interface node, ACL/forwarding và policy |
| DNS lỗi | CoreDNS Pods/EndpointSlice, policy UDP và TCP 53, Service datapath Cilium |
| Gateway lỗi | CRD/chart compatibility, Gateway/HTTPRoute conditions, Secret TLS, listener 8080/8443 trên worker |
| PVC Pending/attach lỗi | Disk mount, CSI Pods, iscsid, Longhorn node/replica/capacity, version open-iscsi |
| Audit/backup đầy disk | Rotation/retention, job upload lỗi, repo ngoài cluster, alert last-success |
Lệnh chẩn đoán chung:
bash
Trên node có lỗi:
bash
20. Tài liệu chính thức
- Kubernetes releases và support window
- Installing kubeadm
- Container runtimes và systemd cgroup
- Kubeadm high availability
- Kubeadm configuration v1beta4
- Ports and protocols
- Encrypting confidential data at rest
- Kubernetes auditing
- Kubeadm upgrade
- etcd disaster recovery
- Keepalived configuration
- HAProxy configuration manual
- Helm installation và verification
- Cilium Kubernetes compatibility
- Cilium kube-proxy replacement
- Cilium Kubernetes IPAM
- Cilium Gateway API và host network
- Cilium Helm reference
- Longhorn installation
- Longhorn production practices
- Longhorn Helm values
- Prometheus Community Helm charts
- Restic documentation