init
This commit is contained in:
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
|
||||
}'
|
||||
```
|
||||
Reference in New Issue
Block a user