Z.S.K.'s Records

ArgoCD学习(argoCD之ResourceCheck及Notifications机制)

在之前一篇体验一把使用argocd对多k8s集群进行gitops的实践,在团队使用过程中会发现,argocd的sync状态跟app health状态是两个步骤,经常出现资源同步成功了但是deployment在k8s一起起不来,在argocd app status 一直都是Processing,如何处理这种情况呢? argocd如何做 resource check,有没有必要引用notification机制

Resource Check

argocd官网文档: health

首先解决一下比较常见的 app的状态一直是Processing

这里就要区别说一下argocd的两个命令:

1
2
3
4
5
6
7
8
9
# 1. argocd app sync 
# app sync只是用于对资源进行同步,也就是说,将git上的资源同步到argocd -- k8s, 一般情况下只要跟集群的连接、权限没有问题,sync一般都会成功,但是这个命令并不会验证资源运行能不能work,因此无法根据这个状态来判断整个pipeline是否成功
# 可以指定超时 --timeout, 单位: 秒

# 2. argocd app wait --health --timeout
# app wait 则是等待资源达到某种状态, 这个是整个app的状态
# --health 表示等待整个app达到health的状态,health状态表示所有同步的资源都运行成功
# --timeout表示超时,如果超过这个时间,app还没有达到health状态,则表示失败
# 比如deployment一直重启,则过了timeout时间后,argocd会发现app未是health状态,则可以让整个pipeline会失败

作者最开始时,只使用app sync,这就忽略了对整个app的health状态的判断,因此会出现CI/CD所有stage都成功了,但是pod一直处于重启状态

为解决这个问题,比较简单一点的做法就是在app sync后使用app wait --health --timeout来对check app health,如果不成功,则pipeline exit 1,这样可以在CI/CD阶段就暴露资源异常问题

但这也有明显的缺点: 如果资源异常,则必须要等timeout时间之后才能发现,这个问题则可以结合k8s集群的监控发现,还能接受.

从官网的文档来,argocd本身提供了对k8s中的常用资源对象的健康检查,比如对于deployment,argocd详细地说明了如何判断其达到health状态的.

同时,也提供了自定义的检查机制,有2种形式,本人看了一下,第一种使用LUA语言写的,也就几行代码,倒也不难,作者没有采用,原因首先现在的业务大部分都是k8s常用资源对象,argocd本身支持度非常高,不需要

第二种则需要以特殊的目录结构来组织,作者也没有采用,实在是在开发端维护这些跟业务无法的文件,会引起复杂性.

取舍作者最后还是采用 app wait的方式,这还有一个好处是,不需要做额外的工作就可以将通知精准地发送给对应的enduser,比如gitlab本身的ci/cd,如果整个pipeline的失败会直接给发起pipeline的人发送邮件

notifications

这里还是需要分析一下argocd里的通知机制, argocd本身不提供notification,要依赖第三方提供的机制, 参考notifications

resource hook

resource hook是argocd本身提供的功能,简单来说,就是在资源同步前,中,后提供hoo脚本来执行相应的动作, 那么想在资源同步后获取app的状态,然后根据状态进行通知就非常简单了,通知可以是很简单的curl命令

1
2
3
4
PreSync: 在同步之前执行相关操作,这个一般用于比如数据库操作等
Sync: 同步时执行相关操作,主要用于复杂应用的编排
PostSync: 同步之后且app状态为health执行相关操作
SyncFail: 同步失败后执行相关操作,同步失败一般不常见

用的最多的就是PostSync,用来获取app是否成功启动,hook一般是放在job中执行,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: batch/v1
kind: Job
metadata:
generateName: app-slack-notification-
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: slack-notification
image: curlimages/curl
command:
- "curl"
- "-X"
- "POST"
- "--data-urlencode"
- "payload={\"channel\": \"#somechannel\", \"username\": \"hello\", \"text\": \"App Sync succeeded\", \"icon_emoji\": \":ghost:\"}"
- "https://hooks.slack.com/services/..."
restartPolicy: Never
backoffLimit: 2

这个job比较容易理解,就是sync同步成功且app状态为health后发送一个slack消息

结合业务来说, 作者并没有采用这种方法来发送通知,原因如下:

  1. 对于PostSync可以发送成功的通知,但对于状态为Processing的无法判断
  2. 存量的业务都需要将这个job加入到git中,最大的考量在于,通知还是没有办法做到谁执行的pipeline,谁接收通知的原则,比如上面的通知收件人,没有办法很好地更细粒度地指定,要么指定一个组,大家都收,要么指定一个人,但是模块都是多人开发,只发给一个人不合适

argocd-notifications

argocd-notification是argocd自家开发的通知系统,也是argocd推荐之一

Argocd-notifications v1.0之前的版本与v1.0+版本有很大的不一样,建议大家认真阅读update

安装很简单,就一条命令

1
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/stable/manifests/install.yaml

起来之后就一个controller应用,这里以邮件为例

首先,配置一下邮箱

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Secret
metadata:
name: argocd-notifications-secret
namespace: argocd
stringData:
service.email: |
host: smtp.xxx.com
port: 587
from: xxx
username: xxx
password: xxx
type: Opaque

然后添加相应状态通知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
# email的参数可以来自上面的secret
service.email: |
host: smtp.gmail.com
port: 587
from: <myemail>@gmail.com
username: $email-username
password: $email-password

# 触发条件
trigger.on-sync-status-unknown: |
- when: app.status.sync.status == 'Unknown' # 指定条件
send: [my-custom-template] # 指定模板

# 发送模板
template.my-custom-template: |
title: <argocd> Sync Application {{.app.metadata.name}} Status {{.app.status.health.status}}.
body: |
App Name: {{.app.metadata.name}}
Cluster Name: {{.context.clusterName}}
Sync Status: {{.app.status.health.status}}
Following Error: {{.app.status.operationState.message}}
Repo URL: {{.repo.FullNameByRepoURL}}
Commit Msg: {{.repo.GetCommitMetadata}}

# 订阅者
subscriptions: |
- recipients:
- email:[email protected]
triggers:
- on-sync-status-unknown

如上面的配置,用于监控argocd同步状态为 Unknown的情况,发送邮件告警

当然, 在argocd部署应用的时候,也可以添加订阅者,直接在annotations中添加即可

1
notifications.argoproj.io/subscribe.on-app-synched.eamil: [email protected]

argocd-notification每隔一分钟就会扫描所有argocd app,感觉还是比较频繁,如果应用一多的话,不知道是不是影响性能,这个时间目前不支持通过参数覆盖,如果需要调整只能修改源码后重新编译

作者最后也没有采用这种形式,原因在于argocd-notification还是用于监控argocd 的sync状态,并不关心app 是否health

argo-kube-notifier

最后argocd也推荐使用argo-kube-notifier,但感觉这个跟argocd本身就没多大关系了,完且是发布后的health check,这个主要用于k8s集群应用状态的check,实现这个目的的组件很多,而且argo-kube-notifier还是没办法实现谁执行的pipeline,谁接收通知的原则

综上,还是直接使用argo app wait简单粗暴,加两行代码,贴合需求

参考文章:

转载请注明出处https://izsk.me

Z.S.K. wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?