Leveraging the JSONPATH of a Kubernetes Deployment

Use Case:

A User wants to gather information from a Kubernetes deployment and leverage it as a variable later on. These values can be leveraged in other Workflows or in a Pipeline! In order to retrieve these specific values, we leverage something called the JSONPATH=`` in the Kubectl tool. This lets the user navigate through a Kubernetes object and specify a specific field they want to view.

Below is what a deployment.json looks like

Run this command to describe the deployment

kubectl describe deployment frontend -o=json

This is the result

{
    "apiVersion": "extensions/v1beta1",
    "kind": "Deployment",
    "metadata": {
        "annotations": {
            "deployment.kubernetes.io/revision": "1",
            "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{\"kubernetes.io/change-cause\":\"kubectl apply --kubeconfig=config --filename=manifests.yaml --record=true\"},\"finalizers\":[],\"labels\":{\"app\":\"guestbook-test\"},\"name\":\"frontend\",\"namespace\":\"dev\",\"ownerReferences\":[]},\"spec\":{\"replicas\":3,\"selector\":{\"matchExpressions\":[],\"matchLabels\":{\"app\":\"guestbook\",\"harness.io/track\":\"stable\",\"tier\":\"frontend\"}},\"template\":{\"metadata\":{\"annotations\":{},\"finalizers\":[],\"labels\":{\"app\":\"guestbook\",\"harness.io/release-name\":\"release-cbb5dd9c-4c21-3704-8a90-1cf22d9b4300\",\"harness.io/track\":\"stable\",\"tier\":\"frontend\"},\"ownerReferences\":[]},\"spec\":{\"containers\":[{\"args\":[],\"command\":[],\"env\":[{\"name\":\"GET_HOSTS_FROM\",\"value\":\"dns\"}],\"envFrom\":[],\"image\":\"gcr.io/google-samples/gb-frontend:v4\",\"name\":\"php-redis\",\"ports\":[{\"containerPort\":80}],\"resources\":{\"limits\":{},\"requests\":{\"cpu\":\"100m\",\"memory\":\"100Mi\"}},\"volumeMounts\":[]}],\"hostAliases\":[],\"imagePullSecrets\":[],\"initContainers\":[],\"nodeSelector\":{},\"tolerations\":[],\"volumes\":[]}}}}\n",
            "kubernetes.io/change-cause": "kubectl apply --kubeconfig=config --filename=manifests.yaml --record=true"
        },
        "creationTimestamp": "2019-12-14T01:02:51Z",
        "generation": 1,
        "labels": {
            "app": "guestbook-test"
        },
        "name": "frontend",
        "namespace": "dev",
        "resourceVersion": "1105661",
        "selfLink": "/apis/extensions/v1beta1/namespaces/dev/deployments/frontend",
        "uid": "73a8d311-1e0d-11ea-9b03-42010a8a0105"
    },
    "spec": {
        "progressDeadlineSeconds": 600,
        "replicas": 3,
        "revisionHistoryLimit": 10,
        "selector": {
            "matchLabels": {
                "app": "guestbook",
                "harness.io/track": "stable",
                "tier": "frontend"
            }
        },
        "strategy": {
            "rollingUpdate": {
                "maxSurge": "25%",
                "maxUnavailable": "25%"
            },
            "type": "RollingUpdate"
        },
        "template": {
            "metadata": {
                "creationTimestamp": null,
                "labels": {
                    "app": "guestbook",
                    "harness.io/release-name": "release-cbb5dd9c-4c21-3704-8a90-1cf22d9b4300",
                    "harness.io/track": "stable",
                    "tier": "frontend"
                }
            },
            "spec": {
                "containers": [
                    {
                        "env": [
                            {
                                "name": "GET_HOSTS_FROM",
                                "value": "dns"
                            }
                        ],
                        "image": "gcr.io/google-samples/gb-frontend:v4",
                        "imagePullPolicy": "IfNotPresent",
                        "name": "php-redis",
                        "ports": [
                            {
                                "containerPort": 80,
                                "protocol": "TCP"
                            }
                        ],
                        "resources": {
                            "requests": {
                                "cpu": "100m",
                                "memory": "100Mi"
                            }
                        },
                        "terminationMessagePath": "/dev/termination-log",
                        "terminationMessagePolicy": "File"
                    }
                ],
                "dnsPolicy": "ClusterFirst",
                "restartPolicy": "Always",
                "schedulerName": "default-scheduler",
                "securityContext": {},
                "terminationGracePeriodSeconds": 30
            }
        }
    },
    "status": {
        "availableReplicas": 3,
        "conditions": [
            {
                "lastTransitionTime": "2019-12-14T01:02:51Z",
                "lastUpdateTime": "2019-12-14T01:03:13Z",
                "message": "ReplicaSet \"frontend-d6b644566\" has successfully progressed.",
                "reason": "NewReplicaSetAvailable",
                "status": "True",
                "type": "Progressing"
            },
            {
                "lastTransitionTime": "2019-12-16T20:23:00Z",
                "lastUpdateTime": "2019-12-16T20:23:00Z",
                "message": "Deployment has minimum availability.",
                "reason": "MinimumReplicasAvailable",
                "status": "True",
                "type": "Available"
            }
        ],
        "observedGeneration": 1,
        "readyReplicas": 3,
        "replicas": 3,
        "updatedReplicas": 3
    }
}

Key Questions:

How does a developer navigate through this?

What pieces of information can we leverage from this?

Online Resources:
To better understand how to traverse the Kubernetes Object YAML and manipulate certain fields please review this doc from Kubernetes: https://kubernetes.io/docs/reference/kubectl/cheatsheet/

Sample Commands

Example 1

This Command gets a deployment called frontend in the namespace dev, we output the object “-o” and specify the JSONPATH of the image. We dump it out to JSON file and run the cut command to get the specific version tag of the image.

kubectl get deployment frontend -n dev -o jsonpath='{.spec.template.spec.containers[].image}' >> deployment.json | cut -d':' -f 2

The Result of the above command

Output: v4

Example 2

If you want to get information about the containers in the deployment, run the command

kubectl get deployment frontend -n dev -o jsonpath='{.spec.template.spec.containers}'

The result is a map with values from the Deployment YAML

[map[env:[map[name:GET_HOSTS_FROM value:dns]] image:gcr.io/google-samples/gb-frontend:v4 imagePullPolicy:IfNotPresent name:php-redis ports:[map[containerPort:80 protocol:TCP]] resources:map[requests:map[cpu:100m memory:100Mi]] terminationMessagePath:/dev/termination-log terminationMessagePolicy:File]]

Example 3

If you want to run a command that gets information about the template spec, run this command

kubectl get deployment frontend -n dev -o jsonpath='{.spec.template.spec}'

The result is a map with all the information about the Spec

map[containers:[map[env:[map[name:GET_HOSTS_FROM value:dns]] image:gcr.io/google-samples/gb-frontend:v4 imagePullPolicy:IfNotPresent name:php-redis ports:[map[containerPort:80 protocol:TCP]] resources:map[requests:map[cpu:100m memory:100Mi]] terminationMessagePath:/dev/termination-log terminationMessagePolicy:File]] dnsPolicy:ClusterFirst restartPolicy:Always schedulerName:default-scheduler securityContext:map terminationGracePeriodSeconds:30]

Example 4

If you want to get information about the deployment template metadata, you would run a command like this:

kubectl get deployment frontend -n dev -o jsonpath='{.spec.template.metadata}'

The result of this command is

map[creationTimestamp: labels:map[app:guestbook harness.io/release-name:release-cbb5dd9c-4c21-3704-8a90-1cf22d9b4300 harness.io/track:stable tier:frontend]]

Example 5
If you just want to target the replicas of deployment leverage this command.

kubectl get deployment frontend -n dev -o jsonpath='{.spec.replicas}'

The result of this command is 3

How might someone leverage this in Harness?

Conclusion

Using the samples commands, users can gather data from their deployments and output them in the context to be leveraged in future shell scripts within a worklow or pipeline. It can be also used as a Summary JIRA of the deployment. Hope this spurs some creativity within our canary community!

1 Like