前言

在上半年的这篇文章中,我们对公司的发版流程进行了优化,通过结合使用阿里云、华为云的免费镜像仓库和加速服务,在改造多架构镜像的同时,大大加快的镜像分发的速度。但是这也带来一个问题,由于镜像不再直接推送到公司的 Harbor 仓库,而是通过一个本地的 Harbor 仓库往三个仓库推送,所以开发看到 Jenkins 任务完成了并不能说明镜像已经到达了仓库,对于镜像何时入仓这个问题变得不再透明,今天我们就来解决这个问题

方法

大概思路有两种

一种是调用各个平台的 SDK ,看云上有什么镜像,想部署的时候去找一下要部署的最新版本的在这个仓库里面有没有,这个做起来比较麻烦,但是对有历史查询需求的就比较友好

另一种是从本地的 Harbor 仓库获取镜像的推送情况,再想办法告知给开发和实施人员

因为没有对历史镜像的查询的需求,并且想要通过“推送”的方式去主动告知开发和实施人员,从标题也能看出来,我们选择了方法二

实现

从 Harbor 里面拿推送数据,可以通过 Harbor 的 SDK 或者通过 WebHook ,在上次的文章中,我们就使用了 Harbor 的 Golang SDK,不过本次的需求就用 WebHook 轻松解决

打开 WebHook

在项目空间中,找到 WebHook 仅接受镜像复制状态改变事件,Endpoint 需要我们起一个 http 服务去接收,方法是 POST , payload 选择默认即可

image-20241123154529962

解析 WebHook 数据

WebHook 里面的数据大致长这样

{
"type": "REPLICATION",
"occur_at": 1732347103,
"operator": "admin",
"event_data": {
"replication": {
"harbor_hostname": "xxx.xxx.xxx.xxx",
"job_status": "Success",
"description": "阿里仓",
"artifact_type": "artifact",
"authentication_type": "basic",
"override_mode": true,
"trigger_type": "EVENT",
"execution_timestamp": 1732346947,
"src_resource": {
"registry_type": "harbor",
"endpoint": "http://xxx.xxx.xxx.xxx:xxx",
"namespace": "xxx"
},
"dest_resource": {
"registry_name": "Ali_ACR_yunzai",
"registry_type": "ali-acr",
"endpoint": "https://registry.cn-hangzhou.aliyuncs.com",
"namespace": "xxx"
},
"successful_artifact": [
{
"type": "artifact",
"status": "Success",
"name_tag": "mars-xxx-xxx [1 item(s) in total]",
"references": [
"sha256:xxx"
]
}
]
}
}
}

解析时需要注意以下问题:

  • job_status (任务结果) 不仅在成功或失败时触发,在任务开始时也会触发,需要过滤一下只推送成功或者失败的数据
  • 里面的 timestamp 是 UNIX 时间
  • description 里面的内容,需要去复制任务里面填写描述
  • name_tag 里面只会显示项目名称
  • references 里面不仅会有 tag ,也会有镜像的 sha256 两种形式,需要过滤一下,只推送版本信息,具体可以看下图

sha256 是构建镜像产物 (artifact) 哈希计算出来的,无论镜像是否打了 tag ,都会有 sha256 的 references

image-20241123155932970

企业微信推送

已经解析了数据,我们只需要推送给开发和实施的同学即可,根据公司 IM 的使用情况,选择了企业微信机器人

把相关的同学拉入群聊,然后添加一个机器人,务必注意保护里面的 key (也就是推送地址)

image-20241123161122486

官方没有提供 SDK ,第三方有 Golang 的 SDK ,但是因为只调一个企业微信机器人接口,我们根据文档快速写一个即可

群机器人配置说明 - 文档 - 企业微信开发者中心

推送的结果有多种模板,最开始我选择了好看的卡片模板,但是卡片模板过于花哨,占用地方过多并且不方便查看和搜索,最后还是改成了文字模板,最后的效果如下图

image-20241123161423886

附录

有类似开发需求的同学,这里提供 Harbor 的 WebHook 和 企业微信机器人 API 的 struct

企业微信机器人 API - 文字模板(MarkDown)

type EnterpriseWechatMarkDownWebHook struct {
Msgtype string `json:"msgtype"`
Markdown Markdown `json:"markdown"`
}
type Markdown struct {
Content string `json:"content"`
}

Harbor WebHook

type HarborWebHook struct {
Type string `json:"type"`
OccurAt int `json:"occur_at"`
Operator string `json:"operator"`
EventData struct {
Replication struct {
HarborHostname string `json:"harbor_hostname"`
JobStatus string `json:"job_status"`
Description string `json:"description"`
ArtifactType string `json:"artifact_type"`
AuthenticationType string `json:"authentication_type"`
OverrideMode bool `json:"override_mode"`
TriggerType string `json:"trigger_type"`
ExecutionTimestamp int `json:"execution_timestamp"`
SrcResource SrcResource `json:"src_resource"`
DestResource DestResource `json:"dest_resource"`
SuccessfulArtifact []SuccessfulArtifact `json:"successful_artifact"`
} `json:"replication"`
} `json:"event_data"`
}

type SrcResource struct {
RegistryType string `json:"registry_type"`
Endpoint string `json:"endpoint"`
Namespace string `json:"namespace"`
}

type DestResource struct {
RegistryName string `json:"registry_name"`
RegistryType string `json:"registry_type"`
Endpoint string `json:"endpoint"`
Namespace string `json:"namespace"`
}

type SuccessfulArtifact struct {
Type string `json:"type"`
Status string `json:"status"`
NameTag string `json:"name_tag"`
References []string `json:"references"`
}