DevOps · 13 min read

Kubernetes YAML Validation Checklist Before Deployment

By StringTo Editorial Team · Updated

Kubernetes YAML validation should happen before a manifest reaches a production cluster. A file can be valid YAML yet still fail because its apiVersion is unsupported, required fields are missing, selectors do not match labels, resource quantities are malformed, or the cluster rejects the object through admission policy. Reliable validation therefore has several layers: YAML syntax, Kubernetes schema, cross-resource consistency, security review, and a dry run against the target cluster. This checklist explains each layer with practical manifest and kubectl examples, helping you find Kubernetes manifest errors before an apply operation changes live infrastructure.

Validate YAML syntax before Kubernetes schema

Begin with generic YAML parsing. Kubernetes cannot inspect a resource until the document is syntactically valid. Common failures include inconsistent indentation, tabs used as indentation, missing spaces after colons, malformed sequences, duplicate keys, and unquoted values containing syntax-significant characters.

Fix the first parser error and validate again. Later messages may be consequences of the original mistake. When the reported line looks correct, inspect the preceding block because an unfinished sequence, mapping, quote, or multiline scalar can cause the parser to fail on the next valid-looking key.

For files containing several resources separated by document markers, validate every document. An empty document or malformed resource later in the stream can be missed when a tool examines only the first object. Formatting after successful parsing makes hierarchy and unexpected nesting easier to review.

# Invalid indentation
spec:
  containers:
    - name: api
      image: example/api:1.0
     ports:
       - containerPort: 8080

# Correct indentation
spec:
  containers:
    - name: api
      image: example/api:1.0
      ports:
        - containerPort: 8080
  • Use spaces consistently and reject indentation tabs.
  • Check mappings, sequences, quotes, and block scalars.
  • Reject duplicate keys instead of relying on loader behavior.
  • Validate every document in a multi-resource YAML file.

Check apiVersion, kind, metadata, and resource scope

Every Kubernetes object needs a recognized apiVersion and kind. The correct apiVersion depends on the resource and the Kubernetes version available in the target cluster. A manifest copied from an older tutorial may use a removed or deprecated API even though its YAML is perfectly valid.

Metadata normally needs a name, or a generateName prefix when the API supports server-generated names. Confirm that names satisfy the resource's naming rules and that the namespace is intentional. Namespaced resources default to the active namespace if metadata.namespace and the command-line namespace are omitted, which can place an otherwise valid object in the wrong environment.

Cluster-scoped resources do not belong to a namespace. Before deployment, identify the scope of each kind, verify that custom resource definitions exist before their custom resources, and ensure the deployment identity has permission to create or update the object.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments-api
  namespace: production
spec:
  replicas: 3
  • Confirm apiVersion and kind against the target cluster.
  • Provide a valid metadata.name or supported generateName.
  • Verify the namespace and whether the resource is namespaced.
  • Install required custom resource definitions before custom resources.

Match labels, selectors, and service targets

Deployment selectors must match the labels in the pod template. A mismatch prevents the controller from managing the intended Pods and is rejected for some workload resources. Treat selector labels as stable identifiers because changing immutable selectors later may require replacing the resource.

A Service selects Pods through labels. Kubernetes can accept a Service whose selector matches nothing, but traffic will not reach the workload. Compare the Service selector with pod-template labels character for character, including capitalization, and confirm that the Service targetPort corresponds to a named port or the container's listening port.

Use consistent recommended labels for application name, instance, version, component, and ownership where they fit the project. Avoid placing sensitive information in labels or annotations, because metadata can be widely visible to cluster users and tooling.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: example/api:1.0
  • Match workload selectors with pod-template labels.
  • Match Service selectors with the labels on target Pods.
  • Verify targetPort names and numbers against container ports.
  • Keep labels consistent and free of sensitive data.

Review containers, images, commands, and configuration

Every Pod template needs at least one valid container definition. Give containers descriptive names and verify image references, registry access, pull policy, command arguments, working directories, ports, and volume mounts. Prefer immutable image digests or controlled version tags for reproducible deployments rather than a floating latest tag.

Environment variables can use literal values, ConfigMaps, Secrets, and field references. Confirm that referenced keys and objects exist in the intended namespace. Optional references should be optional deliberately, not used to hide missing configuration. Never store plaintext production credentials directly in a committed manifest.

Check that volume mount names correspond to declared volumes and that mount paths do not unintentionally shadow files supplied by the image. Validate persistent volume claim names, storage access modes, and the scheduling implications of node-specific or zone-specific storage.

containers:
  - name: api
    image: registry.example.com/api@sha256:REPLACE_WITH_REAL_DIGEST
    ports:
      - name: http
        containerPort: 8080
    envFrom:
      - configMapRef:
          name: api-config
      - secretRef:
          name: api-secrets
  • Use controlled tags or immutable image digests.
  • Verify ConfigMap and Secret names and keys.
  • Match every volumeMount with a declared volume.
  • Keep credentials out of source-controlled YAML.

Validate resource requests, limits, and health probes

Resource requests influence scheduling, while limits constrain runtime consumption. Validate CPU and memory quantity syntax and choose values based on measured behavior. Confusing memory units, assigning a limit below a request, or omitting requests can cause rejection, inefficient scheduling, throttling, eviction, or policy failures.

Readiness probes determine when a container can receive traffic. Liveness probes determine when Kubernetes should restart it, and startup probes protect slow-starting applications from premature liveness failures. Confirm paths, ports, commands, protocols, delays, periods, timeouts, and thresholds against how the application actually behaves.

A syntactically valid probe can still be harmful. A liveness endpoint that depends on an external database may restart healthy application processes during an unrelated outage. Use probe endpoints with intentionally designed semantics, and test failure behavior in a non-production namespace.

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi
readinessProbe:
  httpGet:
    path: /ready
    port: http
  periodSeconds: 10
livenessProbe:
  httpGet:
    path: /live
    port: http
  periodSeconds: 20
  • Use valid CPU and memory quantities.
  • Ensure limits are not lower than requests.
  • Verify probe paths, ports, timing, and failure thresholds.
  • Test probe behavior during startup and dependency outages.

Apply security checks to the Pod specification

Schema validation does not establish that a workload is secure. Review the pod and container security contexts, service account, Linux capabilities, privilege settings, filesystem permissions, host access, and volume types. Policies in the target cluster may reject settings that a generic Kubernetes manifest validator accepts.

When the image supports it, require a non-root user, prevent privilege escalation, drop unnecessary capabilities, and use a read-only root filesystem. Set seccomp behavior according to the cluster's supported policy. Some applications need writable temporary directories, so mount narrowly scoped writable volumes rather than disabling protections for the entire filesystem.

Do not automatically mount service-account credentials when the workload does not call the Kubernetes API. Check role bindings separately and grant only the required verbs and resources. Also review network policies, image provenance, secret delivery, and admission-controller results before production rollout.

securityContext:
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault
containers:
  - name: api
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
  • Run as non-root when the image supports it.
  • Prevent privilege escalation and drop unused capabilities.
  • Avoid host namespaces, privileged mode, and unsafe host paths.
  • Use a least-privilege service account and network policy.

Run client and server dry-run validation

Client-side dry run parses the manifest and performs local validation available to kubectl. It is useful for fast feedback but cannot evaluate every rule configured in the cluster. The behavior also depends on the kubectl version and the schemas it can discover or cache.

Server-side dry run sends the request through the API server's validation, defaulting, admission chain, and authorization path without persisting the object. It is the stronger pre-deployment check because it uses the target cluster's APIs and policies. It still does not prove that containers will start, images can be pulled, volumes will bind, or dependent services are reachable.

Use the same cluster context, namespace, identity, and deployment mechanism that the real rollout will use. Render Helm, Kustomize, or other templates first and validate the rendered output—not only the source templates. Review the resulting diff before apply.

# Fast local check
kubectl apply --dry-run=client -f manifest.yaml

# Validate against the target API server and admission policies
kubectl apply --dry-run=server -f manifest.yaml

# Review the proposed change
kubectl diff -f manifest.yaml
  • Use client dry run for quick local feedback.
  • Use server dry run against the intended cluster and namespace.
  • Validate rendered Helm or Kustomize output.
  • Inspect kubectl diff before applying changes.

Detect deprecated APIs and environment-specific failures

Kubernetes APIs evolve, and versions may be deprecated before removal. Validate manifests against the Kubernetes version used by every target environment. A resource accepted by one cluster can fail in a newer cluster or behave differently when default values and admission policies vary.

Generic online validators cannot know every custom resource definition, validating admission policy, mutation rule, quota, limit range, or organization-specific restriction in a private cluster. Use local tools for early feedback, then rely on server-side validation in an authorized staging or target environment for the final decision.

Keep cluster upgrades in the validation plan. Inventory manifests and rendered resources before upgrading, migrate removed API versions, and test controllers and custom resources against supported versions. Avoid copying manifests from undated examples without checking current API availability.

# Inspect versions supported by the current cluster
kubectl api-resources
kubectl api-versions

# Explain the schema known to the cluster
kubectl explain deployment.spec.template.spec.containers
  • Validate against each target Kubernetes version.
  • Check custom resources and admission policies in-cluster.
  • Migrate deprecated APIs before a cluster upgrade.
  • Treat generic validation as one layer, not the final authority.

Final Kubernetes manifest validation checklist

A dependable workflow moves from cheap deterministic checks to environment-specific checks. Parse and format the YAML, validate Kubernetes structure, review relationships between resources, scan security settings, render templates, and run dry-run validation against the correct cluster. This order produces useful errors earlier and reduces unnecessary API requests.

Automate the repeatable checks in pull requests, but keep human review for operational intent. A validator cannot decide whether three replicas meet availability requirements, whether a probe reflects real application health, or whether a permission is justified. Pair automated findings with ownership and rollback planning.

StringTo's Kubernetes YAML Validator can provide quick browser-based structure checks without uploading editor content. Use the YAML Validator for grammar errors and the JSON-to-YAML converter when configuration begins as JSON. Always follow those local checks with the destination cluster's validation before deployment.

Pre-deployment order:
1. Parse YAML and reject duplicate keys.
2. Validate apiVersion, kind, metadata, and schema.
3. Check selectors, labels, ports, and references.
4. Review resources, probes, and security contexts.
5. Render templates and scan the final YAML.
6. Run server-side dry run in the target context.
7. Review the diff, rollout plan, and rollback path.
  • Automate syntax, schema, policy, and deprecation checks in CI.
  • Review cross-resource relationships and operational intent.
  • Use the exact rendered manifests for final validation.
  • Test rollouts and rollback procedures outside production first.

Frequently asked questions

How do I validate a Kubernetes YAML file?

First validate generic YAML syntax, then check the Kubernetes resource schema and cross-resource references. Render any templates and run kubectl apply with server-side dry run against the intended cluster and namespace before reviewing the diff.

What is the difference between client and server dry run?

Client dry run performs validation available locally in kubectl. Server dry run submits the request to the API server without persisting it, allowing the target cluster to apply its schema, defaulting, authorization, and admission policies.

Why is valid YAML rejected by Kubernetes?

YAML validity only confirms that the text can be parsed. Kubernetes may reject unsupported apiVersions, missing required fields, incorrect types, immutable changes, failed admission policies, quotas, permissions, or unknown custom resources.

Can an online Kubernetes YAML validator detect every error?

No. It can identify syntax and many structural problems, but it cannot know all private custom resources, admission policies, quotas, permissions, or runtime dependencies. Use server-side dry run for the final cluster-specific check.

How do I check for deprecated Kubernetes APIs?

Compare manifests with the API versions supported by each target cluster, inspect api-resources and api-versions, and include deprecation scanning before cluster upgrades. Validate rendered templates rather than only their source files.

Does a successful dry run guarantee a safe deployment?

No. Dry run does not prove that images can be pulled, containers will remain healthy, volumes will bind, dependencies are reachable, or the change meets operational requirements. Test the rollout and rollback plan in staging.

Related developer tools