Be quick with Kubernetes

Daryl Stark
9 min readAug 9, 2023

--

While I’m writing this, I’m studying for the Certified Kubernetes Application Developer (CKAD) certification. The exam for this certification is hands-on practical exam in which the student has to solve a series of case studies on a live Kubernetes cluster. Although I’m not completly sure what kind of case studies I’m about to face, it is clear to me that efficiency with the command line is imperative to a good result. In this post I write about the efficiency steps that I take to improve my speed with the kubectl command.

Because I use Linux as my primary operating system and because Linux is the used operating system on the CKAD exam, I explain everything below for Linux users. Most of the tips are transferrable to other operating systems, like Windows or Mac, though.

Tab completion

The first, most obvious, thing to do to improve speed with the kubectl command is to enable tab completion. Unfortunatly, this is not possible on the command line on the CKAD exam, but I will post here how to enable it to make sure the article is complete.

Tab completion will increase your speed by allowing you to enter only a few letters of each command. By pressing the tab key on your keyboard, the command will be completed automatically. For instance, if you enable tab completion for the kubectl command, you can enter kubectl cr, press tab, and the create command will be completed. But that's not all, if you press tab twice after the kubectl command, it will give you the possibilities. This helps you find the needed command quickly.

To enable tab completion for kubectl, you have to edit your .bashrc file in your homedirectory. You can do this by adding the following line to your .bashrc:

source $(kubectl completion bash)

Now, after logging in (or dot-sourcing the .bashrc file), you can use autocompletion for your kubectl command.

Aliasses

A big quick win in working fast with the kubectl command is by creating aliasses for the most commonly used kubectl commands. I use the following aliasses:

alias k='kubectl'
alias ks='kubectl config use-context'
alias kg='kubectl get'
alias kd='kubectl describe'
alias kc='kubectl create'
alias kd='kubectl delete'

By doing this, I can use k instead of the complete kubectl command and kg to get resources from Kubernetes. The big dissadvantage to this, is that tab completion doesn't work with the aliasses. If tab completion isn't available to you (like on the CKAD exam), creating these aliases can be of great help.

Contexts

The kubectl command works in a specific context. A context tells the command on what Kubernetes cluster to perform the command and on what namespace. By default, it executes the command in the default namespace, but there is big chance you don't want to use that namespace.

To list all configures contexts, enter the command kubectl config get-contexts. The command from my MicroK8s cluster is as follows:

$ kubectl config get-contexts 
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* microk8s microk8s-cluster admin

As you can see, there is one context with the name microk8s that targets the cluster with the name microk8s-cluster. It logs in with the user admin and there is no namespace defined. This means that this context targets the default namespace. The asterisk in the beginning of the line indicates that this is the currently selected context.

To see the clusters that are available for you, enter the kubectl config get-clusters command:

$ kubectl config get-contexts 
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* microk8s microk8s-cluster admin

You can add clusters with kubectl config set-cluster. I won't explain how to do this in this article, but the man pages will get you pretty far, or you can checkout the Kubernetes docs.

Creating and selecting a new context

To create a new context, you use the kubectl config set-context option. After the command you can specify a name for the new context (study, for instance) and with --cluster and --namesapce you can specify what cluster and namespace to use. For instance, to create a context with the name study to operate on the cluster with name microk8s-cluster and namespace study, you would enter the following command:

$ kubectl config set-context study --cluster microk8s-cluster --namespace study --user admin

After creating the context, you can verify your work with kubectl config get-contexts:

$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* microk8s microk8s-cluster admin
study microk8s-cluster admin study

As you can see from the output, the context is created but not selected. To select the context, you use the command kubectl config use-context:

$ kubectl config use-context study
Switched to context "study".

After that, you can see the newly created context is selected:

$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
microk8s microk8s-cluster admin
* study microk8s-cluster admin study

If you enter a kubectl command now, it will be exectued on the cluster and namespace you've selected in the context:

$ kubectl get pods
No resources found in study namespace.

Updating a context

It is possible that you want to update a context you’re working in. You can change for example the namespace for the context or the user. To do that, you use the kubectl config set-context command again, but this time you don't specify a new name, but a existing name for the context. If you specify --current instead of a name, it will update the currently selected context:

$ kubectl config set-context --current --namespace prod
Context "study" modified.

After updating the context, you can see your updates with the kubectl config get-contexts:

$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
microk8s microk8s-cluster admin
* study microk8s-cluster admin prod

Deleting a context

When you’re done with a context, you can delete it. To delete a context, you use the kubectl config delete-context command:

$ kubectl config delete-context study
warning: this removed your active context, use "kubectl config use-context" to select a different one
deleted context study from /var/snap/microk8s/5378/credentials/client.config

As you can see from the output that I got, I deleted the active context. After doing this, the context is deleted, but no new context is selected. If I try to retrieve the pods from Kubernetes now, I get an error:

$ kubectl get pods
Error in configuration: context was not found for specified context: study

To fix this error, all I have to do is to select a existing context:

$ kubectl config use-context microk8s
Switched to context "microk8s".

Using resource abbreviations

Every object in Kubernetes has a name, for instance pod, deployment, replicaset, etc. To retrieve any of these resources, you use the command kubectl get <object>. If you work with bigger named resources, like configmaps or customresourcedefinitions, there is a big chance you make a typo and waste time by having to retype the command. To prevent this, it can be very useful to learn the abbreviations for these resources. The abbreviations for resources are available with the command kubectl api-resources:

$ kubectl api-resources
XPS - 20:45:39 ~$ kubectl api-resources | head -n 16
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
componentstatuses cs v1 false ComponentStatus
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
events ev v1 true Event
limitranges limits v1 true LimitRange
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
podtemplates v1 true PodTemplate
replicationcontrollers rc v1 true ReplicationController
resourcequotas quota v1 true ResourceQuota
secrets v1 true Secret

In this table, you can see that namespaces can be abbreviated with ns. You can use this on the command line:

$ kubectl get ns
NAME STATUS AGE
kube-system Active 62d
kube-public Active 62d
kube-node-lease Active 62d
default Active 62d
metallb-system Active 62d
prod Active 12d
study Active 21d

This prevents typos and improves your speed. Note that in the output of the kubectl api-resources command, you can also find the apiVersion for each resource. I'm always struggeling to remember the apiVersion for resources, so this list if very useful for me. You can also see if a specific resource is tied to namespaces and what the value of the Kind field has to be in Kubernetes manifests.

Live changes on resources

When creating, updating or deleting resources from Kubernetes, you always have to check your work. You can do this by executing a get verb after creating objects. One option I use a lot with kubectl get is -w (or in the longer form --watch=true). This keeps updating you on the state of the resources you're retrieving. If you create a Pod, for instance, and issue a kubectl get pods -w directly after it, you'll see the status of the pod go from Pending, to ContainerCreating to, hopefully, Running:

$ kubectl get pods -w -n study
pod/security-context-demo created
NAME READY STATUS RESTARTS AGE
security-context-demo 0/1 Pending 0 0s
security-context-demo 0/1 Pending 0 0s
security-context-demo 0/1 ContainerCreating 0 1s
security-context-demo 0/1 ContainerCreating 0 2s
security-context-demo 1/1 Running 0 5s

By using the -w option, you don't have to run the kubectl get <resource> command over and over again to see if your resource is created. This can save time because you can see the output very quickly.

If you use the option --watch-only=true instead of -w, the kubectl command won't show the first few lines with the current status; it will only show updates.

Create manifest easily

There are two ways to create resources with kubectl: imperatively and declarative. When creating a resource imperatively, you create it with the command line. For instance, to create a Pod imperatively, you use the following command line:

kubectl run nginx --image=nginx:latest

The declarative way uses a manifest written in in yaml or json. Writing these files can be very useful because you can copy and edit them for other tasks, but creating one can take some time. To create a manifest quick and easy, you can however use the --dry-run=client and --output=yaml (or --output=json if you prefer JSON) options to the imperative method:

$ kubectl run nginx --image=nginx:latest --dry-run=client --output=yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx:latest
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}

You can now copy and paste this to a new file and edit it from there, or you could use shell redirection to write it to a new file immidiatly:

kubectl run nginx --image=nginx:latest --dry-run=client --output=yaml > manifest.yml

After that, you can edit the file to make it meet your demands and create the resource with kubectl create -f manifest.yml. Same goes for creating other resources, like configmaps, jobs, etc.

Resource explanation

By using kubectl explain, you can get detailed information about the attributes objects have. For instance, if you enter kubectl explain pod, you get the description of the attributes of a Pod:

$ kubectl explain pod
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <ObjectMeta>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <PodSpec>
Specification of the desired behavior of the pod. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status <PodStatus>
Most recently observed status of the pod. This data may not be up to date.
Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

You can drill down on these fields to get more information:

$ kubectl explain pod.spec
KIND: Pod
VERSION: v1
FIELD: spec <PodSpec>DESCRIPTION:
Specification of the desired behavior of the pod. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
PodSpec is a description of a pod.
FIELDS:
activeDeadlineSeconds <integer>
Optional duration in seconds the pod may be active on the node relative to
StartTime before the system will actively try to mark it failed and kill
associated containers. Value must be a positive integer.
affinity <Affinity>
If specified, the pod's scheduling constraints
automountServiceAccountToken <boolean>
AutomountServiceAccountToken indicates whether a service account token
should be automatically mounted.
containers <[]Container> -required-
List of containers belonging to the pod. Containers cannot currently be
(... output truncated ...)

That’s it!

That were my tips for speed improvement with Kubernetes. I hope this was informative for you. If you have more tips that can save time when working with kubectl, I would love to hear them via a comment on this article.

--

--

Daryl Stark
Daryl Stark

Written by Daryl Stark

Network Engineer with a big interest in anything that has to do with coding

No responses yet