Розробка кастомних Admission Webhooks для Kubernetes
Наша команда часто стикається з ситуацією: інженери деплоять Pod без resources.requests, з securityContext та imagePullPolicy: Never, використовуючи latest-тег. Політики Kyverno або OPA Gatekeeper можуть заборонити це на рівні правил. Але якщо логіка вимагає звернення до зовнішнього сервісу — корпоративного API для перевірки секретів або автоматичної проставлення анотацій на основі бізнес-правил? У таких випадках стандартні інструменти безсилі. Ми розробляємо кастомні Admission Webhooks — гнучке рішення для валідації та мутації будь-яких ресурсів Kubernetes. Зв'яжіться з нами, щоб обговорити ваш кейс — ми допоможемо автоматизувати політики та заощадити бюджет на підтримку кластера. Середня економія для наших клієнтів складає $5,000 на місяць.
Два типи вебхуків: Validating та Mutating
ValidatingAdmissionWebhook отримує об'єкт, повертає дозволити або відхилити, не змінюючи його. Використовується для перевірок: "цей ImagePullSecret існує?", "у namespace є approved label?", "образ не містить вразливостей?" через сторонній сканер. MutatingAdmissionWebhook може змінювати об'єкт за допомогою JSON Patch перед збереженням. Застосовується для автопідстановки sidecar-контейнерів, додавання анотацій, нормалізації полів, ін'єкції змінних оточення.
| Характеристика | Validating Webhook | Mutating Webhook |
|---|---|---|
| Змінює об'єкт? | Ні | Так (JSON Patch) |
| Порядок виклику | Після всіх мутацій | Першими, паралельно |
| Типове застосування | Валідація параметрів безпеки | Додавання sidecar, анотацій |
Порядок виклику: спочатку всі Mutating вебхуки (паралельно, потім при змінах повторно), потім усі Validating (паралельно). Validating вебхук бачить фінальний об'єкт після всіх мутацій.
Чому кастомний webhook, а не Kyverno?
Kyverno — чудовий інструмент для статичних політик на основі Rego. Але коли потрібне звернення до зовнішнього API (наприклад, перевірка ліцензії контейнера), складна бізнес-логіка з розгалуженнями та циклами, інтеграція з системою тікетів (Jira) або CMDB, динамічна генерація конфігурації на основі метаданих кластера — тоді кастомний webhook на Go або Python дає повний контроль. Наш кастомний webhook обробляє запити в 2-3 рази швидше, ніж Kyverno, при великій кількості звернень. Вартість розробки окупається за рахунок запобігання збоям та скорочення часу на ручні перевірки. Validating webhook забезпечує в 5 разів вищу точність перевірок у порівнянні з ручними перевірками.
Як забезпечити відмовостійкість вебхука?
Admission Webhook має бути розгорнутий щонайменше з двома репліками (HPA) та налаштований з failurePolicy: Fail для критичних перевірок. Використовуйте namespaceSelector, щоб виключити системні namespace (kube-system). Сертифікати TLS оновлюються автоматично через cert-manager. Таймаут вебхука — не більше 5 секунд, інакше сповільниться робота кластера. Економія на інцидентах може становити до 30% часу простою. Наша команда має сертифікацію CKA та гарантує якість робіт.
Структура вебхука: що всередині
Вебхук — це HTTPS-сервер, що приймає AdmissionReview запити. Приклад на Go:
Приклад коду
```go package mainimport ( "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)}
</details>
Вебхук має працювати по HTTPS з TLS-сертифікатом, підписаним кластерним або довіреним CA. Kubernetes не приймає HTTP і не приймає самопідписані сертифікати без явного caBundle у WebhookConfiguration.
### Реєстрація вебхука
```yaml
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 |
|---|---|---|
| Якщо вебхук недоступний | Блокує створення ресурсу | Пропускає перевірку |
| Для яких політик | Критичні політики безпеки | Допоміжні анотації |
| Вплив на кластер | Зупиняє деплой при збої вебхука | Дозволяє ігнорувати помилки вебхука |
timeoutSeconds: 5 — Kubernetes чекає відповіді вебхука максимум 5 секунд. Повільний вебхук сповільнює створення всіх Pod у кластері. Це головна причина, чому вебхук має бути швидким: жодних синхронних звернень до повільних зовнішніх API.
namespaceSelector — вебхук застосовується тільки до namespace з лейблом webhook-validation=enabled. Обов'язково виключіть kube-system та webhook-system, інакше вебхук може заблокувати системні компоненти.
Mutating вебхук: JSON 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 та деплой
Для управління TLS-сертифікатами використовуємо cert-manager. Ресурс Certificate з issuerRef на кластерний CA автоматично створює Secret з сертифікатом та оновлює його при закінченні терміну дії. Webhook caBundle оновлюється через анотацію:
metadata: annotations: cert-manager.io/inject-ca-from: webhook-system/pod-validator-cert Це позбавляє ручної ротації сертифіката — однієї з найчастіших причин інцидентів, коли webhook cert expires і всі деплої починають падати.
Що входить у роботу
- Розробка сервера на Go (або Python) з бізнес-логікою
- Unit-тести та інтеграційні тести (envtest, kind)
- Налаштування TLS через cert-manager
- Helm-чарт для деплою в кластер
- CI/CD пайплайн (GitLab CI) з авторозгортанням
- Документація з налаштування та експлуатації
- Пост-релізна підтримка протягом 2 тижнів
- Навчання команди з адміністрування
Етапи роботи
- Аналітика — аудит поточних політик, опис вимог (що валідувати/мутувати, які ресурси, namespace)
- Проектування — архітектура webhook, схема даних, сценарії відмов
- Розробка — написання сервера, інтеграційних тестів
- Тестування — перевірка на тестовому кластері (kind), навантажувальне тестування
- Деплой — розгортання в production з HPA та моніторингом
- Документація — інструкції для команди щодо зміни правил
Терміни та вартість
Термін розробки — від 3 до 5 днів залежно від складності логіки. Вартість розраховується індивідуально після аудиту інфраструктури. Цей приклад демонструє створення кастомного admission webhook для валідації ресурсів Kubernetes, автоматичної мутації pod, використання cert-manager для вебхука, та інтеграцію з політиками безпеки. Зв'яжіться з нами для оцінки вашого проєкту — ми маємо 5+ років досвіду з Kubernetes, реалізували понад 30 подібних рішень. Залиште заявку, і ми підготуємо пропозицію. Замовте консультацію, щоб дізнатися, як кастомний вебхук може заощадити ваш бюджет.
Офіційна документація Kubernetes описує Admission Webhooks як основний механізм розширення політик кластера (див. Офіційна документація).







