ใน Kubernetes Cluster ที่มีทีมหลายทีมทำงานร่วมกัน คำถามสำคัญคือ จะทำอย่างไรให้ทุกทีมปฏิบัติตามกฎที่กำหนดไว้ เช่น ทุก Pod ต้องมี Resource Limits ห้ามใช้ latest tag ห้ามรัน Container ด้วย Root และต้องมี Label ที่จำเป็นครบถ้วน การพึ่งพาเอกสารหรือ Code Review อย่างเดียวไม่เพียงพอ เพราะมนุษย์ผิดพลาดได้เสมอ
Admission Controllers คือด่านรักษาความปลอดภัยของ Kubernetes ที่ตรวจสอบและบังคับใช้ Policy กับทุก Request ที่เข้ามาใน Cluster ก่อนที่ Resource จะถูกสร้างจริง ในปี 2026 เครื่องมืออย่าง Kyverno และ OPA Gatekeeper ได้กลายเป็นมาตรฐานที่ทุก Cluster ควรมี บทความนี้จะพาคุณเข้าใจตั้งแต่พื้นฐานจนถึงการเขียน Policy จริง
Admission Controllers คืออะไร?
Admission Controller คือ Plugin ที่ทำงานใน Kubernetes API Server ทำหน้าที่ดัก Request ที่เข้ามา (เช่น สร้าง Pod, สร้าง Deployment) แล้วตรวจสอบหรือแก้ไข Request นั้นก่อนที่จะบันทึกลง etcd
Flow ของ Request ใน Kubernetes API Server:
# Request Flow ผ่าน Admission Controllers
#
# kubectl apply → API Server
# │
# ┌──────────▼──────────┐
# │ Authentication │ ← ยืนยันตัวตน (who?)
# └──────────┬──────────┘
# ┌──────────▼──────────┐
# │ Authorization │ ← ตรวจสิทธิ์ (can they?)
# └──────────┬──────────┘
# ┌──────────▼──────────┐
# │ Mutating Admission │ ← แก้ไข Request (modify)
# │ Controllers │
# └──────────┬──────────┘
# ┌──────────▼──────────┐
# │ Object Schema │ ← ตรวจ Schema
# │ Validation │
# └──────────┬──────────┘
# ┌──────────▼──────────┐
# │ Validating Admission│ ← ตรวจสอบ Policy (allow/deny)
# │ Controllers │
# └──────────┬──────────┘
# │
# ┌─────▼─────┐
# │ etcd │ ← บันทึกข้อมูล
# └───────────┘
Mutating vs Validating Admission Controllers
| ประเภท | หน้าที่ | ตัวอย่าง |
|---|---|---|
| Mutating | แก้ไข/เพิ่มเติม Request ก่อนบันทึก | เพิ่ม Default Labels, Inject Sidecar, ตั้ง Default Resource Limits |
| Validating | ตรวจสอบ Request ว่าผ่านกฎหรือไม่ (Allow/Deny) | ห้ามใช้ latest tag, ต้องมี Resource Limits, ห้าม Privileged |
Mutating จะทำงานก่อน Validating เสมอ เพราะ Mutating อาจเปลี่ยนแปลง Request ซึ่ง Validating จะต้องตรวจสอบ Request ที่ถูกแก้ไขแล้ว
Built-in Admission Controllers
Kubernetes มี Admission Controllers ที่ Built-in มาให้หลายตัว บางตัวเปิดใช้งานโดย Default:
| Controller | ประเภท | หน้าที่ |
|---|---|---|
NamespaceLifecycle | Validating | ป้องกันการสร้าง Resource ใน Namespace ที่กำลังถูกลบ |
LimitRanger | Mutating | ตั้ง Default Resource Limits ตาม LimitRange ที่กำหนด |
ResourceQuota | Validating | ตรวจสอบว่า Resource ไม่เกิน Quota ที่กำหนดใน Namespace |
PodSecurity | Validating | บังคับใช้ Pod Security Standards (แทน PodSecurityPolicy ที่ถูกยกเลิก) |
DefaultStorageClass | Mutating | เพิ่ม Default Storage Class ให้ PVC ที่ไม่ได้ระบุ |
MutatingAdmissionWebhook | Mutating | เรียก External Webhook สำหรับ Mutation |
ValidatingAdmissionWebhook | Validating | เรียก External Webhook สำหรับ Validation |
Pod Security Admission (PSA)
ตั้งแต่ Kubernetes 1.25 PodSecurityPolicy (PSP) ถูกยกเลิกไปแล้ว แทนที่ด้วย Pod Security Admission ที่ใช้ Pod Security Standards สามระดับ:
# กำหนด Pod Security Level ให้ Namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
# enforce = บังคับ (deny ถ้าไม่ผ่าน)
pod-security.kubernetes.io/enforce: restricted
# warn = แจ้งเตือน (allow แต่แสดง warning)
pod-security.kubernetes.io/warn: restricted
# audit = บันทึก Log (allow และบันทึก)
pod-security.kubernetes.io/audit: restricted
# Levels:
# privileged — ไม่มีข้อจำกัด (default)
# baseline — ป้องกัน Known Privilege Escalation
# restricted — Best Practice ที่เข้มงวดที่สุด
Webhook Admission Controllers
Built-in Controllers มีข้อจำกัดด้านความยืดหยุ่น Kubernetes จึงรองรับ Webhook Admission Controllers ที่ให้คุณเขียน Logic เองผ่าน HTTPS Webhook ซึ่งเป็นพื้นฐานของเครื่องมืออย่าง Kyverno และ OPA Gatekeeper
# ตัวอย่าง ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: my-custom-validator
webhooks:
- name: validate.example.com
clientConfig:
service:
name: my-webhook-service
namespace: webhook-system
path: /validate
caBundle: LS0tLS1C... # CA Certificate
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
failurePolicy: Fail # Fail = deny ถ้า Webhook ไม่ตอบ
sideEffects: None
การเขียน Webhook เอง เป็นเรื่องที่ซับซ้อน ต้องจัดการ TLS Certificate, HTTP Server, JSON Patch สำหรับ Mutation และ Response Format ที่ถูกต้อง นี่คือเหตุผลที่ Kyverno และ OPA Gatekeeper ถูกสร้างขึ้น เพื่อให้เขียน Policy ได้ง่ายโดยไม่ต้อง Code Webhook เอง
OPA (Open Policy Agent) และ Rego
OPA (Open Policy Agent) เป็น General-purpose Policy Engine ที่ไม่ได้สร้างมาเฉพาะ Kubernetes แต่สามารถใช้ได้กับทุกอย่าง ตั้งแต่ API Authorization, Terraform, CI/CD ไปจนถึง Kubernetes OPA ใช้ภาษา Rego ในการเขียน Policy
Rego Language
# ตัวอย่าง Rego Policy: ห้าม Container ที่ไม่มี Resource Limits
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Pod"
container := input.request.object.spec.containers[_]
not container.resources.limits
msg := sprintf("Container '%v' ต้องมี resource limits", [container.name])
}
# ตรวจสอบว่ามี Label "app" หรือไม่
deny[msg] {
input.request.kind.kind == "Pod"
not input.request.object.metadata.labels.app
msg := "Pod ต้องมี label 'app'"
}
# ห้ามใช้ :latest tag
deny[msg] {
input.request.kind.kind == "Pod"
container := input.request.object.spec.containers[_]
endswith(container.image, ":latest")
msg := sprintf("Container '%v' ห้ามใช้ :latest tag", [container.name])
}
Rego เป็นภาษาที่มีลักษณะเฉพาะตัว (Declarative, Logic Programming) ซึ่งมี Learning Curve สูงสำหรับนักพัฒนาทั่วไป นี่คือเหตุผลที่หลายทีมเลือก Kyverno แทน
Gatekeeper — OPA สำหรับ Kubernetes
Gatekeeper เป็น Kubernetes-native wrapper ของ OPA ที่ทำให้การใช้ OPA กับ Kubernetes ง่ายขึ้น โดยใช้ CRD (Custom Resource Definition) แทนการ Config OPA โดยตรง
# ติดตั้ง Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/v3.15.0/deploy/gatekeeper.yaml
# Gatekeeper ใช้ 2 CRDs:
# 1. ConstraintTemplate — กำหนด "ประเภท" ของ Policy
# 2. Constraint — กำหนด "กฎ" จริงที่ใช้ Template นั้น
ตัวอย่าง: ห้ามใช้ latest tag
# Step 1: สร้าง ConstraintTemplate
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sdisallowedtags
spec:
crd:
spec:
names:
kind: K8sDisallowedTags
validation:
openAPIV3Schema:
type: object
properties:
tags:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdisallowedtags
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
tag := input.parameters.tags[_]
endswith(container.image, concat(":", ["", tag]))
msg := sprintf("Container '%v' ใช้ tag '%v' ซึ่งไม่อนุญาต", [container.name, tag])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not contains(container.image, ":")
msg := sprintf("Container '%v' ไม่ได้ระบุ tag (จะใช้ latest โดย default)", [container.name])
}
---
# Step 2: สร้าง Constraint (กฎจริง)
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowedTags
metadata:
name: no-latest-tag
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces: ["default", "production"]
parameters:
tags: ["latest"]
Kyverno — Policy Engine แบบ YAML-native
Kyverno (ภาษากรีก แปลว่า "govern") เป็น Kubernetes Policy Engine ที่ออกแบบมาเฉพาะสำหรับ Kubernetes ไม่ต้องเรียนรู้ภาษาใหม่ เขียน Policy ด้วย YAML ปกติ ซึ่งคุ้นเคยสำหรับทุกคนที่ทำงานกับ Kubernetes อยู่แล้ว
# ติดตั้ง Kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
# หรือใช้ kubectl
kubectl apply -f https://github.com/kyverno/kyverno/releases/download/v1.12.0/install.yaml
Kyverno Policy Types
Kyverno รองรับ Policy หลายประเภท:
- Validate — ตรวจสอบ Resource ว่าผ่านกฎหรือไม่ (Allow/Deny)
- Mutate — แก้ไข/เพิ่มเติม Resource อัตโนมัติ
- Generate — สร้าง Resource ใหม่อัตโนมัติเมื่อมี Trigger
- VerifyImages — ตรวจสอบ Container Image Signature
ตัวอย่าง Kyverno Policies
# Policy 1: บังคับให้มี Label "app" และ "team"
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce # Enforce = block, Audit = log only
rules:
- name: check-required-labels
match:
any:
- resources:
kinds:
- Pod
- Deployment
validate:
message: "ต้องมี label 'app' และ 'team'"
pattern:
metadata:
labels:
app: "?*"
team: "?*"
---
# Policy 2: ห้ามใช้ :latest tag
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: validate-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "ห้ามใช้ image tag 'latest' — ต้องระบุ version ที่ชัดเจน"
pattern:
spec:
containers:
- image: "!*:latest"
---
# Policy 3: บังคับ Resource Limits
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-resource-limits
match:
any:
- resources:
kinds:
- Pod
validate:
message: "ทุก Container ต้องมี resources.limits.cpu และ resources.limits.memory"
pattern:
spec:
containers:
- resources:
limits:
cpu: "?*"
memory: "?*"
---
# Policy 4: ห้าม Privileged Containers
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged
spec:
validationFailureAction: Enforce
rules:
- name: deny-privileged
match:
any:
- resources:
kinds:
- Pod
validate:
message: "ห้ามรัน Privileged Container ใน Cluster นี้"
deny:
conditions:
any:
- key: "{{ request.object.spec.containers[].securityContext.privileged }}"
operator: AnyIn
value: [true]
---
# Policy 5: Mutate — เพิ่ม Default Labels อัตโนมัติ
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-labels
spec:
rules:
- name: add-managed-by
match:
any:
- resources:
kinds:
- Pod
- Deployment
mutate:
patchStrategicMerge:
metadata:
labels:
managed-by: kyverno
environment: "{{ request.namespace }}"
---
# Policy 6: Generate — สร้าง NetworkPolicy อัตโนมัติเมื่อสร้าง Namespace
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-default-networkpolicy
spec:
rules:
- name: default-deny-ingress
match:
any:
- resources:
kinds:
- Namespace
generate:
synchronize: true
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny-ingress
namespace: "{{ request.object.metadata.name }}"
data:
spec:
podSelector: {}
policyTypes:
- Ingress
Kyverno vs Gatekeeper เปรียบเทียบ
| Feature | Kyverno | OPA Gatekeeper |
|---|---|---|
| ภาษา Policy | YAML (Native K8s) | Rego (DSL เฉพาะ) |
| Learning Curve | ต่ำ (รู้ YAML = เขียนได้) | สูง (ต้องเรียน Rego) |
| Mutating | รองรับ Native | รองรับ (ตั้งแต่ v3.10+) |
| Generate Resources | รองรับ | ไม่รองรับ |
| Image Verification | รองรับ (Sigstore/Cosign) | ต้องเขียนเอง |
| Ecosystem | K8s เท่านั้น | ใช้ OPA ได้กับทุกอย่าง |
| Policy Library | 200+ policies สำเร็จรูป | Gatekeeper Library |
| Testing | Kyverno CLI | OPA test + Gatekeeper test |
| CNCF Status | Graduated (2024) | Graduated |
Policy Testing
Testing Kyverno Policies
# ทดสอบ Policy ด้วย Kyverno CLI
# ติดตั้ง CLI
# brew install kyverno (Mac) หรือ download binary
# สร้าง Test Resource
# test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
labels:
app: myapp
team: backend
spec:
containers:
- name: app
image: nginx:1.25 # มี tag ที่ถูกต้อง
resources:
limits:
cpu: "500m"
memory: "256Mi"
# ทดสอบ
kyverno apply require-labels.yaml --resource test-pod.yaml
# Output: pass (มี label app และ team)
kyverno apply disallow-latest-tag.yaml --resource test-pod.yaml
# Output: pass (ไม่ได้ใช้ :latest)
# ทดสอบ Resource ที่ไม่ผ่าน
# bad-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: bad-pod
# ไม่มี labels!
spec:
containers:
- name: app
image: nginx:latest # ใช้ latest!
# ไม่มี resource limits!
kyverno apply require-labels.yaml --resource bad-pod.yaml
# Output: FAIL — ต้องมี label 'app' และ 'team'
Testing Gatekeeper Policies
# ใช้ OPA test framework
# policy_test.rego
package k8sdisallowedtags
test_latest_tag_denied {
input := {
"review": {
"object": {
"spec": {
"containers": [{
"name": "app",
"image": "nginx:latest"
}]
}
}
}
}
results := violation with input as input
count(results) > 0
}
test_specific_tag_allowed {
input := {
"review": {
"object": {
"spec": {
"containers": [{
"name": "app",
"image": "nginx:1.25.0"
}]
}
}
}
}
results := violation with input as input
count(results) == 0
}
# รัน Test
opa test . -v
Policy Exceptions
บางครั้งมี Resource ที่ต้องได้รับข้อยกเว้นจาก Policy เช่น System Components หรือ Monitoring Tools ทั้ง Kyverno และ Gatekeeper รองรับ Exception:
Kyverno Exception
# PolicyException — ยกเว้น Namespace "kube-system"
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: allow-system-privileged
namespace: kyverno
spec:
exceptions:
- policyName: disallow-privileged
ruleNames:
- deny-privileged
match:
any:
- resources:
kinds:
- Pod
namespaces:
- kube-system
- monitoring
# หรือใช้ exclude ใน Policy โดยตรง
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged
spec:
rules:
- name: deny-privileged
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- monitoring
Audit Mode vs Enforce Mode
การ Deploy Policy ใหม่ควรเริ่มจาก Audit Mode ก่อนเสมอ เพื่อดูว่า Resource ที่มีอยู่แล้วจะถูก Block กี่ตัว แล้วค่อยเปลี่ยนเป็น Enforce เมื่อพร้อม:
# Kyverno: เริ่มด้วย Audit
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Audit # ← Audit ก่อน!
# เมื่อพร้อม เปลี่ยนเป็น Enforce
# validationFailureAction: Enforce
rules:
- name: check-limits
# ...
# ดู Policy Report (Kyverno)
kubectl get policyreport -A
kubectl get clusterpolicyreport
# ดูรายละเอียดว่า Resource ไหนไม่ผ่าน
kubectl describe policyreport -n default
# Gatekeeper: ใช้ enforcementAction
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowedTags
metadata:
name: no-latest-tag
spec:
enforcementAction: dryrun # dryrun = audit
# enforcementAction: deny # deny = enforce
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Policy-as-Code ใน CI/CD
Policy ที่ดีควรอยู่ใน Git Repository เหมือน Application Code และถูกทดสอบใน CI/CD Pipeline ก่อน Deploy:
# .github/workflows/policy-test.yml
name: Test Kyverno Policies
on:
push:
paths:
- 'policies/**'
pull_request:
paths:
- 'policies/**'
jobs:
test-policies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Kyverno CLI
run: |
curl -LO https://github.com/kyverno/kyverno/releases/download/v1.12.0/kyverno-cli_v1.12.0_linux_x86_64.tar.gz
tar -xzf kyverno-cli_v1.12.0_linux_x86_64.tar.gz
sudo mv kyverno /usr/local/bin/
- name: Test Policies Against Good Resources
run: |
for policy in policies/*.yaml; do
echo "Testing $policy..."
kyverno apply "$policy" --resource tests/good-resources/ || exit 1
done
- name: Test Policies Block Bad Resources
run: |
for policy in policies/*.yaml; do
echo "Testing $policy blocks bad resources..."
kyverno apply "$policy" --resource tests/bad-resources/ 2>&1 | grep -q "FAIL" || exit 1
done
- name: Validate Policy Syntax
run: |
kyverno validate policies/
Pre-commit Validation ด้วย Datree
# ติดตั้ง Datree
curl https://get.datree.io | bash
# ตรวจสอบ K8s manifests ก่อน commit
datree test deployment.yaml
# ตัวอย่าง Output:
# [PASS] Ensure each container has a configured memory limit
# [FAIL] Ensure each container image has a pinned tag
# [PASS] Prevent workload from using the default namespace
# [FAIL] Ensure Deployment has more than one replica
# ใช้กับ pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/datreeio/datree
rev: v1.9.0
hooks:
- id: datree
args: ['--policy', 'production']
Polaris — Best Practices Scanner
Polaris เป็นเครื่องมือจาก Fairwinds ที่ตรวจสอบ Kubernetes Resources ตาม Best Practices โดยไม่ต้องเขียน Policy เอง มาพร้อมกฎที่ครอบคลุมด้าน Security, Reliability และ Efficiency:
# ติดตั้ง Polaris
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install polaris fairwinds-stable/polaris --namespace polaris --create-namespace
# หรือใช้ CLI scan
# brew install fairwindsops/tap/polaris
polaris audit --format=pretty
# ตัวอย่าง Output:
# Polaris Audit Report
# ────────────────────
# Deployments:
# default/my-app:
# ✓ Container has resource limits
# ✗ Container is running as root
# ✗ Container image has latest tag
# ✓ Readiness probe is configured
# ✗ Liveness probe is not configured
#
# Score: 65/100
# Polaris Dashboard (Web UI)
kubectl port-forward svc/polaris-dashboard -n polaris 8080:80
# เปิด http://localhost:8080
Common Policy Recipes
Recipe: Enforce Network Policies
# ตรวจสอบว่าทุก Namespace มี NetworkPolicy
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-networkpolicy
spec:
validationFailureAction: Audit
rules:
- name: check-networkpolicy-exists
match:
any:
- resources:
kinds:
- Pod
preconditions:
all:
- key: "{{ request.namespace }}"
operator: NotIn
value: ["kube-system", "kube-public"]
validate:
message: "Namespace '{{ request.namespace }}' ต้องมี NetworkPolicy ก่อนจึงจะสร้าง Pod ได้"
deny:
conditions:
all:
- key: "{{ request.namespace }}"
operator: AnyNotIn
value: "{{ request.object.metadata.namespace }}"
Recipe: Restrict Image Registries
# อนุญาตเฉพาะ Image จาก Registry ที่กำหนด
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "อนุญาตเฉพาะ Image จาก registry ที่อนุมัติเท่านั้น: ghcr.io/myorg, myregistry.azurecr.io"
pattern:
spec:
containers:
- image: "ghcr.io/myorg/* | myregistry.azurecr.io/*"
Recipe: Auto-inject Labels จาก Namespace
# Mutate: เพิ่ม Label cost-center จาก Namespace Annotation
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: inject-cost-center
spec:
rules:
- name: add-cost-center-label
match:
any:
- resources:
kinds:
- Pod
context:
- name: namespaceCostCenter
apiCall:
urlPath: "/api/v1/namespaces/{{ request.namespace }}"
jmesPath: "metadata.annotations."cost-center" || 'unknown'"
mutate:
patchStrategicMerge:
metadata:
labels:
cost-center: "{{ namespaceCostCenter }}"
Admission Controller สำหรับ Security Compliance
ในองค์กรที่ต้องปฏิบัติตาม Compliance Standards เช่น CIS Kubernetes Benchmark, SOC 2, HIPAA Admission Controllers เป็นเครื่องมือสำคัญที่ช่วยบังคับใช้ Security Controls โดยอัตโนมัติ:
| Compliance Requirement | Kyverno Policy |
|---|---|
| CIS 5.2.1: Minimize Privileged Containers | disallow-privileged |
| CIS 5.2.2: Minimize hostPID | disallow-host-pid |
| CIS 5.2.3: Minimize hostNetwork | disallow-host-network |
| CIS 5.2.6: Minimize Root Containers | require-run-as-non-root |
| CIS 5.4.1: Prefer read-only root filesystem | require-ro-rootfs |
| SOC 2: Resource Boundaries | require-resource-limits |
# CIS Benchmark: Require Run As Non-Root
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-run-as-non-root
annotations:
policies.kyverno.io/title: Require Run As Non-Root
policies.kyverno.io/category: CIS Kubernetes Benchmark
spec:
validationFailureAction: Enforce
rules:
- name: run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Container ต้องรันด้วย non-root user (runAsNonRoot: true)"
pattern:
spec:
securityContext:
runAsNonRoot: true
containers:
- securityContext:
runAsNonRoot: true
สรุป
Kubernetes Admission Controllers เป็นกลไกที่ขาดไม่ได้สำหรับ Production Cluster ในปี 2026 ไม่ว่าจะเลือก Kyverno (ง่าย ใช้ YAML ปกติ) หรือ OPA Gatekeeper (ยืดหยุ่น ใช้ Rego) สิ่งสำคัญคือต้องมี Policy Engine บางอย่างใน Cluster ของคุณ เพื่อป้องกัน Misconfiguration ที่อาจนำไปสู่ปัญหา Security หรือ Reliability
เริ่มต้นด้วยการติดตั้ง Kyverno เปิด Audit Mode สำหรับ Policy พื้นฐาน (require labels, disallow latest, require resource limits) ดู Policy Report สักสัปดาห์ แล้วค่อยเปลี่ยนเป็น Enforce เมื่อทุกทีมพร้อม จากนั้นค่อยเพิ่ม Policy ที่ซับซ้อนขึ้นตามความต้องการของ Compliance และ Security Standards ขององค์กร
