204 lines
6.0 KiB
Markdown
204 lines
6.0 KiB
Markdown
# Урок 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
|
||
}'
|
||
```
|