简述
官方文档 https://docs.gitea.cn/
源码仓库 https://github.com/go-gitea/gitea
这个项目最开始是 fork gogs 的,看资讯说是 gogs 的作者控制欲太强, 很多功能和社区期望功能都不愿意加入进来,于是才有的分支。
目前看起来 gitea 的发展得更好,因为大家确实需要一个私有的 github, 而 gitlib 又太重量级了。
功能
核心的代码管理方面相关功能都有,如工单、软件包注册中心,Wiki、钩子等。
硬件需求很低, 1G 内存的主机就够了。
安装方式
支持 二进制部署, docker 部署, k8s 部署, 基本各平台都支持。
详细的这里就不介绍了,看官方文档就行,下面只是简单的介绍一下
基本过程如下
- 提前一个数据库和用户帐号, 如 mysql, pg
- 使用 docker 或 k8s yml 文件进行部署
docker-compose 方式
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
80
81
82
|
version: "3"
services:
gitea:
# 镜像提前从 docker hub 下载好了, 上传到的私有仓库
image: registry.services.wait/cwx/gitea:1.18.5
restart: always
environment:
# 自定义运行用户id, 如果是数据卷和新装,就没有必要指定;
# 因为以前是 bind 挂载所以文件已经有了属主, 所以这里指定只是为了兼容
- USER_UID=1000
- USER_GID=1000
# 指定数据库类型和帐号密码
- DB_TYPE=mysql
- DB_HOST=10.2.1.5:3306
- DB_NAME=gitea
- DB_USER=gitea
- DB_PASSWD=passw0rd
# 随便取一个应用名字
- APP_NAME=WaitCode
- RUN_MODE=prod
# 项目主域,和后续页面上看到的 http 项目地址有关系
- DOMAIN=git.services.wait
# 和 ssh clone 时页面看到的地址有关系
- SSH_DOMAIN=git.services.wait
# 如果 ssh 使用 22 端口的话,需要宿主机让出22端口或配置 ssh透传
# 这里简单使用就避开端口就行
- SSH_PORT=10022
# 禁止用户注册
- DISABLE_REGISTRATION=true
# 需要登陆才能查看项目
- REQUIRE_SIGNIN_VIEW=true
# 最终实际的 http 服务地址
- ROOT_URL=https://git.services.wait/
# 离线模式, 也就不会用到一些 cdn 或外部的 js 文件等
- OFFLINE_MODE=true
volumes:
- gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
# 挂了一个私有CA证书, 因为有向外的 webhook https 请求
- ./config/cwxCA.pem:/etc/ssl/certs/cwxCA.pem:ro
ports:
- "3000:3000"
# - "10022:10022"
depends_on:
- mysql
labels:
- "service_name=gitea"
# 我之前采用的 traefik 做的统一网关, 如果不需要则直接将这一段删除, 并修改一下 ports
- "traefik.enable=true"
- "traefik.http.routers.giteaHttps.entrypoints=https"
- "traefik.http.routers.giteaHttps.service=giteaWeb"
- "traefik.http.routers.giteaHttps.rule=Host(`git.services.wait`)"
- "traefik.http.routers.giteaHttps.tls=true"
- "traefik.http.services.giteaWeb.loadbalancer.server.port=3000"
- "traefik.tcp.routers.giteaSSH.entrypoints=port10022"
- "traefik.tcp.routers.giteaSSH.service=giteaSSH"
- "traefik.tcp.routers.giteaSSH.rule=HostSNI(`*`)"
- "traefik.tcp.services.giteaSSH.loadbalancer.server.port=10022"
logging:
options:
labels: "service_name"
volumes:
gitea:
external: true
|
说明,因为数据持久化用的外部命名卷, 所以这里提前创建一下
docker volume create gitea
docker-compose up -d
k8s helm
1
2
|
helm repo add gitea <https://dl.gitea.io/charts/> \
helm pull gitea/gitea --untar
|
下载下来后修改一下 values 文件的相关配置在安装
方法二: 资源文件方式安装
-
准备 pv 和 pvc 文件, 持久化存储, 我的 pvc 名字是 pvc-nfs-gitea
-
statefulset 方式部署
-
初始配置, 因为需要前置的几个配置也比较少, 所以没有准备 configmap, 直接用的环境变量;
还有个原因, gitea 会将中途修改的内容持久化到 配置文件中, 而配置文件又在卷路径下;
所以最好还是不使用 configmap 来管理初始化配置
-
services 采用的 traefik 的 IngressRoute IngressRouteTCP 方式进行的暴露
k8s 自定义资源文件
statefulset.yml
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
80
81
82
83
84
85
86
87
88
89
|
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: gitea
namespace: cwx
spec:
selector:
matchLabels:
app: gitea
serviceName: gitea
replicas: 1
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea
image: registry.services.wait/cwx/gitea:1.20.2
env:
- name: USER_UID
value: "1000"
- name: USER_GID
value: "1000"
- name: DB_TYPE
value: mysql
- name: DB_HOST
value: wcn7:3306
- name: DB_NAME
value: gitea
- name: DB_USER
value: gitea
- name: DB_PASSWD
value: passw0rd
- name: APP_NAME
value: WaitCode
- name: RUN_MODE
value: prod
- name: DOMAIN
value: git.services.wait
- name: SSH_DOMAIN
value: git.services.wait
- name: SSH_PORT
value: "10022"
- name: SSH_LISTEN_PORT
value: "10022"
- name: DISABLE_REGISTRATION
value: "true"
- name: REQUIRE_SIGNIN_VIEW
value: "true"
- name: ROOT_URL
value: https://git.services.wait/
- name: OFFLINE_MODE
value: "true"
volumeMounts:
- name: data
mountPath: /data
- name: timezone
mountPath: /etc/timezone
readOnly: true
- name: localtime
mountPath: /etc/localtime
readOnly: true
- name: ca
mountPath: /etc/ssl/certs/cwxCA.pem
subPath: cwxCA.pem
readOnly: true
resources:
limits:
cpu: "200m"
memory: "300Mi"
ports:
- containerPort: 3000
name: web
- containerPort: 10022
name: ssh
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-nfs-gitea
- name: timezone
hostPath:
path: /etc/timezone
- name: localtime
hostPath:
path: /etc/localtime
- name: ca
secret:
secretName: cwx-ca-pem
|
service.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: v1
kind: Service
metadata:
name: gitea
namespace: cwx
spec:
selector:
app: gitea
clusterIP: None
ports:
- port: 80
name: web
targetPort: 3000
- port: 22
name: ssh
targetPort: 10022
|
IngressRoute.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: giteaweb
namespace: cwx
annotations:
kubernetes.io/ingress.class: "traefik-class"
spec:
entryPoints:
- https
routes:
- match: Host(`git.services.wait`)
kind: Rule
services:
- name: gitea
namespace: cwx
port: 80
tls:
secretName: key-services-wait
|
ingressRouteTcp.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: giteassh
namespace: cwx
annotations:
kubernetes.io/ingress.class: "traefik-class"
spec:
entryPoints:
- giteassh
routes:
- match: HostSNI(`*`)
services:
- name: gitea
port: 22
namespace: cwx
|
部署完成后事项
-
使用自己配置的域名地址进行访问
https://git.services.wait/
-
第一个用户是超级管理员
-
然后就是正常的使用了
gitea-runner
优点:
- 一套系统完成开发过程中的主要功能, 不需要在多个系统之间切换
- 基本兼容 github actions, 生态友好
- 支持docker和NodeJs 类型的 actions 插件, 上手很容易
- 基本是中小型私有化场景部署的首选了
缺点:
- 太新, 今年初才发布;
- 更新慢, 感觉开发团队进展得很慢,团队资源不足的样子;
- 因为是兼容 github,所以使用过程中需要注意很多地方默认都是 github, 需要手动指定。
- 最大的缺点: k8s 不友好, 目前只支持 docker
文档(只能看github的):
https://docs.github.com/zh/actions/guides
原理
- runner 启动后注册到 gitea 等待 webhook
- 触发事件后拉取代码进行打包发布等操作
runner 自身
只负责和 gitea 通信和 actions 的调度
可以是二进制启动, 也可以是 docker 容器启动 runner
基础的运行环境
因为大部分或者说是官方主要 actions 的插件都是 nodeJs 开发的,
所以需要一个 nodejs 的运行环境,这个和 runner 是独立开的;
runner 只负责以容器的方式启动 一个 nodejs 环境, 然后所有的 js 类型的插件都在这个环境里面运行
如果插件类型是 docker, 则这个 docker action 是在 nodejs 环境运行的;
有几种层级关系
- runner
- runner – nodejsEnv(docker) – js actions
- runner – nodejsEnv(docker) – docker actions(docker)
- runner(docker) – nodejsEnv(docker) – docker actions(docker)
涉及到docker镜像
gitea/act_runner:0.2.5
也就是一个docker 的 runner 运行器, 内部除了附加一个 git 外没有别的工具
node:16-bullseye
一个默认的 nodejs 的运行环境, 内部有一些少量的工具支持
如 node npm python gcc 等, 但主要是为了运行 js 类型的 actions
也支持 docker 命令, 目的是运行 docker 类型的 actions
ghcr.io/catthehacker/ubuntu:act-22.04
一个第三方的 actions 运行环境, 参考 github 的
优点是命令和工具带得非常多, 很多时候不需要外部 action 而直接使用 run 执行 shell 命令就可以了
关于自定义action
使用CICD绕不过去的内容就是自定义插件;
github 支持2种插件形式
- js 类型的插件, 由运行环境上的 nodejs 直接运行
- docker 类型的插件, 由运行环境上的 docker 命令运行,会创建一个新的容器
个人 对 js 不大熟悉, 所以还是推荐 docker actions
这里的要点
1
2
3
4
5
|
- name: actions 的使用格式
uses: actions/xxxx1:v1
uses: actions/xxxx1@master
uses: https://xxxxx/actions/xxxx1@master
uses: docker://registry.services.wait/cwx/xxxx1:v1
|
uses 默认会去 github 上拉取仓库代码, 然后根据里面的 action.yml 文件判断这是一个 js 还是 docker 类型的插件。
如果是 js 类型的, 一般就需要执行 npm 先编译插件自身, 然后再执行插件;
如果是 docker 类型的, 就会按照 提供的 Dockerfile 来创建一个新的 docker 镜像, 并且执行这个镜像;
因为编译镜像是有缓存的, 所以后续再使用到这个docker镜像, 是不需要重新打包镜像的;
如果是不想去仓库拉取插件的代码, 而是使用已有镜像可以采用这种格式;
uses: docker://registry.services.wait/cwx/xxxx1:v1
镜像插件的参数传递
当需要在 yml 文件内把一个参数传递到 运行的 action 镜像内时, 可以如下
1
2
3
4
5
|
- name: actions 的使用格式
uses: actions/xxxx1:v1
with:
cmd1: zzzz1
cmd2: zzzz2
|
with 下面的 key, 会被以环境变量的方式传递到镜像内;
镜像内直接获取对应的环境变量即可获取到值, 但是需要加 INPUT 前缀,如
cmd1=${INPUT_CMD1}
cmd2=${INPUT_CMD2}
输出也是相同道理, 只不过需要定义 OUTPUT 来使用
状态截图


离线actions使用
github-actions 在国内环境不太好用;
私有化环境一般使用 gitea, 搭配 act_runner 来使用, 兼容 github-actions;
离线环境如何使用呢?
尝试过的方案
AI 给出过一些错误的案例, 经验证没有成功
- uses: /local/actions/checkout@v6 本地路径方式,实际是错误的
- 各自 env 方式映射到本地路径,验证无效
- 拷贝 $HOME/.cache/act 缓存的方式, 验证了一半没有成功,理论上应该是可以的;
- 将 github 的相关actiions镜像到本地仓库, 可行;但是不能这样做
- 要镜像太多库,麻烦
- 如果放在本地, 这个库必须是要能免认证就可见的, 企业场景不允许
- 如果单独在拉取时附带一个token, 则语法上就不好看, 就不兼容外网版本的workflows;
gitea使用 actions 的事项
- 默认会去 github 下载
- 可以使用
https://xxx.com/actions/checkout@v6 的方式指定库
- 如果开启 DEFAULT_ACTIONS_URL = self 配置, 则在无域名路径时, 默认去当前的git仓库下载actions
- 除非使用 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd 哈希的方式, 否则每次都需要联网确认tag或分支的具体的hash
最终方案
还是在底层解决,网络代理的方式
1
2
3
4
5
6
7
|
# 允许 act_runner 时附加代理
# 可以连接局域网内的可访问github的socket5相关端口
# 注意一定要使用 NO_PROXY 排除掉自身域名
export HTTPS_PROXY=http://127.0.0.1:1081
export HTTP_PROXY=http://127.0.0.1:1081
export ALL_PROXY=socks5://127.0.0.1:1080
export NO_PROXY=localhost,192.168.5.0/24,127.0.0.0/8,services.wait
|
如果后续要完全离线使用, 则将相关的 workflows 都运行一次,当 actions 下载过一次后,后续就不需要再连github, 也不需要再配置代理了,当然actions版本的位置必须使用 hash 才行;
如果跨网络目标主机不能访问代理时,可以通过 ssh 反向代理到本地
1
2
|
# socket5 反向隧道
ssh -R 1080 -N -f ubuntu@192.168.5.110 -i id_ed25519
|
完全离线场景, 且不能使用代理时
从已经有的主机上拷贝 $HOME/.cache/act 缓存, 必须配合 uses: actions/checkout@de0facxxxxx 的方式使用。
gitea-runner 部署当前站点
当前站点正在使用的一套的集成流程
本站点历史发布模式
早期的脚本模式
- 本地编写好 MD 文件
- 执行 hugo 命令, 构建 WEB静态文件
- scp 传输到目标主机上
将上述流程脚本化
前期-drone
前期采用 drone 进行的自动化编译和部署,参考另一篇单独介绍的文章。
drone无人机-当前站点的发布实践
当前-gitea-runner
我又又又又决定再学一学 ts 了,没办法,搞这个 action 始终绕不过去 js 这一套东西, 虽然单纯的只用 docker 也不是不可以。但是很多既有的 action 也就没法用了。会点 js 至少还能拿来改一改吧。
实际工作流文件
真私有化部署, 不涉及 github 的访问;
流程中存在的问题
- 没有使用 js 类型的 action,太可惜了,后面得补一补
- 拉取代码,拉取镜像,配置环境实现得都不太优雅
.gitea/workflows/work.yml
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
|
# 工作流的名字
name: myblog-dev
on:
push:
branches: [ main ]
jobs:
# 任务名
hugo-task:
# 选择所运行的平台, 也就是哪个类型的 runner
runs-on: ubuntu-latest
# 运行 action 的环境
container:
# 不使用默认的 node:16 的基础容器镜像, 使用支持docker命令的act镜像
image: registry.services.wait/cwx/catthehacker/ubuntu:act-22.04
# volumes:
steps:
# 配置私有 CA 证书
- name: set ca
# 注意这个位置单独拉出来配置, 是因为多行字符串会被解析为多行命令导致, 算是个 bug
run: echo -e "${{ secrets.CWX_CA_PEM }}" >> /usr/local/share/ca-certificates/cwx.crt
# 配置一下后续运行的基础环境
- name: Set run env
run: |
update-ca-certificates
# git config --global http.sslVerify false
git config --global http.sslCAInfo /usr/local/share/ca-certificates/cwx.crt
git --version
# 克隆代码, 包括一份主题模板
- name: clone code
run: |
git clone https://chenwx:${{secrets.CHENWX_TOKEN}}@git.services.wait/chenwx/myblog.git .
git clone https://chenwx:${{secrets.CHENWX_TOKEN}}@git.services.wait/chenwx/hugo-theme-stack.git themes/hugo-theme-stack
# 登陆仓库和拉取后面需要的 docker 镜像, 其实应该合并的 set env 里面去; 调试暂留
# 目前存在个问题, 这个 镜像应该是不需要单独拉取一次的, 但报了认证错误
# 应该是这里配置 login 时所发生的层和 实际 pull 时的层不一样导致, 后面找时间调试一下再修改。
- name: login registry
run: |
echo "${{ secrets.HARBOR_PW }}" | docker login -u "${{ secrets.HARBOR_USER }}" --password-stdin registry.services.wait
docker pull registry.services.wait/cwx/actions-hugo:ubuntu-v0.118
docker pull registry.services.wait/cwx/ssh-scp-action:v1
# 这个镜像只是单纯的将 hugo 命令打包了,并配置 ENTRYPOINT ["hugo"]
- name: 编译-build
uses: docker://registry.services.wait/cwx/actions-hugo:ubuntu-v0.118
# 占个位置,看看有没有生成文件
- name: 测试-test
run: |
ls public/
# 也就是 scp 推送到目标路径
- name: 发布-deploy
uses: docker://registry.services.wait/cwx/ssh-scp-action:v1
with:
key: ${{ secrets.ED25519_KEY }}
host: 10.2.1.5
port: 22
user: wait
ssh_before: |
rm -rf /data/nfs_private/blog-web-data/blog/*
scp: |
public/* wait@10.2.1.5:/data/nfs_private/blog-web-data/blog/
|
