init
This commit is contained in:
96
04-generation/01-configmaps-secrets/README.md
Normal file
96
04-generation/01-configmaps-secrets/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Урок 4.1 — Автоматическое создание ConfigMaps и Secrets
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Триггер | Что создаёт |
|
||||
|------|---------|-------------|
|
||||
| `generate-namespace-config.yaml` | Namespace | ConfigMap с мета-данными namespace |
|
||||
| `generate-default-networkpolicy.yaml` | Namespace | NetworkPolicy deny-all |
|
||||
| `generate-resource-quota.yaml` | Namespace | ResourceQuota по tier |
|
||||
| `quota-defaults-configmap.yaml` | — | ConfigMap с квотами (нужен заранее) |
|
||||
| `clone-registry-secret.yaml` | Namespace | Копия registry Secret |
|
||||
| `generate-developer-rolebinding.yaml` | Namespace+label | RoleBinding для команды |
|
||||
| `developer-clusterrole.yaml` | — | ClusterRole developer (нужна заранее) |
|
||||
|
||||
## Подготовка (применить до политик)
|
||||
|
||||
```bash
|
||||
# 1. Создать ConfigMap с квотами
|
||||
kubectl apply -f quota-defaults-configmap.yaml
|
||||
|
||||
# 2. Создать ClusterRole developer
|
||||
kubectl apply -f developer-clusterrole.yaml
|
||||
|
||||
# 3. Создать мастер-секрет для registry (замените данные на реальные)
|
||||
kubectl create secret docker-registry registry-credentials-master \
|
||||
--docker-server=registry.company.com \
|
||||
--docker-username=robot-account \
|
||||
--docker-password=your-token \
|
||||
--namespace=kyverno
|
||||
|
||||
# 4. Применить все политики
|
||||
kubectl apply -f generate-namespace-config.yaml
|
||||
kubectl apply -f generate-default-networkpolicy.yaml
|
||||
kubectl apply -f generate-resource-quota.yaml
|
||||
kubectl apply -f clone-registry-secret.yaml
|
||||
kubectl apply -f generate-developer-rolebinding.yaml
|
||||
```
|
||||
|
||||
## Тест: создать namespace и проверить генерацию
|
||||
|
||||
```bash
|
||||
# Создать тестовый namespace
|
||||
kubectl create namespace test-team \
|
||||
--dry-run=client -o yaml | \
|
||||
kubectl apply -f -
|
||||
|
||||
kubectl label namespace test-team \
|
||||
team=platform \
|
||||
tier=standard \
|
||||
environment=staging
|
||||
|
||||
# Подождать ~5 секунд для генерации, затем проверить
|
||||
kubectl get configmap,networkpolicy,resourcequota,rolebinding \
|
||||
-n test-team
|
||||
|
||||
# Детали сгенерированных ресурсов
|
||||
kubectl get configmap namespace-config -n test-team -o yaml
|
||||
kubectl get networkpolicy default-deny-all -n test-team -o yaml
|
||||
kubectl get resourcequota default-quota -n test-team -o yaml
|
||||
```
|
||||
|
||||
## Тест synchronize — защита от случайного удаления
|
||||
|
||||
```bash
|
||||
# Удалить NetworkPolicy вручную
|
||||
kubectl delete networkpolicy default-deny-all -n test-team
|
||||
|
||||
# Kyverno восстановит её через несколько секунд
|
||||
sleep 10
|
||||
kubectl get networkpolicy -n test-team
|
||||
# default-deny-all снова присутствует
|
||||
```
|
||||
|
||||
## Тест cascade delete
|
||||
|
||||
```bash
|
||||
# Удалить namespace — все сгенерированные ресурсы удалятся вместе с ним
|
||||
kubectl delete namespace test-team
|
||||
|
||||
# Проверить что ресурсы не зависли
|
||||
kubectl get generaterequests -n kyverno
|
||||
```
|
||||
|
||||
## Мониторинг GenerateRequests
|
||||
|
||||
```bash
|
||||
# Просмотр очереди генерации
|
||||
kubectl get generaterequests -n kyverno -o wide
|
||||
|
||||
# Детали при ошибке
|
||||
kubectl describe generaterequests -n kyverno | grep -A 20 "Status:"
|
||||
|
||||
# Метрики генерации
|
||||
kubectl port-forward -n kyverno svc/kyverno-svc-metrics 8000:8000 &
|
||||
curl -s http://localhost:8000/metrics | grep kyverno_generate
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: clone-registry-secret
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Копирование Registry Secret во все Namespace"
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Namespace
|
||||
policies.kyverno.io/description: >-
|
||||
При создании Namespace копирует Secret с кредентиалами реестра
|
||||
из namespace kyverno (мастер-копия) в новый namespace.
|
||||
synchronize: true — при обновлении мастер-секрета все копии обновятся.
|
||||
Создайте мастер-секрет: kubectl create secret docker-registry
|
||||
registry-credentials-master -n kyverno ...
|
||||
spec:
|
||||
rules:
|
||||
- name: clone-registry-credentials
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
exclude:
|
||||
resources:
|
||||
names:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
name: registry-credentials
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
synchronize: true
|
||||
# clone копирует существующий ресурс вместо создания из шаблона
|
||||
clone:
|
||||
namespace: kyverno
|
||||
name: registry-credentials-master
|
||||
@@ -0,0 +1,36 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: developer
|
||||
labels:
|
||||
app: kyverno-config
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- pods
|
||||
- pods/log
|
||||
- pods/exec
|
||||
- services
|
||||
- configmaps
|
||||
- persistentvolumeclaims
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
- apiGroups: ["apps"]
|
||||
resources:
|
||||
- deployments
|
||||
- statefulsets
|
||||
- daemonsets
|
||||
- replicasets
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
- apiGroups: ["batch"]
|
||||
resources:
|
||||
- jobs
|
||||
- cronjobs
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
- apiGroups: ["networking.k8s.io"]
|
||||
resources:
|
||||
- ingresses
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- secrets
|
||||
verbs: ["get", "list", "watch"] # только чтение секретов
|
||||
@@ -0,0 +1,51 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-default-networkpolicy
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Генерация NetworkPolicy по умолчанию"
|
||||
policies.kyverno.io/category: Security
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Namespace
|
||||
policies.kyverno.io/description: >-
|
||||
При создании Namespace автоматически создаёт NetworkPolicy
|
||||
"запрети весь трафик по умолчанию". Zero Trust сетевая модель:
|
||||
команды явно разрешают нужный трафик поверх этой базовой политики.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-deny-all-networkpolicy
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
exclude:
|
||||
resources:
|
||||
names:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
- monitoring
|
||||
- logging
|
||||
generate:
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
name: default-deny-all
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
synchronize: true
|
||||
data:
|
||||
kind: NetworkPolicy
|
||||
apiVersion: networking.k8s.io/v1
|
||||
metadata:
|
||||
name: default-deny-all
|
||||
labels:
|
||||
generated-by: kyverno
|
||||
annotations:
|
||||
description: >-
|
||||
Запрещает весь входящий и исходящий трафик по умолчанию.
|
||||
Добавьте явные NetworkPolicy для разрешения нужного трафика.
|
||||
spec:
|
||||
podSelector: {} # применяется ко всем подам
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
@@ -0,0 +1,52 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-developer-rolebinding
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Генерация RoleBinding для команды"
|
||||
policies.kyverno.io/category: RBAC
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Namespace
|
||||
policies.kyverno.io/description: >-
|
||||
При создании Namespace с лейблом team: <name> автоматически создаёт
|
||||
RoleBinding, дающий группе <name>-developers права ClusterRole developer.
|
||||
Namespace с лейблом team=payments → группа payments-developers получает доступ.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-team-rolebinding
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: team
|
||||
operator: Exists
|
||||
exclude:
|
||||
resources:
|
||||
names:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
generate:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
name: developer-access
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
synchronize: true
|
||||
data:
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: developer-access
|
||||
labels:
|
||||
generated-by: kyverno
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: developer # ClusterRole должна существовать
|
||||
subjects:
|
||||
- kind: Group
|
||||
name: "{{ request.object.metadata.labels.team }}-developers"
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
@@ -0,0 +1,45 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-namespace-config
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Генерация ConfigMap при создании Namespace"
|
||||
policies.kyverno.io/category: Governance
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Namespace
|
||||
policies.kyverno.io/description: >-
|
||||
При создании нового Namespace автоматически создаёт ConfigMap
|
||||
с базовой конфигурацией. synchronize: true — ConfigMap обновляется
|
||||
при изменении namespace и удаляется вместе с ним.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-config
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
exclude:
|
||||
resources:
|
||||
names:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
name: namespace-config
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
synchronize: true
|
||||
data:
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
generated-by: kyverno
|
||||
policy: generate-namespace-config
|
||||
data:
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
environment: "{{ request.object.metadata.labels.environment || 'unknown' }}"
|
||||
team: "{{ request.object.metadata.labels.team || 'unknown' }}"
|
||||
created-at: "{{ time_now_utc() }}"
|
||||
documentation: "https://wiki.company.com/kubernetes/namespaces"
|
||||
@@ -0,0 +1,59 @@
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: generate-resource-quota
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Генерация ResourceQuota для Namespace"
|
||||
policies.kyverno.io/category: Resources
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Namespace
|
||||
policies.kyverno.io/description: >-
|
||||
При создании Namespace генерирует ResourceQuota.
|
||||
Квота зависит от лейбла tier: standard | premium.
|
||||
Значения квот берутся из ConfigMap quota-defaults.
|
||||
spec:
|
||||
rules:
|
||||
- name: generate-quota
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
exclude:
|
||||
resources:
|
||||
names:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
context:
|
||||
- name: quotaConfig
|
||||
configMap:
|
||||
name: quota-defaults
|
||||
namespace: kyverno
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
name: default-quota
|
||||
namespace: "{{ request.object.metadata.name }}"
|
||||
synchronize: true
|
||||
data:
|
||||
kind: ResourceQuota
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: default-quota
|
||||
labels:
|
||||
generated-by: kyverno
|
||||
spec:
|
||||
hard:
|
||||
# Квота CPU зависит от tier namespace
|
||||
requests.cpu: >-
|
||||
{{ quotaConfig.data.\"{{ request.object.metadata.labels.tier || 'standard' }}_cpu_request\" || '4' }}
|
||||
requests.memory: >-
|
||||
{{ quotaConfig.data.\"{{ request.object.metadata.labels.tier || 'standard' }}_memory_request\" || '8Gi' }}
|
||||
limits.cpu: >-
|
||||
{{ quotaConfig.data.\"{{ request.object.metadata.labels.tier || 'standard' }}_cpu_limit\" || '8' }}
|
||||
limits.memory: >-
|
||||
{{ quotaConfig.data.\"{{ request.object.metadata.labels.tier || 'standard' }}_memory_limit\" || '16Gi' }}
|
||||
pods: "50"
|
||||
services: "20"
|
||||
persistentvolumeclaims: "10"
|
||||
@@ -0,0 +1,25 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: quota-defaults
|
||||
namespace: kyverno
|
||||
labels:
|
||||
app: kyverno-config
|
||||
data:
|
||||
# Standard tier (по умолчанию)
|
||||
standard_cpu_request: "4"
|
||||
standard_memory_request: "8Gi"
|
||||
standard_cpu_limit: "8"
|
||||
standard_memory_limit: "16Gi"
|
||||
|
||||
# Premium tier (для нагруженных сервисов)
|
||||
premium_cpu_request: "16"
|
||||
premium_memory_request: "32Gi"
|
||||
premium_cpu_limit: "32"
|
||||
premium_memory_limit: "64Gi"
|
||||
|
||||
# Dev tier (для разработки)
|
||||
dev_cpu_request: "2"
|
||||
dev_memory_request: "4Gi"
|
||||
dev_cpu_limit: "4"
|
||||
dev_memory_limit: "8Gi"
|
||||
106
04-generation/02-lifecycle/README.md
Normal file
106
04-generation/02-lifecycle/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Урок 4.2 — Управление жизненным циклом генерируемых ресурсов
|
||||
|
||||
## Файлы
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `cleanup-debug-pods.yaml` | CleanupPolicy — автоудаление debug подов старше 4ч |
|
||||
|
||||
## Параметр synchronize — детально
|
||||
|
||||
```yaml
|
||||
generate:
|
||||
synchronize: true # живая ссылка: обновляется, восстанавливается, удаляется вместе
|
||||
synchronize: false # создать один раз, дальше независимо
|
||||
```
|
||||
|
||||
| Событие | synchronize: true | synchronize: false |
|
||||
|---------|-------------------|-------------------|
|
||||
| Источник изменился | Генерируемый обновляется | Без изменений |
|
||||
| Генерируемый удалён | Восстанавливается | Не восстанавливается |
|
||||
| Источник удалён | Генерируемый удаляется | Остаётся |
|
||||
|
||||
## Применение CleanupPolicy
|
||||
|
||||
```bash
|
||||
# CleanupPolicy требует Kyverno >= 1.9
|
||||
kubectl apply -f cleanup-debug-pods.yaml
|
||||
|
||||
# Проверить статус
|
||||
kubectl get clustercleanuppolicies
|
||||
```
|
||||
|
||||
## Тест CleanupPolicy
|
||||
|
||||
```bash
|
||||
# Создать debug-под
|
||||
kubectl run debug-test \
|
||||
--image=busybox:1.36 \
|
||||
--labels="purpose=debug" \
|
||||
--restart=Never \
|
||||
-- sleep 3600
|
||||
|
||||
# Принудительно запустить cleanup (изменив schedule на ближайшую минуту)
|
||||
# Или подождать час и проверить:
|
||||
kubectl get pod debug-test
|
||||
|
||||
# Проверить логи cleanup controller
|
||||
kubectl logs -n kyverno \
|
||||
-l app.kubernetes.io/component=cleanup-controller \
|
||||
--tail=30
|
||||
```
|
||||
|
||||
## Диагностика GenerateRequests
|
||||
|
||||
```bash
|
||||
# Все GenerateRequests
|
||||
kubectl get generaterequests -n kyverno
|
||||
|
||||
# Зависшие в Processing статусе
|
||||
kubectl get generaterequests -n kyverno \
|
||||
-o jsonpath='{range .items[?(@.status.state=="Failed")]}{.metadata.name}{"\n"}{end}'
|
||||
|
||||
# Детали конкретного
|
||||
kubectl describe generaterequest <name> -n kyverno
|
||||
|
||||
# Типичные причины ошибок:
|
||||
# 1. Нет прав у Kyverno ServiceAccount
|
||||
kubectl get clusterrolebinding | grep kyverno
|
||||
# 2. Ресурс уже существует (не управляется Kyverno)
|
||||
# 3. Синтаксическая ошибка в шаблоне generate
|
||||
```
|
||||
|
||||
## Взять под управление существующий ресурс
|
||||
|
||||
```bash
|
||||
# Если ресурс уже существует и нужно передать его Kyverno:
|
||||
kubectl label configmap namespace-config \
|
||||
-n my-namespace \
|
||||
kyverno.io/managed=true
|
||||
|
||||
# Или удалить ресурс, Kyverno пересоздаст его
|
||||
kubectl delete configmap namespace-config -n my-namespace
|
||||
# Kyverno создаст новый через background controller
|
||||
```
|
||||
|
||||
## Bootstrap Namespace — полный сценарий
|
||||
|
||||
```bash
|
||||
# Одна команда создаёт полностью настроенный namespace:
|
||||
kubectl create namespace payments-service
|
||||
kubectl label namespace payments-service \
|
||||
team=payments \
|
||||
tier=premium \
|
||||
environment=production
|
||||
|
||||
# Через ~10 секунд:
|
||||
kubectl get all,configmap,secret,networkpolicy,resourcequota,rolebinding \
|
||||
-n payments-service
|
||||
|
||||
# Ожидаемый результат:
|
||||
# configmap/namespace-config
|
||||
# networkpolicy/default-deny-all
|
||||
# resourcequota/default-quota (с premium квотами)
|
||||
# secret/registry-credentials
|
||||
# rolebinding/developer-access (для группы payments-developers)
|
||||
```
|
||||
29
04-generation/02-lifecycle/cleanup-debug-pods.yaml
Normal file
29
04-generation/02-lifecycle/cleanup-debug-pods.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: kyverno.io/v2alpha1
|
||||
kind: ClusterCleanupPolicy
|
||||
metadata:
|
||||
name: cleanup-debug-pods
|
||||
annotations:
|
||||
policies.kyverno.io/title: "Автоудаление debug подов"
|
||||
policies.kyverno.io/category: Governance
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/description: >-
|
||||
Удаляет поды с лейблом purpose=debug старше 4 часов.
|
||||
Запускается каждый час по расписанию.
|
||||
Предотвращает накопление забытых отладочных подов в кластере.
|
||||
spec:
|
||||
schedule: "0 * * * *" # каждый час в :00
|
||||
match:
|
||||
resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaces:
|
||||
- default
|
||||
- staging
|
||||
selector:
|
||||
matchLabels:
|
||||
purpose: debug
|
||||
conditions:
|
||||
any:
|
||||
- key: "{{ time_since('', request.object.metadata.creationTimestamp, '') }}"
|
||||
operator: GreaterThan
|
||||
value: "4h"
|
||||
Reference in New Issue
Block a user