Webhooks קבלה מותאמים אישית: אימות ומוטציה ב-Kubernetes

מדיניות סטנדרטית לא תמיד מטפלת בלוגיקת ולידציה ומוטציה אוטומטית מורכבת עבור משאבי Kubernetes. אנחנו בונים Custom Admission Webhooks שמבצעים ולידציה ומוטציה על אובייקטים לפי הכללים הייחודיים שלך. הצוות שלנו מספק את הפרויקט במתכונת turnkey—מאודיט ועד יישום ותמיכה שוטפת.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

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) עם פריסה אוטומטית
  • תיעוד להתקנה ותפעול
  • תמיכה לאחר שחרור למשך שבועיים
  • הדרכת צוות בניהול

שלבי העבודה

  1. ניתוח — ביקורת מדיניויות קיימות, תיעוד דרישות (מה לאמת/לשנות, אילו משאבים, namespaces)
  2. עיצוב — ארכיטקטורת webhook, סכמת נתונים, תרחישי כשל
  3. פיתוח — כתיבת שרת, בדיקות אינטגרציה
  4. בדיקות — אימות על קלאסטר בדיקה (kind), בדיקות עומס
  5. פריסה — פריסה לייצור עם HPA וניטור
  6. תיעוד — הוראות לצוות לשינוי חוקים

לוח זמנים ועלות

לוח זמנים לפיתוח: בין 3 ל-5 ימים תלוי במורכבות הלוגיקה. העלות מחושבת באופן אישי לאחר ביקורת תשתית. צרו קשר להערכת מחיר—יש לנו ניסיון של 5+ שנים ב-Kubernetes וסיפקנו למעלה מ-30 פתרונות דומים. שלחו בקשה ונכין הצעה. בקשו ייעוץ כדי ללמוד כיצד webhook מותאם אישית יכול לחסוך בתקציב שלכם.

התיעוד הרשמי של Kubernetes מתאר את Admission Webhooks כמנגנון העיקרי להרחבת מדיניות הקלאסטר (ראו Kubernetes Admission Webhooks).