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,128 @@
# Урок 5.3 — Переиспользуемые шаблоны политик (Helm Chart)
## Структура
```
kyverno-policies/
├── Chart.yaml
├── values.yaml # дефолтные значения
├── values-staging.yaml # overrides для staging
├── values-production.yaml # overrides для production
├── templates/
│ ├── require-resource-limits.yaml
│ ├── disallow-privileged.yaml
│ ├── require-labels.yaml
│ └── generate-networkpolicy.yaml
└── tests/
├── kyverno-test.yaml
└── resources/
├── pod-compliant.yaml
├── pod-no-limits.yaml
├── pod-privileged.yaml
└── deployment-no-labels.yaml
```
## Запуск тестов (без кластера)
```bash
cd kyverno-policies
# Сгенерировать манифесты из шаблонов и протестировать
helm template . -f values.yaml | \
kyverno apply - --resource tests/resources/ --table
# Запустить встроенные kyverno тесты
# (сначала нужно отрендерить шаблоны в обычные YAML)
helm template . -f values.yaml --output-dir /tmp/rendered-policies
kyverno test tests/ \
--policy-report \
--detailed-results
```
## Деплой в кластер
```bash
# Staging — всё в Audit
helm upgrade --install kyverno-policies . \
--namespace kyverno \
--create-namespace \
-f values-staging.yaml
# Production — Enforce
helm upgrade --install kyverno-policies . \
--namespace kyverno \
--create-namespace \
-f values-production.yaml
# Проверить задеплоенные политики
kubectl get clusterpolicies -l helm.sh/chart=kyverno-policies-1.0.0
# Rollback если что-то пошло не так
helm rollback kyverno-policies 1 -n kyverno
```
## PolicyException — управляемые исключения
```bash
# Применить временное исключение для legacy-сервиса
kubectl apply -f - <<EOF
apiVersion: kyverno.io/v2beta1
kind: PolicyException
metadata:
name: legacy-app-exception
namespace: production
annotations:
exception.company.com/expires: "2025-03-01"
exception.company.com/reason: "Migration in progress — JIRA-1234"
exception.company.com/approved-by: "platform-team"
spec:
exceptions:
- policyName: require-resource-limits
ruleNames:
- check-container-limits
match:
resources:
kinds:
- Pod
namespaces:
- production
names:
- legacy-app-*
EOF
# Посмотреть все активные исключения
kubectl get policyexceptions -A
```
## CI/CD для Helm chart политик
```bash
# Линтинг
helm lint . -f values.yaml
helm lint . -f values-production.yaml
# Dry-run деплой
helm upgrade --install kyverno-policies . \
--namespace kyverno \
-f values-production.yaml \
--dry-run
# diff перед применением (требует helm-diff plugin)
helm plugin install https://github.com/databus23/helm-diff
helm diff upgrade kyverno-policies . \
--namespace kyverno \
-f values-production.yaml
```
## Версионирование изменений
```yaml
# При изменении политики — обновляйте версию в Chart.yaml
# и добавляйте запись в аннотацию политики:
annotations:
policies.kyverno.io/version: "1.1.0"
policies.kyverno.io/changelog: |
1.1.0: Добавлена проверка ephemeral containers
1.0.0: Начальная версия
```

View File

@@ -0,0 +1,16 @@
apiVersion: v2
name: kyverno-policies
description: >-
Корпоративные политики безопасности Kyverno.
Содержит базовый набор validation, mutation и generation политик.
type: application
version: 1.0.0
appVersion: "1.11"
keywords:
- kyverno
- policy
- security
- kubernetes
maintainers:
- name: Platform Team
email: platform@company.com

View File

@@ -0,0 +1,42 @@
{{- if .Values.disallowPrivileged.enabled }}
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
annotations:
policies.kyverno.io/title: "Запрет привилегированных контейнеров"
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: critical
policies.kyverno.io/version: {{ .Chart.Version }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
spec:
validationFailureAction: {{ .Values.disallowPrivileged.failureAction | default .Values.global.failureAction }}
background: true
rules:
- name: privileged-containers
match:
resources:
kinds:
- Pod
exclude:
resources:
namespaces:
{{- range .Values.global.excludedNamespaces }}
- {{ . }}
{{- end }}
validate:
message: >-
Контейнер '{{ "{{" }} element.name {{ "}}" }}' имеет privileged: true.
Привилегированные контейнеры запрещены политикой безопасности.
foreach:
- list: >-
request.object.spec.containers[] |
merge(request.object.spec.initContainers[] || `[]`, @) |
merge(request.object.spec.ephemeralContainers[] || `[]`, @)
deny:
conditions:
any:
- key: "{{ "{{" }} element.securityContext.privileged {{ "}}" }}"
operator: Equals
value: true
{{- end }}

View File

@@ -0,0 +1,44 @@
{{- if .Values.generateNetworkPolicy.enabled }}
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/version: {{ .Chart.Version }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
spec:
rules:
- name: generate-deny-all
match:
resources:
kinds:
- Namespace
exclude:
resources:
names:
{{- range (concat .Values.global.excludedNamespaces .Values.generateNetworkPolicy.excludedNamespaces) | uniq }}
- {{ . }}
{{- end }}
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
helm-release: {{ .Release.Name }}
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
{{- end }}

View File

@@ -0,0 +1,40 @@
{{- if .Values.requiredLabels.enabled }}
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-standard-labels
annotations:
policies.kyverno.io/title: "Обязательные стандартные лейблы"
policies.kyverno.io/category: Governance
policies.kyverno.io/severity: medium
policies.kyverno.io/version: {{ .Chart.Version }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
spec:
validationFailureAction: {{ .Values.requiredLabels.failureAction | default .Values.global.failureAction }}
background: true
rules:
- name: check-required-labels
match:
resources:
kinds:
- Deployment
- StatefulSet
- DaemonSet
exclude:
resources:
namespaces:
{{- range .Values.global.excludedNamespaces }}
- {{ . }}
{{- end }}
validate:
message: >-
Ресурс '{{ "{{" }} request.object.metadata.name {{ "}}" }}'
должен иметь все обязательные лейблы:
{{ .Values.requiredLabels.labels | join ", " }}
pattern:
metadata:
labels:
{{- range .Values.requiredLabels.labels }}
{{ . }}: "?*"
{{- end }}
{{- end }}

View File

@@ -0,0 +1,41 @@
{{- if .Values.resourceLimits.enabled }}
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
annotations:
policies.kyverno.io/title: "Обязательные resource limits"
policies.kyverno.io/category: Resources
policies.kyverno.io/severity: high
policies.kyverno.io/version: {{ .Chart.Version }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
spec:
validationFailureAction: {{ .Values.resourceLimits.failureAction | default .Values.global.failureAction }}
background: true
rules:
- name: check-container-limits
match:
resources:
kinds:
- Pod
exclude:
resources:
namespaces:
{{- range .Values.global.excludedNamespaces }}
- {{ . }}
{{- end }}
validate:
message: >-
Контейнер '{{ "{{" }} element.name {{ "}}" }}' не имеет resource limits.
Добавьте resources.limits.memory и resources.limits.cpu.
foreach:
- list: >-
request.object.spec.containers[] |
merge(request.object.spec.initContainers[] || `[]`, @) |
merge(request.object.spec.ephemeralContainers[] || `[]`, @)
pattern:
resources:
limits:
memory: "?*"
cpu: "?*"
{{- end }}

View File

@@ -0,0 +1,31 @@
name: kyverno-policies-chart-tests
policies:
- ../templates/require-resource-limits.yaml
- ../templates/disallow-privileged.yaml
- ../templates/require-labels.yaml
resources:
- resources/pod-compliant.yaml
- resources/pod-no-limits.yaml
- resources/pod-privileged.yaml
- resources/deployment-no-labels.yaml
results:
- policy: require-resource-limits
rule: check-container-limits
resource: pod-compliant
namespace: default
result: pass
- policy: require-resource-limits
rule: check-container-limits
resource: pod-no-limits
namespace: default
result: fail
- policy: disallow-privileged-containers
rule: privileged-containers
resource: pod-privileged
namespace: default
result: fail
- policy: require-standard-labels
rule: check-required-labels
resource: deployment-no-labels
namespace: default
result: fail

View File

@@ -0,0 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-no-labels
namespace: default
# нет лейблов app, team, environment
spec:
replicas: 1
selector:
matchLabels:
run: app
template:
metadata:
labels:
run: app
spec:
containers:
- name: app
image: nginx:1.25.3
resources:
limits:
memory: "128Mi"
cpu: "100m"

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: pod-compliant
namespace: default
spec:
containers:
- name: app
image: nginx:1.25.3
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Pod
metadata:
name: pod-no-limits
namespace: default
spec:
containers:
- name: app
image: nginx:1.25.3

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: pod-privileged
namespace: default
spec:
containers:
- name: app
image: nginx:1.25.3
securityContext:
privileged: true
resources:
limits:
memory: "128Mi"
cpu: "100m"

View File

@@ -0,0 +1,21 @@
# Production overrides
global:
failureAction: Enforce
resourceLimits:
enabled: true
maxMemory: "8Gi"
maxCpu: "8"
disallowLatestTag:
enabled: true
failureAction: Enforce
requiredLabels:
enabled: true
failureAction: Enforce
labels:
- app
- team
- environment
- version

View File

@@ -0,0 +1,10 @@
# Staging overrides — всё в Audit для наблюдения
global:
failureAction: Audit
disallowPrivileged:
enabled: true
failureAction: Audit # в staging даже security в Audit
generateNetworkPolicy:
enabled: false # в staging не генерируем NetworkPolicy

View File

@@ -0,0 +1,55 @@
# Дефолтные значения для kyverno-policies Helm chart.
# Переопределите в values-staging.yaml или values-production.yaml.
global:
# Audit = фиксировать нарушения, Enforce = блокировать
failureAction: Audit
excludedNamespaces:
- kube-system
- kube-public
- kube-node-lease
- kyverno
# --- Политика: resource limits ---
resourceLimits:
enabled: true
failureAction: "" # пусто = использовать global.failureAction
maxMemory: "4Gi"
maxCpu: "4"
# --- Политика: запрет latest тега ---
disallowLatestTag:
enabled: true
failureAction: ""
# --- Политика: обязательные лейблы ---
requiredLabels:
enabled: true
failureAction: ""
labels:
- app
- team
- environment
# --- Политика: привилегированные контейнеры ---
disallowPrivileged:
enabled: true
# security политики всегда Enforce
failureAction: Enforce
# --- Политика: запрет host namespaces ---
disallowHostNamespaces:
enabled: true
failureAction: Enforce
# --- Политика: автодобавление лейблов (mutation) ---
addStandardLabels:
enabled: true
# --- Политика: генерация NetworkPolicy ---
generateNetworkPolicy:
enabled: true
excludedNamespaces:
- monitoring
- logging
- istio-system