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"
|
||||
Reference in New Issue
Block a user