OpsKit
Free · no signup

Kubernetes YAML beautifier

Format, validate, and lint a manifest against 16 production rules. Convert between YAML and JSON. Everything runs in your browser — nothing is uploaded.

Input40 lines · YAML or JSON
  • ErrorDeployment/payment-service

    hostNetwork: true — the pod shares the node's namespace instead of its own.

    spec.template.spec.hostNetwork
  • ErrorDeployment/payment-service

    Container "api" pins :latest — restarts can pull different bytes than the running pods.

    spec.template.spec.containers[0].image
  • ErrorDeployment/payment-service

    Container "api" runs privileged — container isolation is effectively off.

    spec.template.spec.containers[0].securityContext.privileged
  • ErrorDeployment/payment-service

    DB_PASSWORD carries a literal value — move it to a secretKeyRef.

    spec.template.spec.containers[0].env[0].value
  • WarningDeployment/payment-service

    replicas: 1 — every node drain and rollout is downtime.

    spec.replicas
  • WarningDeployment/payment-service

    Container "api" has no memory or CPU limit — it can starve everything else on the node.

    spec.template.spec.containers[0].resources.limits
  • WarningDeployment/payment-service

    Container "api" has no requests, so the scheduler treats it as BestEffort.

    spec.template.spec.containers[0].resources.requests
  • WarningDeployment/payment-service

    Container "api" is missing readinessProbe and livenessProbe.

    spec.template.spec.containers[0].readinessProbe
  • WarningDeployment/payment-service

    Container "api" does not set runAsNonRoot: true, so it may run as UID 0.

    spec.template.spec.containers[0].securityContext.runAsNonRoot
  • WarningDeployment/payment-service

    Container "api" leaves privilege escalation enabled (the default).

    spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
  • InfoDeployment/payment-service

    No namespace set — this applies to whatever namespace the caller's context points at.

    metadata.namespace
  • InfoDeployment/payment-service

    app.kubernetes.io/name is absent, so this object won't be attributed by dashboards or cost tooling.

    metadata.labels
  • InfoDeployment/payment-service

    Container "api" does not drop ALL capabilities before adding back what it needs.

    spec.template.spec.containers[0].securityContext.capabilities.drop
  • InfoDeployment/payment-service

    Container "api" has a writable root filesystem.

    spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
  • InfoService/payment-service

    No namespace set — this applies to whatever namespace the caller's context points at.

    metadata.namespace
  • InfoService/payment-service

    app.kubernetes.io/name is absent, so this object won't be attributed by dashboards or cost tooling.

    metadata.labels
Valid YAML2 documents4 errors6 warnings6 info Runs locally — nothing leaves this tab

The 16 checks, and why each one matters

These are static versions of the checks OpsKit's deployment-guard agent runs before a merge. The paid kit runs them against your live cluster, with the evidence attached.

Errorimage-latest-tag

Image uses :latest or no tag

A mutable tag makes a rollout unreproducible — a restarted pod can pull different bytes than its siblings, and a rollback has nothing to roll back to.

Errorplaintext-secret-env

Secret-looking value in plain text

Credentials in env.value land in the manifest, in Git, and in `kubectl describe` output. Use secretKeyRef or an external secret store.

Errorprivileged-container

Privileged container

privileged: true disables nearly every container isolation boundary. A compromise becomes a node compromise.

Errorhost-namespace

Shares a host namespace

hostNetwork, hostPID, or hostIPC break the pod out of its own namespace and expose the node's interfaces and processes.

Warningmissing-resource-limits

No memory or CPU limit

Without limits a single leaking container can evict its neighbours. It is also the reason most OOMKill investigations end in ambiguity.

Warningmissing-resource-requests

No resource requests

The scheduler places pods by request, not usage. Missing requests produce BestEffort pods that get evicted first under pressure.

Warningmissing-probes

No readiness or liveness probe

Without a readiness probe a rollout sends traffic to a container that hasn't finished starting. Without liveness, a wedged process never restarts.

Warningruns-as-root

May run as root

runAsNonRoot is not set to true, so the container can run as UID 0 and a container escape starts with root on the node.

Warningallow-privilege-escalation

Privilege escalation not blocked

allowPrivilegeEscalation defaults to true. Setting it false stops setuid binaries from gaining more privileges than the parent process.

Warninghostpath-volume

hostPath volume

A hostPath mount ties the pod to one node's filesystem and is a common path to node-level privilege escalation.

Warningsingle-replica

Single replica

One replica means every node drain, rollout, and eviction is downtime. Two is the smallest number that survives a drain.

Infocapabilities-not-dropped

Linux capabilities not dropped

Dropping ALL and adding back only what's needed shrinks the syscall surface a compromised process can reach.

Infowritable-root-filesystem

Writable root filesystem

readOnlyRootFilesystem: true stops an attacker from dropping tooling into the image at runtime. Mount an emptyDir for genuine scratch space.

Infomissing-recommended-labels

Missing app.kubernetes.io/name

The recommended labels are what dashboards, cost tooling, and ownership resolution key on. Without them a workload is hard to attribute.

Infomissing-namespace

No explicit namespace

The object lands wherever kubectl's current context points. In a GitOps repo that is an accident waiting for a context switch.

Infomissing-pdb

No PodDisruptionBudget

Without a PDB a node drain can take every replica down at once. A budget makes voluntary disruption respect your availability target.

A linter reads your file. OpsKit reads your cluster.

Static checks catch what you wrote. They can't tell you why the pod is in CrashLoopBackOff right now. OpsKit gives your AI agent a read-only connection to the live cluster — and proposes the fix as a GitOps PR.