本文分几部分,gitlab的搭建,配置gitlab-runner和自动化部署案例
gitlab搭建
参考:
在多种方法中,我选择了docker compose进行安装
安装docker compose
参考:
docker engine
是docker的核心,我这里举例CentOS安装〰
设置docker存储库
安装yum-utils软件包(提供yum-config-manager)并设置存储库。
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
安装 Docker 及其组件
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动docker:sudo systemctl start docker
可以通过运行镜像sudo docker run hello-world
来查看是否安装成功
管理docker
# 启动/重启/停止docker
sudo systemctl start docker
sudo systemctl restart docker
sudo systemctl stop docker
docker 常用命令
# 查看正在运行的容器信息
docker ps
# 查看所有的容器信息
docker ps -a
# 启动/重启/停止/删除 容器
docker start "容器名/容器ID"
docker restart "容器名/容器ID"
docker stop "容器名/容器ID"
docker rm "容器名/容器ID"
# 查看/删除 镜像
docker images
docker rmi "镜像名/镜像ID"
# 进入容器
docker exec -it "容器名/容器ID" /bin/bash
docker compose 安装 gitlab
参考:
docker-compose.yml
docker版本的gitlab在这里〰查看,自行替换yml中的版本
version: '3.6'
services:
gitlab:
image: gitlab/gitlab-ce:16.11.2-ce.0
container_name: gitlab
restart: always
hostname: '192.168.1.18'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url 'http://192.168.1.18:6666'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
ports:
- '6666:6666'
# - '443:443'
- '2222:22'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'
shm_size: '256m'
我试了,容器内部的gitlab shell,端口就是22,比较难改,所以将端口映射到2222
除此之外,在./config/gitlab.rb
中,也设置了gitlab_rails['gitlab_shell_ssh_port'] = 2222
呵呵,文档上写的是2424,按照文档那样设置绝对有问题,我试了不知道多少次了,就是坑
如果需要备份,直接备份
./config
,./logs
,./data
就行
配置和使用gitlab
自行参考:
集成gitlab runner
参考:
gitlab runner 简单说就是一个个任务的运行器,当git仓库代码有提交时,可以自动发布一个任务,比如打包或者测试或者构建等任务,传递到runner里执行
也就是说,有了gitlab runner,就可以做到自动化部署了
安装
依旧选择docker安装
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
注意:gitlab是向下兼容gitlab runner版本的,可以自行查看版本〰
注册gitlab runner
官网上是说直接sudo gitlab-runner register
实际上是要进入容器中才能执行
- 进入容器:
docker exec -it gitlab-runner /bin/bash
- 在gitlab容器里注册gitlab runner
可以在gitlab的web界面新增gitlab runner,然后复制上面的注册命令,进入到gitlab runner容器里执行,就注册成功了
- 选择 executor 执行器
配置时需要选择 executor 执行器〰,看情况选择即可
一个gitlab runner容器里可以配置多个gitlab runner executor,一般来说docker executor是必须的,其他的看情况,可以参考后面的案例理解
如果修改了config.toml
,要重启容器docker restart gitlab-runner
如果gitlab runner地址是本地hosts设置的,会有点坑,可以参考这里〰
gitlab runner 自动化部署
- ⭐Gitlab-ci:从零开始的前端自动化部署〰,这位大佬讲得挺好
gitlab ci 脚本
项目如果需要使用gitlab ci功能,需要.gitlab-ci.yml
文件
参考:
我简单说一下ci脚本的几个功能:
stages
:指定该ci脚本有多少个阶段,比如build、test、deploytags
:指定标签,让不同的执行器运行脚本rules
:指定规则,可以指定哪些分支执行,哪些分支不执行,或者tag包含什么字段就执行image
:指定镜像,但是只能是docker executor才能使用cache
:可以跨作业,跨阶段缓存,甚至跨流水线缓存artifacts
:可以将构建产物发送到gitlab web并下载,以及后续作业可以继续使用产物script
:脚本内容
除此之外,gitlab web自带了可视化的ci编辑器
前端自动化部署
以前端静态代码部署为例
build-job
任务需要把代码拉下来,生成静态文件,传递给deploy-job
任务,deploy_job
任务需要将静态文件推送到远程服务器
此时为了免密推送,需要配置ssh密钥。我的方案是:在gitlab web上设置变量,把服务器生成的私钥内容赋值给TEST_SSH_PRIVATE_KEY变量,然后在gitlab-ci.yml中引用该变量,写入docker服务器的~/.ssh/id_rsa
即可
介绍一下四个文件:authorized_keys,rsa_id,rsa_id.pub,known_hosts
- authorized_keys:当一个用户尝试通过SSH连接到文件所在服务器时,服务器会检查这个文件,如果公钥匹配,就会允许连接
- rsa_id:这个文件是私钥
- rsa_id.pub:这个文件是公钥
- known_hosts:它包含了文件所在客户端连接过的远程主机的公钥信息
目标:私钥能从docker内获取,公钥放在部署服务器
- 生成密钥
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
- 拷贝公钥
id_rsa.pub
到服务器的~/.ssh/authorized_keys
,在后面追加 - 将私钥
id_rsa
复制进gitlab web,并设置成变量 - 尝试是否可以免密推送
# 指定master分支才执行脚本
workflow:
rules:
- if: $CI_COMMIT_BRANCH == "master"
# cache: # 由于文件又多又小,而且要下载和上传,导致速度更慢了,所以先注释掉
# key: "NODE_CACHE"
# paths:
# - ./node_modules/
# 三个阶段,但是这里我没有写test阶段
stages:
- build
- test
- deploy
build-job:
tags:
- docker # 指定注册的docker执行器执行build-job作业
stage: build # 阶段为build
image: node:20.12.2 # 指定容器
script: # 脚本
- npm install
- npm run build
artifacts: # 把产物上传并保留到后面的作业
paths:
- "./public/"
deploy-job:
tags:
- docker # 指定docker执行器
stage: deploy
image: eeacms/rsync:2.4 # 选择该镜像方便使用rsync这个命令进行文件上传
script:
- rm -rf ~/.ssh
- mkdir -p ~/.ssh
- echo "$TEST_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa # 将测试环境的私钥写入项目的变量中,方便直接写入容器内的私钥文件
- chmod 600 ~/.ssh/id_rsa # 设置私钥文件的权限
- rsync -av --delete -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ./public devops@192.168.1.10:/data/web1/ --rsync-path="sudo rsync" # 将静态文件上传到指定位置,如果目标位置已经存在文件夹,则覆盖
回滚
gitlab ci里可以设置单独任务手动执行,以此基础可以做到先把原来的文件存档,如果有需要再手动回滚
怎么做的?多加两个阶段,一个存档阶段,一个回滚阶段
workflow:
rules:
- if: $CI_COMMIT_BRANCH == "master"
# cache: # 由于文件又多又小,而且要下载和上传,导致速度更慢了,所以先注释掉
# key: "NODE_CACHE"
# paths:
# - ./node_modules/
stages:
- archive # 存档
- build
- deploy
- fallback # 回滚
archive-job: # 存档作业
tags:
- docker
stage: archive
image: eeacms/rsync:2.4
artifacts:
paths:
- ./bigdataview-front # 指定要存档的文件夹
script:
- rm -rf ~/.ssh
- mkdir -p ~/.ssh
- echo "$TEST_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H 192.168.1.18 >> ~/.ssh/known_hosts
# 将远程服务器的文件拉到docker中,用artifacts存档
# 采用此方案的原因是,ssh执行器无法使用缓存
- scp -r devops@192.168.1.18:/data/ssss/web/ncunxin/bigdataview-front .
build-job:
tags:
- docker
stage: build
image: node:20.12.2
script:
- npm install
- npm run generate
- mv ./.output/public/ ./bigdataview-front/
dependencies: [] # 默认是拉取前面阶段的所有的构件的,此处我设置成不拉取任务构件
artifacts:
paths:
- ./bigdataview-front/
deploy-job:
tags:
- docker
stage: deploy
image: eeacms/rsync:2.4
dependencies:
- build-job
script:
- rm -rf ~/.ssh
- mkdir -p ~/.ssh
- echo "$TEST_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- rsync -av --delete -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ./bigdataview-front devops@192.168.1.18:/data/ssss/web/ncunxin/ --rsync-path="sudo rsync"
fallback-job: # 回滚作业
tags:
- docker
stage: fallback
image: eeacms/rsync:2.4
dependencies:
- archive-job # 继承archive-job的构件,注意,同个stage直接依赖是无法直接获取构件的,需要使用needs:artifacts,所以我才分开stage
script:
- rm -rf ~/.ssh
- mkdir -p ~/.ssh
- echo "$TEST_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
# 覆盖新的静态文件
- rsync -av --delete -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ./bigdataview-front devops@192.168.1.18:/data/ssss/web/ncunxin/ --rsync-path="sudo rsync"
when: manual # 需要手动执行
后端自动化部署
后端以springboot为例
build-job
任务需要把代码拉下来,生成jar包,传递给push-job
任务,push-job
任务需要将jar推送到远程服务器,最后的deploy-job
在远程服务器上执行
同样为了免密推送,需要配置ssh密钥,此时要配置的ssh密钥有两个,一个是和上面一样的,为了使用eeacms/rsync:2.4
容器免密推送的密钥。另一个是和gitlab-runner容器的ssh执行器的密钥
具体流程就是
- 生成一对密钥,公钥放要部署的服务器的
authorized_keys
,私钥放gitlab web的变量 - 生成第二对密钥(也可以复用上面生成的密钥),公钥放要部署的服务器,私钥放
gitlab-runner
容器内部的/root/.ssh/id_rsa
(如果连接不成功就去改容器里/etc/gitlab-runner/config.toml
的配置,把ssh密钥的位置改成你设置的)
# 指定master分支才执行脚本
workflow:
rules:
- if: $CI_COMMIT_BRANCH == "master"
# 三个阶段
stages:
- build
- test
- deploy
build-job:
tags:
- docker # 使用docker执行器
stage: build
image: maven:3.8.6-jdk-8-slim # java项目打包,所以选择该镜像
cache:
key: "MAVEN_CACHE" # 写了key的话,可以跨流水线缓存,这里是缓存maven的依赖,那么下次执行,下下次执行就都不用重新下载了
paths:
- ~/.m2/repository # 缓存maven的依赖
script:
- rm -rf /usr/share/maven/conf/settings.xml
- mv ./deploy_maven_settings.xml /usr/share/maven/conf/settings.xml
- mvn install
- mvn package
- rm -rf ./bigdataview-back-0.0.2.jar
- mv ./target/bigdataview-back-0.0.2.jar ./bigdataview-back-0.0.2.jar
artifacts:
paths:
- ./bigdataview-back-0.0.2.jar # 产物上传,并保留到下个作业
push-job:
tags:
- docker # 使用docker执行器
stage: deploy
image: eeacms/rsync:2.4 # 使用rsync镜像,方便上传文件
dependencies:
- build-job # 获取作业build-job的产物
script:
- rm -rf ~/.ssh
- mkdir -p ~/.ssh
- echo "$TEST_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa # 将ssh私钥写入到镜像中
- chmod 600 ~/.ssh/id_rsa
- rsync -av -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ./bigdataview-back-0.0.2.jar devops@192.168.1.18:/data/web/back/
deploy-job:
tags:
- ssh # 使用ssh执行器
stage: deploy
script:
# 杀掉8090端口进程并返回true
- lsof -ti :8090 | xargs -I{} kill -9 {} || true
- cd /data/web/back/
# 清空旧日志文件
- >
if [ -f nohup.log ]; then
> nohup.log
fi
# 使用nohup命令启动程序,并将输出重定向到nohup.log文件
- nohup java -jar ./bigdataview-back-0.0.2.jar --spring.profiles.active=test > nohup.log 2>&1 & disown
# 等待程序启动
- sleep 30
# 检查日志文件中是否包含启动成功的关键字
- if grep -q "Started BigdataviewBackApplication" nohup.log; then echo "Application started successfully"; else echo "Application failed to start"; exit 1; fi
回滚
如果是java的jar的话,方案不少
- 和上面的静态的类似,存档之后恢复
- 指定上次的jar名称恢复
- 如果jar的名字和标签有关,可以联动标签来恢复
等等
这里脚本就不再示例了
以上,才疏学浅,欢迎交流