1. Overview

In this tutorial, we’ll learn about the various output formatting we can use with the kubectl command-line tool.

2. Formatting the kubectl Command’s Output

The kubectl command-line tool allows us to interact with the Kubernetes clusters. For instance, we can retrieve resource details from the cluster using the kubectl get subcommand. To get the pod resources information from our cluster, we can use the kubectl get pods command:

$ kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
example-pod   1/1     Running   0          50s

By default, the command prints a list of pod resource information in the default namespace in a tabular format. The default output displays the most vital information of the resources to make it convenient for us to quickly get the information we want.

When we want to obtain more information or customize the output, we can opt for a different output format offered by the kubectl command. These formats include JSON, YAML, custom columns, JSON Path, and Golang template.

To demonstrate the different output formatting options, we’ll create a simple pod resource on our Kubernetes cluster:

$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    app: example
spec:
  containers:
  - name: nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80
EOF
pod/example-pod created

Let’s explore the different outputting formats we can use with the kubectl command.

3. Wide Tabular Output

The output format supports the -o wide option, which prints a few more columns on top of the default set of columns. This can be beneficial for looking into more information about the resource without having to resort to writing selectors or scripting.

For example, we can pass the -o wide option to the kubectl get pods command to obtain a few more columns of information

$ kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE                 NOMINATED NODE   READINESS GATES
example-pod   1/1     Running   0          19m   10.244.0.99   kind-control-plane   <none>           <none>

For pod resources, the -o wide option prints four additional columns for IP address, node, nominated nodes, and readiness gate.

4. Complete Resource Representation Output

The json and yaml output format retrieves the entire representation of the resources from the Kubernetes cluster. This is in contrast to the default and wide output format, which only returns a selected few columns.

Typically, a dump of the complete resource representation is then passed to a tool like jq or yq to be further processed.

4.1. JSON

To obtain the JSON representation of the resource, we pass the json value to the -o option of the kubectl command:

$ kubectl get -o json pods
{
    "apiVersion": "v1",
    "items": [
        {
            "apiVersion": "v1",
            "kind": "Pod",
            "metadata": {
                "annotations": {
                    "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},..."
                },
                "creationTimestamp": "2024-03-02T01:16:33Z",
                "labels": {
                    "app": "example"
                },
                "name": "example-pod",
...

4.2. YAML

On the other hand, we can specify the -o yaml option to obtain the complete resource representation in YAML format:

$ kubectl get -o yaml pods
apiVersion: v1
items:
- apiVersion: v1
  kind: Pod
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},...
    creationTimestamp: "2024-03-02T01:16:33Z"
    labels:
      app: example
...

5. Customized Output

The kubectl command offers a flexible approach to customize the output. Specifically, the kubectl get command supports the jsonpath output format, which can take a JSON path expression to extract specific field values.

Additionally, we can construct a highly specific output to suit our needs using the custom-columns and go-template output format.

5.1. JSON Path

The JSON path expression models the JSON object as a series of connected nodes. Through the expressions, we can traverse nodes and extract specific values.

For example, we can pass in a JSON path expression to customize the output using the -o jsonpath option:

$ kubectl get pods -o "jsonpath={.items[0].metadata.name}"
example-pod

The expression above takes the first item from the result, and then we extract the value of the name field in the metadata node. Importantly, not all the JSON path expressions are supported by the kubectl command. The official documentation has outlined a list of operators that are supported out of all the JSON path operators.

5.2. Custom Columns

The custom-column output format can create a customized tabular output based on our definition. Specifically, we can define custom columns and the respective selectors for getting the value for that column.

For example, we can construct a tabular output that prints the pod name, and the first container’s image:

$ kubectl get pods -o custom-columns=NAME:.metadata.name,IMAGE:.spec.containers[0].image
NAME          IMAGE
example-pod   nginx:latest

Each column is defined by a column name, followed by the path to obtain the value. Additionally, the column name and path are separated by a colon. Finally, the column definitions are comma-delimited.

5.3. Go Template

The go-template output format takes as input a valid Golang template to customize the resource information before printing it to the console.

For example, we can print the name of the pod and the namespace of the pod side by side using go-template:

$ kubectl get pods -o go-template='{{range .items}}{{.metadata.name}} {{.metadata.namespace}}{{end}}'
example-pod default

With a little tweak, we can print the value row-by-row, instead of side-by-side:

$ kubectl get pods -o go-template='{{range .items}}{{.metadata.name}} {{printf "\n"}}{{.metadata.namespace}}{{end}}'
example-pod
default

5.4. Storing Expression in Files

Notably, all the output format that supports customization has a corresponding option with the -file suffix which supports passing an expression through a file. This is especially handy when our expression gets too complicated for inlining it on the command-line terminal. By storing the expressions in the file, we can enjoy the benefits of indentation, which makes it more readable.

For example, instead of passing the JSON path expression directly to the command with -o jsonpath, we can store the expression in a file, get-resource-name.jsonpath:

$ echo '{.items[0].metadata.name}' >> get-resource-name.jsonpath

Then, we can pass it to the -o jsonpath-file option:

$ kubectl get pods -o jsonpath-file=get-resource-name.jsonpath
example-pod

The command above is functionally equivalent to the inline version that uses the -o jsonpath option.

For go-template and custom-columns, we can use the go-template-file and custom-columns-file options, respectively.

6. Recipes

In this section, we’ll demonstrate some specific use cases that utilize the different output formats of the kubectl command.

6.1. Getting Specific Value From Secret

A single secret resource in the Kubernetes cluster can contain multiple key-value pairs. To obtain a specific value from the key-value list, we can use the go-template output format to select specifically the key for the value we want to retrieve.

For example, let’s say there’s a databasePassword and monitoringApikey in our example-secret resource:

$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: example-secret
type: Opaque
stringData:
  monitoringApikey: b8ea6ae7cf54af7
  databasePassword: dbadmin123
EOF

To retrieve the monitoringApikey value specifically, we can use the go-template expression {{.data.monitoringApikey}}:

$ kubectl get secret example-secret -o go-template='{{.data.monitoringApikey}}' | base64 --decode
b8ea6ae7cf54af7

We use the kubectl command to get the example-secret resource. Then, we format the output of the resource retrieval using the go-template expression. Finally, we pipe the output to the command base64 –decode to decode the base64 encoded secret value.

6.2. Filtering Results Based on Condition

This scenario demonstrates the capability of the go-template syntax to perform simple filtering. As an example, we’ll get all the service resources on our cluster, and then filter the result to print the name of the service that’s using NodePort.

Let’s create multiple types of services:

$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: example-service-nodeport
spec:
  selector:
    app: example
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort

---
apiVersion: v1
kind: Service
metadata:
  name: example-service-clusterip
spec:
  selector:
    app: example
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

---
apiVersion: v1
kind: Service
metadata:
  name: example-service-loadbalancer
spec:
  selector:
    app: example
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
EOF

Then, we can use the kubectl get svc command to get all the services, passing the -o go-template option to filter and format the result list:

$  kubectl get svc -o go-template='{{ range .items }}{{ if eq .spec.type "NodePort" }}{{ .metadata.name }}{{ printf "\n" }}{{
end }}{{ end }}'
example-service-nodeport

The go-template expression above loops over all the services. Then, we print the .metadata.name value and a newline if its .spec.type is equal to NodePort. Specifically, we use the eq function to perform an equality comparison.

In addition to the eq, the Golang template supports other comparators like greater than (gt), less than (lt), greater or equals (ge), lesser or equals (le), and not equals (ne).

7. Conclusion

In this tutorial, we’ve first looked at the various output formatting options of the kubectl command. For example, we’ve seen that the wide output format gives us a few more columns of information. Then, we learned that the json and yaml output formats return the complete resource representation in the respective formats.

We’ve also briefly explored the flexibility offered by the jsonpathgo-template, and custom-columns option to customize the output. Finally, we’ve demonstrated several use cases that utilize the different output formats to extract specific values from resources.