Sự hỗn loạn của các Kubernetes Cluster không giới hạn
Thiết lập cluster Kubernetes đầu tiên cho dự án cá nhân là một việc dễ dàng. Bạn tin tưởng đội ngũ của mình và mọi người đều tuân theo các ‘quy tắc bất thành văn’ khi triển khai. Nhưng khi mở rộng lên 50 namespace và 200 microservice, mọi thứ sẽ nhanh chóng trở nên rắc rối. Tôi đã từng thấy những cluster mà một pod ‘nổi loạn’ không có giới hạn tài nguyên (resource limits) đã gây ra sự sụt giảm 60% hiệu suất cho mọi dịch vụ khác trên node đó. Trong một trường hợp khác, một lập trình viên đã vô tình chạy container dưới quyền root, tạo cơ hội lớn cho các lỗ hổng tiềm tàng bị khai thác.
Dựa vào việc rà soát code thủ công ở quy mô này là con đường dẫn đến sự kiệt sức. Bạn không thể kiểm tra thực tế mọi tệp YAML để đảm bảo tuân thủ bảo mật hoặc các nhãn kiểm soát chi phí. Môi trường ‘Wild West’ này dẫn đến sai lệch cấu hình (configuration drift) và các lỗ hổng bảo mật. Tệ hơn nữa, nó có thể gây ra một hóa đơn đám mây bất ngờ trị giá $2,500 chỉ sau một ngày cuối tuần. Hạ tầng của bạn vẫn sẽ mong manh vì thiếu một phương thức tự động để nói ‘Không’ với các cấu hình sai trước khi chúng tiếp cận cluster.
Khoảng trống: Tại sao RBAC là chưa đủ
Các kỹ sư thường giả định rằng Role-Based Access Control (RBAC) là ‘viên đạn bạc’ cho bảo mật. RBAC rất thiết yếu, nhưng nó chỉ xử lý vấn đề định danh (identity). Nó trả lời câu hỏi: Ai có thể làm gì? Ví dụ, RBAC cho phép một lập trình viên tạo Deployment trong namespace ‘staging’. Tuy nhiên, nó không bao giờ kiểm tra nội dung của Deployment đó.
RBAC tiêu chuẩn sẽ không ngăn được ai đó tạo một LoadBalancer công khai cơ sở dữ liệu nội bộ ra internet. Nó cũng không ngăn chặn việc sử dụng các container registry không được phê duyệt hoặc chứa lỗ hổng. Kubernetes thiếu một cách thức gốc (native), chi tiết để xác thực các thuộc tính cụ thể bên trong nội dung tài nguyên. Policy as Code (PaC) lấp đầy khoảng trống này. Bạn cần một hệ thống đóng vai trò như một thanh tra xây dựng kỹ thuật số, từ chối bất kỳ yêu cầu nào không đáp ứng các tiêu chuẩn của tổ chức.
Giải pháp: Open Policy Agent (OPA) và Gatekeeper
Hãy làm quen với Open Policy Agent (OPA), một engine chính sách đa năng sử dụng ngôn ngữ khai báo gọi là Rego. Trong khi OPA xử lý mọi thứ từ CI/CD pipeline đến xác thực SSH, Gatekeeper là phiên bản dành riêng cho Kubernetes. Nó tích hợp trực tiếp vào Admission Controllers của Kubernetes để thực thi các quy tắc trong thời gian thực.
Hãy tưởng tượng một người gác cổng đứng trước API server của bạn. Khi bạn chạy kubectl apply -f pod.yaml, Gatekeeper sẽ chặn yêu cầu đó lại. Nó so sánh tệp YAML của bạn với các chính sách đã định nghĩa. Nếu pod vi phạm quy tắc, Gatekeeper sẽ hủy yêu cầu ngay lập tức với một thông báo lỗi rõ ràng. Điều này xảy ra trước khi bất kỳ container nào được khởi chạy, giữ cho cluster của bạn luôn ở trạng thái ‘tốt’ đã được xác minh.
Các thành phần chính của Gatekeeper
- ConstraintTemplates: Định nghĩa logic của chính sách bằng ngôn ngữ Rego. Hãy coi đây là ‘bản thiết kế’ hoặc định nghĩa hàm.
- Constraints: Đây là các thực thể (instances) của một template. Chúng xác định chính xác nơi chính sách được áp dụng—nhu các namespace cụ thể—và các giá trị cần kiểm tra. Hãy coi đây là phần ‘triển khai’.
Hướng dẫn: Chính sách đầu tiên của bạn trong thực tế
Tôi đã triển khai thiết lập này trong các môi trường production có lưu lượng truy cập cao, và hiệu quả ổn định mang lại là tức thì. Các bước sau đây sẽ giúp bạn cài đặt Gatekeeper và thực thi một chính sách yêu cầu tất cả Namespace phải có một nhãn (label) cụ thể.
1. Cài đặt Gatekeeper
Sử dụng Helm là con đường nhanh nhất. Chạy các lệnh sau để khởi chạy controller:
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper gatekeeper/gatekeeper --namespace gatekeeper-system --create-namespace
Kiểm tra xem các pod trong namespace gatekeeper-system có hoạt động ổn định không trước khi tiếp tục.
2. Tạo ConstraintTemplate
Chúng ta cần một template để kiểm tra các nhãn. Logic Rego này so sánh các nhãn trên đối tượng đầu vào với danh sách các nhãn bắt buộc được cung cấp trong tham số.
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Thiếu các nhãn bắt buộc: %v", [missing])
}
Áp dụng template: kubectl apply -f template.yaml.
3. Định nghĩa Constraint
Bây giờ, hãy bắt buộc mọi Namespace phải có nhãn cost-center. Điều này đảm bảo bạn có thể theo dõi chi phí đám mây theo từng bộ phận mà không cần phải đi hỏi từng lập trình viên sau này.
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: ns-must-have-cost-center
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
parameters:
labels: ["cost-center"]
Áp dụng constraint này. Gatekeeper hiện đang bảo vệ cluster của bạn.
4. Kiểm tra việc thực thi
Thử tạo một namespace không có nhãn:
kubectl create namespace test-violation
API server sẽ chặn bạn kèm theo một lỗi:
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request:
[ns-must-have-cost-center] Thiếu các nhãn bắt buộc: {"cost-center"}
Bây giờ, hãy thêm nhãn và thử lại. Yêu cầu sẽ được thông qua. Quy trình tự động này đảm bảo tính tuân thủ mà không cần can thiệp thủ công.
Triển khai chiến lược trên Production
Đừng bắt đầu chặn các yêu cầu trên production ngay lập tức. Bạn có khả năng sẽ làm hỏng các CI/CD pipeline hoặc các sự kiện tự động mở rộng. Thay vào đó, hãy sử dụng lộ trình triển khai theo từng giai đoạn.
Gatekeeper bao gồm một trường enforcementAction: dryrun field. Điều này cho phép bạn thấy tài nguyên nào sẽ bị chặn trong log mà không thực sự dừng chúng lại. Hãy kiểm tra (audit) cluster của bạn trước. Dọn dép các tài nguyên không tuân thủ. Sau đó, chuyển sang chế độ enforce khi bạn đã tự tin.
Các trường hợp sử dụng phổ biến trên production bao gồm:
- Registry Whitelisting: Chỉ cho phép các image từ
company.azurecr.io. - Mandatory Resource Limits: Chặn bất kỳ pod nào thiếu khai báo CPU/Memory requests.
- Ingress Collision Prevention: Ngăn chặn hai đội vô tình đăng ký cùng một hostname.
Chuyển dịch sang An toàn Tự động
Policy as Code biến bảo mật từ một mục cần tích ở cuối sprint thành một rào chắn bảo vệ trong thời gian thực. Sử dụng OPA Gatekeeper giúp các lập trình viên di chuyển nhanh chóng trong các ranh giới an toàn. Nó chuyển gánh nặng tuân thủ từ con người sang hệ thống. Trong thế giới cloud-native, đó là cách duy nhất để giữ cho tâm trí bạn được thảnh thơi.

