建立好CI/CD的流程,除了可以减少人工的操作之外,也能透过安排好的测试等排程来让专案更加的稳定。现在也有不同的服务来帮助建立CI/CD流程,例如GitLab还有今天要介绍的bitbucket pipelines
在进入大纲以前,先说明想要建立的自动化部署流程
主机在main branch中透git push将程式码push到bitbucket上bitbucket根据设置的pipelines.yml,先建立虚拟环境进行程式码的测试测试通过后,使用SSH连接到远端主机,进到专案目录根据专案目录的docker配置删除旧容器,建立新的容器完成部署而这篇文章的重点会放在bitbucket想要使用SSH操作远端主机时需要注意的地方,而不是yml本身,所以今天重点都在如何完成第一到第三步的过程
文章大纲
- 远端主机配置
- Bitbucket配置
流程说明
首先我们从上面的Linode部分(远端主机)来看,因为需要操作专案、使用docker建立容器与操作git,所以我们需要建立具备相关权限的群组与用户。虽然在操作docker时很常需要用到root用户,但是建立一个具有操作docker权限的用户才是更安全的做法,而建立群组的好处是能将先前具有操作专案权限的用户纳入群组中
为了要让Bitbucket能使用用户透过SSH连到远端主机,需要在sshd_config档案配置相关参数,以及将Bitbucket建立的公钥放到远端主机的authorized_keys档案中
接着来看下图关于Bitbucket的配置,因为需要让远端主机能够操作git,所以要将远端主机的public key放到Bitbucket的Access keys配置中。并且我们需要在Bitbucket中配置SSH密钥(不论是自己生成,还是拿本机的来用都可以)。生产或是拿来的公钥,如同上段说的要拿去远端主机的authorized_keys档案,而私钥则是之后pipeline需要用在SSH登入时验证
最后来提及Repository variables配置的部分,因为是使用ssh_run镜像,所以需要配置SSH_USER与SERVER才能让pipeline使用SSH登入。而SSH_KEY如果在前面的步骤已经配置在Bitbucket的设定中,这边可以不用填。而其他你需要在专案中用到的环境变数,如果是已经在远端主机的档案配置中的话,这边可以不用配置,我这边配置的是要给测试阶段时,此时环境是Bitbucket的独立虚拟环境,不会有远端主机配置好的环境变数,所以还是要补上。
以上简单的介绍一下流程,如果觉得还有哪边觉得不是很清楚的话,可以看完底下详细的步骤后,再回来把整个流程梳理一次逻辑~
实际操作流程
远端主机配置
- 确认远端主机是否有docker群组
getent group docker
# 如果有的话会显示
docker:x:990:
- 建立用户并设置密码(虽然之后是使用公钥,但还是可以配置密码)
useradd -m -s /bin/bash <username> #建立用户
passwd <username> # 修改密码
- 给予用户能使用docker的权限
usermod -aG docker <username>
用户的部分配置好了,接着要建立群组为什么要建立群组?而不是直接把所有需要的权限丢到刚刚的用户就好了?因为远端主机的专案资料,不是只有这个部署的用户要使用,因此建立群组然后让其有专案资料的权限,最后再将用户们纳入群组之下
- 建立专门的群组
sudo groupadd <group_name>
- 将用户添加到群组,这边除了刚刚建立的用户,也要把之前建立专案的用户纳入
usermod -aG <group_name> <username>
- 修改目录的群组拥有权,同时配置读取与执行权限,以及让新建立的档案自动继承父目录的群组
chown :<group_name> <file_path>
chmod g+rx <file_path>
chmod g+s <file_path>
这边要注意:要从绝对路径开始,直到专案目录的每一层都要配置,并且要注意.git的隐藏资料夹有没有套用到配置,没有的话会部署失败
接下来我们要确认新建立的用户能够使用SSH连线
sudo vim /etc/ssh/sshd_config
并且确认这些参数
PubkeyAuthentication yes # 表示能公钥连线
PasswordAuthentication no # 不使用输入密码的方式登入
AllowUsers <user_name> # 确认能用ssh连线
最后来配置SSH密钥认证时需要的档案与权限
- 建立.ssh目录,并且配置权限,使拥有者有读+写+执行权限
mkdir -p /<root_path>/<username>/.ssh
chown <username>:<username> /<root_path>/<username>/.ssh
chmod 700 /<root_path>/<username>/.ssh
- 在.ssh内建立authorized_keys档案,储存允许登入此用户的公钥
touch /<root_path>/<username>/.ssh/authorized_keys
chown <username>:<username> /<root_path>/<username>/.ssh/authorized_keys
chmod 600 /<root_path>/<username>/.ssh/authorized_keys
同时我们也在这里建立密钥,公钥之后要给Bitbucket的Access keys来使用远程仓库(repository)的权限
ssh-keygen -t rsa -b 4096 -C ""
在远端主机的工作就告一段落了,我们接着来配置Bitbucket
Bitbucket配置
先进到Repository settings中
将刚刚的公钥(id_rsa)放到Bitbucket中
接着我们要来配置Repository settings中的SSH Keys
如果pipeline中需要使用多组SSH keys,那这边可能可以跳过,直接全部配置在Repository variables上。但是我们就只有一组要认证,所以可以直接配置在这里,后面的pipelines.yml可以省略一些步骤
我这边因为有建立了所以长这样,如果是第一次新增也会有按钮让你新增
不过输入Private key时要注意,一定要连第一行跟最后一行都输入进去
-----BEGIN OPENSSH PRIVATE KEY-----
xxxxxxxx
-----END OPENSSH PRIVATE KEY-----
然后用远端主机的ip来建立know host
最后就来配置Repository variables
其中根据官方提供的ssh-run镜像,SSH_USER跟SERVER是必须,其他的变数就根据自己需求来添加
至于pipelines.yml本身大致上的架构如下,毕竟今天重点不是在他身上,就不多做赘述,读者再根据自己需求做调整
pipelines:
default:
- step:
name: Test
image: python:3.12-slim
caches:
- pip
script:
- apt-get update && apt-get install -y gcc python3-dev
# 这里是相对于 repo root
- pip install -r <root_path>/requirements.txt
- cd <file_path>
- pytest -v
- step:
name: Deploy to Production
deployment: production
script:
- pipe: atlassian/ssh-run:0.8.1
variables:
SSH_USER: $SSH_USER
SERVER: $SERVER
COMMAND: >
set -e;
echo "当前用户信息:" && whoami && groups;
echo "开始尝试进入目录:" &&
cd <file_path> &&
echo "成功进入目标目录" &&
pwd &&
echo "开始执行部署步骤" &&
docker-compose ps > previous_state.txt &&
git pull origin main &&
docker-compose --env-file ../.env down &&
docker-compose --env-file ../.env build &&
docker-compose --env-file ../.env up -d &&
if ! docker-compose ps | grep -q "web.*Up"; then
echo "部署失败,正在回滚..." &&
docker-compose down &&
cat previous_state.txt &&
exit 1;
fi &&
docker system prune -f --volumes &&
echo "部署完成!"
definitions:
services:
docker:
memory: 256
总结
这是我第一次建立的CI/CD流程,中间失败了50次以上,主要都是卡在对于权限的配置与SSH中远端主机与Bitbucket所扮演的角色定位不够了解,以及第一次写COMMAND,不知道要用&&而是傻傻用;
整个流程大致上如下:
- 配置远端主机的用户与群组之相关权限
- 使该用户能用SSH连线
- Bitbucket上配置SSH密钥用于SSH连线与配置变数来进行SSH登入
虽然文中是使用Bitbucket,但是了解了相关流程后,使用其他服务也是能照着相同的逻辑去处理~
参考资料
https://support.atlassian.com/bitbucket-cloud/docs/set-up-pipelines-ssh-keys-on-linux/https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/https://bitbucket.org/atlassian/ssh-run/src/master/?source=post_pagehttps://dev.to/manuelbosi/bitbucket-pipelines-configure-ssh-keys-1l56?source=post_page