---
title: "Reports Server"
diataxis: how-to
applies_to:
  product: "kyverno"
audience: ["platform-engineer","devsecops"]
last_updated: 2026-03-25
url: https://docs.nirmata.io/docs/controllers/n4k/reports-server/
---


Reports server provides a scalable solution for storing policy reports and cluster policy reports. It moves reports out of etcd and stores them in an alternate database instance.

### Why Reports Server?

Before understanding the benefits of reports server, it is essential to have a look at the reasons that makes moving reports out of etcd desirable.

#### Reasons to Transition Away from etcd

- **Capacity Constraints**: etcd has a maximum size of 8GB. Reports, being relatively large objects, can quickly consume this capacity in larger clusters with numerous report producers.
- **Performance Under Load**: High levels of report activity (e.g., cluster churn, scanning, analytics) require significant data buffering by the API server, potentially leading to API unavailability.
- **Data Nature**: Reports are ephemeral and analytical in nature, not requiring CAP guarantees. As such, they are better suited for storage outside the transactional etcd database.
- **Philosophical Alignment**: Analytical data like reports should ideally be stored in a system designed for analytical queries, such as a relational database.

#### Benefits of reports server

- Reduced Load on etcd and API Server: By relocating reports, the load and capacity limitations of etcd and the API server are alleviated.
- Improved Efficiency for Consumers:
     - Report consumers often require analytical or aggregate data queries. The Kubernetes API is not optimized for such queries.
     - For instance, querying all reports with a CVSS severity of 8.0 or higher requires retrieving and parsing all reports via the API, which is inefficient.
     - With reports stored in a relational database, consumers can perform robust queries directly, improving performance and enabling new use cases.
     - This approach can replace certain exporters and streamline reporting workflows.

### Prerequisites

- **Helm**: Refer to the [official docs](https://helm.sh/docs/intro/install/) for installation.
- **Kubernetes Cluster**: Any CNCF compliant Kubernetes distribution.

### Installation
#### Installing Reports Server Natively with Enterprise Kyverno
```bash
 helm repo add nirmata https://nirmata.github.io/kyverno-charts/
 helm repo update nirmata
 helm install kyverno --namespace kyverno --create-namespace nirmata/kyverno  --set crds.reportsServer.enabled=true --set reports-server.install=true
```
For a complete list of values, refer to [values.yaml](https://github.com/nirmata/kyverno-charts/blob/main/charts/nirmata/values.yaml).

##### Handling CRD or APIServices Related Errors

If you encounter errors related to existing CRDs or APIServices during installation, such as:

```text

You can resolve this by adding the migration flag to your installation command:

```bash
 helm install kyverno --namespace kyverno --create-namespace nirmata/kyverno  --set crds.reportsServer.enabled=true --set reports-server.install=true --set reports-server.apiServicesManagement.migrateReportsServer.enabled=true
```text

#### Installing Reports Server Independent of Enterprise Kyverno
The Reports Server serves certain report CRDs through its APIService. At the same time, Enterprise Kyverno expects these CRDs to exist for policy reporting. If both Kyverno and the Reports Server try to define or serve these CRDs simultaneously, the Kubernetes apiserver may fail to reconcile duplicate API paths. This is a known limitation in upstream Kubernetes (see [Kubernetes Issue #122668](https://github.com/kubernetes/kubernetes/issues/122668#issuecomment-2577138150)).

To avoid these conflicts:
* Deploy Reports Server independently first
* Confirm its APIService is fully ready
* Then install Enterprise Kyverno separately

This ordering guarantees the CRDs are correctly served and avoids temporary crash loops or installation failures in Kyverno.

**Note:** The below command installs reports-server in etcd mode. For Postgres, see the section below.

Add and update Helm repo.
```bash
 helm repo add nirmata https://nirmata.github.io/kyverno-charts/
 helm repo update nirmata
```text

```bash
 helm install reports-server -n kyverno nirmata/reports-server --create-namespace

 helm install kyverno --namespace kyverno --create-namespace nirmata/kyverno  --set crds.reportsServer.enabled=true
```text

##### Handling CRD or APIServices Related Errors

If you encounter errors related to existing CRDs or APIServices during the independent installation, such as:

```text
Error: INSTALLATION FAILED: 2 errors occurred:
	* apiservices.apiregistration.k8s.io "v1alpha2.wgpolicyk8s.io" already exists
	* apiservices.apiregistration.k8s.io "v1.reports.kyverno.io" already exists
```text

You can resolve this by adding the migration flag to your Reports Server installation command:

```bash
 helm install reports-server -n kyverno nirmata/reports-server --create-namespace --set apiServicesManagement.migrateReportsServer.enabled=true

 helm install kyverno --namespace kyverno --create-namespace nirmata/kyverno  --set crds.reportsServer.enabled=true
```text

### Installing Reports Server using configurations

There are two configurations available for installing the Reports Server in a production cluster:

- **Reports server with embedded etcd storage**: Store reports in a high-availability (HA) etcd instance.
- **Reports server with managed postgres**: Use a centralized postgres database in or outside of the cluster.


#### Embedded etcd storage

To install the Reports Server with embedded etcd storage:
 
Using Helm Commands:
````bash
 helm repo add nirmata https://nirmata.github.io/kyverno-charts/
 helm repo update nirmata
 helm install reports-server -n kyverno nirmata/reports-server --create-namespace
````

#### Managed Postgres

To configure the Reports Server with a PostgreSQL instance:
 
Using Helm Commands:
```bash
 helm repo add nirmata https://nirmata.github.io/kyverno-charts/
 helm repo update nirmata
 helm install reports-server -n kyverno nirmata/reports-server --create-namespace \
         --set config.etcd.enabled=false \
         --set config.db.host=<Host_Name> \
         --set config.db.name=<DB_Name> \
         --set config.db.user=<Postgres_username> \
         --set config.db.password=<Postgress_password>
```text
>Note: Obtain the hostname, database name, PostgreSQL username, and password from your PostgreSQL instance.


##### Managed Postgres in AWS

Reports Server can be installed with managed postgres in AWS. Create a postgres instance in AWS using Amazon RDS and install the reports-server chart using the above command. Refer to the [official AWS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Tutorials.WebServerDB.CreateDBInstance.html) for creating the postgres instance. Get the hostname, dbname, postgres username, postgres password, etc., from the postgres instance and fill the values in helm values.

### Migration from etcd to reports-server

When the Reports Server is enabled, migration from etcd occurs automatically under the following conditions:
- The cluster has Kyverno already installed.
- The cluster has policy reports crds already installed.


### QA Testing 
The Reports Server has been verified on both amd64 and arm64 architectures, ensuring robust performance and compatibility.

---

## Migration Guide


When the Reports Server is enabled, migration from etcd occurs automatically under the following conditions:
- The cluster has Kyverno already installed.
- The cluster has policy reports crds already installed.

## Migration from Kyverno 1.12+
For users running older versions of Kyverno, the recommended migration path is -
1. Upgarde to the latest Nirmata Enterprise for Kyverno version
1. Migrate from K8s etcd to Reports Server

Optionally verify the policyreports stored in etcd.
```text
etcdctl get "/registry/wgpolicyk8s.io/policyreports" --prefix --keys-only
```text

Since Nirmata Enterprise for Kyverno is already running in the cluster, run the following commands to install reports-server:
```bash
 helm repo add nirmata https://nirmata.github.io/kyverno-charts/
 helm repo update nirmata
 helm upgrade kyverno --namespace kyverno --create-namespace nirmata/kyverno  --set crds.reportsServer.enabled=true --set reports-server.install=true --set reports-server.apiServicesManagement.migrateReportsServer.enabled=true
```text

Wait for reports-server pod to come up and check for apiservices.
```bash
kubectl get pods -n kyverno
kubectl get apiservices
```text

>NOTE: Existing policy reports from K8s etcd should be manually cleaned up.

When reports-server is introduced in an active cluster (reports exist in k8s etcd), the reports are copied to the offloaded datastore (etcd or postgres). But these reports are not automatically deleted from k8s etcd. Users have to manually delete those reports.

First check reports are properly copied over to reports-server etcd. We can confirm it by looking at reports-server pod logs using:
```bash
kubectl logs reports-server-969f45d4b-jj9r5 -n kyverno
```text

Manually delete reports from k8s etcd:
```bash
kubectl exec -it etcd-test-rs-control-plane -n kube-system -- sh
```text

Inside the pod, etcdctl is usually installed. Export the following variables:
```bash
export ETCDCTL_API=3
export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.crt
export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/server.crt
export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/server.key
```text

Run the following commands for deleting policy reports:
```text
etcdctl del "/registry/wgpolicyk8s.io/policyreports" --prefix
etcdctl get "/registry/wgpolicyk8s.io/policyreports" --prefix --keys-only
```text

## Rollback from Reports Server
When reports-server is uninstalled, kyverno controllers will start throwing errors for missing report CRDs.

1. Manually install the required report CRDs.
1. Uninstall reports-server.
1. Verify if apiservices are removed and reports-server is deleted.
1. Reports will be lost, so manually scale down and up the background controller to trigger reconciliation and recreate reports.
1. Verify if policyreports are regenerated.

>NOTE: If you are using Postgres for offloading, note that policy reports will have to be manually cleaned up from the database.

