Catch cross-resource bugs offline.
Kix validates the entire cluster definition before anything touches Kubernetes, catching broken selectors, missing Secret keys, and label collisions at build time.
Cross-resource validation before apply
Kix checks the complete definition before applying it. If a Service points to no workload, for example, the error identifies the Service and the selector to check. Other mistakes, such as a Deployment selector drifting from its pod labels, are prevented by how Kix builds the resources.
The scorecard also checks security, reliability, and governance. Its findings are warnings by default, and you can choose which rules should stop a build.
kind: Servicemetadata: name: web namespace: shopspec: selector: app.kubernetes.io/name: shop-wbe ports: - port: 80 The Service has no endpoints, so traffic cannot reach the app.
| The everyday mistake | What Kubernetes does | What Kix says |
|---|---|---|
| The same environment variable defined twice, usually from a copied block. | Accepts it, warns, and the last value wins. | ✗ [web] Container 'web' has duplicate env var name(s): [DATABASE_URL]. |
| The app reads a Secret key that doesn't exist: password, when the key is pass. | The pod fails to start. | ✗ secret "db" does not declare key "password"
declared keys: pass |
| A migration Job reuses the app's labels. | The Service sends real user traffic to the Job's pod for as long as it runs. | ✗ Job shop/migrate pod labels {"app.kubernetes.io/instance":"web","app.kubernetes.io/name":"web"} satisfy Service shop/web selector {"app.kubernetes.io/instance":"web","app.kubernetes.io/name":"web"}; the Service would route traffic to the Job pod |
| A workload names a PriorityClass that doesn't exist. | The workload applies, then every pod is rejected at admission. | ✗ Deployment shop/web sets priorityClassName 'critical', which no resource in this cluster creates. Every pod of this workload would be rejected at admission. Add the PriorityClass, or declare it as externally managed with an import or kix.untrackedRef |
| A PodDisruptionBudget whose selector matches nothing. | It protects nothing, and you find out during a node drain. | ✗ PodDisruptionBudget shop/web selector {"app":"wbe"} matches no workload pod template in namespace shop. Check the selector against the intended workload's pod labels |
| type: LoadBalancer on a cluster with no load balancer provider. | The external IP sits at <pending>. | ✗ [web] Service 'web' uses type=LoadBalancer but no load balancer provider is configured (cluster.roles.loadBalancer.binding = "absent", no provider instance). Use type=ClusterIP or NodePort, add a provider instance, or configure cluster.roles.loadBalancer.binding to match your environment. |