OneDev 自建 Git 服务和 CI/CD

介绍

今天介绍一个可以自建的开源 Git 服务 OneDev, 功能强大,资源占用少,国人 Java 开发。

  • 开箱即用的符号跳转、符号搜索
  • 全功能的 CI/CD,支持 GUI
  • 强大易用的 Commit/Issue/Build/Pull Request 查询语言
  • 代码标注和讨论
  • 更多功能特性看官网说明

目前不足是全英文,文档简洁,还不知道什么时候支持中文,也不算什么大事。另外小 Bug 多,不过作者修复神速。

部署安装

运行环境 k8s v1.21.5,容器运行时 containerd

安装方式直接参考官方文档 helm 装就完事,除了在 k8s 运行也可以直接 docker run 和裸机跑。
helm 安装完成会创建一个 onedevservice typeLoadBalancer,由于我使用 apisix ingress 所以直接改成 ClusterIP 然后外面再套负载均衡走流量。细节不展开了可以参考实践 Apache APISIX Ingress

符号跳转、搜索

支持 Java, JavaScript, C, C++, CSharp, Go, PHP, Python, CSS, SCSS, LESS and R 语言,IDE 级别的功能。
据作者说使用 ANTLR 分析主流语言的语法,并提取符号定义进行增量存储,速度快,占用空间小。

符号搜索
符号跳转

CI/CD

直接来体验下 CI/CD,测试项目依然是我的 wx-msg-push

先创建一个 yaml 配置文件,在 k8s 中 apply,这个是 onedev 在 k8s 中部署应用使用。

1
2
3
4
5
6
7
8
9
10
11
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: gitops-onedev
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "create"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "patch", "create"]

然后在 Administration -> Job Executors 中创建一个 Build 执行方式。类型可以选远程docker、远程shell、k8s。我这里还是选k8s,也可以指定运行节点,Cluster Role 写上刚才创建的 gitops-onedev,镜像仓库用哪写哪就可以,我这里是阿里云。
Job Executors

在项目配置中加上镜像仓库的账号信息。这里 ali-repo-auth 通过 echo -n "username:passwd" | base64 生成。
Job Secrets

然后在项目中点击 .onedev-buildspec.yml 进入 build 配置页面。
.onedev-buildspec.ym

Job

通过这个页面可以一步步配置 CI/CD。 可以设置触发参数、触发逻辑比如push branch或者push tag,可以设置从属关系、重试、超时、缓存等。
我这里 CI 阶段由 push tag 触发,具体分为四个 Step

  • checkout 代码检出
  • make 编译可执行文件
  • build & push 构建镜像推送
  • publish artifact 发布制品,各平台的可执行文件包

通过 View Source 可以看到实际生成的配置文件。
分享下我现在的配置文件,Job Executor 就是刚才创建的 Build 执行方式。

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
version: 16
jobs:
- name: ci
jobExecutor: k8s
steps:
- !CheckoutStep
name: checkout
cloneCredential: !DefaultCredential {}
withLfs: false
withSubmodules: true
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
- !CommandStep
name: make
runInContainer: true
image: zyh94946/golang:v1.18.3
interpreter: !ShellInterpreter
shell: sh
commands:
- make release
useTTY: false
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
- !CommandStep
name: build & push
runInContainer: true
image: zyh94946/kaniko:v1.8.1-debug
interpreter: !ShellInterpreter
shell: /busybox/sh
commands:
- echo "{\"auths\":{\"@secret:ali-repo-url@\":{\"auth\":\"@secret:ali-repo-auth@\"}}}"
> /kaniko/.docker/config.json
- /kaniko/executor --context "/onedev-build/workspace" --dockerfile "/onedev-build/workspace/Dockerfile"
--destination "@secret:ali-repo-url@/zyh94946/nico:wx-msg-push-@tag@"
useTTY: false
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
- !PublishArtifactStep
name: publish artifact
artifacts: '*.zip'
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
triggers:
- !TagCreateTrigger
tags: v*
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
timeout: 3600
- name: cd
jobExecutor: k8s
steps:
- !CheckoutStep
name: checkout
cloneCredential: !DefaultCredential {}
withLfs: false
withSubmodules: true
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
- !CommandStep
name: deploy
runInContainer: true
image: zyh94946/kubectl:v1.21.5
interpreter: !DefaultInterpreter
commands:
- 'echo "tag: @tag@"'
- 'if [ "@tag@" != "" ]; then '
- "\tsed -i \"s/#tag#/@tag@/g\" k8s.deployment.yaml"
- "\tkubectl apply -f k8s.deployment.yaml"
- fi;
useTTY: false
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
jobDependencies:
- jobName: ci
requireSuccessful: true
artifacts: '**'
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
timeout: 3600

由于 k8s 集群容器运行时采用 containerd 所以无法通过 docker 正常构建和推送。这里我通过 google 开源的容器工具 kaniko 构建和推送镜像。
该工具镜像地址为 gcr.io/kaniko-project/executor:debug,建议用 debug 版可以进入 shell,由于原镜像地址太慢自行下载后传到了 dockerhub 上 zyh94946/kaniko:v1.8.1-debug。使用方式也很简单,一条命令就完成构建和推送了,具体看上面的配置。

CD 部分只有两个 Step,代码检出和应用部署,部署中的镜像就是 CI 中创建的。CD 附属于 CI,当 CI 执行成功后手动触发 CD,当然也可以在 CI 完成后自动开始 CD 任务。
在 build 中可以看到日志

在流水线中可以看到当前执行的是哪一个

生成的制品

CD

关于版本回退,可以从 k8s 中执行 Roll Back,或者在 onedev 中单独执行一个指定 tag 的 CD 重新部署。

Roll Back

总结

以上就是在 onedev 中的 CI/CD 应用,通过编译可执行文件,构建镜像推送,最后用 kubectl 在 k8s 中部署。
其中通过 kubectl 部署应用,赋予了 onedev 对 k8s 的操作权限。另外还有一种方式采用 Argo CD 拉取配置来更新,onedev 只做 CI 的事,这样即使采用在 k8s 集群外的 git 服务也能有较好的安全性。