Chương 10: GKE Admission Control & Policy Enforcement — Securing the API
Vì sao chương này là ranh giới sống còn của cluster
Admission control là lớp cuối cùng mà mọi yêu cầu ghi (write) phải đi qua trước khi được lưu vào etcd. Authentication trả lời "bạn là ai", authorization (RBAC) trả lời "bạn được phép làm gì với loại tài nguyên nào", nhưng cả hai đều không nhìn vào nội dung của đối tượng. Admission control là chỗ duy nhất trong đường đi của request có thể đọc, sửa, và từ chối một đối tượng dựa trên chính nội dung của nó: "Pod này có chạy privileged không?", "image có đến từ registry được duyệt không?", "namespace này còn quota không?", "container có thiếu requests không?". Nếu không có admission control, RBAC chỉ cho bạn nói "team A được tạo Pod" — nó không thể nói "team A được tạo Pod nhưng không được privileged".
Đó là lý do admission control vừa là cửa ngõ security mạnh nhất, vừa là điểm đơn lỗi nguy hiểm nhất của một cluster GKE. Hai mặt của cùng một đồng xu:
- Mặt tốt: một ValidatingAdmissionWebhook hoặc một constraint Gatekeeper được cấu hình đúng có thể chặn đứng toàn bộ một lớp lỗ hổng — privilege escalation, image không đáng tin, workload thiếu resource limit — ngay tại thời điểm
kubectl apply, trước khi nó kịp chạy. - Mặt chết người: một webhook cấu hình sai có thể đánh sập toàn bộ khả năng ghi của cluster. Đây không phải lý thuyết. Một webhook với
failurePolicy: Failtrỏ tới một service đã chết, vànamespaceSelectorkhông loại trừkube-system, sẽ làm API server từ chối mọi request CREATE/UPDATE khớp rule của nó — kể cả các Pod hệ thống cần để khôi phục chính webhook đó. Bạn rơi vào deadlock: không thể tạo Pod để sửa webhook, vì webhook đang chặn việc tạo Pod. Toàn bộ section "anti-pattern" của tài liệu Kubernetes về dynamic admission control tồn tại chính vì kiểu sự cố này (Dynamic Admission Control — best practices).
Điểm mấu chốt mà chương này nhấn mạnh xuyên suốt: admission control là một pipeline tuần tự, không phải một bộ lọc đơn lẻ. Request đi qua một chuỗi cố định — built-in mutating plugins → mutating webhooks → built-in validating plugins → validating webhooks → object schema validation → ValidatingAdmissionPolicy — và mỗi mắt xích đều có thể từ chối hoặc làm chậm toàn bộ chuỗi. Trên GKE, một phần chuỗi này do Google quản lý (vị trí trong API server, các built-in plugin được bật), nhưng phần mở rộng (webhook, PSA labels, Gatekeeper, CEL policy) là trách nhiệm hoàn toàn của bạn — và cũng là chỗ phát sinh gần như mọi sự cố admission trong production.
Điều kiện tiên quyết
- Chương 5 (GKE Control Plane Internals): admission control là một pha trong vòng đời request của API server (Authentication → Authorization → Admission → Schema validation → etcd). Phải hiểu API server xử lý request thế nào, API Priority and Fairness ảnh hưởng ra sao đến request bị webhook làm chậm, và Chương 5 đã giới thiệu admission control pipeline ở mức tổng quan — chương này đi sâu vào vận hành và policy enforcement.
- Kubernetes API fundamentals: GroupVersionResource (GVR), sự khác biệt giữa resource và subresource, các operation CREATE/UPDATE/DELETE/CONNECT, và mô hình declarative reconcile. Webhook rule khớp theo chính các trục này.
- Mô hình resource & QoS (Chương 8): ResourceQuota và LimitRange thao tác trực tiếp trên
requests/limitsvà QoS class. Hiểu sai resource model dẫn đến quota và limit range hoạt động ngược ý đồ. - TLS/PKI cơ bản: webhook là một HTTPS server; toàn bộ phần certificate management (CA bundle, serving cert, rotation) yêu cầu nắm chuỗi tin cậy X.509.
Mức độ sâu
5/5 — Chương đi tới mức thứ tự chính xác của các pha admission, cơ chế reinvocationPolicy: IfNeeded và vì sao một mutating webhook có thể bị gọi lại, ngữ nghĩa failurePolicy × timeoutSeconds (mặc định 10s, tối đa 30s) và tác động timeout lên độ trễ p99 của API server, sự khác biệt sideEffects: None vs NoneOnDryRun trong dry-run, từng control cụ thể của profile baseline/restricted trong Pod Security Standards, mô hình ConstraintTemplate→Constraint của Gatekeeper với enforcementAction: deny/dryrun/warn và audit loop, scope selector của ResourceQuota theo PriorityClass, maxLimitRequestRatio của LimitRange, biến CEL (object, oldObject, params, namespaceObject) trong ValidatingAdmissionPolicy (GA từ Kubernetes 1.30), và CEL custom constraint của Organization Policy cho container.googleapis.com/Cluster. Mọi tuyên bố kỹ thuật đối chiếu trực tiếp tài liệu Kubernetes và Google Cloud.
Cấu trúc chapter
1. Admission Pipeline & Built-in Plugins — Bản Đồ Cửa Ngõ API
Vị trí của admission trong vòng đời request và các plugin nội tại.
- Hai pha cố định: Mutating phase (sửa được object) → Validating phase (chỉ đọc, từ chối được)
- Vì sao thứ tự này bất biến và hệ quả: validating luôn thấy object đã được mutate
- Danh sách plugin bật mặc định (Kubernetes 1.36):
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,Priority,PodSecurity,ResourceQuota,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ValidatingAdmissionPolicy... - Bốn plugin then chốt:
LimitRanger(mutating+validating),ResourceQuota(validating),PodSecurity(validating),NodeRestriction(validating — chống node tự nâng quyền) - Trên GKE bạn không sửa
--enable-admission-plugins: Google chốt danh sách; đòn bẩy của bạn là webhook, PSA, Gatekeeper, CEL policy
2. Mutating & Validating Webhooks — Cơ Chế Gọi & Dry-Run
Hợp đồng giữa API server và webhook server của bạn.
MutatingWebhookConfiguration/ValidatingWebhookConfiguration:rules,clientConfig,admissionReviewVersions- Vòng AdmissionReview: request (uid, object, oldObject, userInfo, dryRun) ↔ response (allowed, patch base64 JSONPatch, status, warnings)
reinvocationPolicy: IfNeeded— vì sao mutating webhook có thể bị gọi lại sau khi webhook khác sửa object, và đòi hỏi idempotencymatchPolicy: EquivalentvsExact,objectSelector/namespaceSelectorđể thu hẹp phạm visideEffects(None/NoneOnDryRun/Unknown) và quan hệ với dry-run; vì sao dry-run là công cụ rollout an toàn- Audit vs enforce: dùng webhook chỉ-cảnh-báo để quan sát trước khi bật chặn
3. Webhook Failure Modes, Performance & Stability — Chống Sập Control Plane
Phần dễ gây outage nhất của cả chương.
failurePolicy: FailvsIgnore— đánh đổi security với availability, ma trận quyết địnhtimeoutSeconds(mặc định 10s, tối đa 30s): webhook chậm làm tăng p99 latency mọi request khớp rule- Vì sao webhook nằm trên đường ghi nóng: mỗi CREATE/UPDATE khớp rule phải chờ một round-trip HTTP
- Anti-pattern chí mạng: webhook bắt
kube-system, webhook tự validate chính nó (deadlock),failurePolicy: Failkhông cónamespaceSelectorloại trừ - Chiến lược ổn định: HA webhook server, loại trừ namespace hệ thống, caching, latency budget, fail-open cho path không-bảo-mật-tới-hạn
4. Webhook Certificate Management — CA Bundle & cert-manager
Vì sao webhook "tự nhiên hỏng" sau vài tháng.
- Webhook là HTTPS server: serving cert phải hợp lệ cho
<service>.<namespace>.svc caBundletrong clientConfig: API server dùng nó để verify; cert hết hạn = webhook chết = (nếu Fail) cluster chết- cert-manager:
Certificate+CA Injectortự bơmcaBundlevào WebhookConfiguration - Rotation không downtime, self-signed CA nội bộ vs CA tổ chức, các lỗi
x509thường gặp
5. PodSecurity Admission (PSA) — Modes & Profiles
Cơ chế bảo mật Pod tích hợp sẵn, thay thế PodSecurityPolicy.
- Ba mode:
enforce(chặn),audit(ghi log),warn(cảnh báo người dùng) — cấu hình bằng label namespace - Version pinning:
pod-security.kubernetes.io/enforce-versionđể cố định ngữ nghĩa qua các bản nâng cấp - Ba profile:
privileged/baseline/restricted— từng control chi tiết (host namespaces, privileged, capabilities, hostPath, runAsNonRoot, seccompProfile, drop ALL) - Enforce chỉ áp lên Pod object, audit/warn áp lên cả workload resource — vì sao điều này quan trọng khi rollout
- Exemptions (username/runtimeClass/namespace), giới hạn của PSA và khi nào cần Gatekeeper
6. Gatekeeper / Policy Controller (OPA) — ConstraintTemplate & Constraint
Policy engine khả lập trình khi PSA không đủ.
- Kiến trúc Gatekeeper: webhook + audit controller; OPA/Rego bên dưới
ConstraintTemplate(định nghĩa logic + schema tham số) →Constraint(instance áp dụng giá trị cụ thể)enforcementAction: deny/dryrun/warn; audit loop định kỳ (--audit-interval, mặc định 60s) phát hiện vi phạm tồn tại sẵn- Referential constraints (cross-object, ví dụ ingress host trùng nhau) và
Configsync; constraint template library, policy bundles (PCI-DSS, NIST, CIS) - Policy Controller trên GKE: Gatekeeper được Google đóng gói, tích hợp Config Sync/fleet, dashboard
- Gatekeeper vs PSA: ma trận quyết định khi nào dùng cái nào, dùng cả hai theo lớp
7. ResourceQuota & LimitRange — Quản Trị Tài Nguyên Namespace
Hai admission plugin chống một tenant nuốt cả cluster.
ResourceQuota: compute (requests.cpu/limits.memory...), storage (theo StorageClass), object count (pods,services,count/<resource>)- Scoped quota:
scopeSelectortheoPriorityClass,Terminating/BestEffort— vì sao quota theo priority là nền cho multi-tenancy - Quy tắc bắt buộc: khi có quota CPU/memory thì mọi Pod phải khai báo requests/limits, nếu không bị từ chối
LimitRange:default/defaultRequest(tự điền),min/max,maxLimitRequestRatio— vì sao LimitRange là cặp bài trùng giải cứu ResourceQuota- Thứ tự tương tác: LimitRanger (mutating) điền default → ResourceQuota (validating) kiểm tra tổng
8. ValidatingAdmissionPolicy (CEL) — Policy In-Process Không Cần Webhook
Hướng đi mới: policy chạy trong API server, không round-trip HTTP.
ValidatingAdmissionPolicy(GA Kubernetes 1.30) +ValidatingAdmissionPolicyBinding+paramRef- CEL: biến
object,oldObject,request,params,namespaceObject;matchConstraints,matchConditions,variables validationActions: Deny/Warn/Audit(Deny và Warn không dùng chung),failurePolicy- Vì sao CEL policy loại bỏ phần lớn failure mode của webhook (không có cert, không có service chết, không round-trip) — nhưng kém biểu cảm hơn Rego
MutatingAdmissionPolicy(mới hơn) cho mutation bằng CEL; ma trận chọn giữa webhook / Gatekeeper / CEL policy
9. Organization Policies for GKE & Admission Debugging
Guardrail tầng GCP và cách gỡ lỗi admission.
- Organization Policy cho GKE: managed constraints + custom constraints với CEL trên
container.googleapis.com/ClustervàNodePool - Khác biệt then chốt: Org Policy chặn ở GCP API layer (cấu hình cluster: bật Autopilot, release channel, private nodes) — không phải Kubernetes admission (cấu hình Pod). Hai lớp khác nhau, bổ trợ nhau
- Ví dụ custom constraint: bắt buộc private nodes, cấm Autopilot tắt, ràng node service account
- Debugging admission: audit log (
Policy Denied), dry-run (kubectl --dry-run=server), đọc log webhook và Gatekeeper, metricapiserver_admission_*
Bản đồ tinh thần: pipeline admission từ trái sang phải
Trước khi đi vào từng file, hãy ghim sơ đồ tuần tự này. Một request ghi đi qua đúng thứ tự sau bên trong API server (Admission Controllers Reference):
kubectl apply
│
▼
[Authentication] → bạn là ai
│
▼
[Authorization / RBAC] → bạn được làm gì với loại tài nguyên này
│
▼
┌─────────────────────── ADMISSION ───────────────────────┐
│ 1. MUTATING PHASE (sửa được object) │
│ • Built-in mutating: ServiceAccount, LimitRanger... │
│ • MutatingAdmissionWebhook (của bạn) │
│ └─ reinvocation nếu webhook sau sửa object │
│ 2. Object schema validation │
│ 3. VALIDATING PHASE (chỉ đọc, từ chối được) │
│ • Built-in validating: ResourceQuota, PodSecurity... │
│ • ValidatingAdmissionPolicy (CEL, in-process) │
│ • ValidatingAdmissionWebhook (của bạn) │
└──────────────────────────────────────────────────────────┘
│
▼
[Ghi vào etcd]Ba quan sát quyết định mọi thứ trong chương:
Mutating chạy trước validating, luôn luôn. Hệ quả: validating webhook và PSA luôn thấy object đã được mutate (ví dụ sidecar đã được inject, default request đã được LimitRanger điền). Khi debug "vì sao policy chặn object của tôi", phải nhớ object lúc validating khác object lúc bạn
apply.Webhook nằm trên đường ghi nóng (hot write path). Mỗi CREATE/UPDATE khớp rule là một round-trip HTTP đồng bộ. Webhook chậm/chết không chỉ ảnh hưởng object của bạn — nó làm chậm hoặc chặn mọi request khớp rule trên toàn cluster. Đây là gốc của file 3.
Có ba "engine" enforcement song song: webhook (linh hoạt, ngoài process, nhiều failure mode), Gatekeeper (Rego, mạnh nhưng nặng), và CEL policy (in-process, ít failure mode, kém biểu cảm hơn). Phần lớn quyết định kiến trúc của chương là chọn engine nào cho loại policy nào.
Cách đọc chapter theo mục tiêu công việc
Nếu bạn đang điều tra "cluster không tạo được Pod / mọi apply bị treo"
- File 3: gần như chắc chắn là webhook
failurePolicy: Failtrỏ tới service chết, hoặc bắt nhầmkube-system. - File 4: hoặc cert webhook hết hạn → API server không verify được → timeout → (nếu Fail) chặn.
- File 9: dùng audit log và
kubectl --dry-run=serverđể xác định webhook/policy nào đang từ chối.
Nếu bạn đang thiết kế hardening bảo mật cho cluster mới
- File 5: bật PSA
restricted(audit/warn trước, enforce sau) cho mọi namespace ứng dụng. - File 6: thêm Gatekeeper/Policy Controller cho policy mà PSA không biểu đạt được (image registry, label bắt buộc, ràng buộc tham chiếu).
- File 9: dùng Organization Policy chặn ở tầng cluster (private nodes, release channel) — guardrail không thể bị bỏ qua từ trong cluster.
Nếu bạn đang xây multi-tenancy / chia hạn ngạch theo team
- File 7: ResourceQuota theo namespace + scoped quota theo PriorityClass; LimitRange điền default để quota không từ chối Pod thiếu request.
- File 5: PSA theo namespace để mỗi tenant bị giới hạn quyền Pod.
- File 6/8: policy bắt buộc label
team/cost-centerđể quy trách nhiệm và tính chi phí.
Nếu bạn đang chọn cơ chế enforcement cho một policy mới
- File 8: nếu policy biểu đạt được bằng CEL đơn giản (so sánh field, regex label) → ValidatingAdmissionPolicy, ít failure mode nhất.
- File 6: nếu cần logic phức tạp, cross-object, hoặc thư viện policy chuẩn (CIS/PCI) → Gatekeeper.
- File 2/3: chỉ dùng webhook tự viết khi cần mutation phức tạp hoặc gọi hệ thống ngoài — và chấp nhận gánh nặng vận hành cert + HA.
Khung quyết định production (tóm tắt)
| Quyết định | Tác động chính | Rủi ro nếu làm sai | File nên đọc |
|---|---|---|---|
failurePolicy Fail hay Ignore | Security vs availability | Fail + service chết → outage toàn cluster | 3 |
Loại trừ kube-system khỏi webhook | Tránh deadlock control plane | Không loại trừ → không khôi phục được | 3 |
| Quản lý cert webhook | Webhook sống được dài hạn | Cert hết hạn → webhook chết âm thầm | 4 |
| PSA level (baseline/restricted) | Mức hardening Pod | Restricted ngay → vỡ hàng loạt workload cũ | 5 |
| PSA enforce ngay hay audit trước | An toàn rollout | Enforce ngay không audit → từ chối Pod hợp lệ | 5 |
| Webhook / Gatekeeper / CEL policy | Engine enforcement | Chọn webhook cho policy đơn giản → gánh nặng vô ích | 2, 6, 8 |
| ResourceQuota + LimitRange | Công bằng tài nguyên | Quota không kèm LimitRange → Pod thiếu request bị từ chối | 7 |
| Org Policy tầng GKE | Guardrail không bỏ qua được | Thiếu → cluster sai cấu hình lọt lưới | 9 |
Năm sai lầm xuyên suốt thường gặp ở cấp chương
failurePolicy: Failmà không loại trừ namespace hệ thống. Đây là nguyên nhân số một của outage liên quan admission. Khi webhook service chết (deploy lỗi, node mất, cert hết hạn), API server từ chối mọi request khớp rule — kể cả Pod cần để khôi phục webhook. Luôn loại trừkube-system(và các managed namespace của GKE) quanamespaceSelector, và cân nhắcIgnorecho policy không-bảo-mật-tới-hạn (file 3).- Coi mutating webhook là idempotent mà không thiết kế cho
reinvocation. VớireinvocationPolicy: IfNeeded, một mutating webhook có thể bị gọi nhiều lần nếu webhook khác sửa object sau nó. Webhook "luôn thêm một sidecar" sẽ thêm hai sidecar. Mọi mutation phải kiểm tra trạng thái hiện tại trước khi sửa (file 2). - Bật PSA
restrictedenforce thẳng trên cluster đang chạy. Workload cũ gần như chắc chắn vi phạm (runAsNonRoot, drop ALL capabilities). Phảiwarn+audittrước, sửa workload, rồi mớienforce. Và phải pin version để bản nâng cấp Kubernetes không âm thầm siết thêm control (file 5). - Dùng webhook cho mọi thứ thay vì chọn đúng engine. Webhook có cert để hết hạn, service để chết, round-trip để timeout. Phần lớn policy "field này phải bằng giá trị kia" nên là ValidatingAdmissionPolicy (CEL, in-process, không cert, không round-trip). Webhook chỉ dành cho mutation phức tạp hoặc tích hợp ngoài (file 8 vs 2).
- Đặt ResourceQuota mà quên LimitRange. Khi namespace có quota CPU/memory, mọi Pod buộc phải khai báo requests/limits — Pod thiếu sẽ bị từ chối thẳng. LimitRange tự điền
defaultRequest/defaultđể Pod hợp lệ. Quên LimitRange = developer liên tục bị từ chối Pod mà không hiểu vì sao (file 7).
Cross-reference với Google Cloud Architecture Framework
- Security pillar: admission control là cơ chế "shift-left" cốt lõi — chặn cấu hình không an toàn tại thời điểm tạo, không phải phát hiện sau khi chạy (Security pillar). PSA, Gatekeeper, Binary Authorization (Chương 34) là các lớp bổ trợ.
- Reliability pillar: nghịch lý là cơ chế security này lại là rủi ro reliability lớn nhất nếu cấu hình sai. Latency budget của webhook,
failurePolicy, và loại trừ namespace hệ thống là quyết định reliability (Reliability pillar). - Operational excellence: dùng dry-run/audit trước enforce, version pinning cho PSA, và GitOps (Config Sync) cho policy là các thực hành vận hành chuẩn (Operational excellence pillar).
References chung của chapter
- Kubernetes — Admission Controllers Reference
- Kubernetes — Dynamic Admission Control
- Kubernetes — Pod Security Admission
- Kubernetes — Pod Security Standards
- Kubernetes — ValidatingAdmissionPolicy
- Kubernetes — Resource Quotas
- Kubernetes — Limit Ranges
- GKE — Policy Controller overview
- GKE — Restrict actions on GKE resources using custom organization policies
- Open Policy Agent Gatekeeper
Bảng thuật ngữ then chốt của chương
| Thuật ngữ | Ý nghĩa ngắn gọn |
|---|---|
| Mutating phase | Pha admission đầu, sửa được object (file 1, 2) |
| Validating phase | Pha admission sau, chỉ đọc và từ chối (file 1) |
| reinvocationPolicy | Cờ cho phép gọi lại mutating webhook sau khi object bị sửa (file 2) |
| failurePolicy | Hành vi khi webhook lỗi: Fail (chặn) hay Ignore (cho qua) (file 3) |
| sideEffects | Khai báo webhook có tác dụng phụ không, ảnh hưởng dry-run (file 2) |
| caBundle | CA để API server verify cert webhook (file 4) |
| PSA | PodSecurity Admission — bảo mật Pod tích hợp sẵn (file 5) |
| ConstraintTemplate / Constraint | Cặp định nghĩa-logic / instance-áp-dụng của Gatekeeper (file 6) |
| enforcementAction | deny/dryrun/warn của constraint Gatekeeper (file 6) |
| scopeSelector | Bộ lọc Pod cho ResourceQuota theo PriorityClass/Terminating (file 7) |
| maxLimitRequestRatio | Giới hạn tỷ lệ limit/request trong LimitRange (file 7) |
| ValidatingAdmissionPolicy | Policy CEL in-process, không cần webhook (file 8) |
| Custom org policy constraint | CEL chặn ở tầng GCP API trên cấu hình cluster (file 9) |
Kết luận của chapter
Admission control là nơi security và reliability gặp nhau ở thế đối nghịch trực tiếp: cơ chế mạnh nhất để bảo vệ cluster cũng là cơ chế dễ làm sập cluster nhất. Mọi quyết định trong chương đều là một điểm cân bằng giữa hai cực này — Fail hay Ignore, enforce ngay hay audit trước, webhook ngoài-process hay CEL in-process. Người vận hành giỏi không phải người bật nhiều policy nhất, mà là người hiểu chính xác mỗi mắt xích trong pipeline làm gì, chạy ở đâu, hỏng thế nào, và do đó biết đặt enforcement ở đúng tầng với đúng engine.
Cách dùng chương hiệu quả nhất là biến nó thành một quy trình rollout policy có kỷ luật: bắt đầu bằng dry-run/audit để đo tác động, chọn engine nhẹ nhất biểu đạt được policy (CEL trước webhook), luôn loại trừ namespace hệ thống, luôn quản lý vòng đời cert, và luôn có đường thoát (break-glass) khi enforcement chặn nhầm. Khi đó admission control chuyển từ "quả bom hẹn giờ trong control plane" thành một hệ thống guardrail mà bạn có thể tin tưởng giao phó cả cluster.