How to get Deployments ($ kubectl get deployments) by specifying custom property value? - kubernetes

I have deployed a Kubernetes service and when I query to get the Deployment $ kubectl get deployments, I can see the Deployment.
the json of the Deployment looks like below --
apiVersion: v1
kind: Deployment
metadata:
name: test
spec:
replicas: 1
template:
metadata:
labels:
app: test
release: testRelease
customProp: xyz
My question is how can I frame a query by which I can get the Deployment by specifying the 'customProp' value. Does kubectl support to pass a jsonpath as part of the query? so that I can pass a json path like jsonpath='{$.spec.template.metadata.labels.customProp}' and value against this jsonPath as 'xyz'.
This is what I am thinking to execute:
$ kubectl get deployments -n <namespace> <json path query>
However not sure how to frame the json path query and pass along with $kubectl get deployments.

Kubectl does support query feature, you can use below query
kubectl get pods --selector=customProp=xyz
Kubectl also supports JSON path expressions too, to get more details, follow the link. You can write query following the syntax shown on the link.

Yes, one can query to the kube-apiserver for a resource using jsonpath. Run following command to get what you want:
$ kubectl get deploy test -o=jsonpath='{.spec.template.metadata.labels.customProp}'
For more usage, see https://kubernetes.io/docs/reference/kubectl/jsonpath.

Add a label to your deployment object. Then with below command to query specific deployment
kubectl get deploy - l labelname=labelvalue

To get deployed image name as a string, you can choose from any attribute in deployment yaml.
kubectl get deploy/${image.name} -o jsonpath="{..image}"

Related

Kubernetes reports different apiVersion for the same Deployment

Due to Kubernetes removing deprecated API I am trying to figure out an apiVersion of resources in a cluster and came across the following behavior.
When requesting definition for specific deployment, it reports an old api version:
> kubectl get deployment/some-deployment -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
...
Bud when requesting it for all resources api version reported as new for the same resource:
> kubectl get all -o yaml
...
- apiVersion: apps/v1
kind: Deployment
...
Same goes when checking selfLink in metadata:
kubectl get all -o=custom-columns=NAME:.metadata.name,API-version:.metadata.selfLink
and
kubectl get deployment/some-deployment -o=custom-columns=NAME:.metadata.name,API-version:.metadata.selfLink
How should this be interpreted?
Kubernetes version is 1.15.7.
Quoted from here
kubectl get deployment foo is ambiguous, since the server has deployments in multiple api groups. When a resource exists in multiple api groups, kubectl uses the first group listed in discovery docs published by the server which contains the resource. For backwards compatibility, that is the extensions api group.
If you want to ensure you get a deployment in the apps api group, fully qualify the resource you are requesting by running kubectl get deployments.apps test-nginx
If you want a specific version, like v1, in the apps api group, include that as well: kubectl get deployments.v1.apps test-nginx
Also from here
What stored version is used for?
It is the serialized version in etcd. Whenever you fetch an object, the api server reads it from etcd, converts it into an internal version, then converts it to the version you requested.
So, If you run
$ kubectl get deployments nginx -o name
deployment.extensions/nginx
As you can see requested version for above command is deployment.extensions
And If you run
$ kubectl get all -o name
...
deployment.apps/nginx
The requested version is deployment.apps. so, it returns the version with apps/v1
Ref: https://github.com/kubernetes/kubernetes/issues/58131

How to describe kubernetes resource

I'm trying to get metadata for a given kubernetes resource. Similar to a describe for a REST end-point.
Is there a kubectl to get all possible things that I could provide for any k8s resource ?
For example for the deployment resource, it could be something like this.
apiVersion: apps/v1
kind: Deployment
metadata:
name: <type:String>
<desc: name for the deployment>
namespace: <type:String>
<desc: Valid namespace>
annotations:
...
Thanks in advance !
You can use the kubectl explain CLI command:
This command describes the fields associated with each supported API
resource. Fields are identified via a simple JSONPath identifier:
<type>.<fieldName>[.<fieldName>]
Add the --recursive flag to display all of the fields at once without descriptions. Information about each field is retrieved from the server in OpenAPI format.
Example to view all Deployment associated fields:
kubectl explain deployment --recursive
You can dig into specific fields:
kubectl explain deployment.spec.template
You can also rely on Kubernetes API Reference Docs.
Are you familiar with OpenApi/Swagger? Try to open the following file in swagger-ui https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json
If you have a live kubernetes api available the file should be available under /openapi/v2 like they describe here: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#openapi-and-swagger-definitions

How to Create Manifest for Existing Objects and Strip Identifiers?

Goal: Create a generic manifest for an existing deployment and strip the cluster distinct details. Deploy this manifest on a different cluster.
Progress:
kubectl get deployment <DEPLOYMENT_NAME> -n <NAMESPACE> -o yaml
Generates a deployment file but it has all sorts of info that is distinct to this cluster / instantiation and must be stripped. For example:
lastTransitionTime: 2019-03-20T23:38:42Z
lastUpdateTime: 2019-03-20T23:39:13Z
uid: 53444c69-acac-11e8-b870-0af323746f0a
resourceVersion: "97102711"
creationTimestamp: 2018-08-30T23:27:56Z
... just to name a few.
Is there an option to remove these fields in return or an easy way to only pull the minimum definitions to replicate the object in another cluster?
As suggested by #Matthew L Daniel kubectl get deployment <DEPLOYMENT_NAME> -n <NAMESPACE> -o yaml --export=true will do the work.
You can also find useful kubectl tricks here and here. Additionality full kubectl reference can be found here.

Kubectl create "invalid object"

I am creating namespace using kubectl with yaml. The following is my yaml configuration
apiVersion: v1
kind: Namespace
metadata:
name: "slackishapp"
labels:
name: "slackishapp"
But, when I run kubectl create -f ./slackish-namespace-manifest.yaml, I got an error like the following
error: SchemaError(io.k8s.api.autoscaling.v2beta2.PodsMetricStatus): invalid object doesn't have additional properties.
What goes wrong on my yaml? I am reading about it on the documentation as well. I don't see any difference with my configuration.
There is nothing wrong with your yaml but I suspect you have the wrong version of kubectl.
kubectl needs to be within 1 minor from the cluster you are using as described here.
You can check your versions with
kubectl version
Download the kubectl.exe on https://kubernetes.io/docs/tasks/tools/install-kubectl/#before-you-begin then replace it on Program Files\Docker\Docker\resources\bin if you have docker desktop
Like Andreas Wederbrand said, it is a version problem.
As a workaround, try to create your namespace within imperative mode
kubectl create ns slackishapp && kubectl label ns slackishapp name=slackishapp
And then compare existing yaml with one you have written in order to check what is missing
kubectl get ns slackishapp -o yaml --export

Create Daemonset using kubectl?

I took the CKA exam and I needed to work with Daemonsets for quite a while there. Since it is much faster to do everything with kubectl instead of creating yaml manifests for k8s resources, I was wondering if it is possible to create Daemonset resources using kubectl.
I know that it is NOT possible to create it using regular kubectl create daemonset at least for now. And there is no description of it in the documentation. But maybe there is a way to do that in some different way?
The best thing I could do right now is to create Deployment first like kubectl create deployment and edit it's output manifest. Any options here?
The fastest hack is to create a deployment file using
kubectl create deploy nginx --image=nginx --dry-run -o yaml > nginx-ds.yaml
Now replace the line kind: Deployment with kind: DaemonSet in nginx-ds.yaml and remove the line replicas: 1
However, the following command will give a clean daemonset manifest considering that "apps/v1" is the api used for DaemonSet in your cluster
kubectl create deploy nginx --image=nginx --dry-run -o yaml | \
sed '/null\|{}\|replicas/d;/status/,$d;s/Deployment/DaemonSet/g' > nginx-ds.yaml
You have your nginx DaemonSet.
CKA allows access to K8S documentation. So, it should be possible to get a sample YAML for different resources from there. Here is the one for the Daemonset from K8S documentation.
Also, not sure if the certification environment has access to resources in the kube-system namespace. If yes, then use the below command to get a sample yaml for Daemonset.
kubectl get daemonsets kube-flannel-ds-amd64 -o yaml -n=kube-system > daemonset.yaml
It's impossible. At least for Kubernetes 1.12. The only option is to get a sample Daemonset yaml file and go from there.
The fastest way to create
kubectl create deploy nginx --image=nginx --dry-run -o yaml > nginx-ds.yaml
Now replace the line kind: Deployment with kind: DaemonSet in nginx-ds.yaml and remove the line replicas: 1 , strategy {} and status {} as well.
Otherwise it shows error for some required fields like this
error: error validating "nginx-ds.yaml": error validating data: [ValidationError(DaemonSet.spec): unknown field "strategy" in io.k8s.api.apps.v1.DaemonSetSpec, ValidationError(DaemonSet.status): missing required field "currentNumberScheduled" in io.k8s.api.apps.v1.DaemonSetStatus,ValidationError(DaemonSet.status): missing required field "numberMisscheduled" in io.k8s.api.apps.v1.DaemonSetStatus, ValidationError(DaemonSet.status): missing required field "desiredNumberScheduled" in io.k8s.api.apps.v1.DaemonSetStatus, ValidationError(DaemonSet.status): missing required field "numberReady" in io.k8s.api.apps.v1.DaemonSetStatus]; if you choose to ignore these errors, turn validation off with --validate=false
There is no such option to create a DaemonSet using kubectl. But still, you can prepare a Yaml file with basic configuration for a DaemonSet, e.g. daemon-set-basic.yaml, and create it using kubectl create -f daemon-set-basic.yaml
You can edit new DaemonSet using kubectl edit daemonset <name-of-the-daemon-set>. Or modify the Yaml file and apply changes by kubectl apply -f daemon-set-basic.yaml. Note, if you want to update configuration modifying file and using apply command, it is better to use apply instead of create when you create the DaemonSet.
Here is the example of a simple DaemonSet:
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- name: fluentd-elasticsearch
image: k8s.gcr.io/fluentd-elasticsearch:1.20
You could take advantage of Kubernetes architecture to obtain definition of DaemonSet from existing cluster. Have a look at kube-proxy, which is a network component that runs on each node in your cluster.
kube-proxy is deployed as DaemonSet so you can extract its definition with below command.
$ kubectl get ds kube-proxy -n kube-system -o yaml > kube-proxy.ds.yaml
Warning!
By extracting definition of DaemonSet from kube-proxy be aware that:
You will have to do pliantly of clean up!
You will have to change apiVersion from extensions/v1beta1 to apps/v1
I used this by the following commands:
Either create Replicaset or deployment from Kubernetes imperative command
kubectl create deployment <daemonset_name> --image= --dry-run -o yaml > file.txt
Edit the kind and replace DaemonSet, remove replicas and strategy fields into it.
kubectl apply -f file.txt
During CKA examination you are allowed to access Kubernetes Documentation for DaemonSets. You could use the link and get examples of DaemonSet yaml files. However you could use the way you mentioned, change a deployment specification to DaemonSet specification. You need to change the kind to Daemonset, remove strategy, replicas and status fields. That would do.
Using command to deployment create and modifying it, one can create daemonset very quickly.
Below is one line command to create daemonset
kubectl create deployment elasticsearch --namespace=kube-system --image=k8s.gcr.io/fluentd-elasticsearch:1.20 --dry-run -o yaml | grep -v "creationTimestamp\|status" | awk '{gsub(/Deployment/, "DaemonSet"); print }'