Cụm Kubernetes chạy mượt nhưng đã thực sự an toàn?
Dựng xong cụm Kubernetes, thấy Pod chạy êm và Ingress trỏ đúng domain là anh em thường thở phào. Mình từng như vậy. Đến khi một server test bị bot brute-force SSH qua cổng mở bừa bãi lúc 2 giờ sáng, mình mới thấm: hệ thống chạy được chưa bao giờ đồng nghĩa với hệ thống an toàn.
Mặc định, Kubernetes ưu tiên tính dễ dùng khi khởi tạo. File cấu hình của kube-apiserver, kubelet hay etcd thường để quyền hạn khá thoáng (như quyền 644 hoặc 777). Nếu một Pod web dính lỗi RCE, hacker có thể đọc token service account, khai thác cổng API lỏng lẻo rồi chiếm quyền toàn bộ cụm. Để bịt các lỗ hổng cấu hình này, chúng ta cần một công cụ audit tự động và đáng tin cậy.
CIS Kubernetes Benchmark và Kube-bench là gì?
Muốn audit hiệu quả, trước hết anh em cần nắm rõ 2 công cụ nền tảng sau:
- CIS Kubernetes Benchmark: Bộ tài liệu hơn 200 trang từ Center for Internet Security. Tài liệu đưa ra hàng loạt quy chuẩn cấu hình an toàn cho Control Plane, etcd, Worker Node và cơ chế xác thực.
- Kube-bench: Công cụ mã nguồn mở viết bằng Go của hãng Aqua Security. Kube-bench đối chiếu toàn bộ cấu hình node, file permission và tham số tiến trình với bộ tiêu chuẩn CIS rồi xuất báo cáo chi tiết chỉ sau 10–15 giây.
Thực hành audit bảo mật K8s bằng Kube-bench
Tùy theo kiến trúc cụm (tự dựng bằng kubeadm hay dùng dịch vụ managed như EKS, GKE), bạn có thể chọn 1 trong 2 cách chạy dưới đây.
Cách 1: Chạy Kube-bench bằng Kubernetes Job (Khuyên dùng)
Cách này giúp bạn quét cụm nhanh chóng trực tiếp qua kubectl mà không cần SSH vào từng node.
Tạo file manifest job-kube-bench.yaml:
cat <<EOF > job-kube-bench.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench
spec:
template:
spec:
hostPID: true
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
command: ["kube-bench"]
volumeMounts:
- name: var-lib-etcd
mountPath: /var/lib/etcd
readOnly: true
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
- name: usr-bin
mountPath: /usr/local/mount-from-host/bin
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-etcd
hostPath:
path: /var/lib/etcd
- name: var-lib-kubelet
hostPath:
path: /var/lib/kubelet
- name: etc-systemd
hostPath:
path: /etc/systemd
- name: etc-kubernetes
hostPath:
path: /etc/kubernetes
- name: usr-bin
hostPath:
path: /usr/bin
EOF
Triển khai Job và lấy kết quả log:
# Tạo Job quét
kubectl apply -f job-kube-bench.yaml
# Chờ Pod chạy xong
kubectl wait --for=condition=complete job/kube-bench --timeout=60s
# Xuất báo cáo
kubectl logs job/kube-bench
Cách 2: Chạy trực tiếp binary trên Master / Worker Node
Với các máy chủ bare-metal hoặc VM tự quản lý, chạy binary độc lập là cách trực quan nhất để audit từng node.
# Tải bản release mới nhất
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.8.0/kube-bench_0.8.0_linux_amd64.tar.gz -o kube-bench.tar.gz
tar -xvf kube-bench.tar.gz
# Audit Control Plane node
sudo ./kube-bench run --targets master
# Audit Worker node
sudo ./kube-bench run --targets node
Đọc hiểu kết quả và xử lý các cảnh báo FAIL
Kube-bench phân loại kết quả thành 4 trạng thái:
[PASS]: Cấu hình chuẩn CIS.[FAIL]: Lỗi bảo mật nghiêm trọng, cần xử lý ngay.[WARN]: Cảnh báo cần đánh giá lại theo nhu cầu thực tế.[INFO]: Thông tin tham khảo.
Dưới mỗi mục FAIL, Kube-bench luôn kèm theo block == Remediation == hướng dẫn cụ thể cách sửa. Dưới đây là 2 lỗi phổ biến nhất mình hay gặp trên các cụm K8s vừa dựng:
1. Phân quyền sai file cấu hình API Server (Mục 1.1.1)
Mặc định file manifest chứa secret và token khởi tạo có thể bị đọc bởi user thường trên OS. Hãy siết lại quyền về 600:
sudo chown root:root /etc/kubernetes/manifests/kube-apiserver.yaml
sudo chmod 600 /etc/kubernetes/manifests/kube-apiserver.yaml
2. Kubelet mở xác thực ẩn danh (Mục 4.2.1)
Nếu bật anonymous-auth, bất kỳ ai vào được mạng nội bộ node cũng có thể gửi lệnh trực tiếp tới port 10250 của Kubelet. Sửa file /var/lib/kubelet/config.yaml:
authentication:
anonymous:
enabled: false
webhook:
enabled: true
Khởi động lại tiến trình để áp dụng:
sudo systemctl restart kubelet
Kinh nghiệm thực chiến khi audit cụm K8s
Sau thời gian dài áp dụng Kube-bench trên hệ thống staging và production, mình đúc kết vài điểm mấu chốt:
- Đừng mù quáng sửa cho bằng được 100% PASS: Một số rule khuyên tắt anonymous request hoặc chặn hostPath có thể làm hỏng CNI (như Calico, Cilium) hay Storage CSI. Hãy test kỹ trên staging trước khi sửa trên production.
- Tích hợp CronJob và alert định kỳ: Cài một CronJob quét hàng tuần lúc 3h sáng Chủ Nhật. Bắn log lỗi thẳng về kênh Slack hoặc Telegram của đội DevOps để nắm bắt ngay khi có ai đó lỡ tay đổi quyền file.
- Chọn đúng phiên bản benchmark: Luôn kiểm tra version K8s hiện tại để truyền cờ
--benchmark cis-1.8hoặc bản tương ứng. Chạy lệch version sẽ cho ra kết quả sai lệch.
Bảo mật hạ tầng là cả một quá trình liên tục. Thêm Kube-bench vào pipeline định kỳ sẽ giúp bạn yên tâm ngủ ngon mà không lo cụm K8s bị hở sườn.

