Webhooks קבלה מותאמים אישית עבור Kubernetes
הצוות שלנו נתקל לעתים קרובות בתרחיש הבא: מהנדסים פורסים Pods ללא resources.requests, עם securityContext ו-imagePullPolicy: Never מתירניים, תוך שימוש בתג latest. מדיניות כמו Kyverno או OPA Gatekeeper יכולה לאסור זאת ברמת החוק. אבל מה אם הלוגיקה דורשת קריאה לשירות חיצוני—API ארגוני לבדיקת סודות או הגדרה אוטומטית של annotations בהתבסס על חוקים עסקיים? במקרים כאלה, הכלים הסטנדרטיים אינם מספיקים. אנו מפתחים Admission Webhooks מותאמים אישית—פתרון גמיש לאימות ושינוי (mutation) של כל משאב Kubernetes. צרו קשר כדי לדון במקרה שלכם—נעזור להפוך מדיניות לאוטומטית ולחסוך בתקציב תחזוקת הקלאסטר.
שני סוגי Webhooks: מאמת (Validating) ומשנה (Mutating)
ValidatingAdmissionWebhook מקבל אובייקט ומחזיר allow או deny מבלי לשנות אותו. משמש לבדיקות כמו "האם ImagePullSecret זה קיים?", "האם ל-namespace יש label מאושר?", "האם התמונה נקייה מפגיעויות?" דרך סורק צד שלישי. MutatingAdmissionWebhook יכול לשנות את האובייקט באמצעות JSON Patch לפני השמירה. משמש להזרקה אוטומטית של sidecar containers, הוספת annotations, נרמול שדות, הזרקת משתני סביבה.
| מאפיין | Validating Webhook | Mutating Webhook |
|---|---|---|
| משנה אובייקט? | לא | כן (JSON Patch) |
| סדר קריאה | אחרי כל השינויים | ראשון, במקביל |
| שימוש אופייני | אימות פרמטרי אבטחה | הוספת sidecars, annotations |
סדר קריאה: כל ה-Mutating webhooks רצים ראשונים (במקביל, ואז נקראים שוב אם היו שינויים), ולאחר מכן כל ה-Validating webhooks (במקביל). ה-Validating webhook רואה את האובייקט הסופי אחרי כל השינויים.
למה Webhook מותאם אישית במקום Kyverno?
Kyverno הוא כלי מצוין למדיניות סטטית המבוססת על Rego. אבל כשצריך לקרוא ל-API חיצוני (לדוגמה, לבדוק רישיון container), לוגיקה עסקית מורכבת עם תנאים ולולאות, אינטגרציה עם מערכת ticketing (Jira) או CMDB, או יצירת קונפיגורציה דינמית בהתבסס על מטא-דאטה של הקלאסטר—אז webhook מותאם אישית ב-Go או Python נותן שליטה מלאה. הוא רץ פי 2–3 מהר יותר בעומס גבוה כי הוא לא מבזבז זמן על פירוש חוקי Rego. עלות הפיתוח מתקזזת במניעת תקלות והפחתת בדיקות ידניות.
איך להבטיח סובלנות לתקלות של ה-Webhook?
יש לפרוס את ה-Admission Webhook עם לפחות שתי רפליקות (HPA) ולהגדיר package main import ( "encoding/json" "net/http" admissionv1 "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" ) func validatePod(w http.ResponseWriter, r *http.Request) { var admReview admissionv1.AdmissionReview json.NewDecoder(r.Body).Decode(&admReview) pod := &corev1.Pod{} json.Unmarshal(admReview.Request.Object.Raw, pod) allowed := true message := "" for _, container := range pod.Spec.Containers { if container.Resources.Requests == nil { allowed = false message = "container " + container.Name + " must specify resources.requests" break } } response := admissionv1.AdmissionReview{ TypeMeta: admReview.TypeMeta, Response: &admissionv1.AdmissionResponse{ UID: admReview.Request.UID, Allowed: allowed, Result: &metav1.Status{ Message: message, }, }, } json.NewEncoder(w).Encode(response) } עבור בדיקות קריטיות. השתמשו ב-apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: pod-validator webhooks: - name: validate.pods.example.com admissionReviewVersions: ["v1"] clientConfig: service: name: pod-validator namespace: webhook-system path: /validate caBundle: <BASE64_CA_CERT> rules: - operations: ["CREATE", "UPDATE"] apiGroups: [""] apiVersions: ["v1"] resources: ["pods"] failurePolicy: Fail # Ignore или Fail namespaceSelector: matchExpressions: - key: webhook-validation operator: In values: ["enabled"] sideEffects: None timeoutSeconds: 5 כדי להחריג namespaces מערכתיים (kube-system). תעודות TLS מתחדשות אוטומטית דרך cert-manager. זמן הקצוב (timeout) של ה-webhook חייב להיות ≤ 5 שניות, אחרת פעולות הקלאסטר מואטות. זה יכול להפחית את זמן ההשבתה הקשור לתקלות בעד 30%.
מבנה ה-Webhook: מה יש בפנים
ה-webhook הוא שרת HTTPS שמקבל בקשות AdmissionReview. דוגמה ב-Go:
package main
import (
"encoding/json"
"net/http"
admissionv1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
)
func validatePod(w http.ResponseWriter, r *http.Request) {
var admReview admissionv1.AdmissionReview
json.NewDecoder(r.Body).Decode(&admReview)
pod := &corev1.Pod{}
json.Unmarshal(admReview.Request.Object.Raw, pod)
allowed := true
message := ""
for _, container := range pod.Spec.Containers {
if container.Resources.Requests == nil {
allowed = false
message = "container " + container.Name + " must specify resources.requests"
break
}
}
response := admissionv1.AdmissionReview{
TypeMeta: admReview.TypeMeta,
Response: &admissionv1.AdmissionResponse{
UID: admReview.Request.UID,
Allowed: allowed,
Result: &metav1.Status{
Message: message,
},
},
}
json.NewEncoder(w).Encode(response)
}ה-webhook חייב לרוץ על HTTPS עם תעודת TLS חתומה על ידי ה-CA של הקלאסטר או CA מהימן. Kubernetes לא מקבל HTTP ולא מקבל תעודות self-signed ללא timeoutSeconds: 5 מפורש ב-WebhookConfiguration.
רישום ה-Webhook
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-validator
webhooks:
- name: validate.pods.example.com
admissionReviewVersions: ["v1"]
clientConfig:
service:
name: pod-validator
namespace: webhook-system
path: /validate
caBundle: <BASE64_CA_CERT>
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
failurePolicy: Fail # Ignore или Fail
namespaceSelector:
matchExpressions:
- key: webhook-validation
operator: In
values: ["enabled"]
sideEffects: None
timeoutSeconds: 5
| פרמטר | Fail | Ignore |
|---|---|---|
| אם ה-webhook לא זמין | חוסם יצירת משאבים | מדלג על אימות |
| לאילו מדיניויות | מדיניויות אבטחה קריטיות | annotations משניים |
| השפעה על הקלאסטר | עוצר פריסה בכשל webhook | מאפשר להתעלם משגיאות webhook |
namespaceSelector — Kubernetes ממתין לתגובת webhook למשך 5 שניות לכל היותר. webhook איטי מאט את כל יצירת ה-Pods בקלאסטר. זו הסיבה העיקרית לכך שה-webhook חייב להיות מהיר: הימנעו מקריאות סינכרוניות ל-API חיצוניים איטיים.
webhook-validation=enabled — ה-webhook חל רק על namespaces עם label kube-system. תמיד החריגו את webhook-system ו-patch := []map[string]interface{}{ { "op": "add", "path": "/metadata/labels/injected-by", "value": "admission-webhook", }, { "op": "add", "path": "/spec/containers/0/env/-", "value": map[string]string{ "name": "TENANT_ID", "value": tenantID, }, }, } patchBytes, _ := json.Marshal(patch) patchType := admissionv1.PatchTypeJSONPatch response.Patch = patchBytes response.PatchType = &patchType , אחרת ה-webhook עלול לחסום רכיבי מערכת.
Mutating Webhook: JSON Patch
החזרת patch להוספה אוטומטית של labels ומשתני סביבה:
patch := []map[string]interface{}{
{
"op": "add",
"path": "/metadata/labels/injected-by",
"value": "admission-webhook",
},
{
"op": "add",
"path": "/spec/containers/0/env/-",
"value": map[string]string{
"name": "TENANT_ID",
"value": tenantID,
},
},
}
patchBytes, _ := json.Marshal(patch)
patchType := admissionv1.PatchTypeJSONPatch
response.Patch = patchBytes
response.PatchType = &patchType
TLS ופריסה
אנו משתמשים ב-cert-manager לניהול תעודות TLS. משאב Certificate עם issuerRef המצביע על ה-CA של הקלאסטר יוצר אוטומטית Secret עם התעודה ומחדש אותה לפני פקיעתה. ה-caBundle של ה-webhook מתעדכן דרך annotation:
metadata: annotations: cert-manager.io/inject-ca-from: webhook-system/pod-validator-cert זה מבטל את הצורך בסיבוב תעודות ידני—אחת הסיבות הנפוצות ביותר לתקלות כאשר תעודת ה-webhook פגה וכל הפריסות מתחילות להיכשל.
מה כלול בעבודה
- פיתוח שרת ב-Go (או Python) עם לוגיקה עסקית
- בדיקות יחידה ובדיקות אינטגרציה (envtest, kind)
- הגדרת TLS דרך cert-manager
- Helm chart לפריסה לתוך הקלאסטר
- צינור CI/CD (GitLab CI) עם פריסה אוטומטית
- תיעוד להתקנה ותפעול
- תמיכה לאחר שחרור למשך שבועיים
- הדרכת צוות בניהול
שלבי העבודה
- ניתוח — ביקורת מדיניויות קיימות, תיעוד דרישות (מה לאמת/לשנות, אילו משאבים, namespaces)
- עיצוב — ארכיטקטורת webhook, סכמת נתונים, תרחישי כשל
- פיתוח — כתיבת שרת, בדיקות אינטגרציה
- בדיקות — אימות על קלאסטר בדיקה (kind), בדיקות עומס
- פריסה — פריסה לייצור עם HPA וניטור
- תיעוד — הוראות לצוות לשינוי חוקים
לוח זמנים ועלות
לוח זמנים לפיתוח: בין 3 ל-5 ימים תלוי במורכבות הלוגיקה. העלות מחושבת באופן אישי לאחר ביקורת תשתית. צרו קשר להערכת מחיר—יש לנו ניסיון של 5+ שנים ב-Kubernetes וסיפקנו למעלה מ-30 פתרונות דומים. שלחו בקשה ונכין הצעה. בקשו ייעוץ כדי ללמוד כיצד webhook מותאם אישית יכול לחסוך בתקציב שלכם.
התיעוד הרשמי של Kubernetes מתאר את Admission Webhooks כמנגנון העיקרי להרחבת מדיניות הקלאסטר (ראו Kubernetes Admission Webhooks).







