19 年和朋友交流,朋友在自主创业,聊到生产部署与持续集成,我毫无自觉的打断他,“k8s 生态已经这么成熟了,直接上 k8s 不香吗?”
将近 3 个月没有写 go 了,熟悉了现在的公司用 Ruby 做的 EventSoucing 这套框架后,心血来潮想用 go 尝试一下,权当练手,正好亲人有个小项目,花了元旦 3 天时间,做了一次穷人创业体验。
一个电商小程序,有一些分润和代理的逻辑,没有复杂的促销,单纯下单配送。后端用 golang + pg,管理前端用 react + vite + tailwindcss,小程序用 taro。
只有一台 2C8G 的腾讯云服务器(去年优惠抢的 3 年的),我需要有以下的功能
我的预算很紧张,除了服务器花销,期望每个月在这上面的花销能控制在 100 块以内,我最终选择了以下的方案
最终达成的效果还算喜人,没有吃 cpu 的服务,服务器内存稳定剩余 6GB,每次后端发布用时低于 1 分钟,CLS 日志服务按现在的量级,短时间内也不需要担心费用。
看来即使装不起全套的 Github + Gitlab CI-runner + Jenkins + k8s,穷人还是可以在一个小水管机器上进行持续交付的。
我使用了lego ,自己准备了一个 cron 任务,每天检查证书过期时间并自动更新。
轻量级的 git 服务,我知道的的有 gitlab/gitea/gogs,我选择了 gogs。性能表现上看,没有突出的 CPU 尖刺,内存占用少,不会影响生产环境;代码质量上看,至少能看懂;安全上看,禁用了自主注册后,能防止大多数泄漏问题。
drone server 使用 docker 就迅速运行起来了,runner 的选择上,我选择了 exec runner,这种 runner 是直接在宿主机上运行 shell 指令的,主要基于以下两个原因:
我编写了一个简单的脚本来执行发布,原理是,为每个需要发布的项目指定一段空闲端口号,在需要部署的数目内,逐个进行如下操作:
我的后端流水配置大致如下,准备测试环境数据库,进行测试,再准备生产环境数据库,进行发布
---
kind: pipeline
type: exec
name: default
platform:
os: linux
arch: amd64
steps:
- name: prepare_test_db
commands:
- source /usr/local/rvm/environments/ruby-2.7.3
- cd dbconsole
- cp /data/files/server-db/database.yml config/database.yml
- RAILS_ENV=test rake db:migrate
- name: test
commands:
- source /data/files/server-env/test-env
- go test ./...
environment:
GOPATH: /data/gopath
GOPROXY: https://goproxy.io,direct
- name: prepare_pd_db
commands:
- source /usr/local/rvm/environments/ruby-2.7.3
- cd dbconsole
- cp /data/files/server-db/database.yml config/database.yml
- RAILS_ENV=production rake db:migrate
- name: build_executable
commands:
- source /etc/profile
- go build -o server cmd/server/main.go
- mv server docker/
environment:
GOPATH: /data/gopath
GOPROXY: https://goproxy.io,direct
- name: deploy
commands:
- source /usr/local/rvm/environments/ruby-2.7.3
- cd docker
- cp /data/files/server-env/pd-env pd-env
- export TAG=$(date +"%Y%m%d%H%M%S")
- echo "image name is $APP_NAME:$TAG"
- docker build -f Dockerfile-pd -t $APP_NAME:$TAG .
- ruby ./rolling-update.rb upgrade $TAG
environment:
APP_NAME: 'server'
DEPLOY_COUNT: 4
INNER_PORT: 8100
EXPORT_PORT_START: 8100
按照文档安装腾讯云 CLS 的 log listener,发现不能收集自主管理的 docker container 日志,于是使用 vector 先将多个 docker container 的日志收集到集中的日志存放地,再在腾讯云 CLS 后台配置消费日志。vector 收集 docker container 的配置也非常简单,几行配置就能实现以前需要大量代码实现的功能:
[sources.server]
type = "docker_logs"
docker_host = "/var/run/docker.sock"
include_containers = [ "server" ]
[sinks.server_log_output]
type = "file"
encoding.codec = "text"
inputs = [ "server" ]
compression = "none"
path = "/data/logs/server/%Y-%m-%d.log"
启动 vector 和 log listener 后,就能在腾讯云 TLS 进行日志查询了
整个过程中没有遇到太多的问题,唯一一个让我在休息日还加班的还是 gogs 和 drone 集成的问题,drone 默认支持与 gogs 的集成,但是集成后,自主构建功能无法正常使用,drone 会提示一个反序列化失败的内部错误。
于是加了一会儿班找到了问题,在 19 年末的时候一位老哥不小心更改了 gogs API 接口的路由,导致一个接口不能按原来的约定返回内容了,我本能的逻辑是给下游的 drone 提交 PR,不过看起来有问题的一方是 gogs,由于节假日本就不多,没有太多精力回馈社区,所以放弃了反馈:
自己本地修复后上线,解决了问题。