init
This commit is contained in:
82
03-mutation/01-basics/README.md
Normal file
82
03-mutation/01-basics/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Урок 3.1 — Основы мутации ресурсов
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `add-standard-labels.yaml` | Автодобавление лейблов managed-by, monitored, cost-center |
|
||||
| `add-default-resource-requests.yaml` | Дефолтные requests для контейнеров без них |
|
||||
| `add-default-security-context.yaml` | Безопасный SecurityContext по умолчанию |
|
||||
|
||||
## Как проверить результат мутации
|
||||
|
||||
```bash
|
||||
# Применить политики
|
||||
kubectl apply -f .
|
||||
|
||||
# Создать под без лейблов и requests
|
||||
kubectl apply -f test-resources/pod-before-mutation.yaml
|
||||
|
||||
# Посмотреть что изменилось — сравнить с оригиналом
|
||||
kubectl get pod pod-before-mutation -o yaml | \
|
||||
grep -A 20 "labels:"
|
||||
|
||||
kubectl get pod pod-before-mutation -o yaml | \
|
||||
grep -A 10 "resources:"
|
||||
|
||||
# Dry-run — увидеть результат без реального создания
|
||||
kubectl apply -f test-resources/pod-before-mutation.yaml \
|
||||
--dry-run=server -o yaml | \
|
||||
diff test-resources/pod-before-mutation.yaml - || true
|
||||
```
|
||||
|
||||
## Отладка мутаций через Kyverno CLI
|
||||
|
||||
```bash
|
||||
# Показывает изменённый ресурс в stdout
|
||||
kyverno apply add-standard-labels.yaml \
|
||||
--resource test-resources/pod-before-mutation.yaml \
|
||||
--detailed-results
|
||||
|
||||
# Сохранить мутированный ресурс
|
||||
kyverno apply . \
|
||||
--resource test-resources/pod-before-mutation.yaml \
|
||||
> test-resources/pod-after-mutation.yaml
|
||||
|
||||
cat test-resources/pod-after-mutation.yaml
|
||||
```
|
||||
|
||||
## Типы patch операций
|
||||
|
||||
```yaml
|
||||
# Strategic Merge — наиболее читаемый, для добавления полей
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
labels:
|
||||
+(new-label): value # + = добавить только если нет
|
||||
|
||||
# JSON Patch RFC 6902 — для точечных изменений и удаления полей
|
||||
mutate:
|
||||
patchesJson6902: |-
|
||||
- op: add
|
||||
path: /metadata/annotations/company.com~1reviewed # ~1 = / в имени
|
||||
value: "true"
|
||||
- op: replace
|
||||
path: /spec/replicas
|
||||
value: 3
|
||||
- op: remove
|
||||
path: /spec/template/metadata/annotations/debug
|
||||
```
|
||||
|
||||
## Порядок применения политик
|
||||
|
||||
Если несколько политик мутируют один ресурс — они применяются
|
||||
в **алфавитном порядке** имён политик.
|
||||
|
||||
```bash
|
||||
# Управляйте порядком через числовые префиксы в именах:
|
||||
# 01-add-labels → 02-add-annotations → 03-add-sidecar
|
||||
kubectl get mutatingwebhookconfigurations -o yaml | \
|
||||
grep "name:" | grep kyverno
|
||||
```
|
||||
36
03-mutation/01-basics/add-default-resource-requests.yaml
Normal file
36
03-mutation/01-basics/add-default-resource-requests.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-default-resource-requests
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Дефолтные resource requests"
|
||||
policies.kyverno.io/category: Resources
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Автоматически добавляет дефолтные resource requests контейнерам,
|
||||
у которых они не указаны. Requests нужны для корректного планирования.
|
||||
Символ + добавляет только отсутствующие поля.
|
||||
spec:
|
||||
rules:
|
||||
- name: add-default-requests
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.containers"
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ element.name }}"
|
||||
resources:
|
||||
requests:
|
||||
+(memory): "128Mi"
|
||||
+(cpu): "100m"
|
||||
55
03-mutation/01-basics/add-default-security-context.yaml
Normal file
55
03-mutation/01-basics/add-default-security-context.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-default-security-context
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Дефолтный SecurityContext"
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Автоматически применяет безопасный SecurityContext к подам и контейнерам,
|
||||
если поля не заданы явно. Работает в связке с validation политиками
|
||||
(сначала mutate, потом validate).
|
||||
spec:
|
||||
rules:
|
||||
- name: add-pod-security-context
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
+(securityContext):
|
||||
+(runAsNonRoot): true
|
||||
+(runAsUser): 1000
|
||||
+(seccompProfile):
|
||||
+(type): RuntimeDefault
|
||||
|
||||
- name: add-container-security-context
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.containers"
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ element.name }}"
|
||||
+(securityContext):
|
||||
+(allowPrivilegeEscalation): false
|
||||
+(readOnlyRootFilesystem): true
|
||||
+(capabilities):
|
||||
+(drop):
|
||||
- ALL
|
||||
33
03-mutation/01-basics/add-standard-labels.yaml
Normal file
33
03-mutation/01-basics/add-standard-labels.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-standard-labels
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Добавление стандартных лейблов"
|
||||
policies.kyverno.io/category: Governance
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Deployment,StatefulSet,DaemonSet
|
||||
policies.kyverno.io/description: >-
|
||||
Автоматически добавляет стандартные лейблы к workload ресурсам,
|
||||
если они отсутствуют. Символ + означает "добавить только если нет".
|
||||
spec:
|
||||
rules:
|
||||
- name: add-managed-by-label
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
- DaemonSet
|
||||
exclude:
|
||||
resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
labels:
|
||||
+(managed-by): "kyverno"
|
||||
+(monitored): "true"
|
||||
# Динамически берём namespace как cost-center
|
||||
+(cost-center): "{{ request.object.metadata.namespace }}"
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-before-mutation
|
||||
namespace: default
|
||||
# нет лейблов managed-by, monitored, cost-center
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
# нет resources.requests — будут добавлены мутацией
|
||||
# нет securityContext — будет добавлен мутацией
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
82
03-mutation/02-sidecar/README.md
Normal file
82
03-mutation/02-sidecar/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Урок 3.2 — Автоматическое добавление sidecar контейнеров
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `inject-fluent-bit.yaml` | Opt-in injection Fluent Bit (по аннотации) |
|
||||
| `fluent-bit-configmap.yaml` | ConfigMap с конфигурацией Fluent Bit |
|
||||
| `inject-prometheus-exporter.yaml` | Opt-in injection Prometheus exporter |
|
||||
|
||||
## Подготовка
|
||||
|
||||
```bash
|
||||
# Применить ConfigMap (нужен до создания подов с Fluent Bit)
|
||||
kubectl apply -f fluent-bit-configmap.yaml
|
||||
|
||||
# Применить политики injection
|
||||
kubectl apply -f inject-fluent-bit.yaml
|
||||
kubectl apply -f inject-prometheus-exporter.yaml
|
||||
```
|
||||
|
||||
## Тестирование Fluent Bit injection
|
||||
|
||||
```bash
|
||||
# Под БЕЗ аннотации — sidecar не добавится
|
||||
kubectl apply -f test-resources/pod-no-logging.yaml
|
||||
kubectl get pod pod-no-logging -o jsonpath='{.spec.containers[*].name}'
|
||||
# Вывод: app
|
||||
|
||||
# Под С аннотацией — sidecar добавится автоматически
|
||||
kubectl apply -f test-resources/pod-with-logging.yaml
|
||||
kubectl get pod pod-with-logging -o jsonpath='{.spec.containers[*].name}'
|
||||
# Вывод: app fluent-bit
|
||||
|
||||
# Проверить конфигурацию sidecar
|
||||
kubectl describe pod pod-with-logging | grep -A 30 "fluent-bit:"
|
||||
|
||||
# Удалить тесты
|
||||
kubectl delete pod pod-no-logging pod-with-logging
|
||||
```
|
||||
|
||||
## Тестирование Prometheus exporter injection
|
||||
|
||||
```bash
|
||||
kubectl apply -f test-resources/pod-with-monitoring.yaml
|
||||
|
||||
kubectl get pod pod-with-monitoring \
|
||||
-o jsonpath='{.spec.containers[*].name}'
|
||||
# Вывод: app prometheus-exporter
|
||||
|
||||
# Проверить аннотации
|
||||
kubectl get pod pod-with-monitoring \
|
||||
-o jsonpath='{.metadata.annotations}' | jq .
|
||||
|
||||
kubectl delete pod pod-with-monitoring
|
||||
```
|
||||
|
||||
## Opt-in vs Opt-out
|
||||
|
||||
```yaml
|
||||
# Opt-in: срабатывает только при наличии аннотации
|
||||
preconditions:
|
||||
- key: "{{ request.object.metadata.annotations.\"logging.company.com/enabled\" }}"
|
||||
operator: Equals
|
||||
value: "true"
|
||||
|
||||
# Opt-out: срабатывает везде, кроме явно исключённых
|
||||
preconditions:
|
||||
- key: "{{ request.object.metadata.annotations.\"logging.company.com/disabled\" || 'false' }}"
|
||||
operator: NotEquals
|
||||
value: "true"
|
||||
```
|
||||
|
||||
## Защита от дублирования
|
||||
|
||||
```bash
|
||||
# Попробовать создать под, который уже содержит fluent-bit
|
||||
kubectl apply -f test-resources/pod-already-has-sidecar.yaml
|
||||
# Sidecar НЕ будет дублирован (precondition NotIn защищает)
|
||||
kubectl get pod pod-already-has-sidecar \
|
||||
-o jsonpath='{.spec.containers[*].name}'
|
||||
```
|
||||
41
03-mutation/02-sidecar/fluent-bit-configmap.yaml
Normal file
41
03-mutation/02-sidecar/fluent-bit-configmap.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: fluent-bit-config
|
||||
namespace: default
|
||||
data:
|
||||
fluent-bit.conf: |
|
||||
[SERVICE]
|
||||
Flush 5
|
||||
Log_Level info
|
||||
Daemon off
|
||||
|
||||
[INPUT]
|
||||
Name tail
|
||||
Path /var/log/containers/*.log
|
||||
Parser docker
|
||||
Tag kube.*
|
||||
Refresh_Interval 5
|
||||
Mem_Buf_Limit 5MB
|
||||
Skip_Long_Lines On
|
||||
|
||||
[FILTER]
|
||||
Name kubernetes
|
||||
Match kube.*
|
||||
Kube_URL https://kubernetes.default.svc:443
|
||||
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
Merge_Log On
|
||||
Keep_Log Off
|
||||
|
||||
[OUTPUT]
|
||||
Name stdout
|
||||
Match *
|
||||
# Замените на ваш реальный output (Elasticsearch, Loki, etc.)
|
||||
|
||||
parsers.conf: |
|
||||
[PARSER]
|
||||
Name docker
|
||||
Format json
|
||||
Time_Key time
|
||||
Time_Format %Y-%m-%dT%H:%M:%S.%L
|
||||
57
03-mutation/02-sidecar/inject-fluent-bit.yaml
Normal file
57
03-mutation/02-sidecar/inject-fluent-bit.yaml
Normal file
@@ -0,0 +1,57 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: inject-fluent-bit-sidecar
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Автовнедрение Fluent Bit sidecar"
|
||||
policies.kyverno.io/category: Logging
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Автоматически добавляет Fluent Bit sidecar контейнер ко всем подам
|
||||
с аннотацией logging.company.com/enabled: "true".
|
||||
Подход Opt-in: разработчик явно запрашивает injection.
|
||||
ЗАМЕНИТЕ образ registry.company.com на ваш внутренний реестр.
|
||||
spec:
|
||||
rules:
|
||||
- name: inject-fluent-bit
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
preconditions:
|
||||
all:
|
||||
# Opt-in: только поды с явной аннотацией
|
||||
- key: "{{ request.object.metadata.annotations.\"logging.company.com/enabled\" }}"
|
||||
operator: Equals
|
||||
value: "true"
|
||||
# Не добавлять если sidecar уже есть (защита от дублирования)
|
||||
- key: "fluent-bit"
|
||||
operator: NotIn
|
||||
value: "{{ request.object.spec.containers[].name }}"
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
containers:
|
||||
- name: fluent-bit
|
||||
image: fluent/fluent-bit:2.1 # замените на внутренний реестр
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
readOnly: true
|
||||
- name: fluent-bit-config
|
||||
mountPath: /fluent-bit/etc/
|
||||
volumes:
|
||||
- name: varlog
|
||||
hostPath:
|
||||
path: /var/log
|
||||
- name: fluent-bit-config
|
||||
configMap:
|
||||
name: fluent-bit-config
|
||||
58
03-mutation/02-sidecar/inject-prometheus-exporter.yaml
Normal file
58
03-mutation/02-sidecar/inject-prometheus-exporter.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: inject-prometheus-exporter
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Автовнедрение Prometheus exporter"
|
||||
policies.kyverno.io/category: Monitoring
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Добавляет node-exporter sidecar ко всем подам с аннотацией
|
||||
monitoring.company.com/scrape: "true".
|
||||
Порт scraping берётся из аннотации monitoring.company.com/port
|
||||
или дефолт 8080.
|
||||
spec:
|
||||
rules:
|
||||
- name: inject-exporter
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
preconditions:
|
||||
all:
|
||||
- key: "{{ request.object.metadata.annotations.\"monitoring.company.com/scrape\" }}"
|
||||
operator: Equals
|
||||
value: "true"
|
||||
- key: "prometheus-exporter"
|
||||
operator: NotIn
|
||||
value: "{{ request.object.spec.containers[].name }}"
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
annotations:
|
||||
# Аннотация для Prometheus autodiscovery
|
||||
+(prometheus.io/scrape): "true"
|
||||
+(prometheus.io/port): >-
|
||||
{{ request.object.metadata.annotations.\"monitoring.company.com/port\" || '9100' }}
|
||||
+(prometheus.io/path): "/metrics"
|
||||
spec:
|
||||
containers:
|
||||
- name: prometheus-exporter
|
||||
image: prom/node-exporter:v1.7.0
|
||||
ports:
|
||||
- name: metrics
|
||||
containerPort: 9100
|
||||
protocol: TCP
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 32Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65534
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-already-has-sidecar
|
||||
namespace: default
|
||||
annotations:
|
||||
logging.company.com/enabled: "true"
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
- name: fluent-bit # sidecar уже есть — injection не сработает
|
||||
image: fluent/fluent-bit:2.1
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
14
03-mutation/02-sidecar/test-resources/pod-no-logging.yaml
Normal file
14
03-mutation/02-sidecar/test-resources/pod-no-logging.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-no-logging
|
||||
namespace: default
|
||||
# нет аннотации logging.company.com/enabled — sidecar не добавится
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
15
03-mutation/02-sidecar/test-resources/pod-with-logging.yaml
Normal file
15
03-mutation/02-sidecar/test-resources/pod-with-logging.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-with-logging
|
||||
namespace: default
|
||||
annotations:
|
||||
logging.company.com/enabled: "true" # триггер для injection
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-with-monitoring
|
||||
namespace: default
|
||||
annotations:
|
||||
monitoring.company.com/scrape: "true"
|
||||
monitoring.company.com/port: "8080" # кастомный порт scraping
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
131
03-mutation/03-advanced/README.md
Normal file
131
03-mutation/03-advanced/README.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Урок 3.3 — Продвинутые техники мутации и переменные
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `kyverno-global-config.yaml` | ConfigMap с централизованными настройками |
|
||||
| `set-dynamic-resource-limits.yaml` | Лимиты из ConfigMap по типу сервиса |
|
||||
| `add-creator-audit-annotation.yaml` | Автоматический audit trail |
|
||||
|
||||
## Подготовка
|
||||
|
||||
```bash
|
||||
# Сначала создать ConfigMap с конфигурацией
|
||||
kubectl apply -f kyverno-global-config.yaml
|
||||
|
||||
# Затем политики
|
||||
kubectl apply -f set-dynamic-resource-limits.yaml
|
||||
kubectl apply -f add-creator-audit-annotation.yaml
|
||||
```
|
||||
|
||||
## Тест динамических лимитов
|
||||
|
||||
```bash
|
||||
# Pod типа "api" — получит 512Mi/500m
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: api-pod
|
||||
namespace: default
|
||||
labels:
|
||||
service-type: api
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
EOF
|
||||
|
||||
kubectl get pod api-pod -o jsonpath='{.spec.containers[0].resources}' | jq .
|
||||
# Ожидаем: limits.memory=512Mi, limits.cpu=500m
|
||||
|
||||
# Pod типа "worker" — получит 1Gi/250m
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: worker-pod
|
||||
namespace: default
|
||||
labels:
|
||||
service-type: worker
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
EOF
|
||||
|
||||
kubectl get pod worker-pod -o jsonpath='{.spec.containers[0].resources}' | jq .
|
||||
# Ожидаем: limits.memory=1Gi, limits.cpu=250m
|
||||
|
||||
# Изменить дефолты без изменения политики
|
||||
kubectl edit configmap kyverno-global-config -n kyverno
|
||||
# Измените default_memory: "512Mi", сохраните
|
||||
# Новые поды получат новые дефолты (~30-60 сек на обновление кэша)
|
||||
|
||||
# Удалить тесты
|
||||
kubectl delete pod api-pod worker-pod
|
||||
```
|
||||
|
||||
## JMESPath функции — шпаргалка
|
||||
|
||||
```yaml
|
||||
# Строки
|
||||
{{ to_upper('hello') }} # HELLO
|
||||
{{ to_lower('WORLD') }} # world
|
||||
{{ trim(' spaces ') }} # spaces
|
||||
{{ split('a,b,c', ',') }} # ["a","b","c"]
|
||||
{{ join(['a','b','c'], '-') }} # a-b-c
|
||||
{{ replace_all('foo/bar', '/', '-') }} # foo-bar
|
||||
{{ truncate('long string', 5) }} # long
|
||||
|
||||
# Числа
|
||||
{{ to_number('42') }} # 42
|
||||
{{ divide(`10`, `3`) }} # 3.333
|
||||
|
||||
# Условия (Elvis operator)
|
||||
{{ request.object.metadata.labels.env || 'default' }}
|
||||
|
||||
# Массивы
|
||||
{{ length(request.object.spec.containers) }}
|
||||
{{ request.object.spec.containers[0].name }}
|
||||
{{ request.object.spec.containers[].name }} # все имена
|
||||
|
||||
# Время
|
||||
{{ time_now_utc() }} # текущее UTC время
|
||||
```
|
||||
|
||||
## Тест audit аннотаций
|
||||
|
||||
```bash
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: test-audit
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: test
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: nginx:1.25.3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
EOF
|
||||
|
||||
kubectl get deployment test-audit \
|
||||
-o jsonpath='{.metadata.annotations}' | jq .
|
||||
# Увидите: created-by, created-at, user-groups
|
||||
|
||||
kubectl delete deployment test-audit
|
||||
```
|
||||
34
03-mutation/03-advanced/add-creator-audit-annotation.yaml
Normal file
34
03-mutation/03-advanced/add-creator-audit-annotation.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-creator-audit-annotation
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Аннотация аудита создателя ресурса"
|
||||
policies.kyverno.io/category: Governance
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Deployment,StatefulSet
|
||||
policies.kyverno.io/description: >-
|
||||
При создании Deployment или StatefulSet автоматически добавляет
|
||||
аннотации: кто создал, когда, из каких групп.
|
||||
Создаёт автоматический audit trail без дополнительных инструментов.
|
||||
spec:
|
||||
rules:
|
||||
- name: add-creator-annotation
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
preconditions:
|
||||
any:
|
||||
- key: "{{ request.operation }}"
|
||||
operator: Equals
|
||||
value: CREATE
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
annotations:
|
||||
audit.company.com/created-by: "{{ request.userInfo.username }}"
|
||||
audit.company.com/created-at: "{{ time_now_utc() }}"
|
||||
audit.company.com/user-groups: >-
|
||||
{{ request.userInfo.groups | join(', ', @) }}
|
||||
22
03-mutation/03-advanced/kyverno-global-config.yaml
Normal file
22
03-mutation/03-advanced/kyverno-global-config.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kyverno-global-config
|
||||
namespace: kyverno
|
||||
labels:
|
||||
app: kyverno-config
|
||||
data:
|
||||
# Дефолтные resource limits по типу сервиса
|
||||
api_memory: "512Mi"
|
||||
api_cpu: "500m"
|
||||
worker_memory: "1Gi"
|
||||
worker_cpu: "250m"
|
||||
default_memory: "256Mi"
|
||||
default_cpu: "250m"
|
||||
|
||||
# Node selector defaults
|
||||
default_node_type: "standard"
|
||||
region: "eu-west-1"
|
||||
|
||||
# Allowed registries (через запятую)
|
||||
allowed_registries: "registry.company.com,gcr.io/company-project"
|
||||
44
03-mutation/03-advanced/set-dynamic-resource-limits.yaml
Normal file
44
03-mutation/03-advanced/set-dynamic-resource-limits.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: set-dynamic-resource-limits
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Динамические resource limits из ConfigMap"
|
||||
policies.kyverno.io/category: Resources
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Устанавливает resource limits на основе лейбла service-type пода.
|
||||
Значения берутся из ConfigMap kyverno-global-config в namespace kyverno.
|
||||
Изменение лимитов — это kubectl edit configmap, не изменение политики.
|
||||
Лейблы: service-type: api | worker | (default)
|
||||
spec:
|
||||
rules:
|
||||
- name: set-limits-from-config
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
context:
|
||||
- name: globalConfig
|
||||
configMap:
|
||||
name: kyverno-global-config
|
||||
namespace: kyverno
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.containers"
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ element.name }}"
|
||||
resources:
|
||||
limits:
|
||||
+(memory): >-
|
||||
{{ globalConfig.data.\"{{ request.object.metadata.labels.\"service-type\" || 'default' }}_memory\" || '256Mi' }}
|
||||
+(cpu): >-
|
||||
{{ globalConfig.data.\"{{ request.object.metadata.labels.\"service-type\" || 'default' }}_cpu\" || '250m' }}
|
||||
Reference in New Issue
Block a user