gitlab局域网搭建流程
2024-5-21
·
hexer

本文分几部分,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

实际上是要进入容器中才能执行

  1. 进入容器:
docker exec -it gitlab-runner /bin/bash
  1. 在gitlab容器里注册gitlab runner

可以在gitlab的web界面新增gitlab runner,然后复制上面的注册命令,进入到gitlab runner容器里执行,就注册成功了

  1. 选择 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.yml文件

参考:

我简单说一下ci脚本的几个功能:

  • stages:指定该ci脚本有多少个阶段,比如build、test、deploy
  • tags:指定标签,让不同的执行器运行脚本
  • rules:指定规则,可以指定哪些分支执行,哪些分支不执行,或者tag包含什么字段就执行
  • image:指定镜像,但是只能是docker executor才能使用
  • cache:可以跨作业,跨阶段缓存,甚至跨流水线缓存
  • artifacts:可以将构建产物发送到gitlab web并下载,以及后续作业可以继续使用产物
  • script:脚本内容

除此之外,gitlab web自带了可视化的ci编辑器

前端自动化部署

以前端静态代码部署为例

Diagram

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内获取,公钥放在部署服务器

  1. 生成密钥ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
  2. 拷贝公钥id_rsa.pub到服务器的~/.ssh/authorized_keys,在后面追加
  3. 将私钥id_rsa复制进gitlab web,并设置成变量
  4. 尝试是否可以免密推送
# 指定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为例

Diagram

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的话,方案不少

  1. 和上面的静态的类似,存档之后恢复
  2. 指定上次的jar名称恢复
  3. 如果jar的名字和标签有关,可以联动标签来恢复

等等

这里脚本就不再示例了


以上,才疏学浅,欢迎交流