Chuyển đến nội dung chính

BÀI 24: VALIDATINGADMISSIONPOLICY — GA K8S 1.30

ValidatingAdmissionPolicy GA từ K8s 1.30 — viết policy bằng CEL (Common Expression Language) không cần deploy webhook server. So sánh với OPA/Gatekeeper. Patterns: chặn latest tag, enforce labels, validate resource limits.

🔒 DevSecOps — Bài 24 BÀI 24: VALIDATINGADMISSIONPOLICY — GA K8S 1.30

KUBERNETES: TỪ CƠ BẢN ĐẾN NÂNG CAO

Module 6: Security

xdev.asia

🎯 Mục tiêu bài học

Hiểu ValidatingAdmissionPolicy GA K8s 1.30, viết CEL policies không cần webhook server, và biết khi nào vẫn cần OPA/Gatekeeper.

1. Vấn đề với Admission Webhooks Truyền thống

Webhook-based admission (OPA/Gatekeeper, Kyverno) có nhược điểm:

  • Network overhead: mỗi API request cần gọi HTTP đến webhook service
  • Availability dependency: nếu webhook service down → API requests fail
  • Operational burden: phải maintain webhook deployment, TLS certs
  • Latency: thêm latency cho mọi API call

2. ValidatingAdmissionPolicy — Built-in, No Webhook

ValidatingAdmissionPolicy GA từ K8s 1.30 cho phép viết validation policies trực tiếp trong API server, dùng CEL (Common Expression Language).

  • Chạy trong API server process — zero network overhead
  • Không cần deploy thêm service
  • Không có single point of failure
  • Nhanh hơn webhook ~10x

3. CEL Basics

CEL là một expression language đơn giản, an toàn (không có loops, không có side effects).

# Truy cập object fields
object.spec.replicas < 10

Check field exists

has(object.spec.template.spec.containers)

Array operations

object.spec.template.spec.containers.all(c, has(c.resources) && has(c.resources.limits) )

String operations

!object.spec.template.spec.containers.exists(c, c.image.endsWith(":latest") )

Comparison với quantities

object.spec.template.spec.containers.all(c, c.resources.limits.memory <= resource.Quantity("2Gi") )

4. ValidatingAdmissionPolicy Structure

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: my-policy
spec:
  failurePolicy: Fail    # Fail hoặc Ignore nếu policy error
  matchConstraints:      # áp dụng cho objects nào
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments"]
  validations:           # danh sách expressions
  - expression: "object.spec.replicas <= 10"
    message: "Deployment không được có quá 10 replicas"
    reason: Invalid
  - expression: "has(object.metadata.labels) && has(object.metadata.labels.team)"
    message: "Deployment phải có label 'team'"

5. ValidatingAdmissionPolicyBinding

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: my-policy-binding
spec:
  policyName: my-policy  # reference đến ValidatingAdmissionPolicy
  validationActions:
  - Deny          # reject request nếu vi phạm
  # - Audit       # log nhưng không reject
  # - Warn        # warning nhưng không reject
  matchResources:
    namespaceSelector:
      matchLabels:
        environment: production   # chỉ apply trong production namespaces

6. Common Policies

6.1 Chặn Image với Tag "latest"

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: no-latest-tag
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments", "statefulsets", "daemonsets"]
  validations:
  - expression: |
      object.spec.template.spec.containers.all(c,
        !c.image.contains(":latest") &&
        c.image.contains(":")
      )
    message: "Images phải có specific tag, không được dùng :latest hoặc không có tag"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: no-latest-tag-binding
spec:
  policyName: no-latest-tag
  validationActions: [Deny]

6.2 Yêu cầu Resource Limits

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: require-resource-limits
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments"]
  validations:
  - expression: |
      object.spec.template.spec.containers.all(c,
        has(c.resources) &&
        has(c.resources.limits) &&
        has(c.resources.limits.cpu) &&
        has(c.resources.limits.memory)
      )
    message: "Tất cả containers phải có resource limits (CPU và Memory)"
  - expression: |
      object.spec.template.spec.initContainers.all(c,
        has(c.resources) &&
        has(c.resources.limits) &&
        has(c.resources.limits.cpu) &&
        has(c.resources.limits.memory)
      )
    message: "Tất cả init containers phải có resource limits"

6.3 Require Labels

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: require-labels
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE"]
      resources: ["deployments"]
  validations:
  - expression: "has(object.metadata.labels.team)"
    message: "Deployment phải có label 'team'"
  - expression: "has(object.metadata.labels.app)"
    message: "Deployment phải có label 'app'"
  - expression: |
      object.metadata.labels.environment in ["dev", "staging", "production"]
    message: "Label 'environment' phải là: dev, staging, hoặc production"

6.4 Limit Replicas

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: limit-replicas
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments"]
  validations:
  - expression: "object.spec.replicas <= 20"
    message: "Deployment không được có quá 20 replicas"
  - expression: "object.spec.replicas >= 1"
    message: "Deployment phải có ít nhất 1 replica"

6.5 Prevent Privilege Escalation

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: no-privileged
spec:
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["pods"]
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments", "statefulsets", "daemonsets"]
  validations:
  - expression: |
      !object.spec.template.spec.containers.exists(c,
        has(c.securityContext) &&
        has(c.securityContext.privileged) &&
        c.securityContext.privileged == true
      )
    message: "Privileged containers không được phép"
  - expression: |
      !object.spec.template.spec.containers.exists(c,
        has(c.securityContext) &&
        has(c.securityContext.allowPrivilegeEscalation) &&
        c.securityContext.allowPrivilegeEscalation == true
      )
    message: "allowPrivilegeEscalation phải là false"

7. Policy với Parameters

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: max-replicas-param
spec:
  paramKind:
    apiVersion: v1
    kind: ConfigMap
  matchConstraints:
    resourceRules:
    - apiGroups: ["apps"]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["deployments"]
  validations:
  - expression: "object.spec.replicas <= int(params.data.maxReplicas)"
    message: "Vượt quá số replicas tối đa"
---
# Parameter ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: max-replicas-config
data:
  maxReplicas: "5"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: max-replicas-binding
spec:
  policyName: max-replicas-param
  paramRef:
    name: max-replicas-config
    namespace: default
  validationActions: [Deny]

8. So sánh: ValidatingAdmissionPolicy vs OPA/Gatekeeper

Feature              ValidatingAdmissionPolicy    OPA/Gatekeeper
────────────────────────────────────────────────────────────────
Deploy required      ❌ Built-in                  ✅ Yes (webhook)
Language             CEL                          Rego
Mutating policies    ❌ No                        ✅ Yes
Complex logic        Limited                      Full Rego
Performance          Excellent (in-process)        Good (HTTP call)
Vendor support       Kubernetes core              CNCF project
K8s version          1.30+ (GA)                  Any

Vẫn cần OPA/Gatekeeper khi: cần mutating policies (tự động inject fields), policy logic phức tạp hơn CEL support, hoặc cần mutation webhooks.

Tóm tắt

  • ValidatingAdmissionPolicy GA K8s 1.30: built-in, không cần webhook
  • CEL: safe expression language cho policy logic
  • Cần binding để activate: ValidatingAdmissionPolicyBinding
  • Actions: Deny, Audit, Warn
  • Dùng params (ConfigMap) để policy reusable
  • OPA/Gatekeeper: vẫn cần cho mutating và complex rego logic