k8s系列 – client-go安装原理与基本使用

发现网上关于k8s client-go的用法基本没有,所以特意把基本的安装与使用步骤以及原理记录下来,帮助大家理解整个过程。

client-go项目地址

https://github.com/kubernetes/client-go

用go客户端访问k8s必然是最靠谱的,我们 要做的就是在k8s集群外访问k8s apiserver。

包管理工具问题

golang的包管理方案有好几个,client-go支持了glide、godep这两款。

glide项目说自己未来会停止维护,建议大家用godep;而godep项目说自己未来会停止维护,建议大家用dep;而client-go说自己还没支持dep。

综合看下来,用godep是目前最靠谱的选择。

用包管理工具的前提是知道为什么要用包管理工具。

我们知道go get下载一个项目的时候,它会先下载整个项目到磁盘上,golang认为这是一个go的package,它会找到里面每个.go文件,分析它import了什么包,然后去递归下载它们,这就是下载依赖,当然依赖的依赖都会被下载。

问题就出在这里,go get下载依赖的时候,总是下载它们的master代码,如果依赖的master代码有不兼容的升级,我们的项目就编译不成功了。显然,我们想要的效果是,下载的依赖应该是我们开发项目时用的那个版本,而不是最新master代码。

所以包管理工具就出现了,它们可以帮你记录下你当前使用的依赖是master分支的哪一次git提交,这些信息可以上传到项目git里。下次go get项目之后,我们可以用包管理工具复原到当时的依赖版本,就可以顺利编译了。

实际上,godep更牛逼,它不仅记录当前依赖的版本,还会分析我们项目的代码引入了哪些依赖,然后会去GOPATH下面把所以依赖都拷贝到我们项目的vendor目录下,这样我们项目依赖的包以及二级依赖的包都可以在vendor找到(golang的vendor机制你应该了解一下),完全不会再去GOPATH下寻找了。vendor可以直接上传到项目git里,下次go get项目就不会再去下载依赖了,因为都在vendor里可以找到。

安装client-go

1,找到一台墙外的服务器

因为我们要下载的client-go是托管在google的git仓库里的,所以go get的时候就会被墙。

解决方法有2种:

  • 你有一台美国的服务器,那么去服务器上go get之后再拷贝回来就好。
  • 使用shadowsocks+cow的组合,后者提供http协议代理并基于socks5协议转发给本机的1080端口(也就是ss),从而提供了http协议的翻墙,然后就可以配置git客户端走本机cow的http代理了。

大家自己克服吧!

2,创建一个空的gopath目录

比如,我建立了一个目录:

然后导出一下GOPATH:

现在进入这个目录。

3,安装godep包管理工具

执行:

生成的二进制程序在$GOPATH/bin目录下。

4,下载client-go

执行:

/后面紧接着…是啥意思?

go get在git clone下载了源码后,只会扫描第一级目录中的.go文件,并递归下载它们的依赖。

而client-go项目呢,在第一级目录下没有go文件,都放在子目录里了,所以…的意思就是递归扫描所有层级的目录中的.go文件,下载它们的依赖以及依赖的依赖,就这么个意思。

大家可以看一下client-go项目的外层目录是不是这样:https://github.com/kubernetes/client-go

5,godep恢复依赖

client-go项目使用godep保存了开发时的依赖,放在它的vendor目录下,大家可以去client-go目录下看一下vendor目录。

当我们的项目依赖client-go的时候,client-go则会在自己的vendor下找到自己的依赖,并不会往GOPATH中去查找。

client-go官方给了一点指导建议,就是担心出现这么一种情况:我们在GOPATH下面,下载了一个依赖库A,然而client-go的vendor中也有一个库A,恰好2个库A的版本还不一样。 这种情况下,非client-go包下面的代码就会编译GOPATH下面的A,而client-go包下面的代码会编译vendor下面的A,最后导致编译出的二进制存在问题。

解决方案,就是把client-go的vendor通过godep释放到GOPATH下面覆盖已有的库,这样client-go继续使用vendor中的依赖与其他库使用GOPATH中的依赖是没有区别的了,也就是打平了依赖。

所以我们进入client-go:

执行godep restore释放vendor目录到GOPATH下:

这里…的意思是所有子包的vendor都释放,但其实只有client-go目录有vendor,子目录并没有。

6,下载自己的项目

我们创建一个空的github项目,然后go get下来即可,比如我的项目是:github.com/owenliang/k8s-client-go。

我要在这个项目中使用client-go来访问k8s apiserver。

首先我把k8s master上面的/etc/kubernetes/admin.conf文件拷贝到项目下,里面包含了k8s集群的地址以及认证密钥,client-go就可以成功访问到apiserver了。

我们先实现InitClient方法,建立到K8s的连接,代码在https://github.com/owenliang/k8s-client-go/tree/master/common

然后建立一个demo1目录,写一段测试代码:

这段代码调用core/v1的API,获取了default命名空间下面的pods列表。

7,godep保存依赖

现在,我们要把自己的项目的依赖保存到vendor目录下,然后一起上传到github。

这样的话,以后要下载与编译我们的项目,只需要go get我们的项目即可,所有依赖都可以在vendor下找到,所以go get就不会递归去下载依赖了,也就不存在被墙的问题了。

进入我的项目:

然后执行:

这里…意思就是递归分析整个k8s-client-go项目的所有依赖,然后copy到当前目录的vendor目录中。

其实,只有我们引入的包才会被copy到vendors中,所以vendors目录并不大。

比如我们import了这个包:

实际上只有这个包被copy到vendor,而k8s.io/apimachinery中其他的包是没有copy进来的。

这也意味着,如果以后我们的项目Import了其他client-go的子包,得重新save一次提交到github才能保证是依赖完备的。

现在,我们把整个项目推到github保存,包括vendor目录以及Godeps目录,就是你看到的这个项目了:https://github.com/owenliang/k8s-client-go

8,验证项目

我们新建一个GOPATH目录,然后go get github.com/owenliang/k8s-client-go,应该可以顺利的完成下载,并不会再去墙外下载k8s依赖了,这是因为在k8s-client-go一级目录下没有任何.go文件,所以go get无法分析到任何依赖,如果用go get github.com/owenliang/k8s-client-go/…的话,它就会找到k8s的依赖去下载,还是会被墙,也就是说go get的时候vendor目录是不会被考虑的。

然后进入k8s-client-go目录,进入demo1直接go build就可以成功,因为k8s-client-go目录下有vendor,包含了所有项目依赖:

完结

后续会继续在这个项目下补充各种demo代码,欢迎star。

 

 

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~