Kubernetes YAML Linter
Paste one or more Kubernetes manifests separated by ---. The linter checks required fields, removed or wrong apiVersions, selector and label mismatches, resource requests and limits, probes, security context, :latest images, Services that select nothing, Ingress backends and CronJob schedules.
Private by design: anything you enter is processed in your browser only. It is never uploaded to or logged on our servers. Manifests are linted locally and never sent to a cluster or API server, so Secret values stay on your machine unless you create a share link, which stores the YAML in the link itself.
Separate multiple resources with a --- line. Lints as you type.
About this Kubernetes YAML linter
Kubernetes accepts a surprising number of manifests that later misbehave: a Deployment whose selector does not match its Pod labels is rejected outright, a Service whose selector matches nothing silently has no endpoints, and a container without resource requests can be squeezed off a busy node. This linter parses every document in a multi-document YAML file and checks each resource for structural mistakes, removed API versions and widely recommended reliability and security settings.
Findings show the document number, resource kind and name, and the line, so you can click straight to the problem. Errors are things the API server would reject or that cannot work, such as a removed apiVersion, a selector mismatch, an unquoted number in an environment variable or an invalid CronJob schedule. Warnings cover security and reliability: privileged containers, privilege escalation, running as root, host namespaces, hostPath volumes, missing resource requests and :latest images. Info items are suggestions such as single-replica Deployments or missing liveness probes.
The checks are static and work offline. They do not know which Custom Resource Definitions or admission policies your cluster has, so custom kinds only get the generic checks (apiVersion, kind and a valid name). Before applying, confirm against your real cluster with kubectl apply --dry-run=server -f file.yaml, or validate against the official JSON schemas in CI with kubeconform.
Templating with Helm? Compare and merge chart values with the Helm values tool. Running containers locally first? Check the image with the Dockerfile linter and your local stack with the Docker Compose validator. To turn a manifest into JSON for kubectl patch or jq, use the data format converter, and test CronJob schedules with the cron expression builder.
Reference Guide
Current apiVersion for common kinds, and versions that have been removed:
| Kind | Use | Removed versions |
|---|---|---|
| Pod, Service, ConfigMap, Secret, Namespace, PersistentVolumeClaim, ServiceAccount | v1 | – |
| Deployment, StatefulSet, DaemonSet, ReplicaSet | apps/v1 | extensions/v1beta1, apps/v1beta1, apps/v1beta2 (removed in 1.16) |
| Ingress, IngressClass | networking.k8s.io/v1 | extensions/v1beta1, networking.k8s.io/v1beta1 (1.22) |
| NetworkPolicy | networking.k8s.io/v1 | extensions/v1beta1 (1.16) |
| Job, CronJob | batch/v1 | CronJob batch/v1beta1 (1.25) |
| HorizontalPodAutoscaler | autoscaling/v2 | autoscaling/v2beta1 (1.25), autoscaling/v2beta2 (1.26) |
| PodDisruptionBudget | policy/v1 | policy/v1beta1 (1.25) |
| Role, ClusterRole, RoleBinding, ClusterRoleBinding | rbac.authorization.k8s.io/v1 | rbac.authorization.k8s.io/v1beta1 (1.22) |
| CustomResourceDefinition | apiextensions.k8s.io/v1 | apiextensions.k8s.io/v1beta1 (1.22) |
Required fields:
| Resource | Must have |
|---|---|
| Every object | apiVersion, kind, metadata.name (or generateName); most names allow lowercase letters, digits, - and ., while Service and Namespace names cannot contain dots |
| Deployment, StatefulSet, DaemonSet, ReplicaSet | spec.selector whose labels match spec.template.metadata.labels; at least one container with name and image |
| Job, CronJob | restartPolicy: Never or OnFailure in the Pod template; CronJob needs schedule and jobTemplate |
| Service | spec.ports (except type: ExternalName); a selector unless you manage endpoints yourself |
Ingress (networking.k8s.io/v1) | pathType on every path and backend.service.name + backend.service.port |
| Labels, annotations, ConfigMap data, env values | String values. Quote numbers and booleans: value: "8080", enabled: "true" |
Security context best practices (the Pod Security Standards "restricted" profile):
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.example.com/app:1.4.2
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { memory: 256Mi }
- Avoid
privileged: true,hostNetwork,hostPID,hostIPCandhostPathvolumes unless the workload is a node agent that truly needs them. - Set memory limits to protect the node. Many teams leave CPU limits off to avoid throttling and rely on CPU requests for scheduling.
readinessProbecontrols whether a Pod receives Service traffic;livenessProberestarts a stuck container. Do not point liveness at dependencies such as the database.
Validate against a cluster: kubectl apply --dry-run=server -f manifests.yaml runs the real API validation and admission webhooks without saving anything. Offline, kubeconform -strict -summary manifests.yaml checks against the Kubernetes JSON schemas, and kubectl explain deployment.spec.template.spec documents every field.
Example input
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: web
image: nginx:latest
env:
- name: WORKERS
value: 4
securityContext:
privileged: true
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cleanup
spec:
schedule: "0 25 * * *"
...
This sample loads automatically when you open the tool. Use Load Sample to bring it back.
Frequently Asked Questions
It checks each manifest for required fields, removed or deprecated API versions, selectors that do not match pod labels, missing resource requests and limits, missing probes, latest image tags and insecure security context settings.
Yes. Paste multiple documents separated by --- and each one is checked, with findings labelled by document and line.
No. Values under data are only Base64 encoded, which anyone can decode. Keep Secret manifests out of Git or use a tool such as Sealed Secrets or an external secrets manager.
Related Tools
All DevOps Tools →Helm Values Tool
Compare and merge Helm values.yaml files the way Helm does,...
Log Analyzer
Parse Nginx/Apache access logs, JSON logs and plain applicat...
SLA & Uptime Calculator
Convert an SLA percentage such as 99.9% into allowed downtim...
JSON, YAML, CSV & XML Converter Online
Convert data between JSON, YAML, CSV and XML in any directio...
HTML Beautifier & Formatter Online
Beautify and format HTML markup online with configurable ind...
CSS Beautifier & Pretty Printer Online
Beautify and format CSS stylesheets with consistent spacing...