Kubernetes deployments are commonly defined using YAML manifests. These files describe Deployments, Services, ConfigMaps, Jobs, RBAC resources, and many other objects that make up an application.

YAML is flexible and easy to write, but it can also be difficult to validate consistently. Formatting, typing, indentation, and subtle structural differences can create problems that are not always obvious during code review.

Kubernetes 1.37 continues to improve KYAML, a Kubernetes-oriented YAML representation designed to provide more predictable handling of Kubernetes configuration. For development and platform teams, this creates an opportunity to treat Kubernetes manifests more like application source code: validate them locally, check them in CI/CD, and reject invalid configuration before it reaches a cluster.

For .NET teams deploying ASP.NET Core services to Kubernetes, manifest validation is especially useful because a deployment problem can otherwise appear as an application failure even when the .NET application itself is working correctly.

What Is KYAML?

KYAML is a Kubernetes-oriented YAML format and tooling approach designed around Kubernetes API data.

The broader problem it addresses is that generic YAML is a serialization format, while Kubernetes manifests have their own API conventions, types, defaults, and structural requirements.

A simplified workflow is:

Kubernetes Object
       |
       v
KYAML Representation
       |
       v
Validation / Conversion
       |
       v
Kubernetes API

The goal is to make Kubernetes configuration more predictable and suitable for tooling.

Kubernetes documentation describes KYAML as a strict YAML subset intended to avoid ambiguities present in general-purpose YAML and to make Kubernetes configuration easier to process consistently.

Why Manifest Validation Matters

Consider an ASP.NET Core application with this Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: orders-api
  template:
    metadata:
      labels:
        app: orders-api
    spec:
      containers:
        - name: orders-api
          image: example/orders-api:1.0

A small configuration mistake can prevent the application from deploying correctly.

For example:

Wrong selector
Missing container image
Incorrect resource type
Invalid field
Wrong indentation
Incorrect value type

A CI validation step can detect many configuration problems before deployment.

The workflow becomes:

Developer
    ↓
Manifest Change
    ↓
CI Validation
    ↓
PASS → Deploy
FAIL → Stop

YAML Syntax Validation vs Kubernetes Validation

These are different checks.

YAML Syntax

This verifies that the document is valid YAML.

Is the YAML structurally readable?

Kubernetes Validation

This asks:

Is this a valid Kubernetes object?

A file can be valid YAML but invalid Kubernetes configuration.

For example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-api
spec:
  replicas: three

The YAML itself can be parsed, but replicas is expected to represent an integer for a Kubernetes Deployment.

A useful CI pipeline therefore validates both syntax and Kubernetes semantics.

Why Strict Configuration Helps

Generic YAML parsers can support many YAML features that are unnecessary or undesirable for Kubernetes configuration.

A strict representation reduces ambiguity.

For example, application configuration often contains values such as:

replicas: 3
enabled: true
port: 8080

Those values should have predictable types.

Strict configuration processing helps prevent a situation where the same text is interpreted differently by different tools.

For infrastructure repositories, predictable parsing is particularly important because the configuration may pass through several systems:

Git
 ↓
CI
 ↓
Validation
 ↓
Templating
 ↓
kubectl / API
 ↓
Kubernetes

Validating a Deployment

A basic Kubernetes workflow can start with:

kubectl apply --dry-run=client -f deployment.yaml

This checks the manifest without sending it to the Kubernetes API server.

For stronger server-side validation:

kubectl apply --dry-run=server -f deployment.yaml

Server-side validation allows Kubernetes itself to evaluate the object against the API server's schema and configuration.

This is often more useful in CI because it tests the manifest against the target cluster's API behavior.

Validating Without Changing the Cluster

The --dry-run option is important in CI.

For example:

kubectl apply \
  --dry-run=server \
  -f k8s/

The pipeline can validate a complete directory of manifests without actually changing the cluster.

A useful deployment pipeline is:

Build
  ↓
Generate Manifests
  ↓
Validate
  ↓
Security Scan
  ↓
Deploy

The deployment step should happen only after the earlier checks pass.

Using kubectl diff

Another useful validation step is:

kubectl diff -f k8s/

This shows how the desired manifests differ from the resources currently present in the cluster.

For CI/CD, this can provide useful review information before applying changes.

However, kubectl diff requires access to the target cluster, so it should be used only in a trusted CI environment with appropriately restricted credentials.

Validating .NET Deployment Resources

A typical ASP.NET Core Deployment may define resource requests and limits:

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"
  limits:
    cpu: "1"
    memory: "512Mi"

These values are part of the Kubernetes configuration, not the .NET application code.

A validation pipeline can therefore catch missing resource configuration before deployment.

For example, an organization might enforce:

Every production .NET Deployment must define:
- CPU request
- Memory request
- CPU limit
- Memory limit

The exact policy should reflect the organization's operational requirements.

Validating Services

The same approach applies to Services.

apiVersion: v1
kind: Service
metadata:
  name: orders-api
spec:
  selector:
    app: orders-api
  ports:
    - port: 80
      targetPort: 8080

A common application-level failure occurs when:

Service selector
      ≠
Pod labels

For example:

selector:
  app: order-api

while the Pod uses:

labels:
  app: orders-api

The manifest can be syntactically valid, yet the Service will not select the intended Pods.

This demonstrates why Kubernetes-aware validation is more useful than YAML syntax checking alone.

KYAML and Security Validation

Manifest validation should also be part of Kubernetes security testing.

Consider an RBAC resource:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: orders-reader
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - list

A security gate can inspect the manifest and identify overly broad permissions.

For example, a policy might reject:

verbs:
  - "*"

or:

resources:
  - "*"

when such permissions are not justified.

This turns Kubernetes configuration into a security-testable artifact.

Building a CI Validation Pipeline

A practical pipeline can contain several stages:

1. YAML / KYAML validation
2. Kubernetes schema validation
3. Policy validation
4. Security scanning
5. Deployment

For example:

name: Kubernetes Validation

on:
  pull_request:

jobs:
  validate:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Validate manifests
        run: |
          kubectl apply \
            --dry-run=client \
            -f k8s/

      - name: Server-side validation
        run: |
          kubectl apply \
            --dry-run=server \
            -f k8s/

The server-side step requires a Kubernetes cluster and appropriate credentials.

For pull requests from untrusted forks, production cluster credentials should not be exposed simply to perform validation.

Separating Pull Request and Release Validation

A safer enterprise workflow can use two levels:

Pull Request
    |
    +--> Static validation
    +--> Policy checks
    +--> Security checks
    |
    v
Merge

Release
    |
    +--> Server-side validation
    +--> Diff
    +--> Deployment

This reduces the need to expose privileged cluster credentials to every pull request.

Validating Generated Manifests

Many teams do not maintain final manifests manually.

They may use:

Helm
Kustomize
Jsonnet
Custom generators
CI templates

In that situation, validate the rendered output, not only the source templates.

For example:

Helm Chart
    ↓
helm template
    ↓
Rendered YAML
    ↓
Kubernetes Validation
    ↓
Deploy

A valid Helm template can still produce an invalid Kubernetes object after values are applied.

The generated artifact is what matters to the Kubernetes API.

Example Helm Validation

A simple Helm workflow might use:

helm lint ./chart

followed by:

helm template orders-api ./chart \
  --values values-production.yaml

The rendered output can then be passed to Kubernetes-aware validation tools.

This gives the pipeline a clear separation:

Template correctness
        +
Rendered manifest correctness
        ↓
Deployment readiness

Manifest Validation for Multiple Environments

Production and development environments often have different values.

For example:

values-development.yaml
values-staging.yaml
values-production.yaml

The same chart can produce different Kubernetes objects.

Therefore, validation should be performed against every production-relevant configuration.

For example:

helm template orders-api ./chart \
  --values values-production.yaml

should be validated separately from:

helm template orders-api ./chart \
  --values values-development.yaml

Testing only development values can leave production-specific configuration errors undiscovered.

Common Mistakes

Checking Only YAML Syntax

A YAML parser cannot determine whether every field is valid for a Kubernetes resource.

Validating Templates Instead of Rendered Output

Generated manifests can differ significantly from source templates.

Using Production Credentials for Every Pull Request

Do not expose privileged cluster access unnecessarily.

Ignoring Resource Configuration

A Deployment can be valid while still being operationally incomplete.

Allowing Broad RBAC Permissions

Configuration validation should include security policies where possible.

Treating Dry Run as a Complete Production Test

Dry-run validation cannot prove that the application will start successfully.

You still need application tests and deployment verification.

Troubleshooting Validation Failures

Invalid API Version

Check:

apiVersion: apps/v1

against the resource type supported by the target Kubernetes version.

Unknown Field

A field may be valid in another resource or Kubernetes version but invalid for the current schema.

Selector Mismatch

Compare:

selector:

with:

template:
  metadata:
    labels:

Missing Required Values

Inspect generated manifests rather than only source templates.

Cluster-Specific Failure

If client-side validation succeeds but server-side validation fails, inspect the target cluster version, enabled APIs, admission policies, and configuration.

Best Practices

  1. Validate Kubernetes manifests in CI before deployment.

  2. Use strict configuration formats where appropriate.

  3. Perform both syntax and Kubernetes-aware validation.

  4. Prefer server-side dry runs for trusted release environments.

  5. Validate rendered Helm or Kustomize output.

  6. Validate production-specific configurations separately.

  7. Add security-policy checks for RBAC and sensitive resources.

  8. Avoid exposing production cluster credentials to untrusted pull requests.

  9. Keep manifests version-controlled and reviewable.

  10. Treat configuration changes with the same discipline as application-code changes.

Advantages and Disadvantages

Advantages

Disadvantages

Conclusion

Kubernetes configuration is application infrastructure, and it deserves the same validation discipline as source code.

KYAML's focus on predictable Kubernetes configuration complements a broader CI/CD validation strategy:

Source
  ↓
Generate Manifest
  ↓
Validate Structure
  ↓
Validate Kubernetes Schema
  ↓
Security Policy
  ↓
Dry Run
  ↓
Deploy
  ↓
Verify

For .NET teams, this can prevent a common debugging mistake: assuming that a failed ASP.NET Core deployment is an application problem when the actual issue is an invalid or incomplete Kubernetes configuration.

The most effective approach is to validate the exact manifests that will be deployed, keep security checks in the same workflow, and use server-side validation in trusted release environments. This makes Kubernetes deployments more predictable without adding unnecessary complexity to the application itself.