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

简介: 在我们使用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,以供大家学习交流。

参考链接

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
813 4
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
1301 0
|
JavaScript 前端开发 Java
【GoWails】Go做桌面应用开发?本篇文章带你上手Wails框架!一步步带你玩明白前后端双端的数据绑定!
wails是一个可以让你使用Go和Web技术编写桌面应用的项目 可以将它看作Go的快并且轻量级的Electron替代品。可以使用Go的功能,并结合现代化UI完成桌面应用程序的开发
1819 5
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
673 61
|
开发框架 安全 前端开发
Go Web开发框架实践:模板渲染与静态资源服务
Gin 是一个功能强大的 Go Web 框架,不仅适用于构建 API 服务,还支持 HTML 模板渲染和静态资源托管。它可以帮助开发者快速搭建中小型网站,并提供灵活的模板语法、自定义函数、静态文件映射等功能,同时兼容 Go 的 html/template 引擎,具备高效且安全的页面渲染能力。
|
人工智能 缓存 安全
Go开发遇见的一次Data Race
本文通过一段 Go 语言代码示例,分析了并发编程中的数据竞争(Data Race)问题。代码实现了一个带缓存的内存存储系统,包含 `LRUCache` 和 `MemoryCache` 两个核心组件。尽管在 `MemoryCache` 的 `Set` 方法中加了锁保护,但由于直接调用 `LRUCache` 的 `GetLength` 方法时未加锁,导致底层数据结构在多 goroutine 环境下被同时读写,从而触发 Data Race。文章详细解析了问题根源,并提出了解决方案:为 `LRUCache` 的 `Add` 方法添加锁保护,确保并发安全。
211 1
|
Go API 定位技术
MCP 实战:用 Go 语言开发一个查询 IP 信息的 MCP 服务器
随着 MCP 的快速普及和广泛应用,MCP 服务器也层出不穷。大多数开发者使用的 MCP 服务器开发库是官方提供的 typescript-sdk,而作为 Go 开发者,我们也可以借助优秀的第三方库去开发 MCP 服务器,例如 ThinkInAIXYZ/go-mcp。 本文将详细介绍如何在 Go 语言中使用 go-mcp 库来开发一个查询 IP 信息的 MCP 服务器。
982 2
|
存储 算法 Go
Go语言实战:错误处理和panic_recover之自定义错误类型
本文深入探讨了Go语言中的错误处理和panic/recover机制,涵盖错误处理的基本概念、自定义错误类型的定义、panic和recover的工作原理及应用场景。通过具体代码示例介绍了如何定义自定义错误类型、检查和处理错误值,并使用panic和recover处理运行时错误。文章还讨论了错误处理在实际开发中的应用,如网络编程、文件操作和并发编程,并推荐了一些学习资源。最后展望了未来Go语言在错误处理方面的优化方向。
298 5
|
开发框架 Go 计算机视觉
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
619 5
|
Go 数据安全/隐私保护 开发者
Go语言开发
【10月更文挑战第26天】Go语言开发
297 3

推荐镜像

更多