Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool

JSON-based Configuration for Kubernetes Deployments

Kubernetes configurations, known as manifests, are most commonly authored in YAML. This is the de facto standard for human-readable configuration files within the Kubernetes ecosystem. However, the Kubernetes API fundamentally communicates using JSON (JavaScript Object Notation).

Every YAML manifest you apply to a Kubernetes cluster is parsed and converted into its JSON equivalent before being sent to the API server. Conversely, when you retrieve the state of resources from the API server using tools like kubectl, you are receiving JSON data (though kubectl often formats it nicely for display).

Understanding the JSON structure of Kubernetes objects is crucial for several reasons:

  • API Interaction: Direct interaction with the K8s API often involves sending and receiving JSON.
  • Tooling and Automation: Many tools, scripts, and client libraries that work with Kubernetes process or generate configurations in JSON.
  • Debugging: Examining the JSON output of kubectl get ... -o json can provide a precise view of how Kubernetes interprets your configuration.

This article explores how to define Kubernetes Deployments using JSON, providing examples and discussing practical aspects.

Kubernetes Manifest Structure in JSON

A Kubernetes manifest, whether in YAML or JSON, describes a desired state for a resource (like a Deployment, Service, Pod, etc.). All K8s objects share a common top-level structure:

Core Fields:

  • apiVersion: Specifies the Kubernetes API version (e.g., apps/v1 for Deployments, v1 for Pods/Services).
  • kind: The type of Kubernetes resource being created or modified (e.g., Deployment, Service, Pod, ReplicaSet).
  • metadata: An object containing data to uniquely identify the object, including name, namespace, labels, and annotations.
  • spec: An object describing the desired state of the resource. The structure of the spec field is specific to each kind of object.
  • status: (Optional, managed by K8s) An object describing the current state of the resource. This is usually present in retrieved objects but not in the configuration you apply.

YAML vs. JSON: A Simple Deployment

Let's look at a minimal Nginx Deployment in both YAML and JSON formats to see the structural differences.

YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

JSON Equivalent

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "nginx-deployment",
    "labels": {
      "app": "nginx"
    }
  },
  "spec": {
    "replicas": 2,
    "selector": {
      "matchLabels": {
        "app": "nginx"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "nginx"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "nginx",
            "image": "nginx:latest",
            "ports": [
              {
                "containerPort": 80
              }
            ]
          }
        ]
      }
    }
  }
}

As you can see, the hierarchical structure maps directly: YAML's indentation and key-value pairs become JSON's curly braces {} for objects and square brackets [] for arrays. YAML lists become JSON arrays of objects or primitive types.

JSON Data Types in K8s Manifests

Kubernetes resources use standard JSON data types:

  • "string": Used for names, image tags, paths, configuration values, etc.
  • 123 or 12.3: Numbers, used for counts (replicas), ports, resource values (CPU/memory sometimes strings, sometimes numbers depending on field).
  • true / false: Booleans, used for flags or toggles.
  • null: Explicitly representing a missing or null value (less common in typical manifests you write, more in API responses).
  • { "key": "value" }: Objects, used for structured data like metadata, labels, spec, container resource limits/requests, etc.
  • [ "value1", "value2" ] or [ {...}, {...} ]: Arrays, used for lists of items, such as containers, ports, env variables, volumeMounts, etc.

Examples of JSON Deployments

Deployment with Environment Variables

Environment variables are defined as an array of objects within the container specification.

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "app-with-env"
  },
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "app": "my-app"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "my-app"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "main-container",
            "image": "my-image:v1.0",
            "env": [
              {
                "name": "NODE_ENV",
                "value": "production"
              },
              {
                "name": "LOG_LEVEL",
                "value": "info"
              }
            ]
          }
        ]
      }
    }
  }
}

Deployment with Resource Limits and Requests

CPU and memory requests/limits are defined in a nested object within the container specification. Resource values are typically strings in Kubernetes.

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "app-with-resources"
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": {
        "app": "resource-hungry-app"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "resource-hungry-app"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "main-container",
            "image": "another-image:latest",
            "resources": {
              "limits": {
                "cpu": "500m",
                "memory": "512Mi"
              },
              "requests": {
                "cpu": "250m",
                "memory": "256Mi"
              }
            }
          }
        ]
      }
    }
  }
}

Adding Labels and Annotations

Labels and annotations are key-value pairs defined within the metadata object. Labels are used for selecting groups of objects (e.g., by Deployments to find Pods). Annotations are for non-identifying metadata.

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "app-with-meta",
    "namespace": "default",
    "labels": {
      "app": "my-web-app",
      "tier": "frontend"
    },
    "annotations": {
      "description": "Frontend web server deployment",
      "owner": "team-a@example.com"
    }
  },
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "app": "my-web-app"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "my-web-app",
          "tier": "frontend"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "web",
            "image": "my-webapp:latest"
          }
        ]
      }
    }
  }
}

Working with JSON and kubectl

You can use kubectl directly with JSON files.

Applying JSON Manifests

Save your JSON configuration to a file (e.g., deployment.json) and apply it using:

kubectl apply -f deployment.json

This command works exactly like applying a YAML file.

Getting Resource Output as JSON

To see the full JSON representation of a running resource, use the -o json (or --output=json) flag:

kubectl get deployment nginx-deployment -o json

This will output the complete state of the Deployment object, including status fields managed by Kubernetes, in JSON format. This output can be significantly larger than your input YAML/JSON because it includes runtime information.

Converting Between YAML and JSON

kubectl can convert configurations between formats locally without sending them to the cluster. Use the kubectl convert command (requires the appropriate API version installed, though this command is becoming less common and features might be moving). A more robust method is using kubectl create --dry-run=client -o json or pipeline tools like yq or jq.

Example using kubectl dry-run:

kubectl create deployment my-app --image=my-image --dry-run=client -o json

This command generates a basic Deployment object and outputs its JSON representation locally. You can pipe this output to a file or other tools.

Pros and Cons of JSON for K8s Configs

Advantages

  • API Native: JSON is the format the Kubernetes API understands directly.
  • Machine Readability/Writability: Ideal for programmatic generation, parsing, and modification of manifests using standard JSON libraries in any programming language. Excellent for building custom operators or automation tools.
  • Strict Format: JSON is less forgiving than YAML regarding syntax (e.g., requiring commas between list items, strict quoting), which can sometimes help catch simple errors early in automated processes.

Disadvantages

  • Verbosity: JSON syntax with its repetitive braces{}, brackets[], and quotes makes it significantly more verbose and harder for humans to read and write compared to YAML's cleaner, indentation-based structure.
  • Syntax Sensitivity: A single missing comma or misplaced brace can invalidate the entire document, which can be frustrating for manual editing.
  • Comments: JSON does not natively support comments, making it difficult to add explanatory notes within the configuration file itself (YAML supports comments).

Practical Considerations

  • YAML is King for Manual Editing: For configuration files that humans write and maintain, YAML is overwhelmingly preferred in the K8s community due to its readability.
  • JSON for Automation: If you are building a tool, script, or application that dynamically generates or modifies Kubernetes manifests, working with JSON programmatically is often more straightforward using standard libraries than manipulating YAML strings.
  • Conversion Tools: Be familiar with tools like jq (for processing JSON) and YAML-to-JSON converters (like the one built into kubectl or dedicated tools) to switch between formats as needed.

Conclusion

While YAML is the standard for writing Kubernetes manifests, JSON is the underlying format used by the API. Understanding the JSON structure of Kubernetes objects, particularly Deployments, provides valuable insight into how the API works and is essential for building automation, integrating with other tools, or debugging configurations by inspecting the live state of resources.

You are unlikely to write all your Deployments in JSON manually, but being able to read, understand, and generate JSON manifests will make you a more effective Kubernetes developer and operator.

Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool