init
This commit is contained in:
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"
|
||||
Reference in New Issue
Block a user