Trivy

Continuous vulnerability scanning for running workloads via Trivy Operator.

What is Trivy Operator?

Trivy Operator is a Kubernetes operator by Aqua Security that continuously scans all running workloads for container image vulnerabilities (CVEs), Kubernetes configuration issues, and compliance violations. Results are stored as Kubernetes Custom Resources queryable with kubectl.

Why Trivy?

Trivy is the most widely adopted open-source vulnerability scanner. The Operator pattern means scanning happens automatically whenever a workload changes — no manual scans required, no separate CI pipeline integration needed.

ToolScan typeWhen
Trivy OperatorRunning workloads in clusterContinuous, on pod change
FalcoSyscall behaviorRuntime (live)
Harbor's TrivyImages on push to registryOn registry push

How It's Used Here

Trivy Operator runs as a single-replica Deployment in the trivy namespace. It watches for new or updated Pods and spawns scan Jobs that pull the image and check it against the Trivy vulnerability database.

Source: workloads/security/trivy.go

Configuration

SettingValueWhy
NamespacetrivyIsolated namespace
Chart versiontrivy-operator v0.32.0Pinned version
Replicas1Single operator instance
scanJobsConcurrentLimit3Max parallel scan Jobs
scanJobsRetryDelay30sWait between retries on scan failure
scanJobTimeout5mTimeout for each scan Job
serviceMonitor.enabledtrueVMAgent scrapes Trivy metrics
Resources (limit)500m / 512MiOperator itself is lightweight; scan Jobs are separate

What It Scans

Scan typeCRDDescription
Container imagesVulnerabilityReportCVEs in container images of running pods
ConfigurationConfigAuditReportKubernetes security misconfigs (e.g., no resource limits, privileged containers)
Exposed secretsExposedSecretReportSecrets found in image layers or environment variables
SBOMSbomReportSoftware Bill of Materials for image layers

Querying Reports

# List vulnerability reports across all namespaces
kubectl get vulnerabilityreports -A

# Summary: just namespace + name + critical/high counts
kubectl get vulnerabilityreports -A \
  -o custom-columns="NS:.metadata.namespace,NAME:.metadata.name,CRITICAL:.report.summary.criticalCount,HIGH:.report.summary.highCount"

# Inspect a specific report
kubectl describe vulnerabilityreport <name> -n <namespace>

# List config audit reports
kubectl get configauditreports -A

# List exposed secret reports
kubectl get exposedsecretreports -A

How It Connects

New/updated Pod in any namespace
  → Trivy Operator detects change
  → Spawns scan Job (pulls image, checks against vulnerability DB)
  → Stores results as VulnerabilityReport CR in same namespace
  → VMAgent scrapes Trivy metrics via ServiceMonitor
  → Grafana dashboard (optional — CRD-based data, not metrics-based)

Troubleshooting

Scan Jobs Failing

Symptoms: VulnerabilityReport not created after deploying a new workload.

# Check scan jobs
kubectl get jobs -A | grep trivy

# Check job logs
kubectl logs -n <target-namespace> job/<trivy-scan-job>

Common causes: Image pull failure (private registry without credentials), scan timeout (large image).

CRDs Not Present

Trivy Operator's CRDs are downloaded at CDK8s synthesis time from the Helm chart tarballs. If TRIVY_OPERATOR_SKIP_CRDS=true is set in the environment, CRDs are skipped.

# Verify CRDs are installed
kubectl get crd | grep aquasecurity