This commit is contained in:
2026-04-08 20:22:14 +07:00
commit 34fbdd1412
96 changed files with 5321 additions and 0 deletions

View 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
```

View File

@@ -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

View File

@@ -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"] # только чтение секретов

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"