Cobra + Client-go实现K8s 自定义插件开发

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 在我们使用kubectl查看k8s资源的时候,想直接查看对应资源的容器名称和镜像名称,目前kubectl还不支持该选型,需要我们describe然后来查看,对于集群自己比较多,不是很方便,因此萌生了自己开发kubectl 插件来实现该功能。

一 背景

在我们使用kubectl查看k8s资源的时候,想直接查看对应资源的容器名称和镜像名称,目前kubectl还不支持该选型,需要我们describe然后来查看,对于集群自己比较多,不是很方便,因此萌生了自己开发kubectl 插件来实现该功能。

二 相关技术

2.1 Cobra

Cobra是一个命令行程序库,其是一个用来编写命令行的神器,提供了一个脚手架,用于快速生成基于Cobra应用程序框架。我们可以利用Cobra快速的去开发出我们想要的命令行工具,非常的方便快捷。

2.2 Client-go

在K8s运维中,我们可以使用kubectl、客户端库或者REST请求来访问K8S API。而实际上,无论是kubectl还是客户端库,都是封装了REST请求的工具。client-go作为一个客户端库,能够调用K8S API,实现对K8S集群中资源对象(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增删改查等操作。

2.3 k8s 插件krew

Krew 是 类似于系统的apt、dnf或者brew的 kubectl插件包管理工具,利用其可以轻松的完成kubectl 插件的全上面周期管理,包括搜索、下载、卸载等。

kubectl 其工具已经比较完善,但是对于一些个性化的命令,其宗旨是希望开发者能以独立而紧张形式发布自定义的kubectl子命令,插件的开发语言不限,需要将最终的脚步或二进制可执行程序以kubectl- 的前缀命名,然后放到PATH中即可,可以使用kubectl plugin list查看目前已经安装的插件。

三 插件规划

  • 插件命名为:kubeimg。
  • 目前仅简单实现一个image命令,用于查看不同资源对象(deployments/daemonsets/statefulsets/jobs/cronjobs)的名称,和对应容器名称,镜像名称。
  • 支持json格式输出。
  • 最后将其作为krew插件使用。
  • 可以直接根据名称空间来进行查看对应资源。

四 实战开发

4.1 项目初始化

  • 安装cobra
go get -v github.com/spf13/cobra/cobra 
  • 初始化项目
 $ ~/workspace/goworkspace/src/github.com/kaliarch/kubeimg  /Users/xuel/workspace/goworkspace/bin/cobra init --pkg-name kubeimg
Your Cobra application is ready at
/Users/xuel/workspace/goworkspace/src/github.com/kaliarch/kubeimg
$ ~/workspace/goworkspace/src/github.com/kaliarch/kubeimg  ls
LICENSE cmd     main.go
$ ~/workspace/goworkspace/src/github.com/kaliarch/kubeimg  tree

├── LICENSE
├── cmd
│   └── root.go
└── main.go

1 directory, 3 files
  • 创建go mod,下载相关包
go mod init kubeimg

4.2 增加子命令

增加一个子命令image。

$ /Users/xuel/workspace/goworkspace/bin/cobra add image
image created at /Users/xuel/workspace/goworkspace/src/github.com/kaliarch/kubeimg

4.3 添加参数


// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
    cobra.CheckErr(rootCmd.Execute())
}

func init() {
    KubernetesConfigFlags = genericclioptions.NewConfigFlags(true)
    imageCmd.Flags().BoolP("deployments", "d", false, "show deployments image")
    imageCmd.Flags().BoolP("daemonsets", "e", false, "show daemonsets image")
    imageCmd.Flags().BoolP("statefulsets", "f", false, "show statefulsets image")
    imageCmd.Flags().BoolP("jobs", "o", false, "show jobs image")
    imageCmd.Flags().BoolP("cronjobs", "b", false, "show cronjobs image")
    imageCmd.Flags().BoolP("json", "j", false, "show json format")
    KubernetesConfigFlags.AddFlags(rootCmd.PersistentFlags())
}

4.4 实现image命令

var imageCmd = &cobra.Command{
    Use:   "image",
    Short: "show resource image",
    Long:  `show k8s resource image`,
    RunE:  image,
}

func init() {
    rootCmd.AddCommand(imageCmd)
}

4.5 初始化clientset

// ClientSet k8s clientset
func ClientSet(configFlags *genericclioptions.ConfigFlags) *kubernetes.Clientset {
    config, err := configFlags.ToRESTConfig()
    if err != nil {
        panic("kube config load error")
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {

        panic("gen kube config error")
    }
    return clientSet
}

4.6 实现查看资源对象

利用反射实现根据不同资源类型查看具体对应资源镜像及镜像名称功能。

func image(cmd *cobra.Command, args []string) error {

    clientSet := kube.ClientSet(KubernetesConfigFlags)
    ns, _ := rootCmd.Flags().GetString("namespace")
    // 生命一个全局资源列表
    var rList []interface{}

    if flag, _ := cmd.Flags().GetBool("deployments"); flag {
        deployList, err := clientSet.AppsV1().Deployments(ns).List(context.Background(), v1.ListOptions{})
        if err != nil {
            fmt.Printf("list deployments error: %s", err.Error())
        }
        rList = append(rList, deployList)
    }
  ...
      deployMapList := make([]map[string]string, 0)
    for i := 0; i < len(rList); i++ {
        switch t := rList[i].(type) {
        case *kv1.DeploymentList:
            for k := 0; k < len(t.Items); k++ {
                for j := 0; j < len(t.Items[k].Spec.Template.Spec.Containers); j++ {
                    deployMap := make(map[string]string)
                    deployMap["NAMESPACE"] = ns
                    deployMap["TYPE"] = "deployment"
                    deployMap["RESOURCE_NAME"] = t.Items[k].GetName()
                    deployMap["CONTAINER_NAME"] = t.Items[k].Spec.Template.Spec.Containers[j].Name
                    deployMap["IMAGE"] = t.Items[k].Spec.Template.Spec.Containers[j].Image
                    deployMapList = append(deployMapList, deployMap)
                }
            }

4.6 实现输出

利用tabel来对结果进行输出


func GenTable(mapList []map[string]string) *table.Table {
    t, err := gotable.Create(title...)
    if err != nil {
        fmt.Printf("create table error: %s", err.Error())
        return nil
    }
    t.AddRows(mapList)
    return t
}

最终项目结构:

五 测试

对完成的插件进行测试,编译go build生成kubeimg二进制可执行文件。

5.1 查看帮助

  • 查看所有帮助

其中可以看到cobra帮我们自动生成了help和completion两个命令,可以快速实现table补全,支持bash/fish/zsh/powershell

./kubeimg --help

  • 查看image命令flags
./kubeimg image --help

5.1 查看deployment资源

不知地ing名称名称空间,默认查看所有,名称空间下的资源

./kubeimg image -d

5.2 查看某个名称空间下资源

./kubeimg image -d -n kube-system

5.3 查看所有资源

可以看到imlc-operator-controller-manager 一个pod中有两个container。

./kubeimg image -b -e -d -o -f

5.4 json格式输出

./kubeimg image -o -j

六 作为krew插件使用

需要将最终的脚步或二进制可执行程序以kubectl- 的前缀命名,然后放到PATH中即可,可以使用kubectl plugin list查看目前已经安装的插件。

$ kubectl plugin list
The following compatible plugins are available:=
/usr/local/bin/kubectl-debug
  - warning: kubectl-debug overwrites existing command: "kubectl debug"
/usr/local/bin/kubectl-v1.10.11
/usr/local/bin/kubectl-v1.20.0
/Users/xuel/.krew/bin/kubectl-df_pv
/Users/xuel/.krew/bin/kubectl-krew

# 将自己开发的插件重新命名为kubectl-img放到可执行路基下
$ cp kubeimg /Users/xuel/.krew/bin/kubectl-img

$ kubectl plugin list
The following compatible plugins are available:=
/usr/local/bin/kubectl-debug
  - warning: kubectl-debug overwrites existing command: "kubectl debug"
/usr/local/bin/kubectl-v1.10.11
/usr/local/bin/kubectl-v1.20.0
/Users/xuel/.krew/bin/kubectl-df_pv
/Users/xuel/.krew/bin/kubectl-krew
/Users/xuel/.krew/bin/kubectl-img

$ cp kubeimg /Users/xuel/.krew/bin/kubectl-img

之后就可以想使用kubectl插件一样使用了。

6682eaeda7cf45b7b74e8a56adeedbd5~tplv-k3u1fbpfcp-zoom-1.image

其他

目前实现的比较简单,以此来抛砖引玉的功能,后期可以进行更多功能或其他插件的开发,自己动手丰衣足食。

后期待再完善开源到github,个人主页:github,以供大家学习交流。

参考链接

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3月前
|
缓存 弹性计算 API
用 Go 快速开发一个 RESTful API 服务
用 Go 快速开发一个 RESTful API 服务
|
16天前
|
Go 数据安全/隐私保护 开发者
Go语言开发
【10月更文挑战第26天】Go语言开发
32 3
|
17天前
|
Java 程序员 Go
Go语言的开发
【10月更文挑战第25天】Go语言的开发
26 3
|
1月前
|
Kubernetes Docker 微服务
微服务实践k8s&dapr开发部署实验(1)服务调用(一)
微服务实践k8s&dapr开发部署实验(1)服务调用(一)
49 2
|
1月前
|
Kubernetes JavaScript 前端开发
k8s学习--chart包开发(创建chart包)
k8s学习--chart包开发(创建chart包)
|
2月前
|
Kubernetes 容器 Perl
Kubernetes网络插件体系及flannel基础
文章主要介绍了Kubernetes网络插件体系,特别是flannel网络模型的工作原理、配置和测试方法。
108 3
Kubernetes网络插件体系及flannel基础
|
1月前
|
Kubernetes Docker 微服务
微服务实践k8s&dapr开发部署实验(1)服务调用(二)
微服务实践k8s&dapr开发部署实验(1)服务调用(二)
50 0
|
3月前
|
Kubernetes Docker Perl
在K8S中,如果是因为开发写的镜像问题导致pod起不来该怎么排查?
在K8S中,如果是因为开发写的镜像问题导致pod起不来该怎么排查?
|
3月前
|
Kubernetes 监控 Cloud Native
"解锁K8s新姿势!Cobra+Client-go强强联手,打造你的专属K8s监控神器,让资源优化与性能监控尽在掌握!"
【8月更文挑战第14天】在云原生领域,Kubernetes以出色的扩展性和定制化能力引领潮流。面对独特需求,自定义插件成为必要。本文通过Cobra与Client-go两大利器,打造一款监测特定标签Pods资源使用的K8s插件。Cobra简化CLI开发,Client-go则负责与K8s API交互。从初始化项目到实现查询逻辑,一步步引导你构建个性化工具,开启K8s集群智能化管理之旅。
53 2
|
3月前
|
JSON 编解码 中间件
go-zero代码生成器助你高效开发
go-zero代码生成器助你高效开发