KubeMacro是一个kubectl插件,它用于把一组针对于kubectl命令或Kubernetes API的调用封装成一个命令,以便于在命令行多次执行。KubeMacro是一个位于GitHub上的开源项目。

作为KubeMacro系列的第三篇文章,本文将向大家介绍如何编写一个kube macro

自己动手写Macro

KubeMacro本质上是一个kube macro的执行器。默认情况下,它并不绑定任何预定义的macro。我们可以通过访问 KubeMacro Hub 网站浏览并安装由他人开发的kube macro。

如果现有的macro无法满足需求,你也可以编写属于你自己的macro。本文里,我将带着大家一步一步编写出一个macro,用于打印一组pod及其所包含的容器。此外,也非常欢迎大家把自己开发的macro提交到KubeMacro Hub,这样其他人也可以从中获益。

创建Shell脚本文件

首先,让我们创建一个shell脚本文件,取名为get-pod-containers.sh,并将它放到$HOME/.kubemacro目录下。这里是KubeMacro加载所有macro的地方。每当KubeMacro启动时,它会寻找该目录下的所有.sh文件,并作为macro加载到内存。

在这个脚本文件里,我们是通过一个shell函数来实现macro的逻辑的。在我们的例子里,这个函数的名字是get-pod-containers,目前函数体还是空的:

#!/bin/bash
function get-pod-containers {
 :
}

为了测试这个macro,我们可以调用kubectl macro命令,并指定函数名get-pod-containers作为该macro的名字:

kubectl macro get-pod-containers

正常情况下,我们会看到命令能够正确返回,只是返回结果是空的。接下来,让我们为函数加入具体的实现逻辑。

实现Macro的逻辑

将下列逻辑加入get-pod-containers函数:

#!/bin/bash
function get-pod-containers {
  local args=()
  local ns=''
  # Parse the arguments input from command line
  while [[ $# -gt 0 ]]; do
    case "$1" in
    -n|--namespace|-n=*|--namespace=*)
      ns=$2
      args+=("$1 $2")
      shift
      shift ;;
    -A|--all-namespaces)
      ns="all namespaces"
      args+=("$1")
      shift ;;
    *)
      args+=("$1")
      shift ;;
    esac
  done
  # Run kubectl get and define custom columns to include pod container names
  local custom_columns="NAME:.metadata.name,CONTAINERS:.spec.containers[*].name"
  if [[ $ns == "all namespaces" ]]; then
    custom_columns="NAMESPACE:.metadata.namespace,$custom_columns"
  fi
  kubectl get pods ${args[@]} -o custom-columns=$custom_columns
}

大体而言,上述函数做了两件事情:

  • 解析从命令行传入的输入参数。
  • 执行kubectl get命令,并定制了输出列,通过指定JSONPath,把从pod定义中解析得到的容器名显示输出。

现在,让我们再次执行该macro。这一次我们会看到,命令会把所有位于当前namespace下的pod及其容器都返回回来:

kubectl macro get-pod-containers

为Macro添加注释

到目前为止,我们已经实现了macro的全部逻辑。是不是很简单啊?不过,还有一件事情我们需要做。当执行kubectl macro并带着-h/--help参数或者不带任何参数时,为了能够让我们的macro出现在已安装macro的列表里,我们还需要为macro添加一个特别的注释。

此外,当我们执行kubectl macro <macro>命令并带着-h/--help参数时,为了能够打印输出针对该macro的帮助信息,我们还需要提前准备好相应的帮助信息。这些信息也是通过macro注释添加的。

不仅如此,如果你希望通过KubeMacro Hub把自己的macro分享给其他人,为macro定义更为详细的描述说明与使用方法同样也必须通过这个macro注释来实现。

为macro添加的注释必须以##开头,并以##结尾,两者之间包含了若干个字段,每个字段的名字都是以@打头的。下面是一个注释模版,包含了每个字段的详细解释:

##
# @Name: <Input your single-line macro name here>
# @Description: <Input your single-line macro description here>
# <Input detailed description for your macro started from here>
# <It supports multiple lines and markdown syntax>
# @Author: <Input single-line author name here, support markdown syntax>
# @Usage: <Input your single-line macro usage information here>
# @Options:
#   <Input help information for all your options started from here>
#   <It supports multiple lines>
# @Examples:
#   <Input detailed information for all examples started from here>
#   <It supports multiple lines>
# @Dependencies: <Input single-line comma-separated dependencies of your macro here>
##

下面是针对get-pod-containers的注释内容:

##
# @Name: get-pod-containers
# @Description: List the pods with their containers.
#
# This is a sample macro to demonstrate how to write a macro by your own.
# It can be used to list pods and their containers. For example, to list
# all pods and their containers in `kube-system` namespace:
# ```shell
# kubectl macro get-pod-containers -n kube-system
# NAME                                         CONTAINERS
# coredns-6955765f44-gtx2q                     coredns
# coredns-6955765f44-tz96m                     coredns
# etcd-kind-control-plane                      etcd
# kindnet-4pzm7                                kindnet-cni
# kube-apiserver-kind-control-plane            kube-apiserver
# kube-controller-manager-kind-control-plane   kube-controller-manager
# kube-proxy-b6wn8                             kube-proxy
# kube-scheduler-kind-control-plane            kube-scheduler
# ```
#
# @Author: [morningspace](https://github.com/morningspace/)
# @Usage: kubectl macro get-pod-containers [options]
# @Options:
#   -A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current
#   context is ignored even if specified with --namespace.
#   -h, --help: Print the help information.
#   -n, --namespace='': If present, the namespace scope for this CLI request.
#   -l, --selector='': Selector (label query) to filter on, not including uninitialized ones.
#       --version: Print the version information.
#   -w, --watch=false: After listing/getting the requested object, watch for changes. Uninitialized objects are excluded
#   if no object name is provided.
#       --watch-only=false: Watch for changes to the requested object(s), without listing/getting first.
# @Examples:
#   # To list all pods with their containers in a namespace.
#   kubectl macro get-pod-containers -n foo
#   # To list all pods with their containers in all namespaces.
#   kubectl macro get-pod-containers -A
# @Dependencies: kubectl
##
function cluster {
  ...
}

为了验证,我们可以执行如下命令,看一下我们的macro是否已经出现在已安装macro的列表中了:

kubectl macro --help

如果一切正常,我们会在返回结果中找到get-pod-containers。执行如下命令,打印输出macro的帮助信息:

kubectl macro get-pod-containers --help

我们会看到如下输出结果,这正是我们在注释里定义的内容:

get-pod-containers: List the pods with their containers.
Usage: kubectl macro get-pod-containers [options]
Options:
  -A, --all-namespaces=false: If present, list the requested object(s) across all namespaces. Namespace in current
  context is ignored even if specified with --namespace.
  -h, --help: Print the help information.
  -n, --namespace='': If present, the namespace scope for this CLI request.
  -l, --selector='': Selector (label query) to filter on, not including uninitialized ones.
      --version: Print the version information.
  -w, --watch=false: After listing/getting the requested object, watch for changes. Uninitialized objects are excluded
  if no object name is provided.
      --watch-only=false: Watch for changes to the requested object(s), without listing/getting first.
Examples:
  # To list all pods with their containers in a namespace.
  kubectl macro get-pod-containers -n foo
  # To list all pods with their containers in all namespaces.
  kubectl macro get-pod-containers -A

关于Macro的依赖

也许你已经注意到了,在前面的macro注释里有一个@Dependencies字段。一个macro可能会包含多个依赖。比如,有的macro需要用jq命令来解析JSON数据,有的macro则依赖于其他macro来共同完成一项任务。为了成功执行一个macro,需要确保其所依赖的部分已经事先安装好了。

当编写一个macro的时候,我们可以根据需要为macro定义它的依赖。每当KubeMacro执行一个macro时,它首先会检查该macro是否存在任何依赖。如果有的话,KubeMacro会检查这些依赖是否已存在。如果不存在,则会报错。

小结

get-pod-containers的最终版本可以从这里找到。至此,我们可以看到,编写一个kube macro是非常容易的。如果你发现现有macro都不能满足你的需求时,那就自己动手写一个吧。你还可以以pull request的形式把macro提交到KubeMacro Hub的GitHub库。一旦被成功合并,其他人也能从中获益。

如果你想了解更多有关KubeMacro的信息,请阅读它的在线文档。如果你喜欢这个项目,欢迎给它加星。同时,也非常欢迎针对该项目的任何形式的贡献,比如bug报告以及代码提交。

留下评论

您的电子邮箱地址并不会被展示。请填写标记为必须的字段。 *

正在加载...