Advanced Kubectl Commands for Managing Your Kubernetes Cluster

Oct 11, 2023 • 8 min

Navigating the world of Kubernetes can be daunting, but with the right set of commands, you can master it!

In our previous article on Kubectl Commands: Efficient Kubernetes Cluster Administration, I introduced you to the tool and some of the main kubectl commands.

Today, we delve deeper into the DevOps jungle to discover these fascinating creatures known as advanced kubectl commands. Let’s go! 🦍

Advanced Kubectl Commands for Everyday Daily Operations

Here, we’ll explore slightly complex kubectl commands that can be very useful in daily operations. In some cases, you might even set up an alias for easier access.

Managing Secrets in Kubernetes: Kubectl Create/get Secret

Secret management is often seen as a tedious task. The reason I frequently mention is that secrets, being in base64 format, constantly need encoding/decoding. When our secret contains multiple keys, this can quickly become time-consuming and error-prone.

Here are two commands to effortlessly create and read a secret, bypassing the base64 encoding hassle:

# create a secret
kubectl create secret generic <NAME> -n <NAMESPACE> --from-env-file <FILENAME> --dry-run=client -o yaml > secret.yaml
# read and decode this secret
kubectl get secrets -n <NAMESPACE> <NAME> -o json | jq '(.data[] |= @base64d).data'

Personally, I’ve added two functions to my bashrc for these frequently used commands:

# .bashrc ========================================
alias k=kubectl # a must-have 😉

# converts the environment variable $NS into a namespace flag if this variable exists (used in the following functions)
function ns_flag {
    local ns_flag="-n $NS"
    if [ -n "$NS" ]; then echo "$ns_flag"; fi
}

# create a k8s secret from an environment file
function kmakesec {
    k create secret generic $1 --from-env-file $2 $(ns_flag) --dry-run=client -o yaml
}

# retrieve a k8s secret in json format and base64-decoded
function kgetsec {
    local get_secret="k get secrets $1 $(ns_flag) -o json | jq '(.data[] |= @base64d).data'"
    if [ -n "$2" ]; then
        eval "$get_secret" | jq -r ".[\"$2\"]"
    else
        eval "$get_secret -C"
    fi
}

# examples ========================================

$ NS=[NAMESPACE] kmakesec <SECRET_NAME> <ENV_FILE>
$ NS=[NAMESPACE] kgetsec <SECRET_NAME> [SECRET_KEY]

A small usage example would be welcome, wouldn’t it? 😉

Label Management: Kubectl Label

In some cases, whether for easier resource listing or to allow an operator to function, it’s useful to apply labels and annotations to specific resources.

While you can manually edit the resource to add the desired labels, it’s better to use the dedicated kubectl command: kubectl label <KIND> <NAME> <LABEL_NAME>=<LABEL_VALUE>. To remove the label, use the same command, prefixing the <LABEL_VALUE> with a minus sign.

Kubernetes Resource Annotations: Kubectl Annotate

Similarly, you can annotate a resource using kubectl annotate <KIND> <NAME> <ANNOTATION_NAME>=<ANNOTATION_VALUE>. Removing an annotation is done in the same way as a label.

Once your resources are labeled, you can easily filter them by label, for example, kubectl get pod -l <LABEL> to list pods with the given label. You can also specify a value to refine the filter.

Then, with the --show-labels flag, you can add a column with all labels, or add a column with the values of a particular label using the flag--label-column <LABEL_NAME>.

Launch a Container Without Yaml Using Kubectl Run

Sometimes you need to quickly launch a container for testing or to perform actions directly from within the cluster.

Having to manually write a manifest for a simple pod might seem tedious to some, including me. With the kubectl run command, you can launch a pod by configuring it directly via flags.

For example, to launch an Nginx server, you can use the command kubectl run nginx --image=nginx --port=80 and then create a port-forward as described in the first article on kubectl commands to access it locally.

We sometimes use it at Enix to run commands directly in a cluster pod with a specific configuration:

kubectl run --rm -it oonk-tools --image=enix/oonk-tools -n oonk --overrides='{"spec": {"imagePullSecrets": [{"name": "registry-credentials"}]}}' --env OS_AUTH_URL

=http://keystone:5000/v3

This command includes the flags --rm, -i, and -t from the docker run command. They allow the pod to be deleted once finished and provide an interactive terminal to the user. Then there’s the image and namespace, followed by a bit of json that allows for fine-tuning the pod specifications as in a regular yaml. Finally, there’s an environment variable.

⚠️ Caution! In some cases, you can’t use kubectl run, for example, if you need to attach a volume to a container. Indeed, kubectl does not merge the container configuration with the generated one; the –image flag, for example, will have no effect even if it remains mandatory. In this case, the command’s usefulness is lost.

Update Resources: Kubectl Rollout

Kubernetes keeps a history of resource versions.

If you update a resource and realize the new version doesn’t work, you can retrieve the previous version from this history if you no longer have that version’s manifest: kubectl rollout undo <RESOURCE> <NAME>. However, be careful, as the rollout command doesn’t support all resources. It’s typically used for a deployment or a daemonset.

To rollback to an even older version, you can list the history and then choose its revision number:

kubectl rollout history <RESOURCE> <NAME>
kubectl rollout undo <RESOURCE> <NAME> --to-revision=<REVISION_ID>

You can also use it to cleanly restart the pods of a deployment and then “watch” its status until completion:

kubectl rollout restart <RESOURCE> <NAME>
kubectl rollout status -w <RESOURCE> <NAME>

Dive Into the Heart of Kubernetes

In this section, we’ll study more advanced commands that aren’t necessarily used as often. You’ll likely find some useful commands here.

Advanced Configuration Options: Kubectl Config Set/get-context

For those who frequently switch between different clusters, managing kubeconfig files can be a challenge.

By default, kubectl reads the ~/.kube/config file. Fortunately, kubectl allows specifying an alternative configuration file via the KUBECONFIG environment variable or the --kubeconfig parameter. If you have many clusters, I recommend kubie. It’s a handy CLI tool that easily manages contexts and configuration files.

If you prefer having a single kubeconfig file and don’t use kubie, you can choose which context to use from those listed in your kubeconfig file. Use the kubectl config set-context <CONTEXT_NAME> command for this. List these contexts with the kubectl config get-contexts command. Finally, to more easily merge your configuration files, you can source multiple files using the previously mentioned methods and then save the configuration in a new file to use: KUBECONFIG=kubeconfig.1:kubeconfig.2 kubectl config view > kubeconfig.3.

Kubectl: A Kubernetes API Client

Edit a Resource Programmatically and Kubectl Patch

At its core, kubectl’s role is to communicate with the Kubernetes API, which is why developers have integrated the capability to build API requests to Kubernetes using the --raw flag.

For example, to retrieve the server version, you can execute kubectl get --raw=/version. And if you wish to remove a deployment, use kubectl delete --raw=/apis/apps/v1/namespaces/<NAMESPACE>/deployments/<NAME>.

Lastly, in some cases, you might want to edit a resource very precisely (in a bash script, for instance). In this case, the apply command might not be the ideal solution. Fortunately, kubectl allows editing its resources via a jsonpatch! For example, to add a value to a config map: kubectl patch cm test --type json -p '[{"op": "add", "path": "/data/<KEY>", "value": "<VALUE>"}]'.

Check User Permissions: Kubectl Auth can-i

Wondering what actions a user is allowed to perform via the Kubernetes API? Kubectl offers an impersonation feature that allows let’s you make a request impersonating another user: kubectl get pods --as-group="<GROUP>" --as="<USER>". The user can be a regular user or a service account, and the --as-group flag can be used multiple times.

To simply test if a user has the right to execute a command without actually launching it, use kubectl auth can-i <COMMAND> with the --as flags and optionally --as-group. You can also replace the command to test with the --list flag to list all possibilities.

# displays "yes" or "no" with exit codes 0 or 1, respectively
kubectl --as <USER> --as-group="<GROUP1>" --as-group="<GROUP2>" auth can-i delete secrets

# displays a list of resources and routes with their associated permissions
kubectl --as <USER> auth can-i --list

Bonus: Extracting Metadata and Info from a Kubernetes Cluster

As a bonus to conclude these two articles on kubectl, here are some commands that aren’t particularly advanced but might be useful to you. They provide valuable information about the cluster, its configuration, and its versions.

  • kubectl config view: Displays the current kubectl configuration
  • kubectl cluster-info: Lists the control-plane addresses and services with the kubernetes.io/cluster-service=true label or dumps debugging information.
  • kubectl api-resources: Lists the cluster’s resource types
  • kubectl api-versions: Lists the cluster’s API versions
  • kubectl version: Displays the version of kubectl and the API server
  • kubectl top pods / nodes: Displays the CPU and RAM consumption of your pods or nodes.

Conclusion

Thanks to numerous utility commands and the ability to directly access the API, we’ve seen that it’s possible to list, edit, create, or delete a Kubernetes cluster’s resources very precisely. We’ve also been able to test user or service access permissions to the API, all with varying granularity levels.

Kubectl is a relatively simple tool to use, but it’s particularly powerful because it allows performing extremely precise actions on its cluster. This tool is both essential and indispensable for those who work daily on Kubernetes platforms (or their clients' platforms!). In any case, at Enix, even if we manage clusters partly with GUIs, we enjoy using kubectl right from our breakfast!


Do not miss our latest DevOps and Cloud Native blogposts! Follow Enix on Twitter!