---
title: "Kubernetes YAML Validator"
description: "This skill provides a comprehensive validation workflow for Kubernetes YAML resources, combining syntax linting, schema validation, cluster dry-run testing, and intelligent CRD documentation lookup. Validate any Kubernetes manifest with confidence before applying it to the cluster."
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/skill-101
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:43:31.357Z
license: CC-BY-4.0
attribution: "Kubernetes YAML Validator — Claudary (https://claudary.paisolsolutions.com/skills/skill-101)"
---

# Kubernetes YAML Validator
This skill provides a comprehensive validation workflow for Kubernetes YAML resources, combining syntax linting, schema validation, cluster dry-run testing, and intelligent CRD documentation lookup. Validate any Kubernetes manifest with confidence before applying it to the cluster.

## Overview

---
name: k8s-yaml-validator
description: Validate, lint, audit, or dry-run Kubernetes manifests (Deployment, Service, ConfigMap, CRD).
---

# Kubernetes YAML Validator

## Overview

This skill provides a comprehensive validation workflow for Kubernetes YAML resources, combining syntax linting, schema validation, cluster dry-run testing, and intelligent CRD documentation lookup. Validate any Kubernetes manifest with confidence before applying it to the cluster.

**IMPORTANT: This is a REPORT-ONLY validation tool.** Do NOT modify files, do NOT use Edit tool, do NOT use AskUserQuestion to offer fixes. Generate a comprehensive validation report with suggested fixes shown as before/after code blocks, then let the user decide what to do next.

## Trigger Phrases

Use this skill when prompts look like:
- "Validate this Kubernetes YAML before deploy."
- "Lint these manifests and report what is broken."
- "Check this CRD manifest and explain schema issues."
- "Run dry-run checks on this manifest."
- "Find line-level errors in this multi-document YAML."

## When to Use This Skill

Invoke this skill when:
- Validating Kubernetes YAML files before applying to a cluster
- Debugging YAML syntax or formatting errors
- Working with Custom Resource Definitions (CRDs) and need documentation
- Performing dry-run tests to catch admission controller errors
- Ensuring YAML follows Kubernetes best practices
- Understanding what validation errors exist in manifests (report-only, user fixes manually)
- The user asks to "validate", "lint", "check", or "test" Kubernetes YAML files

## Read-Only Boundary (Mandatory)

This skill is strictly report-only:
- Do NOT modify any user files.
- Do NOT run Edit for fixes.
- Do NOT ask for permission to apply fixes.
- Do provide before/after snippets as suggestions in the report.

## Deterministic Path Setup

Run with explicit paths so commands are repeatable:

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
SKILL_DIR="$REPO_ROOT/devops-skills-plugin/skills/k8s-yaml-validator"
TARGET_FILE="$REPO_ROOT/<relative/path/to/file.yaml>"
```

Path checks:
- If `REPO_ROOT` is empty, stop and ask for repository root.
- If `SKILL_DIR` does not exist, stop and report path mismatch.
- If `TARGET_FILE` does not exist, stop and ask for the correct file.

## Validation Workflow

Follow this sequential validation workflow. Each stage catches different types of issues:

### Stage 0: Pre-Validation Setup (Deterministic Resource Count)

Before running validators, count documents using the bundled script:

```bash
python3 "$SKILL_DIR/scripts/count_yaml_documents.py" "$TARGET_FILE"
```

Expected output (example):
```json
{
  "file": ".../manifests.yaml",
  "documents": 3,
  "separators": 2
}
```

Gate rules:
- If `documents >= 3`, load `references/validation_workflow.md` before Stage 1.
- Always include the document count in the final report summary.
- If `python3` is unavailable, use fallback:
```bash
awk 'BEGIN{d=0;seen=0} /^[[:space:]]*---[[:space:]]*$/ {if(seen){d++;seen=0}; next} /^[[:space:]]*#/ {next} NF{seen=1} END{if(seen)d++; print d}' "$TARGET_FILE"
```
and mark the count as `estimated` in the report.

### Stage 1: Tool Check

Before starting validation, verify required tools are installed:

```bash
bash "$SKILL_DIR/scripts/setup_tools.sh"
```

Required tools:
- **yamllint**: YAML syntax and style linting
- **kubeconform**: Kubernetes schema validation with CRD support
- **kubectl**: Cluster dry-run testing (optional but recommended)

If tools are missing, display installation guidance from script output and continue with available tools. Document missing tools and skipped stages in the report.

### Stage 2: YAML Syntax Validation

Validate YAML syntax and formatting using yamllint:

```bash
yamllint -c "$SKILL_DIR/assets/.yamllint" "$TARGET_FILE"
```

**Common issues caught:**
- Indentation errors (tabs vs spaces)
- Trailing whitespace
- Line length violations
- Syntax errors
- Duplicate keys

**Reporting approach:**
- Report all syntax issues with file:line references
- For fixable issues, show suggested before/after code blocks
- Continue to next validation stage to collect all issues before reporting

### Stage 3: CRD Detection and Documentation Lookup

Before schema validation, detect if the YAML contains Custom Resource Definitions:

```bash
bash "$SKILL_DIR/scripts/detect_crd_wrapper.sh" "$TARGET_FILE"
```

The wrapper script automatically handles Python dependencies by creating a temporary virtual environment if PyYAML is not available.

**Resilient Parsing:** The script is resilient to syntax errors in individual documents. If a multi-document YAML file has some valid and some invalid documents, the script will:
- Parse valid documents and detect their CRDs
- Report errors for invalid documents but continue processing
- This matches kubeconform's behavior of validating 2/3 resources even when 1/3 has syntax errors

The script outputs JSON with resource information and parse status:
```json
{
  "resources": [
    {
      "kind": "Certificate",
      "apiVersion": "cert-manager.io/v1",
      "group": "cert-manager.io",
      "version": "v1",
      "isCRD": true,
      "name": "example-cert"
    }
  ],
  "parseErrors": [
    {
      "document": 1,
      "start_line": 2,
      "error_line": 6,
      "error": "mapping values are not allowed in this context"
    }
  ],
  "summary": {
    "totalDocuments": 3,
    "parsedSuccessfully": 2,
    "parseErrors": 1,
    "crdsDetected": 1
  }
}
```

**For each detected CRD:**

1. **Try Context7 MCP first (preferred):**
   - Resolve library:
     - Tool: `mcp__context7__resolve-library-id`
     - `libraryName`: CRD project name (example: `cert-manager` for `cert-manager.io`)
   - Query docs:
     - Tool: `mcp__context7__query-docs`
     - `libraryId`: resolved library ID from previous step
     - `query`: include CRD kind, group, and version (example: `Certificate cert-manager.io v1 required fields in spec`)

2. **Fallback to `web.search_query` if Context7 fails or returns insufficient details:**
   ```
   Search query pattern:
   "<kind>" "<group>" kubernetes CRD "<version>" documentation spec

   Example:
   "Certificate" "cert-manager.io" kubernetes CRD "v1" documentation spec
   ```

3. **Extract key information:**
   - Required fields in `spec`
   - Field types and validation rules
   - Examples from documentation
   - Version-specific changes or deprecations

**Secondary CRD Detection via kubeconform:** If `detect_crd_wrapper.sh` cannot identify CRDs (for example, syntax errors in all documents), but kubeconform still validates a CRD resource, look up docs for that CRD anyway. Parse kubeconform output to identify validated CRDs and perform Context7/`web.search_query` lookups.

**Why this matters:** CRDs have custom schemas not available in standard Kubernetes validation tools. Understanding the CRD's spec requirements prevents validation errors and ensures correct resource configuration.

### Stage 4: Schema Validation

Validate against Kubernetes schemas using kubeconform:

```bash
kubeconform \\
  -schema-location default \\
  -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' \\
  -strict \\
  -ignore-missing-schemas \\
  -summary \\
  -verbose \\
  "$TARGET_FILE"
```

**Options explained:**
- `-strict`: Reject unknown fields (recommended for production - catches typos)
- `-ignore-missing-schemas`: Skip validation for CRDs without available schemas
- `-kubernetes-version 1.30.0`: Validate against specific K8s version

**Common issues caught:**
- Invalid apiVersion or kind
- Missing required fields
- Wrong field types
- Invalid enum values
- Unknown fields (with -strict)

**For CRDs:** If kubeconform reports "no schema found", this is expected. Use the documentation from Stage 3 to manually validate the spec fields.

**kubeconform line number behavior — two distinct cases:**

kubeconform does NOT report file-absolute line numbers. You must translate:

1. **Parse errors** (e.g. `error converting YAML to JSON: yaml: line N`):
   - `N` is **document-relative** (line N within that document's content).
   - Convert to file-absolute: `file_line = doc_start_line + N - 1`
   - `doc_start_line` comes from the `start_line` field in `detect_crd_wrapper.sh` output.
   - Example: document starts at file line 4, kubeconform says `yaml: line 5` →
     file-absolute line = 4 + 5 − 1 = **line 8** (matches yamllint output).

2. **Schema validation errors** (e.g. `got string, want integer`):
   - kubeconform reports **JSON path only**, no line number.
   - Example: `at '/spec/template/spec/containers/0/ports/0/containerPort': got string, want integer`
   - To find the line: search the YAML file for the field name (e.g. `containerPort`) within
     the relevant document section, using file-absolute line numbers from the surrounding context.

Always present line numbers as file-absolute in the validation report even when translating
from kubeconform's document-relative output.

### Stage 5: Cluster Dry-Run (if available)

**IMPORTANT: Always try server-side dry-run first.** Server-side validation catches more issues than client-side because it runs through admission controllers and webhooks.

**Decision Tree:**

```
1. Try server-side dry-run first:
   kubectl apply --dry-run=server -f "$TARGET_FILE"

   └─ If SUCCESS → Use results, continue to Stage 6

   └─ If FAILS with connection error (e.g., "connection refused",
      "unable to connect", "no configuration"):
      │
      ├─ 2. Attempt client-side dry-run (parse-only fallback):
      │     kubectl apply --dry-run=client --validate=false -f "$TARGET_FILE"
      │
      │     ├─ If SUCCESS:
      │     │    Document in report: "Server-side validation skipped (no cluster access); client fallback ran in parse-only mode"
      │     │
      │     └─ If FAILS with discovery/openapi error (e.g., "unable to recognize",
      │        "failed to download openapi", "couldn't get current server API group list"):
      │        Document in report: "Dry-run skipped (cluster discovery unavailable)"
      │        Continue to Stage 6
      │
      └─ If FAILS with validation error (e.g., "admission webhook denied",
         "resource quota exceeded", "invalid value"):
         └─ Record the error, continue to Stage 6

   └─ If FAILS with parse error (e.g., "error converting YAML to JSON",
      "yaml: line X: mapping values are not allowed"):
      └─ Record the error, skip client-side dry-run (same error will occur)
         Document in report: "Dry-run blocked by YAML syntax errors - fix syntax first"
         Continue to Stage 6
```

**Note:** Parse errors from earlier stages (yamllint, kubeconform) will also cause dry-run to fail. Do NOT attempt client-side dry-run as a fallback for parse errors - it will produce the same error. Parse errors must be fixed before dry-run validation can proceed.

**Server-side dry-run catches:**
- Admission controller rejections
- Policy violations (PSP, OPA, Kyverno, etc.)
- Resource quota violations
- Missing namespaces
- Invalid ConfigMap/Secret references
- Webhook validations

**Client-side dry-run with `--validate=false` catches (fallback, when command succeeds):**
- YAML/JSON conversion and request-construction issues
- Whether `kubectl` can process and submit the manifest shape in client mode
- **Note:** `--validate=false` disables schema/type/required-field validation and still does NOT catch admission controller or policy issues.

**Document in your report which mode was used:**
- If server-side: "Full cluster validation performed"
- If client-side with `--validate=false`: "Limited parse-only validation (no cluster access) - schema and admission policies not checked"
- If skipped: "Dry-run skipped - kubectl not available"
- If skipped after client fallback attempt: "Dry-run skipped (cluster discovery unavailable)"

**For updates to existing resources:**
```bash
kubectl diff -f "$TARGET_FILE"
```
This shows what would change, helping catch unintended modifications.

### Stage 6: Generate Detailed Validation Report (REPORT ONLY)

After completing all validation stages, generate a comprehensive report. **This is a REPORT-ONLY stage.**

**NEVER do any of the following:**
- Do NOT use the Edit tool to modify files
- Do NOT use AskUserQuestion to offer to fix issues
- Do NOT prompt the user asking if they want fixes applied
- Do NOT modify any YAML files

**ALWAYS do the following:**
- Generate a comprehensive validation report
- Show before/after code blocks as SUGGESTIONS only
- Let the user decide what to do after reviewing the report
- End with "Next Steps" for the user to take manually

1. **Summarize all issues found** across all stages in a table format:

   ```
   | Severity | Stage | Location | Issue | Suggested Fix |
   |----------|-------|----------|-------|---------------|
   | Error | Syntax | file.yaml:5 | Indentation error | Use 2 spaces |
   | Error | Schema | file.yaml:21 | Wrong type | Change to integer |
   | Warning | Best Practice | file.yaml:30 | Missing labels | Add app label |
   ```

2. **Categorize by severity:**
   - **Errors** (must fix): Syntax errors, missing required fields, dry-run failures
   - **Warnings** (should fix): Style issues, best practice violations
   - **Info** (optional): Suggestions for improvement

3. **Show before/after code blocks for each issue:**

   For every issue, display explicit before/after YAML snippets showing the suggested fix:

   ```
   **Issue 1: deployment.yaml:21 - Wrong field type (Error)**

   Current:
   ```yaml
           - containerPort: "80"
   ```

   Suggested Fix:
   ```yaml
           - containerPort: 80
   ```

   **Why:** containerPort must be an integer, not a string. Kubernetes will reject string values.
   Reference: See k8s_best_practices.md "Invalid Values" section.
   ```

4. **Provide validation summary:**

   ```
   ## Validation Report Summary

   File: deployment.yaml
   Resources Analyzed: 3 (Deployment, Service, Certificate)

   | Stage | Status | Issues Found |
   |-------|--------|--------------|
   | YAML Syntax | ❌ Failed | 2 errors |
   | CRD Detection | ✅ Passed | 1 CRD detected (Certificate) |
   | Schema Validation | ❌ Failed | 1 error |
   | Dry-Run | ❌ Failed | 1 error |

   Total Issues: 4 errors, 2 warnings

   ## Detailed Findings

   [List each issue with before/after code blocks as shown above]

   ## Next Steps

   1. Fix the 4 errors listed above (deployment will fail without these)
   2. Consider addressing the 2 warnings for best practices
   3. Re-run validation after fixes to confirm resolution
   ```

5. **Do NOT modify files** - this is a reporting tool only
   - Present all findings clearly
   - Let the user decide which fixes to apply
   - User can request fixes after reviewing the report

## Objective Stage Gates (Repeatable)

Use this table to keep stage decisions deterministic:

| Stage

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/skill-101) · https://claudary.paisolsolutions.com
