Introduction
If you haven’t found what you’re looking for in the existing kubectl plugins, it’s quite easy to create your own plugin for kubectl. Indeed, as soon as a file in the PATH starts with kubectl- and is executable, it can be used as a plugin.
The script can be written in any language that offers to create CLIs, but the most used are Bash and Go. The name of the file defines the command that will have to be typed to use it: a script called kubectl-test can be executed with the kubectl test command.
However, it is not possible to override existing commands in kubectl, or even create subcommands of existing commands. For example, a plugin named kubectl-get will never be called, because the existing kubectl get command will take over.
Example of the kubectl plugin in Bash
Now we will see how to create a plugin for kubectl in Bash.
To do this, we will create a file named kubectl-hello and copy the following code into it:
#!/bin/bash
if [[ "$1" == "world" ]]
then
echo "Hello World!"
exit 0
fi
echo "Welcome to kubectl-hello"
This code allows to display a different message to the user depending on whether a specific argument is passed to the script or not.
Next, we will make this script executable, and move it into the PATH:
chmod +x ./kubectl-hello
sudo mv ./kubectl-hello /usr/local/bin
We can then run this plugin using the kubectl command:
# vérifier que le plugin est bien reconnu
$ kubectl plugin list
The following compatible plugins are available:
/usr/local/bin/kubectl-hello
$ kubectl hello
Welcome to kubectl-hello
$ kubectl hello world
Hello World!
Naming your kubectl plugin correctly
As we saw earlier, a plugin for kubectl is simply a script whose name starts with kubectl-.
To decide which plugin to use based on the command called, kubectl searches for plugins starting with those with the longest name. Once a plugin is found, it is called with any remaining parameters passed as arguments.
For example, if we run the command kubectl abc, it will first look for a plugin named kubectl-abc, then another one named kubectl-ab, and so on.
The search also stops when it encounters a named parameter and passes the rest of the arguments as parameters to the plugin.
To illustrate how this works, here is an example:
$ export PATH="$HOME/kubectl-plugins:$PATH"
$ kubectl plugin list
The following compatible plugins are available:
/home/xxx/kubectl-plugins/kubectl-a-b
/home/xxx/kubectl-plugins/kubectl-a-b-c
$ cat ~/kubectl-plugins/kubectl-a-b
#!/bin/bash
echo "Plugin A B"
for i in $*; do
echo $i
done
$ cat ~/kubectl-plugins/kubectl-a-b-c
#!/bin/bash
echo "Plugin A B C"
for i in $*; do
echo $i
done
$ kubectl a b c d
Plugin A B C
d
$ kubectl a b c
Plugin A B C
$ kubectl a b
Plugin A B
$ kubectl a
error: unknown command "a" for "kubectl"
$ kubectl a b --param=test c d
Plugin A B
--param=test
c
d
If we want to use a hyphen in the name of our plugin, it is also possible, but we must then replace it with an underscore in the file name.
It should be kept in mind, however, that when using this method, the general naming rule still applies. The plugin can therefore also be called with underscores instead of hyphens in the kubectl command.
$ cat ~/kubectl-plugins/kubectl-my_plugin
#!/bin/bash
echo "My kubectl plugin"
$ kubectl my-plugin
My kubectl plugin
$ kubectl my_plugin
My kubectl plugin
If your plugin is not recognized by kubectl, the kubectl plugin list command can detect the most common naming errors and display a warning with the details.
It can detect three types of errors:
- A plugin has the same name as an existing kubectl command;
- Two plugins use the same name;
- A plugin is not executable despite a correct name.
$ kubectl plugin list
The following compatible plugins are available:
/usr/local/bin/kubectl-hello
/home/xxx/kubectl-plugins/kubectl-get
- warning: kubectl-get overwrites existing command: "kubectl get"
/home/xxx/kubectl-plugins/kubectl-hello
- warning: /home/xxx/kubectl-plugins/kubectl-hello is overshadowed by a similarly named plugin: /usr/local/bin/kubectl-hello
/home/xxx/kubectl-plugins/kubectl-notexecutable
- warning: /home/xxx/kubectl-plugins/kubectl-notexecutable identified as a kubectl plugin, but it is not executable
error: 3 plugin warnings were found
Write the plugin content
There are some best practices that can be adopted to make it easier to use a kubectl plugin later on.
The first recommendation is to have consistency between the commands in your plugin and those that are native to kubectl. For example, it is advisable to implement the following options to avoid losing users:
- -n and –namespace : to select the namespace on which the commands will apply;
- -A and –all-namespaces : to apply the commands to all namespaces;
- -h and –help : to display help on using the plugin.
In addition to these options, it is recommended to display help on the use of the plugin (identical to that of the –help option ) when the user calls it without any arguments.
If we are in the case of a script with a tree of commands and subcommands, we can also split the code by putting each subcommand in a dedicated script instead of using conditions within the same script. This reduces the complexity of the code produced. This is made possible by the naming conventions we saw previously.
In the following example, we define a plugin called myplugin that has three actions: one by default if we don’t use any subcommands, as well as two subcommands named list and create. To do this, we will create three different files:
$ cat ~/kubectl-plugins/kubectl-myplugin
#!/bin/bash
echo "My kubectl plugin"
$ cat ~/kubectl-plugins/kubectl-myplugin-list
#!/bin/bash
echo "List my kubectl plugin"
$ cat ~/kubectl-plugins/kubectl-myplugin-create
#!/bin/bash
echo "Create my kubectl plugin"
$ kubectl myplugin
My kubectl plugin
$ kubectl myplugin create
Create my kubectl plugin
$ kubectl myplugin list
List my kubectl plugin
Finally, a general good practice is not to reinvent the wheel. In the case of writing a plugin in Go, there are many resources available from the community.
We can use the cli-runtime project which is already used by kubectl and which allows interaction with the Kubernetes API and offers management of a certain number of default options, including those we saw above.
To get off to a good start, an example plugin is also available in the sample-cli-plugin repository , the purpose of which is to change the default namespace on which kubectl commands apply.!
Publish the kubectl plugin to Krew
Krew is the equivalent of a package manager for kubectl plugins. It allows users to download these different plugins, and manages many aspects of the lifecycle such as version upgrades.
Once our plugin has been well tested and it brings something to the community, it can be shared to the public. To do this, there are three main steps to follow.
First, you need to make the plugin code available as open source. To do this, you can create a repository on GitHub and deposit your code there. It is also necessary to make available an archive containing the plugin source code, which can then be downloaded by Krew. This archive must be versioned using semantic versioning . First, you can create it manually and then make it available on the same GitHub repository.
Next, you need to write a plugin manifest for Krew. It takes the form of a YAML document that describes metadata about the plugin, how it should be downloaded and then installed on a user’s machine.
A full description of this file is available on the Krew website, with a list of options that can be used. To write it, it is recommended to copy and adapt existing plugin manifests . Here is an example of a manifest extracted from the ctx plugin:
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: ctx
spec:
homepage: https://github.com/ahmetb/kubectx
shortDescription: Switch between contexts in your kubeconfig
version: v0.9.4
description: |
Also known as "kubectx", a utility to switch between context entries in
your kubeconfig file efficiently.
caveats: |
If fzf is installed on your machine, you can interactively choose
between the entries using the arrow keys, or by fuzzy searching
as you type.
See https://github.com/ahmetb/kubectx for customization and details.
platforms:
- selector:
matchExpressions:
- key: os
operator: In
values:
- darwin
- linux
uri: https://github.com/ahmetb/kubectx/archive/v0.9.4.tar.gz
sha256: 91e6b2e0501bc581f006322d621adad928ea3bd3d8df6612334804b93efd258c
bin: kubectx
files:
- from: kubectx-*/kubectx
to: .
- from: kubectx-*/LICENSE
to: .
Finally, we can test the plugin installation from the manifest and the archive using the following command:
kubectl krew install --manifest=foo.yaml --archive=foo.tar.gz
If this works, we can then open a Pull Request on the official Krew repository by adding our manifest in the plugins/ folder and wait for it to be merged. When it is, the plugin will be available to all users using the kubectl krew search command.
In addition, a list of prerequisites that must be validated is available on the Krew website (in English).
Conclusion
Plugins for kubectl allow you to add many features to those already existing in this tool. If you can’t find a plugin that does what you want, you can create your own.
In the simplest version, a kubectl plugin takes the form of a Bash script with a specific name, and this already offers many possibilities simply by playing on the naming of this plugin. However, this type of plugin will not work on Windows for example. We can then create more complex CLIs, in Go in particular.
This already allows you to automate actions that you perform often. If a plugin can be useful to the community, it is then possible to make it available to everyone by adding it to the Krew package manager.
Sources :
https://krew.sigs.k8s.io/docs/developer-guide/
https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/