Dọn Dẹp Toàn Bộ và Tổng Kết

K
Kai··5 min read

Bảy mươi mốt bài trước dựng và mổ xẻ một cụm Kubernetes hoàn chỉnh. Cụm đó chạy trên sáu EC2 thật, và mỗi giờ nó chạy là một khoản tiền. Bài cuối này dọn sạch hạ tầng, nhưng trước hết nói thẳng về chi phí — vì "dọn dẹp" không phải lúc nào cũng là xóa hẳn.

Ba lựa chọn và giá của chúng

Cụm gồm sáu instance (1× t3.small làm load balancer, 5× t3.medium cho control plane + worker), mỗi máy một ổ root gp3 20 GB, và một Elastic IP gắn vào load balancer. Giá niêm yết ap-southeast-1 cho ba cách xử lý:

Lựa chọn Compute EBS (120 GB gp3) Elastic IP ~Tổng/tháng
Chạy tiếp ~$212 $11.52 trong giá IPv4 ~$245
Stop (giữ để dành) $0 $11.52 $3.65 ~$15
Teardown (xóa hẳn) $0 $0 $0 $0

Ba con số rất khác nhau, và lựa chọn tùy mục đích. Học xong, không động tới nữa → teardown, về $0. Còn muốn quay lại thực hành → stop: instance tắt không tính tiền compute, nhưng ổ EBS vẫn giữ nguyên toàn bộ trạng thái (etcd, certificate, cấu hình), nên aws ec2 start-instances là cụm chạy lại. ~$15/tháng cho một cụm HA sáu node sẵn sàng bật lại là rẻ. Phần dưới là teardown đầy đủ; nếu chọn stop thì chỉ cần aws ec2 stop-instances --instance-ids <6 id> và dừng ở đó.

Teardown đúng thứ tự

Xóa theo thứ tự để không kẹt phụ thuộc. Bắt đầu bằng terminate sáu instance — vì root volume đặt DeleteOnTermination=true, sáu ổ gp3 tự xóa theo, không phải dọn tay:

REGION=ap-southeast-1
aws ec2 terminate-instances --region $REGION --instance-ids \
  i-01e955f527ff25a57 i-05d8b7584a933394a i-07d62211877ed360b \
  i-0ee0d05a3f68f2b73 i-0a33782c408f5bf09 i-0f1ab7628507cb9cd
aws ec2 wait instance-terminated --region $REGION --instance-ids <6 id>

Kiểm ổ đĩa đã đi theo (không còn volume nào available sót lại tính tiền):

aws ec2 describe-volumes --region $REGION \
  --query 'Volumes[?State==`available`].VolumeId'
[]

Trả Elastic IP — khi instance đã terminate, EIP thành "không gắn" và bắt đầu tính tiền nếu để đó, nên release:

aws ec2 release-address --region $REGION --allocation-id <alloc-id-của-203.0.113.10>

Gỡ IAM dựng ở Bài 43 cho EBS CSI (phải tách policy và rút role khỏi instance profile trước khi xóa):

aws iam remove-role-from-instance-profile --instance-profile-name k8s-scratch-ebs-csi --role-name k8s-scratch-ebs-csi
aws iam delete-instance-profile --instance-profile-name k8s-scratch-ebs-csi
aws iam detach-role-policy --role-name k8s-scratch-ebs-csi --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy
aws iam delete-role --role-name k8s-scratch-ebs-csi

Cuối cùng dọn những thứ nhỏ còn lại: key pair, security group, và VPC nếu đã tạo riêng cho cụm (Bài 3):

aws ec2 delete-key-pair --region $REGION --key-name k8s-scratch
# xóa security group + subnet + VPC dành riêng nếu có (sau khi không còn ENI nào dùng)

Snapshot EBS thì không có gì để xóa — các snapshot demo ở Bài 44 đã dọn ngay khi đó. Sau những bước này, tài khoản về trạng thái như trước Bài 3, không còn gì tính tiền.

Nhìn lại hành trình

Cụm bắt đầu từ chỗ không có gì. Part I dựng nó từng mảnh bằng tay: một CA tự ký rồi toàn bộ certificate (Bài 2–4), etcd ba node (Bài 6), API server / controller-manager / scheduler chạy bằng systemd thay vì static pod (Bài 7–8), kubelet và container runtime trên worker (Bài 10–11), rồi tự nối mạng pod, CoreDNS, tới lúc smoke test cả cụm xanh (Bài 16). Không kubeadm, nên mỗi cờ, mỗi cert, mỗi route đều phải hiểu mới dựng được — đó là cả mục đích.

Cụm dựng xong trở thành phòng thí nghiệm cho phần còn lại. Ta đi qua vòng đời pod và workload controller (Part III–IV), scheduling và autoscaling (Part VII–VIII), storage với EBS CSI thật (Part IX), rồi thay cả datapath: từ kube-proxy iptables sang Cilium eBPF kube-proxy-less, NetworkPolicy theo identity, Ingress và Gateway API (Part X). Part XI siết bảo mật từ authentication tới Secret và những lối vòng của nó. Part XII mở rộng chính API server — CRD, webhook, operator, aggregation. Part XIII giữ cụm sống: sao lưu etcd, version skew, quan sát, leader election — phần lớn kiểm chứng bằng thao tác thật, kể cả một lần failover leader có kiểm soát. Và Part XIV dùng chính cụm v1.36 này thử những tính năng vừa graduate ở phiên bản đó: admission bằng CEL (thay webhook), in-place pod resize, storage mới (OCI volume, VolumeAttributesClass), query log node và phân quyền kubelet chi tiết.

Điểm xuyên suốt không phải là thuộc lệnh kubectl, mà là thấy mỗi tính năng cấp cao tựa lên cái gì bên dưới: kubectl logs là một file CRI trên đĩa, resources.limitsmemory.max trong cgroup v2, một Service ClusterIP là vài dòng eBPF, một custom resource là một key trong etcd. Dựng tay từ số không cho ta đúng cái nhìn đó — khi có sự cố trên một cụm production, ta biết nhìn vào đâu vì đã từng tự ráp từng tầng.

Toàn bộ manifest, script và lệnh của series ở github.com/nghiadaulau/kubernetes-from-scratch. Cụm có thể dựng lại bất cứ lúc nào từ Part I — và giờ thì bạn biết từng mảnh trong đó làm gì.

Tổng kết

Hạ tầng đã dọn, hoặc stop để dành, tùy bạn — chạy tiếp ~$245/tháng, stop ~$15/tháng (EBS giữ trạng thái, bật lại được), teardown $0. Quy trình teardown theo thứ tự: terminate instance (kéo theo ổ gp3 nhờ DeleteOnTermination), release Elastic IP, gỡ IAM role/instance profile của EBS CSI, xóa key pair và VPC riêng — về đúng trạng thái trước Bài 3. Và nhìn lại: từ một certificate tự ký, ta dựng tay một cụm Kubernetes HA hoàn chỉnh rồi dùng chính nó để deep-dive gần như toàn bộ concept của Kubernetes, luôn kiểm chứng bằng cụm thật. Giá trị còn lại sau khi xóa hạ tầng không phải cái cụm, mà là hiểu được cái gì nằm dưới cái gì — thứ không mất đi khi instance terminate.

Cảm ơn bạn đã đi hết chặng đường này.