Урок 6.3 — Производительность и оптимизация
Измерение текущей производительности
# Открыть метрики
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
# МЕДЛЕННО — матчит всё подряд
match:
resources:
kinds:
- "*"
# БЫСТРО — только нужные ресурсы и namespace
match:
resources:
kinds:
- Pod
namespaces:
- production
- staging
Оптимизация 2: preconditions для быстрого выхода
# Добавить precondition перед дорогим context.apiCall
# Правило запустит apiCall только если precondition прошёл
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: разбивать мегаполитики
# Посмотреть сколько правил в каждой политике
kubectl get clusterpolicies -o json | \
jq -r '.items[] | "\(.metadata.name): \(.spec.rules | length) rules"' | \
sort -t: -k2 -rn | head -10
# Политики с >5 правилами — кандидаты на разбивку
# Каждая политика применяется параллельно с другими
# Правила внутри политики — последовательно
Оптимизация 4: ресурсы для Kyverno
# Проверить текущее потребление ресурсов
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
# МЕДЛЕННО — 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
# Включить 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
Нагрузочное тестирование политик
# Создать много подов быстро и измерить время
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'