背景
我们的项目是一个基于Kubernetes的云原生项目,会使用到Kubernets的一些组件和依赖。我们的项目是一个基于Kubernetes
的云原生项目,会使用到Kubernets
的一些组件和依赖。
最开始的项目依赖大概是这样的:
Code Block | ||
---|---|---|
| ||
require ( git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef github.com/ClickHouse/clickhouse-go v1.4.8 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0 github.com/gogf/gf/v2 v2.1.4 github.com/golang/mock v1.4.3 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/json-iterator/go v1.1.10 github.com/modern-go/reflect2 v1.0.1 github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.7.0 github.com/smartystreets/assertions v1.0.1 github.com/smartystreets/goconvey v1.6.4 github.com/spf13/cobra v1.1.3 github.com/tencentyun/cos-go-sdk-v5 v0.7.35 github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible go.opentelemetry.io/otel v1.7.0 go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92 google.golang.org/grpc v1.33.1 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.19.8 k8s.io/apimachinery v0.19.8 k8s.io/client-go v11.0.0+incompatible ) replace ( google.golang.org/grpc => google.golang.org/grpc v1.29.1 k8s.io/api => k8s.io/api v0.19.6 k8s.io/apimachinery => k8s.io/apimachinery v0.19.6 k8s.io/client-go => k8s.io/client-go v0.19.6 ) |
引入ArgoWorkflow服务依赖
随着项目的发展,业务上需要流程编排服务。当然作为大自然的代码搬运师,我们从github
上找到了适合的、贴合我们云原生理念的ArgoWorkflow
服务。它作为独立的服务运行,我们只需要在当前的项目中依赖其SDK即可,但是在依赖SDK的过程中出现了组件冲突。先看看我们有问题的项目依赖:
Code Block | ||
---|---|---|
| ||
require ( git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef github.com/ClickHouse/clickhouse-go v1.4.8 github.com/HdrHistogram/hdrhistogram-go v1.1.2 github.com/argoproj/argo-workflows/v3 v3.1.5 github.com/argoproj/pkg v0.9.1 github.com/aws/aws-sdk-go v1.33.16 github.com/clbanning/mxj/v2 v2.5.6 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/go-resty/resty/v2 v2.7.0 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0 github.com/gogf/gf/v2 v2.1.4 github.com/golang/mock v1.4.3 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/json-iterator/go v1.1.10 github.com/mattn/go-colorable v0.1.12 // indirect github.com/modern-go/reflect2 v1.0.1 github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.7.0 github.com/smartystreets/assertions v1.0.1 github.com/smartystreets/goconvey v1.6.4 github.com/spf13/cobra v1.1.3 github.com/tencentyun/cos-go-sdk-v5 v0.7.35 github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible go.opentelemetry.io/otel v1.7.0 go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92 google.golang.org/grpc v1.33.1 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.19.8 k8s.io/apimachinery v0.19.8 k8s.io/client-go v11.0.0+incompatible k8s.io/component-base v0.19.6 sigs.k8s.io/yaml v1.2.0 ) replace ( google.golang.org/grpc => google.golang.org/grpc v1.29.1 k8s.io/api => k8s.io/api v0.19.6 k8s.io/apimachinery => k8s.io/apimachinery v0.19.6 k8s.io/client-go => k8s.io/client-go v0.19.6 k8s.io/code-generator => k8s.io/code-generator v0.19.6 k8s.io/component-base => k8s.io/component-base v0.19.6 ) |
执行 go mod tidy
没有问题,但是编译的时候会报以下错误:
看起来像是第三方组件版本不兼容问题引起。当项目依赖很多第三方组件的时候,如果不同的第三方组件依赖到同一个组件A
并且版本不同时(如1
和2
),Golang
的版本管理机制将会使用其中高版本(版本2
)的组件A
来执行构建。当组件A
的不同版本之间存在兼容问题时(版本1
和2
不兼容),那么依赖低版本(版本1
)的第三方组件构建将会出问题。
这个问题在Golang
中比较常见,特别是在依赖的第三方组件越多时,这种风险将会变大。
其中kubernetes
经过了一系列版本依赖分析,我们找到了这些依赖中共同依赖的组件A
:klog
。因此我们通过加了一个replace
来workaround
该问题:强制将klog
的版本升级到v2.60.0
。
Code Block | ||
---|---|---|
| ||
replace (
k8s.io/klog/v2 => k8s.io/klog/v2 v2.60.0
) |
这个问题看似告一段落。有的时候,忽然项目经过一系列莫名其妙的操作还能够走狗屎运跑起来,就可以先不管了快乐撸码,不是吗?
引入ArgoCD服务依赖
随着项目的发展,我们又需要一个CD
服务,所以我们引入了ArgoCD
服务,当然这个时候我们又要引入ArgoCD
的SDK
,于是又开始遇到第三方组件各种版本兼容问题。我们的同学经过几天的摸索,搞出来以下组件依赖和replace
版本替换:
Code Block | ||
---|---|---|
| ||
require ( git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef git.woa.com/maxqzhu/argocd-sdk v0.0.0-20220919094321-a21a39049255 github.com/ClickHouse/clickhouse-go v1.4.8 github.com/HdrHistogram/hdrhistogram-go v1.1.2 github.com/argoproj/argo-cd/v2 v2.0.4 github.com/argoproj/argo-workflows/v3 v3.1.5 github.com/argoproj/pkg v0.9.1 github.com/aws/aws-sdk-go v1.33.16 github.com/clbanning/mxj/v2 v2.5.6 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-git/go-billy/v5 v5.3.1 github.com/go-git/go-git/v5 v5.4.2 github.com/go-resty/resty/v2 v2.7.0 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0 github.com/gogf/gf/v2 v2.1.4 github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang/mock v1.4.4 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/json-iterator/go v1.1.10 github.com/mattn/go-colorable v0.1.12 // indirect github.com/modern-go/reflect2 v1.0.1 github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.7.0 github.com/smartystreets/assertions v1.0.1 github.com/smartystreets/goconvey v1.6.4 github.com/spf13/cobra v1.1.3 github.com/stretchr/testify v1.7.1 github.com/tencentyun/cos-go-sdk-v5 v0.7.38 github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible go.opentelemetry.io/otel v1.7.0 go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92 google.golang.org/grpc v1.33.1 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.20.4 k8s.io/apimachinery v0.21.1 k8s.io/client-go v11.0.1-0.20190816222228-6d55c1b1f1ca+incompatible k8s.io/component-base v0.20.4 sigs.k8s.io/yaml v1.2.0 ) replace ( google.golang.org/grpc => google.golang.org/grpc v1.29.1 k8s.io/klog/v2 => k8s.io/klog/v2 v2.60.0 ) replace ( github.com/argoproj/gitops-engine => github.com/argoproj/gitops-engine v0.2.2 k8s.io/api => k8s.io/api v0.19.6 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.19.6 k8s.io/apimachinery => k8s.io/apimachinery v0.19.6 k8s.io/apiserver => k8s.io/apiserver v0.19.6 k8s.io/cli-runtime => k8s.io/cli-runtime v0.19.6 k8s.io/client-go => k8s.io/client-go v0.19.6 k8s.io/cloud-provider => k8s.io/cloud-provider v0.19.6 k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.19.6 k8s.io/code-generator => k8s.io/code-generator v0.19.6 k8s.io/component-base => k8s.io/component-base v0.19.6 k8s.io/component-helpers => k8s.io/component-helpers v0.19.6 k8s.io/controller-manager => k8s.io/controller-manager v0.19.6 k8s.io/cri-api => k8s.io/cri-api v0.19.6 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.19.6 k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.19.6 k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.19.6 k8s.io/kube-proxy => k8s.io/kube-proxy v0.19.6 k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.19.6 k8s.io/kubectl => k8s.io/kubectl v0.19.6 k8s.io/kubelet => k8s.io/kubelet v0.19.6 k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.19.6 k8s.io/metrics => k8s.io/metrics v0.19.6 k8s.io/mount-utils => k8s.io/mount-utils v0.19.6 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.19.6 ) |
引入ArgoWorkflow服务依赖
可当执行编译的时候,报错依旧,老泪纵横:
当同学都准备放弃,开始采用骚操作来WorkAround
的时候。秉着坑踩得越多,责任也就越大。我来看看吧,毕竟这个项目还要长久维护的。
这个问题看起来是由两个组件的版本不兼容引起的,处理起来会更棘手一些。
……
此处省略一万字。
……
经过一系列复杂的版本分析、依赖分析、兼容分析,对于此次版本冲突问题,加了以下replace
语句来解决:
Code Block | ||
---|---|---|
| ||
replace (
github.com/argoproj/argo-cd/v2 => github.com/argoproj/argo-cd/v2 v2.0.1
github.com/bombsimon/logrusr => github.com/gqcn/logrusr v1.3.0
github.com/go-openapi/spec => github.com/go-openapi/spec v0.17.0
sigs.k8s.io/kustomize/v2 => sigs.k8s.io/kustomize/v2 v2.1.0
) |
没想到的是居然有4
个组件的版本冲突。其中大家应该注意到一个组件 github.com/gqcn/logrusr
,这个组件是我从 github.com/bombsimon/logrusr
项目fork
的一份,升级了内部依赖的 github.com/go-logr/logr
组件版本到当前项目整体依赖比较适中的版本v1.2.3
,即将整体的冲突的版本通过强制升级的方式来解决。在执行强制升级的时候,组件之间依赖的接口和方法兼容非常重要,不是简单升级版本那么简单。此外,虽然本次组件版本冲突不得不维护一个自定义的组件仓库,但维护一个基本不变的组件比维护一个可能变化的组件成本和风险会更小一些。随着项目的发展,业务上需要流程编排服务。当然作为大自然的代码搬运师,我们从github上找到了适合的贴合我们云原生理念的ArgoWorkflow服务,作为独立的服务运行,我们只需要在当前的项目中依赖其SDK即可