Trivy Operator в Kubernetes: непрерывное сканирование уязвимостей
Published: 2026-02-26
trivy image в CI ловит уязвимости на этапе сборки. Но что с образами, которые уже работают в продакшене и месяц назад были чистыми? Trivy Operator непрерывно сканирует все рабочие нагрузки в кластере и публикует результаты в виде Kubernetes-ресурсов — с метриками Prometheus для алертов.
Установка через Helm / FluxCD
yamlapiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: trivy-operator
spec:
interval: 1h
chart:
spec:
chart: trivy-operator
version: "0.x"
sourceRef:
kind: HelmRepository
name: aquasecurity
namespace: flux-system
values:
operator:
vulnerabilityScannerEnabled: true
configAuditScannerEnabled: true
rbacAssessmentScannerEnabled: true
infraAssessmentScannerEnabled: true
metricsVulnIdEnabled: true
scanJobsConcurrentLimit: 2
trivy:
ignoreUnfixed: true
mode: Standalone
severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
serviceMonitor:
enabled: true
labels:
release: kube-prom-stack
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1000m
memory: 2048Mi
ignoreUnfixed: true критически важен: уязвимости без исправлений неустранимы. Без этого дашборды забиваются тысячами CVE, с которыми ничего нельзя сделать.
scanJobsConcurrentLimit: 2 — без лимита оператор при первой установке одновременно запускает по одной джобе на каждую рабочую нагрузку и перегружает ноды.
mode: Standalone — Trivy скачивает базу уязвимостей прямо в джобе сканирования. Для изолированных (air-gapped) окружений используйте ClientServer.
Что сканируется
Оператор создаёт джобы сканирования для отчётов:
- VulnerabilityReport — CVE в образах (на каждый контейнер в поде)
- ConfigAuditReport — небезопасные настройки Kubernetes (нет
securityContext, privileged-контейнеры и т.д.) - RbacAssessmentReport — избыточно широкие RBAC-роли
- InfraAssessmentReport — проверки hardening для control plane
bashkubectl get vulnerabilityreport -A
kubectl get configauditreport -A
kubectl get rbacassessmentreport -A
Результаты хранятся как Kubernetes CRD в том же неймспейсе, что и рабочая нагрузка, и обновляются каждые 24 часа.
Чтение VulnerabilityReport
bash# Сводка
kubectl get vulnerabilityreport -n app my-app-deployment-my-container \
-o jsonpath='{.report.summary}'
json{"criticalCount":0,"highCount":3,"lowCount":47,"mediumCount":12}
Детали HIGH CVE:
bashkubectl get vulnerabilityreport -n app my-app-deployment-my-container \
-o json | jq '.report.vulnerabilities[] | select(.severity=="HIGH") | {id: .vulnerabilityID, pkg: .resource, fixed: .fixedVersion}'
Метрики Prometheus и алерты
promql# CRITICAL CVE по всем рабочим нагрузкам
sum(trivy_image_vulnerabilities{severity="CRITICAL"}) by (namespace, resource_name)
yaml- alert: TrivyCriticalVulnerabilities
expr: sum(trivy_image_vulnerabilities{severity="CRITICAL"}) by (namespace, resource_name) > 0
for: 10m
labels:
severity: high
annotations:
summary: "{{ $labels.resource_name }} в {{ $labels.namespace }}: {{ $value }} CRITICAL CVE"
description: "Обновите базовый образ или добавьте .trivyignore для принятых рисков"
- alert: TrivyConfigAuditFailed
expr: trivy_resource_configaudits{severity="CRITICAL"} > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Config audit: критическая находка в {{ $labels.resource_name }}"
Дашборд Grafana: ID 17813 (Trivy Operator - Vulnerabilities Dashboard).
CI vs Trivy Operator: нужны оба
CI ловит уязвимости до попадания в продакшен. Оператор ловит то, что появляется после деплоя:
- В ОС базового образа нашли новый CVE, а пересборки не было
- Зависимость из работающего образа только что добавили в NVD
- Новая рабочая нагрузка развёрнута мимо CI (хотфикс, ручной
kubectl apply)
Не выбирайте — запускайте оба.
Trivy в GitLab CI
yamltrivy-scan:
image: aquasec/trivy:latest
script:
- trivy image
--format json
--output trivy-report.json
--severity HIGH,CRITICAL
--exit-code 1
registry.example.com/myapp:$CI_COMMIT_SHORT_SHA
artifacts:
reports:
container_scanning: trivy-report.json
when: always
--exit-code 1 останавливает пайплайн с ошибкой при находках HIGH или CRITICAL. Известные ложные срабатывания подавляются так:
# .trivyignore
# Известный false-positive, исправления нет (2026-02-26)
CVE-2023-12345
Коммитьте файл рядом с Dockerfile — так подавление на виду и его легко проверить при аудите.
Исключение namespace
yamlvalues:
operator:
excludeNamespaces: "kube-system,flux-system,cert-manager"
Это снижает шум и убирает лишние джобы сканирования для инфраструктурных компонентов.