githubactions持续集成构建部署go站点服务
目录
背景
之前有一篇文章是关于 www.9ong.com 静态站点通过以下方式实现持续集成构建: githubactions 持续集成构建部署 hugo
考虑到,未来几年可能会因为服务器价格问题,频繁更换迁移服务器,所以需要完善下原来的工作流,方便后续迁移服务时,只要调整域名解析、准备服务器相关权限和秘钥对、工作流变量调整,即可完成自动迁移。(如果哪天服务越来越干净简洁时,还可以直接镜像,镜像有个前提是确保系统版本兼容,对于 ubuntu 每 2 年就有个 LTS 版本)
今天这篇文章是备忘如何通过 githubactions 持续集成构建部署 go 动态站点 share.9ong.com 。
GitHub Actions
GitHub Actions 提供了直接在 GitHub 仓库中创建软件生命周期工作流(workflow)的功能,极大地方便了持续集成、持续部署的实现。
GitHub 做了一个官方市场,可以搜索到他人提交的 actions。另外,还有一个 awesome actions 的仓库,也可以找到不少 action。
GitHub Marketplace · Actions to improve your workflow
复制来源另一份文档。
基本思路
基本思路是在每次 push 到 GitHub 之后触发 Actions 将最新代码 checkout 到 GitHub Actions 虚拟环境中,并开始编译构建,构建成功后通过 rsync 同步部署到 VPS 或云服务器,成功后允许通过 ssh 再执行系统指令,比如重启服务等。
sequenceDiagram;
Local-->>9ong.git: push
9ong.git-->>GitHubActions:checkout
GitHubActions-->>vps:rsync
GitHubActions-->>vps:command
构造工作流
1、准备 systemctl 管理 go 服务
目标:在工作流中编译构建 go 二进制文件后,最后将二进制文件与其他配置、HTML 模板文件同步到目标服务器后,需要重启二进制文件对应的服务,比如我们这里叫 microblog
服务。
所以我们需要对这个服务进行管理,比如 systemctl、supervisorctl 等管理服务状态、启动、重启、重试、日志等。
这里我们选择系统自带的 systemctl
,避免引入其他模块。直接给结果,不详述过程:
-
1.1 准备 microblog.service 配置文件
参考:
tsingchan@iZ7xvds2ldv3fezqxvka5zZ:~$ cat /etc/systemd/system/microblog.service
内容如下,copilot 补充了注释说明:
[Unit] Description=9ong-microblog # 描述该服务的名称或用途 ConditionFileIsExecutable=/var/www/html/microblog-new/microblog # 检查文件是否可执行 After=network-online.target # 在 network-online.target 启动后运行 Wants=network-online.target # 依赖于 network-online.target [Service] StandardOutput=journal+console # 将标准输出同时记录到系统日志和控制台 StandardError=journal+console # 将标准错误输出同时记录到系统日志和控制台 StartLimitInterval=3600 # 限制启动次数的时间间隔(单位:秒) StartLimitBurst=10 # 启动次数的限制阈值 ExecStart=/var/www/html/microblog-new/microblog # 指定要运行的命令或程序 WorkingDirectory=/var/www/html/microblog-new # 设置工作目录 Restart=on-failure # 在失败时自动重启服务 RestartSec=120 # 重启间隔(单位:秒) [Install] WantedBy=multi-user.target # 指定服务在 multi-user.target 启动时启用
注:这里特别注意要设置
WorkingDirectory
该配置项用于服务在哪个工作目录启动,确保当前目录就是工作目录,方便读取对应的配置与模板文件。 -
1.2 reload 生效
sudo systemctl daemon-reload
-
1.3 检查与测试
事前,可以先准备一个测试的 go 二进制文件。
sudo systemctl status microblog
● microblog.service - 9ong-microblog Loaded: loaded (/etc/systemd/system/microblog.service; disabled; vendor preset: enabled) Active: active (running) since Sun 2024-04-21 00:15:13 CST; 11h ago Main PID: 8602 (microblog) Tasks: 5 (limit: 1939) Memory: 14.2M CPU: 64ms CGroup: /system.slice/microblog.service └─8602 /var/www/html/microblog-new/microblog 00:15:13 iZ7xvds2ldv3fezqxvka5zZ systemd[1]: Started 9ong-microblog. ... ...
支持:
start
restart
,更多详见 systemctl 命令选项。 -
1.4 系统启动时自启动服务
tsingchan@iZ7xvds2ldv3fezqxvka5zZ:~$ sudo systemctl enable microblog Created symlink /etc/systemd/system/multi-user.target.wants/microblog.service → /etc/systemd/system/microblog.service.
这个命令会创建一个符号链接,将服务单元文件指向/etc/systemd/system/multi-user.target.wants/目录,这表明服务应该在达到多用户运行级别时启动。
2、准备github工作流yaml配置
略去过程,直接给结果。在项目代码中的 .github/workflows 目录下新增 go.yml 文件,copilot 加工注释:
This workflow will build a golang project
For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: publish microblog # 设置工作流的名称
on:
push:
branches: [ "master" ] # 当代码推送到 master 分支时触发工作流
paths-ignore: # 下列文件的变更不触发部署,可以自行添加
- '.gitignore'
- 'README.md'
jobs:
build:
runs-on: ubuntu-latest # 在 Ubuntu 最新版本上运行作业
steps:
- uses: actions/checkout@v3 # 使用 actions/checkout 动作以获取代码
- name: Set up Go # 设置 Go 环境
uses: actions/setup-go@v4
with:
go-version: '1.16.8'
- name: Build # 编译 Go 项目
run: go build -v
#- name: Test
#run: go test -v ./...
- uses: webfactory/ssh-agent@v0.4.1 # 使用 ssh-agent 动作以设置 SSH 密钥
with:
ssh-private-key: |
${{ secrets.BLOG_DEPLOY_KEY_166 }}
- name: Scan public keys # 扫描公钥
run: |
ssh-keyscan ${{ secrets.BLOG_DEPLOY_HOST_166 }} >> ~/.ssh/known_hosts
- name: Deploy # 部署到远程服务器
run: |
rsync -a ./ tsingchan@${{ secrets.BLOG_DEPLOY_HOST_166 }}:/var/www/html/microblog-new
# rsync 不要加--delete 选项,避免将 micro_server.db 给删除了,TODO,更换 db 的路径。
- name: executing remote ssh commands using password # 使用密码执行远程 SSH 命令
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.BLOG_DEPLOY_HOST_166 }}
username: ${{ secrets.BLOG_DEPLOY_USERNAME_166 }}
password: ${{ secrets.BLOG_DEPLOY_PASSWORD_166 }}
port: ${{ secrets.BLOG_DEPLOY_PORT_166 }}
script: echo ${{ secrets.BLOG_DEPLOY_PASSWORD_166 }}|sudo -S systemctl restart microblog
第一个版本就先这样,不做多余说明,该优化的可以在后续工作流使用中进一步优化。
3、工作流环境变量
go.yml 文件
环境变量:其中会使用到环境变量,这些环境变量可以在 github 对应项目中的 setting 中的 secrets and variables
- action
中添加。
-
BLOG_DEPLOY_HOST_166
目标服务器 ip。
-
BLOG_DEPLOY_USERNAME_166 目标服务器可访问用户名。建议将该用户加入 sudo 组。
-
BLOG_DEPLOY_PASSWORD_166 USERNAME 对应的密码。
-
BLOG_DEPLOY_PORT_166 目标服务器 ssh 支持的端口,一般默认是 22。
-
BLOG_DEPLOY_KEY_166 工作流使用 ssh 连接目标服务器,目标服务器需要为工作流提供一个私钥用于访问目标服务器。秘钥对详见 4、SSH秘钥对。
这个环境变量是私钥内容。公钥需要加入目标服务器
4、SSH秘钥对
在 Deploy 部署环节,需要使用 rsync(基于 SSH)连接到 VPS,因此使用 ssh-keygen 命令生成一对密钥(推荐使用 ed25519 算法)。注意此对密钥不能加密码保护(passphrase),以便在工作流中无人值守。此步骤可在任意一台支持 ssh-keygen 命令的设备上完成,但注意密钥不要泄露,因为没有密码保护。
ssh-keygen -t ed25519 -f ~/.ssh/9ong_deploy_key
再将公钥 ~/.ssh/9ong_deploy_key.pub 的内容添加到 VPS 的 ~/.ssh/authorized_keys 中linux 服务器上 authorized_keys 文件用途,将私钥 ~/.ssh/9ong_deploy_key 的内容添加到 GitHub 仓库的 Settings -> Secrets 中并命名为 BLOG_DEPLOY_KEY。
就可以在工作流中以环境变量 ${{secrets.BLOG_DEPLOY_KEY}} 的形式使用私钥,而不需要将私钥内容直接贴在工作流中。
环境变量 ${{secrets.BLOG_DEPLOY_HOST}} 同理。