前置内容:
通过Docker Compose部署GitLab和GitLab Runner(一)
使用GitLab自带的CI/CD功能在本地部署项目(二)
目录
一、在GitLab服务器上生成私钥与公钥
二、将公钥拷贝到应用服务器上
三、将私钥给到Docker Executor使用
1.在GitLab页面上设置全局的与SSH命令相关的CI/CD变量
2.在GitLab页面上设置全局的阿里云私人镜像仓库相关的CI/CD变量
3.编写.gitlab-ci.yml文件
四、验证
五、总结
要想在GitLab Runner容器中通过Docker Executor将eshop.webapi镜像部署到远程应用服务器上,最关键的步骤就是要能够在Docker Executor内通过ssh命令免密操作应用服务器上的docker进行部署,如下面的结构图所示。
ssh免密的核心就是通过私钥和公钥与想要连接的客户端建立连接,省去了需要用户输入客户端登录密码的步骤。那我们这个案例具体的实现步骤如下:
(1)在GitLab服务器上生成私钥与公钥
(2)将公钥拷贝到应用服务器上,并把公钥内容写入authorized_keys文件
(3)将私钥给到Docker Executor使用
下面将详细展开说明这三个步骤,尤其是步骤三很关键。
一、在GitLab服务器上生成私钥与公钥
在GitLab服务器上执行以下命令,会在/root/.shh/目录下生成两个文件,它们就是私钥 (id_rsa) 与公钥 (id_rsa.pub)文件
ssh-keygen -t rsa
注意:如果之前就已经生成过,就没必要执行这个命令重新生成了,它会覆盖原有的私钥公钥信息,会导致无法连接到曾经免密登录过的其他客户端。
二、将公钥拷贝到应用服务器上
在GitLab服务器上执行以下命令将公钥拷贝到应用服务器上:
scp /root/.ssh/id_rsa.pub root@172.24.142.64:/root/.ssh/id_rsa_gitlab.pub
在应用服务器上执行以下命令,将GitLab服务器的公钥内容写入authorized_keys文件
cat /root/.ssh/id_rsa_gitlab.pub >> /root/.ssh/authorized_keys
在GitLab服务器上执行以下命令,可以发现不用输入用户名密码就可以登录到应用服务器了
ssh 172.24.142.64
三、将私钥给到Docker Executor使用
通过上面两步操作之后,GitLab服务器已经可以使用自己的私钥通过ssh免密登录到应用服务器了。那GitLab Runner容器中的Docker Executor如果能拿到这个私钥,是不是也就能够ssh到应用服务器执行各种操作啦?我将通过以下步骤来实现这个方案:
(1)在GitLab页面上设置全局的与SSH命令相关的CI/CD变量;
(2)在GitLab页面上设置全局的阿里云私人镜像仓库相关的CI/CD变量;
(3)编写.gitlab-ci.yml文件,引用全局的CI/CD变量,将eshop.webapi镜像推送到阿里云私人镜像仓库,ssh到应用服务器从阿里云私人镜像仓库下载镜像并部署该镜像容器。
接下来将详细介绍这些步骤的操作过程。
1.在GitLab页面上设置全局的与SSH命令相关的CI/CD变量
可以参考GitLab官方的ssh key文档:Using SSH keys with GitLab CI/CD | GitLab
(1)将GitLab服务器的私钥内容设置成全局的CI/CD变量
使用以下命令查看私钥内容,然后复制它们
cat /root/.ssh/id_rsa
在GitLab页面上,通过 【Admin Area → Settings → CI/CD → Variables → Expand → Add Variable】菜单路径,执行添加私钥全局变量操作,如图所示:
注意:粘贴私钥内容后,一定要按回车符,添加新行
(2)将应用服务器SSH_KNOWN_HOSTS设置成全局的CI/CD变量
在GitLab服务器上使用以下命令收集应用服务器(IP:172.24.142.64)公钥相关内容,并复制它们:
ssh-keyscan 172.24.142.64
在GitLab页面上,通过 【Admin Area → Settings → CI/CD → Variables → Expand → Add Variable】菜单路径,执行添加SSH_KNOWN_HOSTS全局变量操作,如图所示:
注意:粘贴ssh-keyscan生成的内容后,一定要按回车符,添加新行
(3)将应用服务器IP设置成全局的CI/CD变量
与ssh相关的全局变量添加成功,如图所示:
2.在GitLab页面上设置全局的阿里云私人镜像仓库相关的CI/CD变量
如何使用阿里云私人镜像仓库,网上资料非常多,请大家自行学习,本篇文章不作介绍。假设你已经有了自己的阿里云私人镜像仓库,那么需要设置成全局变量的无非就是镜像仓库名称、用户名、密码,使用上述的方法:在GitLab页面上,通过 【Admin Area → Settings → CI/CD → Variables → Expand → Add Variable】菜单路径,继续添加这些全局变量,如图所示:
当然,读者可以试着使用其他云厂商镜像仓库(腾讯云,华为云等),也可以尝试使用私有部署的Harbor镜像仓库。
3.编写.gitlab-ci.yml文件
我们已经添加了6个全局的CI/CD变量:
重新修改上一篇文章介绍的使用.Net8开发的EShop.WebApi项目的.gitlab-ci.yml文件内容,文件中将会使用到上面定义的6个全局变量,如下:
stages:
- build
- deploy
variables:
## 镜像版本号
Docker_ImageTag: "latest"
## 镜像名称
Docker_Image: "eshop.webapi:$Docker_ImageTag"
## 阿里云镜像名称
Ali_Docker_Image: "$Ali_Docker_Registry/eshop/$Docker_Image"
build:
stage: build
script:
## 构建镜像
- docker build -f "./EShop.WebApi/Dockerfile" -t $Docker_Image .
## 将镜像标记为阿里云镜像名称
- docker tag $Docker_Image $Ali_Docker_Image
## 登录阿里云私人镜像仓库
- docker login -u $Ali_Docker_UserName --password "$Ali_Docker_Password" $Ali_Docker_Registry
## 将镜像推送到阿里云镜像仓库
- docker push $Ali_Docker_Image
only:
- main
deploy:
stage: deploy
before_script:
## 安装ssh-agent
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
## 将GitLab服务器私钥添加到ssh-agent代理中
- chmod 400 "$SSH_PRIVATE_KEY"
- ssh-add "$SSH_PRIVATE_KEY"
## 创建~/.ssh目录
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
## 创建SSH_KNOWN_HOSTS
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
## 使用ssh免密登录应用服务器,执行部署eshop.webapi容器命令
- ssh -t $ESHOP_SERVER_IP "(docker stop EShop.WebApi && docker rm EShop.WebApi || echo 'Container EShop.WebApi not found, skipping removal.') && docker login -u $Ali_Docker_UserName --password "$Ali_Docker_Password" $Ali_Docker_Registry && docker run -d --name EShop.WebApi -p 9527:80 $Ali_Docker_Image"
only:
- main
在.gitlab-ci.yml文件中我们通过ssh登录到应用服务器,然后使用docker命令进行部署,当然也可以使用docker compose命令部署,甚至可以使用k8s来部署,以后有机会将继续介绍如何通过k8s来部署。
关于ssh-agent的知识,可以参考这篇文章:了解ssh代理:ssh-agent_eval ssh-agent-CSDN博客
四、验证
在GitLab的EShopWebApi仓库页面手动执行Pipeline:
Pipeline执行成功之后,可以看到镜像已经推送到了阿里云镜像仓库:
并且应用服务器上已经部署了eshop.webapi容器:
在浏览器上输入接口地址:http://172.24.142.64:9527/WeatherForecast,可以看到返回的信息:
至此,通过GitLab自带的CI/CD实现远程服务器部署应用大功告成!
五、总结
远程部署的核心在于能够使用ssh命令免密登录到应用服务器执行部署命令。