目前团队使用argo-cd做为统一发布平台,承接所有的环境的发布,最近碰到一个很有意思的问题(下文描述),跟随这个问题引出另一个问题: argo-cd是如何绑定资源的呢?用了argo-cd这么久了,感叹自己从来都没细致研究过,呵呵了.
问题
简单描述就是,argo上的应用出现了本不属于它资源
这里使用kustomize,kustomization.yaml文件如下:
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
正常来说,发布到k8s中的资源对象,只会有resources下指定的,但是在某个时间点,argo ui上却出现了其它资源,状态是这样的
作者非常确定这个资源对象不包含在上述3个文件中,那这个对象是怎么来的呢?
排查
作者记得之前应该出现过一二次,但由于当时没有时间仔细排查,还以为是开发团队自己的原因,即没有深究,这次又出现,作者感到绝非偶然,是时候认真排查一下了
作者又想起,另一个组员跟我反映过,测试环境某个服务的NodePort好几次都莫名地被删除了,测试环境开发是没有权限做删除操作的,但也是作者小组内的同事删的,那又是怎么回事呢?
由于作者在发布某应用,使用的命令如下:
1 | argocd --prune |
其中 –prune会将当前集群中存在的但是在git上不存在的资源进行delete.
嗯,这二者有关系
从上面的图中来看,这个资源对象的名称非常符合作者对使用NodePort的统一命名规范,即应用的名字-nodeport,可以肯定的是,这个资源是组员为了开发的某个需求创建的,且是在rancher UI(一种开源的k8s集群管理平台)上进行创建的,这里要说明一下,rancher ui上支持直接对常用资源比如deployment,service等对象进行clone
跟同事确认了,这个资源也确实是这么创建的,那这个资源又是如何同步反应到argo上的呢?
因为在作者看来,argo只会关联kustomization.yaml中resource指定的资源,这个不速之客显然不属于
这就引入一个作者想错或者未细致地了解的问题: argo到底是根据什么绑定资源的呢?
带着这个疑问,开始找官方文档,作者从将argo-cd引入到生产环境之前,已经将argo-cd官方的文档翻了好几遍,好像没有映象有这方面的介绍,也确实没有找到相关文档
作者这里犯了个错误,没有第一时间检查clone资源有没有差异,而是直接从argo-cd上查找答案,导致将问题复杂化了.
作者从这个issue上找到了问题所在,然后再回头查看clone的资源,然后做了个实验确认事实即是如此
结论
由于argo controller是根据资源中的annotations里的key(argocd.argoproj.io/instance)来判定这个资源是不是属于某个app,在日常使用的过程,由于团队中使用的是rancher做为容器管理平台,rancher上提供了非常便利的对资源的clone手段,就会产生clone后的资源也会带上相同的annotations,但是在原app下的manifest并不包含这个资源,因此在app下就会出现这个资源且这个资源会被标注为require pruning
,那么在每次sync后,这个clone后的资源就会被删除, 这也就解释了为什么会出现NodePort会莫名其妙地被删了
那么解决也很简单,在clone时将annotations删除掉即可,这样argo-controller就不会将其绑定到某应用下.
误区
这个有个作者的误区,即作者以为argo-cd只会关联kustomization.yaml中resource指定的资源(这里以kustomize为例,argo-cd支持的其它的如helm原理也是如此),但具体如何关联,作者没有深究,也没有第一时间想到,argo-cd其实也是通过CRD controller机制实现