有 helm charts 管理经验的人都晓得 helm charts 发布后需要打包一个 tar 放到目录里面。helm 会要求一个特定的目录结构获取不同版本的 tar 包。在 openbayes 就有这么一个 helm charts 项目里面存放了一系列的 tar 包。目前来看这些 tar 包都很小(只有几百 K)为了方便部署,就直接把这些文件和 nginx 打包到镜像里了,部署起来就能直接提供服务了,没有其他对象存储之类的外部依赖。
我们也希望把打包部署的流程通过 github workflow 实现自动化。按照上面的描述,可以分成两个步骤:
同时,为了适用 reusable workflow ,可调用的 workflow 必须是一个独立的 job 出现在调用方的 workflow 里。我们需要把上述两个工作分成 github workflow 中两个独立的 job:
name: release a new helm version
on:
...
jobs:
release:
...
build-and-push:
needs: release
...
但遇到一个很奇怪的问题,在 release 中明明提交了新的内容,在 build-and-push 中却拿不到。我的第一感觉就怀疑是 github 的 actions/checkout@v2
action 的行为有点问题。简单搜索了下,发现 actions/checkout@v2
默认会获取触发这次 github workflow 的 commit。也就是说,虽然我在 release 有新的提交,但是我在下一步 build-and-push 的 job 里还是 checkout 了上一个 commit 而已。
查看 actions/checkout@v2
的 README 发现,如果想要修改上述的行为,需要修改其 ref
参数。修改成想要获取最新 commit 的 branch 名称即可。而具体在 github action 里则可以使用 github.ref_name
(在 https://docs.github.com/en/actions/learn-github-actions/contexts#github-context 可以看到相关文档)这个变量获取当前的 branch。这里我提供一个例子:
name: test commit
on:
push:
branches:
- master
jobs:
make-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: |
FILENAME=`date +"%y%m%d%H%M%S"`.txt
echo 123 > $FILENAME
echo "::set-output name=$FILENAME"
id: write
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "add ${{ steps.write.outputs.name }}"
checkout-commit:
needs: make-commit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.ref_name }} # <-------- 如果不修改这里就拿不到上面提交的文件
- run: |
ls -lh
我在 github-checkout-test 这个仓库里做了上述的 workflow 的测试。增加 ref
参数为 ${{ github.ref_name }}
就可以获取最新的提交文件了。
最近更换了新的 macbook pro 一方面由于架构发生了变化,原来电脑里的一些东西应该不能运行了;另一方面,原来的电脑有太多乱七八糟的东西了,我想要从新做一个干净的环境。所以决定一点点安装东西,后续会有一系列内容介绍这个过程中的查漏补缺。
众所周知,java 的方法不支持 name parameter 的,也没有默认值之说。在参数比较长的时候,按照顺序传递参数很容易忘记下一个参数到底是什么。
语言不行 IDE 来凑,Intellij 就在这方面做了加强,会在传递的参数前面显示这个参数的名字(如上图所示)。不过很遗憾,这里默认的配置并没有展示完整的信息,只在一些 Intellij 觉得你容易迷失的地方增加了提示。不过很显然它高估了我的水平,事实上我希望可以提供健全的参数信息。
幸好 Intellij 可以很容易的做这个修改:
再回到刚才的方法,就可以看到提供了健全的参数信息了:
同时我发现视频录制可以更加有表现力,相较于繁琐的文字介绍视频可能会更清晰的展示一些工作流程。这里我就把刚才的设置录制了个视频:
之所以要尝试 k3s 是因为它相对于标准的 k8s 所用的内存资源要减半,非常适合比较小型的设备,尤其是自己买来的小机器(树莓派?)。而对于标准的虚拟机环境,我们大可不必这么折腾了,毕竟越来越多的云厂商已经可以点点点就创建一个 k8s 集群了。
其实相关的主题已经非常多了,不过这里还会希望记录一下在国内环境部署高可用 k3s 一些不太一样的地方,也尝试了 k3s 的 config file 参数。
首先,这里安装的是内嵌 etcd 的高可用版本,不是使用外部数据库的版本。不过为了让 worker 节点高可用,需要在 worker 和 master 节点之间增加一层负载均衡。虽然刚刚在说折腾 k3s 是针对非云环境的,不过考虑 bare-metal 的负载均衡还是需要一些稍微复杂的技术,这里就先不考虑了,后续会准备一个完全体。
那么整个架构就像 rancher 官方 提供的那样:
不过很显然,这里的 etcd 已经不是一个外部的东西了,而是内嵌在每一个 server(master)节点里了。
这里的测试环境用的 ucloud 。这里主要测试 master 的高可用,我准备了三台 master 以及一个 worker 节点。然后准备了一个内网的 ulb。
这里另外一个值得一提的是 ucloud 的内网 ulb 是需要在每台 master 做额外的设置的,参见官方文档:
/etc/netplan/lo-cloud-init.yaml
,其中 $VIP
为 ulb 的内网 IPnetwork:
ethernets:
lo:
addresses:
- $VIP/32
sudo netplan apply
通过命令 ip a
可以看到 lo
的网卡已经增加了 $VIP
。
由于我目前安装的 k3s 没用其内置的 containerd
而是用了 docker
所以需要为每台机器首先安装:
sudo apt update && sudo install docker.io -y
整个过程是这样的:
首先在 master0 执行如下命令:
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn sh -s - server -c /home/ubuntu/master0-config.yaml
k3s server
下一个 -c
的参数,这个参数可以将命令参数以 yaml
的形式传进来,这个就是看喜好了,传一系列 --xxx 形式的参数也应该没什么问题。其中 master0-config.yaml
内容如下:
write-kubeconfig-mode: "0644"
tls-san:
- 10.60.210.147 # ulb ip
- 10.60.172.234 # master0
- 10.60.227.248 # master1
- 10.60.82.205 # master 2
- 117.50.162.155 # master0 external ip
- 117.50.172.65 # master1 external ip
- 117.50.172.104 # master2 external ip
docker: true
cluster-init: true
token: VNVIyKGNPtSKTfhi
disable: servicelb
tls-san
同时把内网负载均衡节点 ip 也放了进来。docker: true
。cluster-init
的方式启动。servicelb
如果想要同时关掉 traefik
就可以写成 disable: servicelb,traefik
;注意 像配置 tls-san
那样用 yaml
的数组的语法是不行的,这也是让我多花了点时间的地方。等 master0 的命令执行成功后输入命令 k3s kubectl get nodes -w
等待第一个节点准备完毕后在第二台 master 执行如下命令:
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn sh -s - server -c /home/ubuntu/master-others.config.yaml
其中 master-others.config.yaml
内容如下:
write-kubeconfig-mode: "0644"
tls-san:
- 10.60.210.147 # ulb ip
- 10.60.172.234 # master0
- 10.60.227.248 # master1
- 10.60.82.205 # master 2
- 117.50.162.155 # master0 external ip
- 117.50.172.65 # master1 external ip
- 117.50.172.104 # master2 external ip
docker: true
server: https://10.60.172.234:6443 # master0 kubernetes api server address
token: VNVIyKGNPtSKTfhi
disable: servicelb
注意 两台 master 要陆续添加,必须等第一个结束了再去添加第二台。
三台 master 都加入集群后,集群的核心安装过程就结束了。
下面就尝试添加一台 worker:
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn K3S_TOKEN=VNVIyKGNPtSKTfhi sh -s - agent --docker --server="https://10.60.210.147:6443"
等 worker 变为 Ready
后集群的构建就算是完成了。这时候去任意一台 master 将 /etc/rancher/k3s/k3s.yaml
拷贝到自己的电脑上并修改里面 server 的 ip 为任意一台 master 的外网 ip 就可以作为 kubeconfig 文件使用了。
还有个安装工具 k3sup 可以帮助快速安装集群,不过看起来更新的频率不高了,以及国内环境显然也不能直接用。
rancher cn 的团队也做了个 autok3s 在官网上就有介绍,不过看起来更新频率也不太高,并且 k3s 本身的安装成本真的很低了,所以就没去了解了。
除了安装之外,其实集群后续的维护工作也是挺重要的,毕竟你不希望集群慢慢老去不得不兼容各种奇怪问题,后面希望记录如何升级,如何集群数据备份和恢复两部分内容。
k3s 本身有一些局限性,比如它的 CNI 插件默认是 flannel 如果想要其他的就要自己去安装了,这个我并没有做更多的尝试了。