This is the kind of report you receive from the read-only assessment. It covers a fictional company, Northwind Logistics, with two clusters (staging and production) that run Flux. A census wrote it: a rule-based read of one repository. This is the code that reads a customer repository.
The census found 54 files that hold Kubernetes objects. An agent can analyse 48 of them (88.9%). The sections below cover the other files.
A root is a top-level directory that holds Flux objects or the files they apply. The table counts files per root. "Render inputs" are files that shape a kustomize build, such as kustomization.yaml. No agent analyses them as objects.
| Flux root | Files | Render inputs | Analysable | Shared by clusters | Unresolved |
|---|---|---|---|---|---|
apps | 32 | 10 | 29 | 27 | 0 |
clusters | 6 | 0 | 6 | 0 | 0 |
infrastructure | 13 | 10 | 13 | 9 | 0 |
manual | 3 | 0 | 0 | 0 | 3 |
Each row below is one Flux Kustomization. The table shows which cluster reconciles it and how many files it applies. A shared file counts once for each Kustomization that applies it.
| Cluster that reconciles | Flux Kustomization | Files it applies |
|---|---|---|
production | flux-system/apps | 32 |
production | flux-system/flux-system | 3 |
production | flux-system/infra-configs | 2 |
production | flux-system/infra-controllers | 6 |
production | flux-system/infra-sources | 3 |
staging | flux-system/apps | 27 |
staging | flux-system/flux-system | 3 |
staging | flux-system/infra-configs | 2 |
staging | flux-system/infra-controllers | 6 |
staging | flux-system/infra-sources | 3 |
Placement says where Flux applies a file. Here, every cluster reconciles itself, so placement is "local" or "shared". A file that both clusters apply counts once for each cluster. The rows can add up to more than the file total.
| Placement | Meaning | Files |
|---|---|---|
local | applied on the cluster that reconciles it | 15 |
multi | reconciled by more than one cluster (shared base) | 36 |
unresolved:uncovered_path | no Kustomization reaches the path | 3 |
| Workload cluster | Files |
|---|---|
production | 46 |
staging | 41 |
These directories run on both clusters. A change to a file here reaches staging and production.
| Directory | Files that run on both clusters |
|---|---|
apps/base/fleet-gateway | 5 |
apps/base/notifier | 4 |
apps/base/orders-api | 6 |
apps/base/route-planner | 7 |
apps/base/tracking-web | 5 |
infrastructure/controllers/base | 6 |
infrastructure/sources | 3 |
A finding is a problem that a rule detected. Each finding names its rule, the file and a short message. The report does not suggest a fix.
| Severity | Rule | Path | Message |
|---|---|---|---|
| warn | reach.flux.autogenerated_kustomization | clusters/production | Flux will recursively generate a Kustomization for this manifest directory |
| warn | reach.flux.autogenerated_kustomization | clusters/staging | Flux will recursively generate a Kustomization for this manifest directory |
| warn | reach.flux.substitution_undeclared | apps/production/fleet-gateway-env.yaml | substitutions REGION, SENTRY_HOST not declared |
| info | reach.flux.uncovered_path | manual/debug-pod.yaml | path is outside every declared reconciliation root |
| info | reach.flux.uncovered_path | manual/legacy-cronjob.yaml | path is outside every declared reconciliation root |
| info | reach.flux.uncovered_path | manual/old-ingress.yaml | path is outside every declared reconciliation root |
reach.flux.autogenerated_kustomization · 2 in this report. A Flux Kustomization points at this directory, but the directory has no kustomization.yaml. Flux then builds one and includes every YAML file in the directory. This is normal for a bootstrap directory. Check that every file there should deploy.
reach.flux.substitution_undeclared · 1 in this report. The file uses a ${VARIABLE} that no Kustomization declares under postBuild.substitute. Flux cannot fill in a value it does not know, so the deployed value may be empty or wrong. Check where the value comes from.
reach.flux.uncovered_path · 3 in this report. No Flux Kustomization applies this file, so Flux does not deploy it. The file may be old, or someone may apply it by hand. Decide if it should stay.
The repository refers to Google GKE. The census reads the repository, not the cluster, so a hint is evidence, not proof. We confirm the platform with you.
| Platform | Path | Object | Signal |
|---|---|---|---|
| Google GKE | apps/base/route-planner/service.yaml | Service route-planner | Annotation: cloud.google.com/neg |
19 maintenance opportunities, by type. Each rule reads plain manifests in the repository, without an AI model. The chart rule also reads public chart indexes. A rule does not check whether a change is safe, and it proposes no change. Objects that a Helm chart creates are not visible to these rules. Some rules say that something is missing. These rules stay silent if the census could not read every object, or if kustomize or Flux change labels at build time.
| Type | Count |
|---|---|
| Deprecated API version | 3 |
| Container without resource requests | 8 |
| Single replica, no autoscaler | 1 |
| Several replicas, no disruption budget | 3 |
| Chart version differs between clusters | 1 |
| ServiceMonitor that selects no Service | 1 |
| Chart behind the newest version | 2 |
The rule reads the apiVersion line only.
| Path | Object | What the file declares |
|---|---|---|
apps/base/orders-api/hpa.yaml | HorizontalPodAutoscaler orders-api | autoscaling/v2beta2 → autoscaling/v2 |
infrastructure/controllers/base/monitoring/helmrelease.yaml | HelmRelease monitoring | helm.toolkit.fluxcd.io/v2beta2 → helm.toolkit.fluxcd.io/v2 |
manual/old-ingress.yaml | Ingress legacy-portal | networking.k8s.io/v1beta1 → networking.k8s.io/v1 |
Without requests the scheduler cannot place the pod by size. The right numbers need usage metrics, so the assessment does not suggest any.
| Path | Object | What the file declares |
|---|---|---|
apps/base/billing-worker/deployment.yaml | Deployment billing-worker | Containers: billing-worker |
apps/base/fleet-gateway/deployment.yaml | Deployment fleet-gateway | Containers: fleet-gateway |
apps/base/notifier/deployment.yaml | Deployment notifier | Containers: notifier |
apps/base/orders-api/deployment.yaml | Deployment orders-api | Containers: orders-api |
apps/base/route-planner/deployment.yaml | Deployment route-planner | Containers: route-planner |
apps/base/tracking-web/deployment.yaml | Deployment tracking-web | Containers: tracking-web |
manual/debug-pod.yaml | Pod netshoot | Containers: netshoot |
manual/legacy-cronjob.yaml | CronJob nightly-export | Containers: export |
One pod means a node drain or a crash stops the workload.
| Path | Object | What the file declares |
|---|---|---|
apps/base/billing-worker/deployment.yaml | Deployment billing-worker | declares replicas: 1 and no HorizontalPodAutoscaler in this repository targets it |
Without a PodDisruptionBudget a node drain can evict all replicas at the same time.
| Path | Object | What the file declares |
|---|---|---|
apps/base/fleet-gateway/deployment.yaml | Deployment fleet-gateway | runs at least 2 replicas and no PodDisruptionBudget in this repository selects its pods |
apps/base/notifier/deployment.yaml | Deployment notifier | runs at least 2 replicas and no PodDisruptionBudget in this repository selects its pods |
apps/base/orders-api/deployment.yaml | Deployment orders-api | runs at least 2 replicas and no PodDisruptionBudget in this repository selects its pods |
The same release gets a different chart version per cluster, after the overlay patches. Sometimes this is on purpose, for example staging first.
| Path | Object | What the file declares |
|---|---|---|
infrastructure/controllers/base/ingress-nginx/helmrelease.yaml | HelmRelease ingress-nginx | Per cluster: production 4.11.3, staging 4.12.0 |
The label selector matches no Service label in the repository, so Prometheus may scrape nothing.
| Path | Object | What the file declares |
|---|---|---|
apps/base/fleet-gateway/servicemonitor.yaml | ServiceMonitor fleet-gateway | Selector: app.kubernetes.io/name=fleet-gateway |
The pinned chart version is older than the newest stable version in the public chart index. The rule does not read the changelog.
| Path | Object | What the file declares |
|---|---|---|
infrastructure/controllers/base/ingress-nginx/helmrelease.yaml | HelmRelease ingress-nginx | 4.11.3 → 4.12.0 (newest in the repository index) |
infrastructure/controllers/base/monitoring/helmrelease.yaml | HelmRelease monitoring | 65.1.1 → 67.4.0 (newest in the repository index) |
The census compared 3 pinned chart versions with a saved copy of each public chart index. 2 of them are behind. It checked every pinned chart.
The assistant has agents for many object kinds. For some kinds it has none. The report lists them. You then know which part of your repository the assistant only maps. The census places objects of these kinds on a cluster. No agent checks them.
| Kind | Objects | Why it is not analysed |
|---|---|---|
gateway.networking.k8s.io/HTTPRoute | 1 | The census knows this kind, but no agent reads it. |
autoscaling/HorizontalPodAutoscaler | 2 | The census does not know this kind yet. |
Pod | 1 | The census does not know this kind yet. |
The report above reads only your repository. If you want, you can also run one read-only command per cluster and send us the file: kubectl get kustomizations.kustomize.toolkit.fluxcd.io -A -o json. Our script cluster-snapshot.sh runs it for you. It reads no Secret and changes nothing. The census then shows two more things. For this sample we used fictional snapshot files.
For each object, the census looks for it in the Flux inventory of its cluster. An object that is not in the inventory was not applied by Flux, or was removed by hand. Unknown means the repository alone cannot say which object to look for.
| Cluster | In the Flux inventory | Not in the inventory | Unknown |
|---|---|---|---|
| production | 48 | 1 | 0 |
| staging | 44 | 0 | 0 |
| Cluster | Path | Object | Reason |
|---|---|---|---|
| production | apps/base/notifier/service.yaml | Service notifier | not_in_inventory |
| Cluster | Flux Kustomization | Ready | Reason | Message |
|---|---|---|---|---|
| staging | flux-system/apps | False | HealthCheckFailed | timeout waiting for: [Deployment/northwind/route-planner status: 'InProgress'] |
The report is a map of your setup, not a list of fixes. These come later, in the dry run after onboarding:
Generated by scripts/assessment_sample_report.py from a fictional repository. The page changes only when the repository or the census code changes.
A few questions, about four minutes. You see an honest fit as you answer. We never ask for passwords, tokens or hostnames.
Get started →