init
This commit is contained in:
134
06-monitoring/01-logging/README.md
Normal file
134
06-monitoring/01-logging/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Урок 6.1 — Логирование и мониторинг Kyverno
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `grafana-dashboard.json` | Готовый Grafana dashboard |
|
||||
| `../03-reporting/prometheus-alert-rules.yaml` | Alerting правила |
|
||||
| `../03-reporting/service-monitor.yaml` | ServiceMonitor |
|
||||
|
||||
## Настройка уровня логирования
|
||||
|
||||
```bash
|
||||
# Изменить уровень логирования без перезапуска (через Helm upgrade)
|
||||
helm upgrade kyverno kyverno/kyverno \
|
||||
--namespace kyverno \
|
||||
--reuse-values \
|
||||
--set admissionController.extraArgs="{--v=4\,--loggingFormat=json}"
|
||||
|
||||
# Уровни:
|
||||
# --v=1 production (warnings + important events)
|
||||
# --v=2 informational (policy apply/deny events)
|
||||
# --v=4 debug (full AdmissionReview)
|
||||
# --v=6 trace (очень детально, только для отладки)
|
||||
```
|
||||
|
||||
## Просмотр логов
|
||||
|
||||
```bash
|
||||
# Логи admission controller
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=admission-controller \
|
||||
--tail=100 -f
|
||||
|
||||
# Логи background controller (для generate политик)
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=background-controller \
|
||||
--tail=50
|
||||
|
||||
# Фильтрация — только нарушения
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=admission-controller \
|
||||
--tail=200 | grep '"result":"fail"'
|
||||
|
||||
# Фильтрация — конкретная политика
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=admission-controller \
|
||||
--tail=200 | grep '"policy":"require-resource-limits"'
|
||||
```
|
||||
|
||||
## Метрики через port-forward
|
||||
|
||||
```bash
|
||||
# Открыть порт metrics
|
||||
kubectl port-forward -n kyverno \
|
||||
svc/kyverno-svc-metrics 8000:8000 &
|
||||
|
||||
# Все метрики
|
||||
curl -s http://localhost:8000/metrics | grep kyverno_ | head -40
|
||||
|
||||
# Конкретная метрика
|
||||
curl -s http://localhost:8000/metrics | \
|
||||
grep kyverno_policy_results_total
|
||||
|
||||
# Топ метрик по нарушениям
|
||||
curl -s http://localhost:8000/metrics | \
|
||||
grep 'kyverno_policy_results_total.*rule_result="fail"'
|
||||
|
||||
# Остановить port-forward
|
||||
kill %1
|
||||
```
|
||||
|
||||
## Импорт Grafana Dashboard
|
||||
|
||||
```bash
|
||||
# Способ 1: через UI
|
||||
# Grafana → Dashboards → Import → Upload JSON file → grafana-dashboard.json
|
||||
|
||||
# Способ 2: через ConfigMap (если используете Grafana Operator)
|
||||
kubectl create configmap kyverno-dashboard \
|
||||
--from-file=grafana-dashboard.json \
|
||||
--namespace=monitoring
|
||||
|
||||
kubectl label configmap kyverno-dashboard \
|
||||
-n monitoring \
|
||||
grafana_dashboard=1
|
||||
```
|
||||
|
||||
## Ключевые PromQL запросы
|
||||
|
||||
```promql
|
||||
# Compliance rate (цель: 100%)
|
||||
sum(rate(kyverno_policy_results_total{rule_result="pass"}[5m])) /
|
||||
sum(rate(kyverno_policy_results_total[5m])) * 100
|
||||
|
||||
# p95 латентность в миллисекундах
|
||||
histogram_quantile(0.95,
|
||||
sum(rate(kyverno_admission_review_duration_seconds_bucket[5m])) by (le)
|
||||
) * 1000
|
||||
|
||||
# Нарушений за сутки по политикам
|
||||
topk(10, sum by(policy_name)(
|
||||
increase(kyverno_policy_results_total{rule_result="fail"}[24h])
|
||||
))
|
||||
|
||||
# Нарушений за сутки по namespace
|
||||
sum by(resource_namespace)(
|
||||
increase(kyverno_policy_results_total{rule_result="fail"}[24h])
|
||||
)
|
||||
|
||||
# Процент ошибок обработки
|
||||
rate(kyverno_admission_requests_total{admission_request_type="error"}[5m]) /
|
||||
rate(kyverno_admission_requests_total[5m]) * 100
|
||||
|
||||
# CPU throttling Kyverno
|
||||
rate(container_cpu_cfs_throttled_seconds_total{
|
||||
namespace="kyverno",
|
||||
container=~"kyverno.*"
|
||||
}[5m])
|
||||
```
|
||||
|
||||
## События Kubernetes
|
||||
|
||||
```bash
|
||||
# PolicyViolation события
|
||||
kubectl get events -A \
|
||||
--field-selector reason=PolicyViolation \
|
||||
--sort-by='.lastTimestamp'
|
||||
|
||||
# События от Kyverno
|
||||
kubectl get events -A \
|
||||
--field-selector source.component=kyverno-admission \
|
||||
--sort-by='.lastTimestamp' | tail -20
|
||||
```
|
||||
130
06-monitoring/01-logging/grafana-dashboard.json
Normal file
130
06-monitoring/01-logging/grafana-dashboard.json
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"title": "Kyverno Policy Dashboard",
|
||||
"uid": "kyverno-main",
|
||||
"tags": ["kyverno", "policy", "security"],
|
||||
"timezone": "browser",
|
||||
"refresh": "30s",
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Policy Compliance Rate",
|
||||
"type": "stat",
|
||||
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(kyverno_policy_results_total{rule_result=\"pass\"}[5m])) / sum(rate(kyverno_policy_results_total[5m])) * 100",
|
||||
"legendFormat": "Compliance %"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"reduceOptions": {"calcs": ["lastNotNull"]},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{"color": "red", "value": 0},
|
||||
{"color": "yellow", "value": 90},
|
||||
{"color": "green", "value": 99}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Admission Requests/s",
|
||||
"type": "stat",
|
||||
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 0},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(rate(kyverno_admission_requests_total[5m]))",
|
||||
"legendFormat": "Requests/s"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Admission Latency p95 (ms)",
|
||||
"type": "stat",
|
||||
"gridPos": {"h": 4, "w": 6, "x": 12, "y": 0},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(kyverno_admission_review_duration_seconds_bucket[5m])) by (le)) * 1000",
|
||||
"legendFormat": "p95 latency"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{"color": "green", "value": 0},
|
||||
{"color": "yellow", "value": 100},
|
||||
{"color": "red", "value": 500}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Total Violations (24h)",
|
||||
"type": "stat",
|
||||
"gridPos": {"h": 4, "w": 6, "x": 18, "y": 0},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(increase(kyverno_policy_results_total{rule_result=\"fail\"}[24h]))",
|
||||
"legendFormat": "Violations"
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{"color": "green", "value": 0},
|
||||
{"color": "yellow", "value": 10},
|
||||
{"color": "red", "value": 100}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Top Violated Policies (1h)",
|
||||
"type": "bargauge",
|
||||
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "topk(10, sum by(policy_name)(increase(kyverno_policy_results_total{rule_result=\"fail\"}[1h])))",
|
||||
"legendFormat": "{{policy_name}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Violations by Namespace (24h)",
|
||||
"type": "table",
|
||||
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 4},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sort_desc(sum by(resource_namespace)(increase(kyverno_policy_results_total{rule_result=\"fail\"}[24h])))",
|
||||
"legendFormat": "{{resource_namespace}}",
|
||||
"instant": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"title": "Admission Latency over time",
|
||||
"type": "timeseries",
|
||||
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 12},
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.50, sum(rate(kyverno_admission_review_duration_seconds_bucket[5m])) by (le)) * 1000",
|
||||
"legendFormat": "p50"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, sum(rate(kyverno_admission_review_duration_seconds_bucket[5m])) by (le)) * 1000",
|
||||
"legendFormat": "p95"
|
||||
},
|
||||
{
|
||||
"expr": "histogram_quantile(0.99, sum(rate(kyverno_admission_review_duration_seconds_bucket[5m])) by (le)) * 1000",
|
||||
"legendFormat": "p99"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
203
06-monitoring/02-debugging/README.md
Normal file
203
06-monitoring/02-debugging/README.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Урок 6.2 — Отладка проблем с политиками
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `policy-exception-example.yaml` | Пример PolicyException |
|
||||
| `debug-context-inspector.yaml` | DEBUG политика для инспекции переменных |
|
||||
|
||||
## Диагностический чеклист
|
||||
|
||||
Когда политика не работает — проверяйте по порядку:
|
||||
|
||||
### Шаг 1: Политика применена и Ready?
|
||||
|
||||
```bash
|
||||
kubectl get clusterpolicies
|
||||
# Колонка READY должна быть True
|
||||
|
||||
kubectl get clusterpolicy my-policy -o yaml | grep -A 10 "status:"
|
||||
# conditions[0].status: "True"
|
||||
# conditions[0].type: Ready
|
||||
```
|
||||
|
||||
### Шаг 2: Match срабатывает?
|
||||
|
||||
```bash
|
||||
# Kyverno CLI — самый быстрый способ проверить
|
||||
kyverno apply my-policy.yaml \
|
||||
--resource my-resource.yaml \
|
||||
--detailed-results
|
||||
|
||||
# Вывод:
|
||||
# Rule my-rule -> resource: PASS/FAIL/SKIP
|
||||
# SKIP = match не сработал
|
||||
```
|
||||
|
||||
### Шаг 3: Ресурс не попадает в exclude?
|
||||
|
||||
```bash
|
||||
# Проверить лейблы namespace
|
||||
kubectl get namespace my-namespace --show-labels
|
||||
|
||||
# Проверить лейблы ресурса
|
||||
kubectl get pod my-pod --show-labels
|
||||
```
|
||||
|
||||
### Шаг 4: Логи admission controller
|
||||
|
||||
```bash
|
||||
# Включить более детальные логи временно
|
||||
kubectl set env deployment/kyverno-admission-controller \
|
||||
-n kyverno \
|
||||
KYVERNO_LOG_LEVEL=4
|
||||
|
||||
# Затем смотреть логи
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=admission-controller \
|
||||
--tail=50 -f | grep "my-policy\|my-resource"
|
||||
|
||||
# Вернуть обратно
|
||||
kubectl set env deployment/kyverno-admission-controller \
|
||||
-n kyverno \
|
||||
KYVERNO_LOG_LEVEL=2
|
||||
```
|
||||
|
||||
### Шаг 5: Dry-run для проверки мутаций
|
||||
|
||||
```bash
|
||||
# Видеть итоговый ресурс после мутации без создания
|
||||
kubectl apply -f my-pod.yaml --dry-run=server -o yaml
|
||||
|
||||
# Diff оригинала и мутированной версии
|
||||
diff <(cat my-pod.yaml) \
|
||||
<(kubectl apply -f my-pod.yaml --dry-run=server -o yaml 2>/dev/null)
|
||||
```
|
||||
|
||||
## Типичные ошибки и решения
|
||||
|
||||
### Ошибка 1: JMESPath — экранирование аннотаций
|
||||
|
||||
```yaml
|
||||
# НЕПРАВИЛЬНО — парсер не поймёт /
|
||||
key: "{{ request.object.metadata.annotations.company.com/env }}"
|
||||
|
||||
# ПРАВИЛЬНО — экранировать / через \"
|
||||
key: "{{ request.object.metadata.annotations.\"company.com/env\" }}"
|
||||
```
|
||||
|
||||
### Ошибка 2: Опциональные поля
|
||||
|
||||
```yaml
|
||||
# НЕПРАВИЛЬНО — упадёт если поле не задано
|
||||
pattern:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
|
||||
# ПРАВИЛЬНО — = для опциональных полей
|
||||
pattern:
|
||||
spec:
|
||||
=(securityContext):
|
||||
=(runAsNonRoot): true
|
||||
```
|
||||
|
||||
### Ошибка 3: foreach по несуществующему массиву
|
||||
|
||||
```yaml
|
||||
# НЕПРАВИЛЬНО — упадёт если initContainers не задан
|
||||
foreach:
|
||||
- list: "request.object.spec.initContainers"
|
||||
|
||||
# ПРАВИЛЬНО — fallback на пустой массив
|
||||
foreach:
|
||||
- list: "request.object.spec.initContainers || `[]`"
|
||||
```
|
||||
|
||||
### Ошибка 4: Match по kind без учёта controller
|
||||
|
||||
```yaml
|
||||
# Если хотите проверять Deployment — матчите Deployment
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Deployment # проверяет сам Deployment
|
||||
|
||||
# Если хотите проверять Pod через Deployment — матчите Pod
|
||||
# (Deployment controller создаёт Pod — Kyverno поймает его)
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
```
|
||||
|
||||
## Инспекция переменных через debug-политику
|
||||
|
||||
```bash
|
||||
# Создать namespace для отладки
|
||||
kubectl create namespace debug-namespace
|
||||
|
||||
# Применить debug политику (она всегда выдаёт fail с данными)
|
||||
kubectl apply -f debug-context-inspector.yaml
|
||||
|
||||
# Создать тестовый под — получить ошибку с содержимым переменных
|
||||
kubectl run debug-pod --image=nginx:1.25.3 \
|
||||
--restart=Never -n debug-namespace \
|
||||
--dry-run=server 2>&1
|
||||
|
||||
# Вывод покажет все переменные в сообщении ошибки:
|
||||
# [DEBUG] Pod: debug-pod
|
||||
# Namespace: debug-namespace
|
||||
# Namespace labels: map[kubernetes.io/metadata.name:debug-namespace]
|
||||
# ...
|
||||
|
||||
# Удалить debug политику после использования
|
||||
kubectl delete -f debug-context-inspector.yaml
|
||||
kubectl delete namespace debug-namespace
|
||||
```
|
||||
|
||||
## Работа с PolicyException
|
||||
|
||||
```bash
|
||||
# Применить исключение
|
||||
kubectl apply -f policy-exception-example.yaml
|
||||
|
||||
# Проверить что исключение работает
|
||||
kubectl run legacy-app-test \
|
||||
--image=nginx:1.25.3 \
|
||||
--restart=Never \
|
||||
-n production
|
||||
# Под без limits должен создаться без ошибок
|
||||
|
||||
# Посмотреть все активные исключения
|
||||
kubectl get policyexceptions -A
|
||||
|
||||
# Найти истекающие исключения (скрипт)
|
||||
kubectl get policyexceptions -A -o json | \
|
||||
jq -r '.items[] |
|
||||
.metadata.name + " expires: " +
|
||||
.metadata.annotations["exception.company.com/expires"]' | \
|
||||
sort
|
||||
```
|
||||
|
||||
## Анализ PolicyReport для диагностики
|
||||
|
||||
```bash
|
||||
# Найти ресурс который нарушает политику
|
||||
POLICY="require-resource-limits"
|
||||
kubectl get policyreports -A -o json | \
|
||||
jq --arg p "$POLICY" \
|
||||
-r '.items[] | .metadata.namespace as $ns |
|
||||
.results[] |
|
||||
select(.policy == $p and .result == "fail") |
|
||||
"\($ns)/\(.resources[0].name): \(.message)"'
|
||||
|
||||
# Сводная статистика
|
||||
kubectl get policyreports -A -o json | \
|
||||
jq '{
|
||||
total: [.items[].results[]] | length,
|
||||
pass: [.items[].results[] | select(.result=="pass")] | length,
|
||||
fail: [.items[].results[] | select(.result=="fail")] | length
|
||||
}'
|
||||
```
|
||||
42
06-monitoring/02-debugging/debug-context-inspector.yaml
Normal file
42
06-monitoring/02-debugging/debug-context-inspector.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: debug-context-inspector
|
||||
annotations:
|
||||
policies.kyverno.io/title: "DEBUG: Инспектор контекстных переменных"
|
||||
policies.kyverno.io/description: >-
|
||||
ТОЛЬКО ДЛЯ ОТЛАДКИ. Всегда отклоняет запрос, выводя содержимое
|
||||
переменных в сообщении ошибки. Помогает понять, что видит политика.
|
||||
УДАЛИТЕ после отладки — не держите в production.
|
||||
spec:
|
||||
validationFailureAction: Enforce
|
||||
background: false # не запускать в background — только для живых запросов
|
||||
rules:
|
||||
- name: print-context
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaces:
|
||||
- debug-namespace # применяем только в отдельном namespace
|
||||
context:
|
||||
- name: nsLabels
|
||||
apiCall:
|
||||
urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}"
|
||||
jmesPath: "metadata.labels"
|
||||
validate:
|
||||
# Всегда fail — выводим данные в сообщении
|
||||
message: >-
|
||||
[DEBUG] Pod: {{ request.object.metadata.name }}
|
||||
Namespace: {{ request.object.metadata.namespace }}
|
||||
Namespace labels: {{ nsLabels }}
|
||||
Pod labels: {{ request.object.metadata.labels }}
|
||||
User: {{ request.userInfo.username }}
|
||||
Groups: {{ request.userInfo.groups }}
|
||||
Operation: {{ request.operation }}
|
||||
Containers: {{ request.object.spec.containers[].name }}
|
||||
deny:
|
||||
conditions:
|
||||
- key: "true"
|
||||
operator: Equals
|
||||
value: "true"
|
||||
24
06-monitoring/02-debugging/policy-exception-example.yaml
Normal file
24
06-monitoring/02-debugging/policy-exception-example.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: kyverno.io/v2beta1
|
||||
kind: PolicyException
|
||||
metadata:
|
||||
name: legacy-app-resource-limits-exception
|
||||
namespace: production
|
||||
annotations:
|
||||
# Обязательные поля для аудита — заполняйте всегда
|
||||
exception.company.com/expires: "2025-06-01"
|
||||
exception.company.com/reason: "Legacy приложение в процессе миграции. JIRA-4321"
|
||||
exception.company.com/approved-by: "platform-team"
|
||||
exception.company.com/created-by: "john.doe"
|
||||
spec:
|
||||
exceptions:
|
||||
- policyName: require-resource-limits
|
||||
ruleNames:
|
||||
- check-container-limits
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaces:
|
||||
- production
|
||||
names:
|
||||
- legacy-app-* # только legacy поды
|
||||
185
06-monitoring/03-performance/README.md
Normal file
185
06-monitoring/03-performance/README.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Урок 6.3 — Производительность и оптимизация
|
||||
|
||||
## Измерение текущей производительности
|
||||
|
||||
```bash
|
||||
# Открыть метрики
|
||||
kubectl port-forward -n kyverno svc/kyverno-svc-metrics 8000:8000 &
|
||||
|
||||
# p95 и p99 латентность
|
||||
curl -s http://localhost:8000/metrics | \
|
||||
grep 'kyverno_admission_review_duration_seconds_bucket' | \
|
||||
tail -20
|
||||
|
||||
# Найти самые медленные политики (через Prometheus)
|
||||
# topk(10,
|
||||
# histogram_quantile(0.99,
|
||||
# sum by(policy_name, rule_name, le)(
|
||||
# rate(kyverno_admission_review_duration_seconds_bucket[5m])
|
||||
# )
|
||||
# )
|
||||
# )
|
||||
|
||||
# Измерить время admission вручную
|
||||
time kubectl run perf-test \
|
||||
--image=nginx:1.25.3 \
|
||||
--restart=Never \
|
||||
--dry-run=server
|
||||
|
||||
kubectl delete pod perf-test 2>/dev/null || true
|
||||
kill %1
|
||||
```
|
||||
|
||||
## Пороговые значения
|
||||
|
||||
| Метрика | Хорошо | Приемлемо | Проблема |
|
||||
|---------|--------|-----------|---------|
|
||||
| p95 латентность | < 100ms | < 500ms | > 500ms |
|
||||
| p99 латентность | < 200ms | < 1000ms | > 1000ms |
|
||||
| CPU throttling | 0% | < 5% | > 10% |
|
||||
| Error rate | 0% | < 0.1% | > 0.1% |
|
||||
|
||||
## Оптимизация 1: точные selectors
|
||||
|
||||
```yaml
|
||||
# МЕДЛЕННО — матчит всё подряд
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- "*"
|
||||
|
||||
# БЫСТРО — только нужные ресурсы и namespace
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaces:
|
||||
- production
|
||||
- staging
|
||||
```
|
||||
|
||||
## Оптимизация 2: preconditions для быстрого выхода
|
||||
|
||||
```bash
|
||||
# Добавить precondition перед дорогим context.apiCall
|
||||
# Правило запустит apiCall только если precondition прошёл
|
||||
```
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
- name: expensive-check
|
||||
match:
|
||||
resources:
|
||||
kinds: [Pod]
|
||||
preconditions:
|
||||
any:
|
||||
# Быстрая проверка лейбла ДО дорогого apiCall
|
||||
- key: "{{ request.object.metadata.labels.\"needs-check\" }}"
|
||||
operator: Equals
|
||||
value: "true"
|
||||
context:
|
||||
- name: externalData # вызывается только если precondition прошёл
|
||||
apiCall:
|
||||
urlPath: "..."
|
||||
```
|
||||
|
||||
## Оптимизация 3: разбивать мегаполитики
|
||||
|
||||
```bash
|
||||
# Посмотреть сколько правил в каждой политике
|
||||
kubectl get clusterpolicies -o json | \
|
||||
jq -r '.items[] | "\(.metadata.name): \(.spec.rules | length) rules"' | \
|
||||
sort -t: -k2 -rn | head -10
|
||||
|
||||
# Политики с >5 правилами — кандидаты на разбивку
|
||||
# Каждая политика применяется параллельно с другими
|
||||
# Правила внутри политики — последовательно
|
||||
```
|
||||
|
||||
## Оптимизация 4: ресурсы для Kyverno
|
||||
|
||||
```bash
|
||||
# Проверить текущее потребление ресурсов
|
||||
kubectl top pods -n kyverno
|
||||
|
||||
# Проверить CPU throttling
|
||||
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/kyverno/pods | \
|
||||
jq '.items[] | {name: .metadata.name, cpu: .containers[].usage.cpu}'
|
||||
|
||||
# Увеличить ресурсы если нужно
|
||||
helm upgrade kyverno kyverno/kyverno \
|
||||
--namespace kyverno \
|
||||
--reuse-values \
|
||||
--set admissionController.resources.limits.cpu=2000m \
|
||||
--set admissionController.resources.limits.memory=1Gi
|
||||
```
|
||||
|
||||
## Оптимизация 5: замена apiCall на ConfigMap
|
||||
|
||||
```yaml
|
||||
# МЕДЛЕННО — apiCall при каждом запросе
|
||||
context:
|
||||
- name: registries
|
||||
apiCall:
|
||||
urlPath: "/api/v1/namespaces/kyverno/configmaps/allowed-registries"
|
||||
jmesPath: "data.list"
|
||||
|
||||
# БЫСТРО — ConfigMap кэшируется Kyverno
|
||||
context:
|
||||
- name: registries
|
||||
configMap:
|
||||
name: allowed-registries
|
||||
namespace: kyverno
|
||||
```
|
||||
|
||||
## Оптимизация 6: HPA для Kyverno
|
||||
|
||||
```bash
|
||||
# Включить HPA для admission controller
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: kyverno-admission-hpa
|
||||
namespace: kyverno
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: kyverno-admission-controller
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 60
|
||||
EOF
|
||||
|
||||
kubectl get hpa -n kyverno
|
||||
```
|
||||
|
||||
## Нагрузочное тестирование политик
|
||||
|
||||
```bash
|
||||
# Создать много подов быстро и измерить время
|
||||
time for i in $(seq 1 50); do
|
||||
kubectl run perf-pod-$i \
|
||||
--image=nginx:1.25.3 \
|
||||
--restart=Never \
|
||||
--dry-run=server > /dev/null 2>&1
|
||||
done
|
||||
|
||||
# Запустить параллельно
|
||||
seq 1 20 | xargs -P 10 -I {} \
|
||||
kubectl run perf-pod-{} \
|
||||
--image=nginx:1.25.3 \
|
||||
--restart=Never \
|
||||
--dry-run=server
|
||||
|
||||
# Во время нагрузки мониторить latency
|
||||
watch -n 2 'curl -s http://localhost:8000/metrics | \
|
||||
grep admission_review_duration_seconds_sum'
|
||||
```
|
||||
Reference in New Issue
Block a user