SiamCafe · Blog
OPA Gatekeeper กับ Real-time Processing —
บทความ

OPA Gatekeeper กับ Real-time Processing —

เผยแพร่ 28 พฤษภาคม 2569

OPA Gatekeeper คืออะไร

OPA Gatekeeper เป็น Policy Engine สำหรับ Kubernetes ที่ทำงานเป็น Admission Controller คอยตรวจสอบทุก Request ที่เข้ามายัง Kubernetes API Server ว่าเป็นไปตาม Policy ที่กำหนดหรือไม่ ถ้า Request ไม่ผ่าน Policy จะถูก Reject ทันทีก่อนที่ Resource จะถูกสร้างบน Cluster

Gatekeeper ใช้ Open Policy Agent (OPA) เป็น Policy Engine ภายใน และใช้ภาษา Rego สำหรับเขียน Policy Logic จุดเด่นคือใช้ Kubernetes CRD (Custom Resource Definition) ในการกำหนด Policy ทำให้จัดการ Policy ด้วย kubectl ได้เลย ไม่ต้องแก้ Config File บน Server

Use Case หลักของ Gatekeeper คือ Security Policy Enforcement เช่น ห้ามรัน Container เป็น Root, บังคับให้มี Resource Limits, ห้ามใช้ Image จาก Registry ที่ไม่ได้รับอนุญาต, บังคับให้มี Labels ที่จำเป็น และตรวจสอบ Network Policy

การติดตั้ง OPA Gatekeeper

# วิธีที่ 1: ติดตั้งด้วย kubectl
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.15.0/deploy/gatekeeper.yaml

# ตรวจสอบการติดตั้ง
kubectl get pods -n gatekeeper-system
# NAME                                            READY   STATUS    RESTARTS   AGE
# gatekeeper-audit-7c84869dbf-rg9kq               1/1     Running   0          60s
# gatekeeper-controller-manager-6bcc7f8fb5-2j4hk   1/1     Running   0          60s
# gatekeeper-controller-manager-6bcc7f8fb5-9xbtl   1/1     Running   0          60s

# วิธีที่ 2: ติดตั้งด้วย Helm
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper/gatekeeper \
  --name-template=gatekeeper \
  --namespace gatekeeper-system \
  --create-namespace \
  --set audit.replicas=1 \
  --set controllerManager.replicas=3 \
  --set audit.logLevel=INFO \
  --set constraintViolationsLimit=50

# ตรวจสอบ CRDs ที่ถูกสร้าง
kubectl get crd | grep gatekeeper
# assign.mutations.gatekeeper.sh
# assignmetadata.mutations.gatekeeper.sh
# configs.config.gatekeeper.sh
# constraintpodstatuses.status.gatekeeper.sh
# constrainttemplatepodstatuses.status.gatekeeper.sh
# constrainttemplates.templates.gatekeeper.sh
# expansiontemplate.expansion.gatekeeper.sh
# modifyset.mutations.gatekeeper.sh
# providers.externaldata.gatekeeper.sh

# ตรวจสอบ Webhook
kubectl get validatingwebhookconfigurations
# NAME                          WEBHOOKS   AGE
# gatekeeper-validating-webhook-configuration   2    2m

เขียน Constraint Templates

# 1. ห้ามรัน Container เป็น Root
# constraint-template-no-root.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8spspprivilegedcontainer
spec:
  crd:
    spec:
      names:
        kind: K8sPSPPrivilegedContainer
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8spspprivilegedcontainer

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.privileged == true
          msg := sprintf("Container '%v' ห้ามรันแบบ Privileged", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.runAsUser == 0
          msg := sprintf("Container '%v' ห้ามรันเป็น Root (UID 0)", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          container.securityContext.privileged == true
          msg := sprintf("InitContainer '%v' ห้ามรันแบบ Privileged", [container.name])
        }
---
# บังคับใช้กับทุก Namespace ยกเว้น kube-system
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
  name: no-privileged-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces:
      - kube-system
      - gatekeeper-system
  enforcementAction: deny

---
# 2. บังคับให้มี Resource Limits
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredresources
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredResources
      validation:
        openAPIV3Schema:
          type: object
          properties:
            limits:
              type: array
              items:
                type: string
            requests:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredresources

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          required := input.parameters.limits[_]
          not container.resources.limits[required]
          msg := sprintf("Container '%v' ต้องกำหนด resource limit: %v", [container.name, required])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          required := input.parameters.requests[_]
          not container.resources.requests[required]
          msg := sprintf("Container '%v' ต้องกำหนด resource request: %v", [container.name, required])
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
  name: must-have-resource-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces:
      - kube-system
  parameters:
    limits:
      - cpu
      - memory
    requests:
      - cpu
      - memory

---
# 3. ห้ามใช้ Image จาก Registry ที่ไม่ได้รับอนุญาต
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sallowedrepos
spec:
  crd:
    spec:
      names:
        kind: K8sAllowedRepos
      validation:
        openAPIV3Schema:
          type: object
          properties:
            repos:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sallowedrepos

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not startswith_any(container.image, input.parameters.repos)
          msg := sprintf("Container '%v' ใช้ Image '%v' จาก Registry ที่ไม่ได้รับอนุญาต อนุญาตเฉพาะ: %v", [container.name, container.image, input.parameters.repos])
        }

        startswith_any(str, prefixes) {
          prefix := prefixes[_]
          startswith(str, prefix)
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: allowed-repos
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - production
      - staging
  parameters:
    repos:
      - "gcr.io/company-project/"
      - "ghcr.io/company/"
      - "registry.company.com/"

Audit Mode และ Dry Run

Gatekeeper มี Audit Controller ที่สแกน Resource ที่มีอยู่แล้วบน Cluster เพื่อตรวจหา Policy Violations ไม่ใช่แค่ตรวจตอนสร้างใหม่เท่านั้น

# ตรวจสอบ Violations ทั้งหมด
kubectl get constraints
# NAME                          ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
# no-privileged-containers      deny                 3
# must-have-resource-limits     deny                 12
# allowed-repos                 deny                 5

# ดูรายละเอียด Violations
kubectl describe k8srequiredresources must-have-resource-limits
# Status:
#   Violations:
#     - enforcementAction: deny
#       kind: Pod
#       message: Container 'nginx' ต้องกำหนด resource limit: cpu
#       name: nginx-deployment-abc123
#       namespace: default

# ตั้งเป็น Dry Run (แจ้งเตือนแต่ไม่ Block)
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
  name: must-have-resource-limits-dryrun
spec:
  enforcementAction: dryrun  # dryrun = แจ้งเตือนเท่านั้น, deny = Block
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    limits: ["cpu", "memory"]
    requests: ["cpu", "memory"]

# ทดสอบ Policy ด้วย gator CLI
# gator test -f policy/ -f testdata/
# gator verify -f policy/

Real-time Monitoring และ Alerting

# Prometheus ServiceMonitor สำหรับ Gatekeeper Metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: gatekeeper-metrics
  namespace: gatekeeper-system
spec:
  selector:
    matchLabels:
      gatekeeper.sh/system: "yes"
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics

---
# Grafana Dashboard Query ตัวอย่าง
# Total Violations
# gatekeeper_violations{enforcement_action="deny"}

# Admission Request Duration
# histogram_quantile(0.95, rate(gatekeeper_request_duration_seconds_bucket[5m]))

# Admission Request Count by Action
# sum(rate(gatekeeper_request_count_total[5m])) by (admission_status)

---
# Alert Rules
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: gatekeeper-alerts
  namespace: gatekeeper-system
spec:
  groups:
    - name: gatekeeper
      rules:
        - alert: GatekeeperHighViolations
          expr: gatekeeper_violations > 20
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Gatekeeper พบ Violations มากกว่า 20 รายการ"

        - alert: GatekeeperWebhookErrors
          expr: rate(gatekeeper_request_count_total{admission_status="error"}[5m]) > 0.1
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "Gatekeeper Webhook มี Error Rate สูง"

        - alert: GatekeeperDown
          expr: up{job="gatekeeper-controller-manager"} == 0
          for: 1m
          labels:
            severity: critical
          annotations:
            summary: "Gatekeeper Controller Manager ไม่ทำงาน"

Best Practices สำหรับ OPA Gatekeeper

  • เริ่มจาก Dry Run: ตั้ง enforcementAction เป็น dryrun ก่อนเสมอเพื่อดูผลกระทบก่อนบังคับใช้จริง
  • Exclude System Namespaces: ยกเว้น kube-system, gatekeeper-system และ Namespace ของ Infrastructure Components เพื่อป้องกันปัญหา
  • ใช้ Gatekeeper Library: ใช้ Constraint Templates จาก Gatekeeper Library (github.com/open-policy-agent/gatekeeper-library) แทนการเขียนเอง
  • Test Policies: ใช้ gator CLI ทดสอบ Policy ก่อน Deploy ทุกครั้ง เขียน Unit Test สำหรับ Rego
  • Version Control: เก็บ Constraint Templates และ Constraints ใน Git ใช้ GitOps (ArgoCD/Flux) สำหรับ Deploy
  • Monitor Performance: ติดตาม Admission Webhook Latency เพราะ Gatekeeper เพิ่ม Latency ให้ทุก API Request
  • Gradual Rollout: เริ่มบังคับใช้ Policy ทีละ Namespace ไม่ใช่ทั้ง Cluster พร้อมกัน

OPA Gatekeeper คืออะไร

OPA Gatekeeper เป็น Kubernetes Admission Controller ที่ใช้ Open Policy Agent ตรวจสอบ Resource ที่ถูกสร้างหรือแก้ไขบน Kubernetes ว่าเป็นไปตาม Policy หรือไม่ ถ้าไม่ผ่านจะ Reject Request ทันที ช่วยบังคับใช้ Security, Compliance และ Governance Policy บน Cluster