© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
O. YilmazExtending Kuberneteshttps://doi.org/10.1007/978-1-4842-7095-0_2

2. kubectl Plugins

Onur Yilmaz1  
(1)
Berlin, Germany
 

We shape our tools, and thereafter our tools shape us.

—Marshall McLuhan

Media scholar and critic

Command-line tools are the Swiss Army knives of the developers. You can connect to backend systems, run complex commands, and automate your daily tasks with them. The official command-line tool for Kubernetes is kubectl. As the god of gates Janus in mythology, kubectl is the god of entrances into the cluster. It lets you create workloads, manage resources, and check statuses by communicating with Kubernetes API. In this chapter, we will focus on extending the kubectl by writing plugins. At the end of this chapter, you will develop and install new plugins into kubectl and run custom commands.

Let’s start by installing the gods of the Kubernetes API gateways to your local workstation.

kubectl Installation and Usage

kubectl is the client tool to communicate with the Kubernetes API. Therefore, it is good to have a kubectl version exactly or close to the Kubernetes API version. Otherwise, it is possible to have incompatible API requests and failed operations. Source code of kubectl is a part of the official Kubernetes repository, and its releases are jointly managed with the Kubernetes releases. However, you need to check the kubernetes/kubectl1 repository in Figure 2-1 for the issues related to kubectl.
../images/503015_1_En_2_Chapter/503015_1_En_2_Fig1_HTML.jpg
Figure 2-1

Kubernetes kubectl repository

The installation of kubectl is fairly straightforward since it is a single-binary application. You need first to download the binary from the release repository for your operating system as shown in Listing 2-1.
# Linux
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/kubectl
# macOS
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/darwin/amd64/kubectl
Listing 2-1

Downloading kubectl binary

Then you need to make the binary executable.
chmod +x ./kubectl
Listing 2-2

Executable kubectl binary

Finally, you need to move the binary into your PATH.
sudo mv ./kubectl /usr/local/bin/kubectl
Listing 2-3

Moving kubectl binary

You can test the kubectl with the following command in Listing 2-4.
kubectl version --client
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:30:33Z", GoVersion:"go1.15", Compiler:"gc", Platform:"darwin/amd64"}
Listing 2-4

kubectl version check

The command prints the client version of kubectl, which is v1.19.0. In the following exercise, you will create a local Kubernetes cluster and continue with more complex kubectl commands interacting with the cluster.

EXERCISE: STARTING A LOCAL KUBERNETES CLUSTER

Although Kubernetes is a container management system for large clouds, it is possible to create single-instance Kubernetes clusters locally. minikube is the recommended and officially supported way of creating single-node clusters. It is mostly used for development and testing purposes.

In this exercise, you will install minikube and start a new Kubernetes cluster.
  1. 1.
    Download the binary of minikube according to your operating system:
    # Linux
    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    # macOS
    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
     
  2. 2.
    Install the binary to the path:
    # Linux
    sudo install minikube-linux-amd64 /usr/local/bin/minikube
    # macOS
    sudo install minikube-darwin-amd64 /usr/local/bin/minikube
     
  3. 3.
    Start a local cluster with minikube:
    ../images/503015_1_En_2_Chapter/503015_1_En_2_Figa_HTML.png
     

The simplicity of Kubernetes operations is packed into the single command of the minikube start. It downloads the images, starts control plane components, enables addons, and verifies the cluster components. In the last step, it configures kubectl to connect to the cluster created by minikube.

You have a Kubernetes cluster and a client tool. Now, it is time to have fun with Kubernetes by deploying applications, scaling them, and checking their statuses.

Usage of kubectl is based on the following syntax in Listing 2-5.
kubectl [command] [TYPE] [NAME] [flags]
Listing 2-5

kubectl syntax

command specifies the operation, such as creating, getting, describing, or deleting that you want to execute against Kubernetes API. You can list all the commands by running kubectl --help. It lists all the commands grouped by their functionality and details like in Listing 2-6.
$ kubectl --help
kubectl controls the Kubernetes cluster manager.
 Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/
Basic Commands (Beginner):
  create        Create a resource from a file or from stdin.
  expose        Take a replication controller, service,
                deployment or pod and expose it as a new Kubernetes Service
  run           Run a particular image on the cluster
  set           Set specific features on objects
Basic Commands (Intermediate):
  explain       Documentation of resources
  get           Display one or many resources
  edit          Edit a resource on the server
  delete        Delete resources by filenames, stdin,
                resources and names, or by resources and label
                selector
...
Listing 2-6

kubectl help output

TYPE specifies the type of the Kubernetes API resource such as pods, deployments, or nodes. It is possible to list the supported API resources on Kubernetes API with the following command in Listing 2-7.
$ kubectl api-resources --output=name
bindings
componentstatuses
configmaps
endpoints
events
limitranges
namespaces
nodes
persistentvolumeclaims
persistentvolumes
pods
podtemplates
replicationcontrollers
Listing 2-7

kubectl API resources

It is a long list with more than 50 resources supported currently in Kubernetes API.

NAME specifies the name of the resource to execute the command on it, the operations. If you do not specify a NAME, the commands are executed for all the resources in the TYPE.

flags are the optional variables for commands such as --namespace or --kubeconfig. You can list the options that can be passed to any command with kubectl options as shown in Listing 2-8.
$ kubectl options
The following options can be passed to any command:
...
--cluster='': The name of the kubeconfig cluster to use
--context='': The name of the kubeconfig context to use
...
--kubeconfig='': Path to the kubeconfig file to use for CLI requests.
-n, --namespace='': If present, the namespace scope for this CLI request
...
--token='': Bearer token for authentication to the API server
...
-v, --v=0: number for the log level verbosity
Listing 2-8

kubectl options output

You can run kubectl <command> --help to get more information such as options, usage, and examples on a given command. Considering the high number of resources and commands, kubectl is a tool packed with numerous actions. It is advised to get your hands dirty with kubectl by trying different commands. kubectl is almost exclusively the single-entry point to the cluster for deployment, status tracking, and troubleshooting. In the following exercise, you will use the most common kubectl commands to get used to it before developing extensions.

EXERCISE: GETTING STARTED WITH kubectl
In this exercise, you will use kubectl to interact with the Kubernetes cluster.
  1. 1.
    Start with checking the version of your client tool and the API server:
    $ kubectl version
    Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:30:33Z", GoVersion:"go1.15", Compiler:"gc", Platform:"darwin/amd64"}
    Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.0", GitCommit:"e19964183377d0ec2052d1f1fa930c4d7575bd50", GitTreeState:"clean", BuildDate:"2020-08-26T14:23:04Z", GoVersion:"go1.15", Compiler:"gc", Platform:"linux/amd64"}

    It shows that both the client and the server have the version 1.19.0.

     
  2. 2.
    Check the nodes available in the cluster:
    $ kubectl get nodes
    NAME     STATUS ROLES  AGE VERSION
    minikube Ready  master 88s v1.19.0

    Nodes are also a resource type in Kubernetes, and the command is to retrieve them from the Kubernetes API. You will have one node since you are running a minikube cluster.

     
  3. 3.
    Create a deployment with the following command:
    $ kubectl create deployment my-first-deployment ​--image=nginx
    deployment.apps/my-first-deployment created

    This command creates a resource type of deployment with the name my-first-deployment using the image nginx.

     
  4. 4.
    Check the status of the deployment created in Step 3:
    $ kubectl get deployment my-first-deployment
    NAME                READY  UP-TO-DATE  AVAILABLE AGE
    my-first-deployment  1/1   1           1         16s

    This command retrieves the resource with its name. The deployment has one ready instance available.

     
  5. 5.
    Scale the deployment to five instances:
    $ kubectl scale deployment/my-first-deployment ​--replicas=5
    deployment.apps/my-first-deployment scaled

    This is a special command to scale the number of instances of the resource provided. The --replicas flag specifies the requested replica count.

     
  6. 6.
    Check the pods after scale-up:
    $ kubectl get pods
    NAME                            READY   STATUS    RESTARTS   AGE
    my-first-deployment-...-26xpn   1/1     Running   0          13s
    my-first-deployment-...-87fcw   1/1     Running   0          13s
    my-first-deployment-...-b7nzv   1/1     Running   0          2m45s
    my-first-deployment-...-kxg2w   1/1     Running   0          13s
    my-first-deployment-...-wmg92   1/1     Running   0          13s

    As expected, there are now five pods, and the last four ones are created after the first one.

     
  7. 7.
    Clean the deployment with the following command:
    $ kubectl delete deployment my-first-deployment
    deployment.apps "my-first-deployment" deleted
     

Your CLI environment has a new member, and you have started discovering its capabilities. Now, it is time to go one step further and extend its skills. In the following section, we will continue with the plugin design to add custom commands to kubectl.

kubectl Plugin Design

Core kubectl commands are essential for interacting with the Kubernetes API. Plugins extend the kubectl with new subcommands for new custom features. kubectl extensions implement the binary plugin approach. As in the binary plugin pattern, kubectl executes third-party applications as extensions. There are three main rules for plugin binaries:

  • - Executable

  • - Anywhere on the user’s PATH

  • - Begin with kubectl-

These three rules are based on how kubectl discovers the plugins. Let’s have a look at the source code of plugin handling in kubectl.
// Lookup implements PluginHandler
func (h *DefaultPluginHandler) Lookup(filename string) (string, bool) {
      for _, prefix := range h.ValidPrefixes {
            path, err := exec.LookPath(fmt.Sprintf("%s-%s", prefix, filename))
            if err != nil || len(path) == 0 {
      continue
      }
      return path, true
            }
            return "", false
      }
Listing 2-9

Plugin handler in kubectl

Note Source code of the DefaultPluginHandler is available at https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cmd.go.

DefaultPluginHandler checks for the executables in the path starting with the ValidPrefix, kubectl. Therefore, any binary named kubectl-my-first-plugin or kubectl-whoami in the PATH environment variable is an appropriate kubectl plugin. The plugin names are interpreted as subcommands, such as the binary with the name kubectl-whoami for kubectl whoami command . Thus, kubectl will check whether there are any commands in native implementation and then the plugins as shown in Figure 2-2.
../images/503015_1_En_2_Chapter/503015_1_En_2_Fig2_HTML.jpg
Figure 2-2

kubectl command handling

Let’s have a look at how the plugins are executed in kubectl.
// Execute implements PluginHandler
func (h *DefaultPluginHandler) Execute(executablePath string, cmdArgs, environment []string) error {
    // Windows does not support exec syscall.
    if runtime.GOOS == "windows" {
         cmd := exec.Command(executablePath, cmdArgs...)
         cmd.Stdout = os.Stdout
         cmd.Stderr = os.Stderr
         cmd.Stdin = os.Stdin
         cmd.Env = environment
         err := cmd.Run()
         if err == nil {
              os.Exit(0)
         }
         return err
    }
  // invoke cmd binary relaying the environment and args given
    ..
    return syscall.Exec(executablePath, append([]string{executablePath}, cmdArgs...), environment)
}
Listing 2-10

kubectl binary plugin handling

Note Source code of the DefaultPluginHandler is available at https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cmd.go.

DefaultPluginHandler has an Execute function with the inputs of the executable path, arguments, and environment variables. The function passes these variables to the third-party binary, which is the plugin. In Windows, it connects the standard input and output to the command and then executes it. In Linux and macOS, the function uses syscall on the operating system level with the arguments and environment variables.

Now, it is time to add a new custom command to the kubectl by creating the plugin.

Create Your First kubectl Plugins

You can list the available plugins with the kubectl plugin commands locally.
$ kubectl plugin list
error: unable to find any kubectl plugins in your PATH
Listing 2-11

Installed plugins

There are no plugins found locally by kubectl. Now, create a file named kubectl-whoami with the following content.
#!/bin/bash
kubectl config view --template='{{ range .contexts }}{{ if eq .name "'$(kubectl config current-context)'" }}User: {{ printf "%s " .context.user }}{{ end }}{{ end }}'
Listing 2-12

Plugin code

Move the file to a folder in your PATH environment variable and make it executable.
sudo chmod +x ./kubectl-whoami
sudo mv ./kubectl-whoami /usr/local/bin
Listing 2-13

Plugin installation

Now, rerun the kubectl plugin list command.
$ kubectl plugin list
The following compatible plugins are available:
/usr/local/bin/kubectl-whoami
Listing 2-14

Installed plugins

It shows that kubectl can discover the plugin. Let’s test it and see it in action.
$ kubectl whoami
User: minikube
Listing 2-15

kubectl whoami plugin

There are two critical points about running the last command. The first point is that kubectl whoami is an extended command not available in the native implementation. However, with the extension capabilities, you can run a custom subcommand. The second point is that it is possible to retrieve information and interfere with the operations of kubectl now.

In the following exercise, you will create a kubectl prompt command to show the current Kubernetes cluster and the username in the bash prompt.

EXERCISE: KUBERNETES BASH PROMPT
Dealing with one Kubernetes cluster is easy, but it becomes cumbersome when it becomes tens of clusters in a daily routine. It is helpful to know the current cluster and the user in the terminal bash prompt not to make critical mistakes. We will have a string displayed before each command with the (user @ cluster) information.
  1. 1.
    Create a file with the name kubectl-prompt with the following content:
    #!/bin/bash
    currentContext=$(kubectl config current-context)
    prompt="(%s @ %s) > "
    template="{{ range .contexts }}{{ if eq .name "$currentContext" }}{{ printf "$prompt" .context.user .context.cluster}}{{ end }}{{ end }}"
    kubectl config view --template="$template"

    The script checks for all the contexts in the kubeconfig and retrieves the cluster and username fields.

     
  2. 2.
    Move the file to a folder in PATH environment variable and make it executable:
    sudo chmod +x ./kubectl-prompt
    sudo mv ./kubectl-prompt /usr/local/bin
     
  3. 3.
    Test the plugin with the following command:
    $ kubectl prompt
    (minikube @ minikube) >
     
  4. 4.
    Set the prompt environment variable:
    $ export PS1=$(kubectl prompt)
    (minikube @ minikube) >
     

From now on, every terminal command will have the prompt available. It will always be on your sight which cluster and user are in control.

Plugins extend the kubectl and help you achieve more while interacting with the Kubernetes clusters. It is expected to have similar difficulties while operating the clusters, which leads to developing similar plugins. In the following section, the focus will be on plugin repository for kubectl and how to use it.

Plugin Repository: krew

Kubernetes community has a kubectl plugin manager named krew . The plugin manager helps to discover, install, and update open source and community-maintained plugins. Currently, there are more than 100 plugins distributed on krew. Therefore, it is noteworthy to check the plugin repository before creating a new one. It is already possible someone in the Kubernetes community has developed the same functionality and distributed it.

Let’s start installing the krew, a kubectl plugin itself, and discover some repository plugins. Run this command in the terminal to download krew.
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.tar.gz"
tar zxf krew.tar.gz
Listing 2-16

Downloading krew

Now, install the binary accordingly to the operating system.
# Linux
./krew-linux_amd64 install krew
# macOS
./krew-darwin_amd64 install krew
Adding "default" plugin index from https://github.com/kubernetes-sigs/krew-index.git.
Updated the local copy of plugin index.
Installing plugin: krew
Installed plugin: krew
 | Use this plugin:
 | kubectl krew
 | Documentation:
 | https://krew.sigs.k8s.io/
 | Caveats:
 |
 | | krew is now installed! To start using kubectl plugins, you need to add
 | | krew's installation directory to your PATH:
 | |
 | | * macOS/Linux:
 | | - Add the following to your ~/.bashrc or ~/.zshrc:
 | | export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
 | | - Restart your shell.
 | |
 | | * Windows: Add %USERPROFILE%.krewin to your PATH environment variable
 | |
 | | To list krew commands and to get help, run:
 | | $ kubectl krew
 | | For a full list of available plugins, run:
 | | $ kubectl krew search
 | |
 | | You can find documentation at
 | | https://krew.sigs.k8s.io/docs/user-guide/quickstart/.
 | /
/
Listing 2-17

Downloading krew

Finally, add the krew installation directory to the path.
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
Listing 2-18

Path expansion

Now, we can test it by calling as a kubectl plugin.
$ kubectl krew
krew is the kubectl plugin manager.
You can invoke krew through kubectl: "kubectl krew [command]..."
Usage:
  kubectl krew [command]
Available Commands:
  help        Help about any command
  index       Manage custom plugin indexes
  info        Show information about an available plugin
  install     Install kubectl plugins
  list        List installed kubectl plugins
  search      Discover kubectl plugins
  uninstall   Uninstall plugins
  update      Update the local copy of the plugin index
  upgrade     Upgrade installed plugins to newer versions
  version     Show krew version and diagnostics
Flags:
  -h, --help      help for krew
  -v, --v Level   number for the log level verbosity
Use "kubectl krew [command] --help" for more information about a command.
Listing 2-19

kubectl krew output

It is now possible to search, install, and upgrade plugins managed by krew. An up-to-date list of the plugins is available on the krew website with the name, description, and GitHub popularity as shown in Figure 2-3.
../images/503015_1_En_2_Chapter/503015_1_En_2_Fig3_HTML.jpg
Figure 2-3

krew plugin list

Let’s assume you are running a web application in Kubernetes, and it has a service in front of the instances. To access and test the app, you need to reach the service endpoint. Luckily, the Kubernetes community has a plugin for this task. open-svc is the kubectl plugin to open the specified service URL in the browser through a local proxy server. You can install it via krew.
$ kubectl krew install open-svc
Updated the local copy of plugin index.
Installing plugin: open-svc
Installed plugin: open-svc
 | Use this plugin:
 | kubectl open-svc
 | Documentation:
 | https://github.com/superbrothers/kubectl-open-svc-plugin
/
WARNING: You installed plugin "open-svc" from the krew-index plugin repository.
   These plugins are not audited for security by the Krew maintainers.
   Run them at your own risk.
Listing 2-20

Installing open-svc plugin

Note If you have not enabled the Kubernetes dashboard for your cluster, you can run minikube dashboard to install it.

Now, let’s open the Kubernetes dashboard by using the kubectl open-svc plugin.
$ kubectl open-svc kubernetes-dashboard -n kubernetes-dashboard
Starting to serve on 127.0.0.1:8001
Opening service/kubernetes-dashboard in the default browser...
Listing 2-21

open-svc plugin in action

The command should open the dashboard in the browser like in Figure 2-4.
../images/503015_1_En_2_Chapter/503015_1_En_2_Fig4_HTML.jpg
Figure 2-4

Kubernetes dashboard

It is just a couple of commands to install new plugins from the repository and start using them. Therefore, it is useful to check what has already been developed by the community before creating it from scratch.

Key Takeaways

  • kubectl is the official client to interact with the Kubernetes API.

  • Native kubectl commands are essential to operate Kubernetes clusters.

  • It is possible to extend kubectl with new commands by creating plugins.

  • kubectl plugins are third-party binaries, and they are executed by kubectl.

  • There is a community-maintained plugin repository for kubectl, named krew.

In the following chapter, we will continue with API flow extensions and learn how to extend the flow with authentication, authorization, and admission controls.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.4.181