# How Trivy Kubernetes Cluster Scanning Works: Architecture and Implementation

> Discover how Trivy Kubernetes cluster scanning works. Learn about its architecture, implementation, and how it collects data and scans for vulnerabilities, secrets, and misconfigurations.

- Repository: [Aqua Security/trivy](https://github.com/aquasecurity/trivy)
- Tags: architecture
- Published: 2026-03-23

---

**Trivy Kubernetes cluster scanning connects to a target cluster via the `trivy-kubernetes` library, collects manifests and runtime data through an optional node-collector Job, and processes artifacts through a specialized scanner that delegates to Trivy's existing vulnerability, secret, and misconfiguration engines.**

The `trivy k8s` command in the aquasecurity/trivy repository orchestrates a multi-stage pipeline that treats Kubernetes resources as scannable artifacts. This architecture bridges cluster API objects with Trivy's generic scanner to detect vulnerabilities in container images, misconfigurations in manifests, and security issues in core cluster components like the kubelet and API server.

## Architecture Overview

When you execute `trivy k8s`, the scanner runs a six-step pipeline defined across three core packages:

1. **Cluster Connection** – Builds a `k8s.Cluster` object using the current kube-config or a specified context.
2. **Artifact Collection** – Uses the `trivy-kubernetes` library to enumerate manifests and optionally deploy a node-collector Job for runtime data.
3. **Scanner Initialization** – Creates a `scanner.Scanner` in [`pkg/k8s/scanner/scanner.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/scanner/scanner.go) that wraps Trivy's standard scanners.
4. **Parallel Execution** – Processes artifacts concurrently, invoking image, OS, language, and Infrastructure-as-Code (IaC) scanners as needed.
5. **Result Aggregation** – Constructs a `k8s/report.Report` containing resources, findings, and summary metadata.
6. **Output Generation** – Emits results via [`pkg/k8s/report/report.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/report/report.go) in JSON, table, or CycloneDX SBOM formats.

## CLI Entry Point

The `k8s` subcommand is registered in [`pkg/commands/app.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/commands/app.go). When invoked, it delegates to [`pkg/k8s/commands/run.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/commands/run.go):

```go
func Run(ctx context.Context, args []string, opts flag.Options) error {
    // build k8s.Cluster based on kube-config and optional context argument
    return k8scommands.Run(ctx, args, opts)
}

```

This entry point handles context parsing and passes control to the Kubernetes-specific command layer.

## Cluster Initialization

In [`pkg/k8s/commands/run.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/commands/run.go), Trivy constructs a `k8s.Cluster` interface using user-supplied options:

```go
clusterOptions := []k8s.ClusterOption{
    k8s.WithKubeConfig(opts.K8sOptions.KubeConfig),
    k8s.WithBurst(opts.K8sOptions.Burst),
    k8s.WithQPS(opts.K8sOptions.QPS),
}
if len(args) > 0 {
    clusterOptions = append(clusterOptions, k8s.WithContext(args[0]))
}
cluster, err := k8s.GetCluster(clusterOptions...)

```

The resulting cluster object exposes methods like `GetClusterVersion()` and `GetCurrentContext()`, abstracting the underlying Kubernetes API interactions.

## Artifact Collection

The `clusterRun` function in [`pkg/k8s/commands/cluster.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/commands/cluster.go) determines which artifacts to collect based on the output format and scanner flags:

| Format | Collection Strategy |
|--------|-------------------|
| **CycloneDX** | `ListClusterBomInfo()` gathers version metadata for SBOM generation only. |
| **JSON / Table** | `ListArtifacts()` fetches all manifests. If **misconfiguration scanning** is enabled and node collection is not disabled, `ListArtifactAndNodeInfo()` runs the **node-collector Job** to extract runtime data. |

The **node-collector** is an optional short-lived Job that executes embedded command files from `trivy-checks` to gather kubelet versions and container runtime details directly from cluster nodes.

## Scanner Implementation

The core scanning logic resides in [`pkg/k8s/scanner/scanner.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/scanner/scanner.go). The `Scan` method orchestrates three distinct analysis paths:

```go
func (s *Scanner) Scan(ctx context.Context, artifactsData []*artifacts.Artifact) (report.Report, error) {
    // (a) Separate core components (ControlPlane, Node, Cluster) from regular manifests.
    // (b) Run misconfiguration scans on raw YAML/Helm manifests via s.scanMisconfigs().
    // (c) For each container image, invoke s.scanVulns() using the generic Trivy image scanner.
    // (d) Scan core components via s.scanK8sVulns() for kubelet and control-plane binary vulnerabilities.
    // (e) Assemble the final report with resources, cluster name and schema version.
}

```

**Misconfiguration Scanning** – The `scanMisconfigs` function writes manifests to a temporary directory and calls `runner.ScanFilesystem` to execute Trivy's config scanner on raw YAML.

**Vulnerability Scanning** – The `scanVulns` function iterates over container images discovered in manifests, sets `opts.Target` to the image reference, and calls `runner.ScanImage`.

**Core Component Scanning** – The `scanK8sVulns` function extracts version strings from control-plane and node components, creates pseudo-applications (`ftypes.Application`) with `LangType: "k8s"`, and invokes the Kubernetes-specific scanner.

## Low-Level Kubernetes Scanner

[`pkg/k8s/k8s.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/k8s.go) implements a thin wrapper around Trivy's **local.Scanner** service:

```go
type ScanKubernetes struct {
    localScanner local.Service
}

func (sk ScanKubernetes) Scan(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (types.Results, ftypes.OS, error) {
    return sk.localScanner.ScanTarget(ctx, target, options)
}

```

This design ensures that core component scans reuse the same detection logic as file-system and container image scans, maintaining consistent vulnerability data across all target types.

## Reporting and Output

[`pkg/k8s/report/report.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/report/report.go) handles the final serialization of `report.Report` objects:

- **JSON** – Marshals the complete report structure including all findings and resource metadata.
- **Table** – Renders a human-readable summary with cluster-wide statistics.
- **CycloneDX** – Uses `clusterInfoToReportResources` to build a Software Bill of Materials (SBOM) suitable for supply chain documentation.

## Practical Usage Examples

### Basic Cluster Scan

Scan the current context and display a summary table:

```bash
trivy k8s --report summary

```

Scan a specific context named `prod-cluster` and output detailed JSON results:

```bash
trivy k8s prod-cluster --format json > prod-cluster.json

```

Generate a CycloneDX SBOM for the entire cluster:

```bash
trivy k8s --format cyclonedx --output cluster-sbom.json

```

### Enabling Runtime Data Collection

To scan nodes and collect runtime information (kubelet version, container runtime):

```bash
trivy k8s --include-namespaces default,kube-system \
          --node-collector-namespace trivy-node-collector \
          --node-collector-image-ref aquasec/trivy-node-collector:latest

```

This deploys the node-collector Job in the specified namespace to gather information unavailable through the Kubernetes API alone.

### Programmatic Scanning

Import the Kubernetes commands package to scan programmatically:

```go
import (
    "context"
    "github.com/aquasecurity/trivy/pkg/k8s/commands"
    "github.com/aquasecurity/trivy/pkg/flag"
)

func main() {
    ctx := context.Background()
    opts := flag.Options{
        ScanOptions: flag.ScanOptions{
            Scanners: types.AllScanners,
        },
        K8sOptions: flag.K8sOptions{
            KubeConfig: "/path/to/kubeconfig",
        },
    }

    if err := commands.Run(ctx, nil, opts); err != nil {
        panic(err)
    }
}

```

This Go implementation mirrors the CLI behavior, building the cluster connection and executing the full scanner pipeline.

## Summary

- **Trivy Kubernetes cluster scanning** uses a six-stage pipeline from cluster connection to final report generation.
- The `trivy-kubernetes` library in `pkg/k8s/commands` handles Kubernetes API communication and optional node-collector deployment.
- Core scanning logic in [`pkg/k8s/scanner/scanner.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/scanner/scanner.go) separates misconfiguration checks, image vulnerability scans, and core component analysis.
- All scans ultimately delegate to Trivy's standard `local.Service` in [`pkg/k8s/k8s.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/k8s.go) to ensure consistent detection rules across targets.
- Output formatting in [`pkg/k8s/report/report.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/k8s/report/report.go) supports JSON, table, and CycloneDX SBOM representations.

## Frequently Asked Questions

### What Kubernetes resources does Trivy scan?

Trivy scans all cluster artifacts discovered through the Kubernetes API, including Pod specifications, Deployment manifests, ConfigMaps, and cluster nodes. When misconfiguration scanning is enabled, it analyzes raw YAML/Helm manifests for security issues. When vulnerability scanning is enabled, it identifies container images referenced in workloads and scans them for CVEs.

### How does Trivy scan Kubernetes cluster nodes?

Trivy can scan nodes by deploying a **node-collector Job** inside the cluster. This Job runs on cluster nodes and executes embedded scripts from the `trivy-checks` repository to extract runtime data such as kubelet versions, container runtime details, and configuration file paths. You enable this by omitting the `--node-collector-disable` flag and optionally specifying `--node-collector-image-ref`.

### Can Trivy generate SBOMs for Kubernetes clusters?

Yes. When you specify `--format cyclonedx`, Trivy generates a CycloneDX Software Bill of Materials (SBOM) representing the cluster state. In this mode, Trivy uses `ListClusterBomInfo()` to collect version information for core components and container images without performing full vulnerability analysis, creating a comprehensive inventory of cluster software.

### What is the difference between `trivy k8s` and scanning individual container images?

The `trivy k8s` command performs **contextual scanning** that understands Kubernetes-specific resources and relationships. It can detect misconfigurations in manifests, scan core cluster components like the kubelet and API server that aren't container images, and correlate findings with specific cluster resources. Scanning individual images with `trivy image` only analyzes the image contents without Kubernetes context or infrastructure configuration.