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
OPA Gatekeeper ต่างจาก OPA ปกติอย่างไร
OPA เป็น General-purpose Policy Engine ใช้ได้กับทุกระบบ Gatekeeper เป็น OPA ที่ออกแบบเฉพาะสำหรับ Kubernetes ใช้ CRD แทน Config File มี Audit Controller สแกน Resource ที่มีอยู่แล้ว และ Integrate กับ Admission Webhook โดยตรง จัดการ Policy ด้วย kubectl ได้
Constraint Template คืออะไร
Constraint Template เป็น CRD ที่กำหนด Policy Logic ด้วยภาษา Rego เช่น ห้ามรัน Privileged Container บังคับ Resource Limits จำกัด Image Registry จากนั้นสร้าง Constraint จาก Template เพื่อกำหนดว่าจะบังคับใช้กับ Namespace หรือ Resource ประเภทไหน
การติดตั้ง OPA Gatekeeper บน Kubernetes ทำอย่างไร
ใช้ kubectl apply จาก GitHub Release URL หรือ Helm Chart ติดตั้ง Gatekeeper จะสร้าง Namespace gatekeeper-system, Deploy Controller Manager, Audit Controller และ CRDs อัตโนมัติ ใช้เวลาไม่ถึง 5 นาที แนะนำใช้ Helm สำหรับ Production เพราะ Customize ค่าได้ง่ายกว่า
สรุปและแนวทางปฏิบัติ
OPA Gatekeeper เป็นเครื่องมือจำเป็นสำหรับ Kubernetes Cluster ที่ต้องการ Policy Enforcement แบบ Real-time ช่วยป้องกัน Misconfiguration ที่อาจนำไปสู่ Security Incident การเริ่มต้นที่ดีคือติดตั้ง Gatekeeper แล้วใช้ Constraint Templates จาก Gatekeeper Library ตั้งเป็น Dry Run ก่อน ดู Violations ที่พบ แก้ไข Resource ที่ไม่ผ่าน แล้วค่อยเปลี่ยนเป็น Deny เก็บ Policy ใน Git ใช้ GitOps Deploy และ Monitor Webhook Latency เพื่อให้แน่ใจว่า Gatekeeper ไม่กระทบ Performance ของ Cluster
