go mod 依赖管理的心路历程

在用kubebuilder写一个k8s operator defaultvm,主要是串起ovn网络和虚机的创建,为用户提供默认可用的虚机。

Kubebuilder 是一个基于 CRD 来构建 Kubernetes API 的框架,可以使用 CRD 来构建 API、Controller 和 Admission Webhook。

代码里面调用了 kubevirt.io/client-go 定义的 virtualmachine,使用go mod进行依赖管理,默认引用了 kubevirt.io/client-go v0.23.0,但在编译时就报错了,适中拉不到prometheus的包

go: github.com/prometheus/[email protected]+incompatible: unexpected status (https://goproxy.io/github.com/prometheus/prometheus/@v/v2.9.2+incompatible.info): 410 Gone

确认依赖问题

单独使用go mod download验证确实拉不到包。

[root@master01 queqiao]# go mod download github.com/prometheus/[email protected]+incompatible
go: finding github.com/prometheus/prometheus v2.9.2+incompatible
github.com/prometheus/[email protected]+incompatible: reading https://goproxy.io/github.com/prometheus/prometheus/@v/v2.9.2+incompatible.info: 410 Gone

google找到一种说法,因为国内墙的原因,只能使用export GOPROXY=https://goproxy.io && export GO111MODULE=on,然后goproxy.io缺少对[email protected]+incompatible的支持。可以将GOPROXY改成direct试试,export GOPROXY=direct,不过由于国内的fgw,改成direct后,就卡死了,只能放弃。

切低版本kubevirt

[email protected]+incompatible是kubevit的依赖,我们无法控制,我们只能控制kubevirt,从小伙伴哪儿的得知kubevit v0.19.0没有对prometheus v2.9.2+incompatible的依赖,

go mod edit -replace=kubevirt.io/[email protected]=kubevirt.io/[email protected]

使用go mod edit切换回kubevit v0.19.0,果然顺利编译通过了。不过可悲的是,调试运行一段时间后,触发了kubevirt新的bug,而这个bug在v0.23.0版本修复了

参考:https://github.com/kubevirt/k...

因此只能重新面对依赖这个问题

拉取kubevirt代码

为了不对kubevirt 依赖,我们决定直接抠出kubevirt 中对virtual machine这个cr的定义。这个方法确实行之有效,减去了对kubevirt的依赖,不过却造成了一系列我没预想到的包之间版本不匹配的问题

如:最开始遇到的报错

# k8s.io/client-go/rest
vendor/k8s.io/client-go/rest/request.go:598:31: not enough arguments in call to watch.NewStreamWatcher
    have (*versioned.Decoder)
    want (watch.Decoder, watch.Reporter)

go的依赖库都是用go mod进行自动管理的,没想到会有依赖库之间版本不匹配的问题。

匹配依赖库版本

既然go mod管理有问题,那只能从问题入手,人工匹配正确的依赖库版本。

参考: https://github.com/kubernetes...

That apimachinery change is in the master branch, and the call you linked to is updated in client-go on master.

The [email protected] tag works with the release-1.14 branch of apimachinery, which still has the signature that matches client-go v11.0.0:

https://github.com/kubernetes/apimachinery/blob/release-1.14/pkg/watch/streamwatcher.go#L51-L52

Ensure you are using the release-1.14 branch of apimachinery.

根据大佬的提示,使用release-1.14版本的apimachinery,

[root@master01 queqiao]# go mod download -json k8s.io/[email protected]
go: finding k8s.io/apimachinery release-1.14
go: finding k8s.io/apimachinery latest
{
    "Path": "k8s.io/apimachinery",
    "Version": "v0.0.0-20191004074956-c5d2f014d689",
    "Info": "/root/go/pkg/mod/cache/download/k8s.io/apimachinery/@v/v0.0.0-20191004074956-c5d2f014d689.info",
    "GoMod": "/root/go/pkg/mod/cache/download/k8s.io/apimachinery/@v/v0.0.0-20191004074956-c5d2f014d689.mod",
    "Zip": "/root/go/pkg/mod/cache/download/k8s.io/apimachinery/@v/v0.0.0-20191004074956-c5d2f014d689.zip",
    "Dir": "/root/go/pkg/mod/k8s.io/[email protected]",
    "Sum": "h1:q9CWH+mCm21qUeXH537D0Q9K1jdEkreNSRU5E7jh+QM=",
    "GoModSum": "h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0="
}

确实解决了之前的报错。但是依然有新的报错,排查是哪个依赖库调用的报错,然后采用类似的办法,切换到release-1.14,最终go.mod中手动配置的依赖库版本为:

replace (
    k8s.io/api => k8s.io/api v0.0.0-20191004102349-159aefb8556b
    k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191004105649-b14e3c49469a
    k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004074956-c5d2f014d689
    sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.3.0
)

最后提一下sigs.k8s.io/controller-runtime ,查看了它的所有版本,然后一次次尝试,才发现v0.3.0可以编译通过。

感慨

这个依赖库问题花了我近两天的时间,期间搜了很多方法,踩了很多的坑,远比文中描述的糟心。正因为糟心,才写下来,一方面加深自己的体会,另一方面,以希望能够帮助到同样遇到这个问题的小伙伴。

in the peace

你可能感兴趣的:(golang,k8s,kubernetes)