Cơn ác mộng mang tên mạng “phẳng”
Kubernetes mặc định dùng mạng “phẳng” (flat network). Nghĩa là mọi Pod thoải mái “nói chuyện” với nhau mà không gặp rào cản nào, dù chúng nằm ở khác Namespace. Tiện thì có tiện, nhưng đây là lỗ hổng chết người.
Tôi từng xử lý một ca xâm nhập thực tế: Hacker chiếm quyền một Pod Frontend qua lỗi code cũ. Vì Cluster không có Network Policy, kẻ tấn công chỉ mất 15 phút để quét sạch dải IP nội bộ, tìm thấy DB nhạy cảm ở Namespace khác và lấy toàn bộ dữ liệu. Nếu bạn không muốn thức trắng đêm xử lý sự cố như tôi, hãy coi Network Policy là lớp tường lửa lớp 3-4 bắt buộc phải có.
Tại sao K8s lại “mở cửa” sẵn như vậy?
Vấn đề nằm ở CNI (Container Network Interface). Các CNI đời cũ như Flannel ưu tiên việc ứng dụng chạy thông suốt ngay lập tức nên mở thông mọi kết nối. Tuy nhiên, trên môi trường Production, việc một Pod chạy thử nghiệm (Dev) có thể kết nối tới Database khách hàng (Prod) là rủi ro không thể chấp nhận.
Để an toàn, chúng ta cần tư duy theo kiểu Zero Trust: Mặc định không tin bất kỳ ai, kể cả các thành phần nội bộ.
Kiểm tra CNI: Điều kiện cần để thực thi chính sách
Lưu ý quan trọng: Không phải CNI nào cũng hỗ trợ Network Policy. Nếu bạn dùng Flannel, các file YAML bạn viết sẽ vô dụng. Bạn cần Calico, Cilium, Weave Net hoặc CNI mặc định của các ông lớn Cloud (GKE, EKS, AKS).
Kiểm tra xem CNI của bạn (ví dụ Calico) có đang chạy không bằng lệnh:
kubectl get pods -n kube-system | grep calico
3 Bước cô lập hệ thống thực chiến
1. Thiết lập Default Deny (Khóa toàn bộ)
Đừng mở rồi mới khóa. Hãy khóa hết rồi mở dần. Đây là quy tắc vàng của bảo mật. Policy dưới đây sẽ chặn đứng mọi traffic đi vào (Ingress) và đi ra (Egress) của Namespace production.
Tạo file default-deny-all.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Áp dụng xong, các Pod sẽ bị cô lập hoàn toàn. Chúng không thể gọi nhau, thậm chí không thể truy cập Internet hay phân giải DNS.
2. Cho phép kết nối nội bộ Namespace
Sau khi khóa, hãy cho các Pod trong cùng Namespace production nói chuyện với nhau để ứng dụng không bị “chết đứng”.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: production
spec:
podSelector: {}
ingress:
- from:
- podSelector: {}
3. Chỉ mở đúng Port cần thiết (Least Privilege)
Giả sử Pod frontend cần gọi api-service qua port 8080. Đừng mở cả dải IP, hãy chỉ định đích danh nhãn (label) của Pod.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: api-service
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Kịch bản thực tế: Cho phép Monitoring quét dữ liệu
Hệ thống Monitoring (như Prometheus) thường nằm ở Namespace riêng. Bạn cần cho phép nó truy cập vào Namespace app để lấy thông số (metrics), nhưng phải chặn các Namespace khác.
Trước tiên, hãy gắn nhãn cho Namespace monitoring:
kubectl label namespace monitoring usage=monitoring
Sau đó, cấu hình cho phép traffic từ các Namespace có nhãn này đi vào:
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
usage: monitoring
Kinh nghiệm “xương máu” để tránh lỗi hệ thống
Triển khai Network Policy rất dễ làm sập ứng dụng nếu bạn quên những điều sau:
- Đừng quên DNS: Khi chặn Egress, Pod sẽ không thể gọi
google.comhay thậm chí là DB nội bộ qua tên miền. Hãy luôn mở Port 53 (UDP/TCP) tớikube-dns. - Tính cộng dồn: Network Policy trong K8s mang tính cộng dồn (additive). Chỉ cần một Policy cho phép, kết nối sẽ được thông, bất kể các Policy khác có chặn hay không.
- Visualizer là cứu cánh: Hãy dùng công cụ như Cilium Service Map để nhìn trực quan luồng traffic. Đừng ngồi đoán mò tại sao ứng dụng báo Timeout.
- Bật Logging: Nếu dùng Calico, hãy bật log cho các gói tin bị Drop. Bạn sẽ biết ngay Pod nào đang cố truy cập trái phép hoặc bạn đang cấu hình thiếu ở đâu.
Việc thiết lập ban đầu có thể tốn thời gian, nhưng nó giúp Cluster của bạn thoát khỏi cảnh “vườn không nhà trống”. Hãy bắt đầu từ những Namespace quan trọng nhất ngay hôm nay.

