gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验

1. 总览

关键字: k8s, gitlab, kubesphere, kubenetes, springboot, springcloud, .gitlab-ci.yml, minio

1.1 服务版本信息

服务名 版本 备注
gitlab GitLab Community Edition 11.3.5 公司自建服务,非k8s体系
kubesphere v3.3.2
kubernetes v1.23.10 使用kubesphere搭建k8s服务
minio RELEASE.2023-09-30T07-02-29Z 使用helm部署, 作为gitlab ci的外部缓存; 可以不使用minio,使用gilab ci自带缓存也可以
registry - 使用阿里云镜像库个人版,可以用harbor等私有部署代替

1.2 CI/CD流程图

gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第1张图片

此流程图是一个简易的流程示意图, 包含两个stage build和deploy, 每个stage中分别包含一个job,因此会触发初始化两个临时pod容器组

  1. 本地git推送到远程git服务器, 通过服务通过识别根目录的 .gitlab-ci.yml 决定是否启动gitlab ci流程
  2. 成功判断根目录 .gitlab-ci.yml 文件后, 通过only条件(分支,标签,表达式等)初步判断需要运行的job
  3. 将需要执行的job信息发送至k8s runner, 进行初始化执行pod调度
  4. 将环境变量,挂载卷, 挂载configmap信息传递到执行器pod进行初始化,进行【build】构建流程
  5. 构建结束后若job配置cache信息,会将指定目录cache存储到minio服务
  6. 完成构建会销毁pod, 需要传递到下一个job 执行器pod的内容需要通过cache缓存或者artifact制品进行传递,注意: 无法通过环境变量值变更传递到下一个pod
  7. build流程执行完毕, runner会调度执行初始化下一个【deploy】流程pod, 注意这里与步骤4一样, 会新启动一个新的pods容器组
  8. 若此job中配置了cache同时 cache:key与【build】job中相同, 则会从minio中拉取拉取缓存
  9. 同5一样,若执行无错误, 流程完成, 执行结果为pass,runner调度流程结束,构建流程及日志会同步在gitlab ci 中展示。

2. 需求及目标

2.1 需求

2.1.1 一句话需求

能够使用gitlab ci流程完成springboot项目前后端的持续集成及持续部署

2.1.2 具体需求

  1. 仅在merge_request到dev分支或push到dev分支时,触发构建流程
  2. springboot项目为微服务架构,存在多个子模块,均为独立部署的微服务,需要根据提交内容自动识别所在的模块并部署
  3. 多环境部署, 可以根据不同的分支,部署到不同的环境下

3. 实践流程

3.1 k8s(kubesphere) runner部署

3.1.1 runner分类

下图是官网对不同类型runner的能力描述,因为我们是k8s环境,因此我选择k8s类型runner

gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第2张图片

3.1.2 配置helm应用仓库

gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第3张图片

在企业空间页面,选择应用管理-应用仓库,点击添加


gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第4张图片

将gitlab chart库填入(https://charts.gitlab.io), 点击确定即可保存,
保存成功后即可在项目中新建gitlab应用


gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第5张图片

选择gitlab-runner应用,版本影响不大, 我的gitlab是11, 选取最新16.4.1安装也没有事


接下来是很重要的应用设置文件,下面的应用配置是我的个人应用配置

image:
  registry: registry.gitlab.com
  image: gitlab-org/gitlab-runner
useTini: false
imagePullPolicy: IfNotPresent
gitlabUrl: 'https://git.xxx.cn'
image_pull_secrets: 
 1. 'aliyun-hangzhou-reg'
runnerRegistrationToken: "sdfsdfsdf"
terminationGracePeriodSeconds: 3600
privileged: true
concurrent: 10
checkInterval: 30
sessionServer:
  enabled: false
rbac:
  create: true
  rules:
    - resources:
        - configmaps
        - events
        - pods
        - pods/attach
        - pods/exec
        - secrets
        - services
      verbs:
        - get
        - list
        - watch
        - create
        - patch
        - update
        - delete
    - apiGroups:
        - ''
      resources:
        - pods/exec
      verbs:
        - create
        - patch
        - delete
  clusterWideAccess: false
  serviceAccountName: lit
  podSecurityPolicy:
    enabled: false
    resourceNames:
      - gitlab-runner
metrics:
  enabled: false
  portName: metrics
  port: 9252
  serviceMonitor:
    enabled: false
service:
  enabled: false
  type: NodePort
runners:
  config: |
    [[runners]]
      environment = ["REG_USER_NAME=", "REG_PASSWD="]
      cache_dir = "/cache"
      [runners.cache]
        Type = "s3"
        Path = "/cache"
        Shared = false
        [runners.cache.s3]
          ServerAddress = "minio-w1hko6-svc:9000"
          AccessKey = "minio"
          SecretKey = "minio"
          BucketName = "runners-cache"
          BucketLocation = "cn-hb-wh-1"
          Insecure = true
      [runners.kubernetes]
        namespace = "{{.Release.Namespace}}"
        image = "ubuntu:22.04"
        [[runners.kubernetes.host_aliases]]
          ip = "192.168.10.128"
          hostnames = ["lb.kubesphere.local"]
        [[runners.kubernetes.volumes.config_map]]
          name = "runner-config"
          mount_path = "/runner-config"
        [[runners.kubernetes.volumes.pvc]]
          name = "gitlab-runner-local-pvc"
          mount_path = "/root/.m2/repository"
        [[runners.kubernetes.volumes.host_path]]
          name = "docker-sock"
          mount_path = "/var/run/docker.sock"
          host_path = "/var/run/docker.sock"
  configPath: ''
  cache: {}
securityContext:
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: false
  runAsNonRoot: true
  privileged: false
  capabilities:
    drop:
      - ALL
podSecurityContext:
  runAsUser: 100
  fsGroup: 65533
resources: {}
affinity: {}
nodeSelector: {}
tolerations: []
hostAliases: []
deploymentAnnotations: {}
deploymentLabels: {}
podAnnotations: {}
podLabels: {}
priorityClassName: ''
secrets: []
configMaps: {}
volumeMounts: 
 - mountPath: /maven
   name: volume-runner
volumes: 
 - name: volume-runner
   persistentVolumeClaim:
      claimName: gitlab-runner-local-pvc
  1. image: 这部分配置了GitLab Runner使用的容器镜像信息。它从registry.gitlab.com拉取gitlab-org/gitlab-runner的镜像。useTini设置为false,表示不使用Tini作为PID 1进程。imagePullPolicy 设置为 IfNotPresent,表示仅在本地不存在镜像时才拉取。
  2. gitlabUrl: 设置GitLab的URL为https://git.quadimodo.cn,这是GitLab实例的URL。
  3. image_pull_secrets: 这里列出了用于从私有镜像仓库拉取镜像的密钥。在这个配置中,使用名为’aliyun-hangzhou-reg’的密钥。这里使用的是k8s secrets配置名称
  4. runnerRegistrationToken: 这是GitLab Runner注册时需要提供的令牌。注1:这个参数在group或project的settings—CI/CD—Runners-Setup a specific Runner manually 中获取。注2:不同版本gitlab使用的参数可能不同,可能高级版本中使用的是runnerToken参数, 但是值是一样的。
  5. concurrent: 设置GitLab Runner 的并发任务数为10。
  6. rbac: 启用RBAC(Role-Based Access Control),为GitLab Runner创建相关的RBAC角色和服务帐户。同时指定了相应的权限规则。
  7. serviceAccountName: 设置GitLab Runner使用的服务帐户的名称为’lit’。是k8s配置的账户
  8. runners: 这个部分包含GitLab Runner的配置信息,包括运行环境,缓存设置,Kubernetes相关配置等。这个部分很重要,后面会单独详细讲解
  9. securityContext: 定义了容器的安全上下文,包括不允许提权,只读根文件系统,以及不以root用户身份运行容器。
  10. podSecurityContext: 设置了Pod的安全上下文,包括运行用户和文件系统组。
  11. volumeMounts 和 volumes: 定义了容器的挂载卷和卷的声明,用于将数据或配置文件挂载到容器中。此处其实可以不用挂载maven配置, 只是为了看下build pods 下载依赖包后的效果,才挂载到runner pods上
  12. 最后的几个部分(resources、affinity、nodeSelector、tolerations、hostAliases、deploymentAnnotations、deploymentLabels、podAnnotations、podLabels、priorityClassName、secrets、configMaps)都为空,表示没有为GitLab Runner配置任何资源限制、亲和性、节点选择、容忍度、主机别名、注释、标签等其他选项。

总的来说,这个配置文件用于在Kubernetes上部署GitLab Runner,并指定了一些安全性、并发性、挂载卷以及GitLab连接信息等方面的配置。根据需要,可以根据实际情况进行修改和自定义。

3.1.2.1 runner配置
runners:
  config: |
    [[runners]]
      environment = ["REG_USER_NAME=", "REG_PASSWD="]
      cache_dir = "/cache"
      [runners.cache]
        Type = "s3"
        Path = "/cache"
        Shared = false
        [runners.cache.s3]
          ServerAddress = "minio-w1hko6-svc:9000"
          AccessKey = "minio"
          SecretKey = "minio"
          BucketName = "runners-cache"
          BucketLocation = "cn-hb-wh-1"
          Insecure = true
      [runners.kubernetes]
        namespace = "{{.Release.Namespace}}"
        image = "ubuntu:22.04"
        [[runners.kubernetes.host_aliases]]
          ip = "192.168.10.128"
          hostnames = ["lb.kubesphere.local"]
        [[runners.kubernetes.volumes.config_map]]
          name = "runner-config"
          mount_path = "/runner-config"
        [[runners.kubernetes.volumes.pvc]]
          name = "gitlab-runner-local-pvc"
          mount_path = "/root/.m2/repository"
        [[runners.kubernetes.volumes.host_path]]
          name = "docker-sock"
          mount_path = "/var/run/docker.sock"
          host_path = "/var/run/docker.sock"
  1. [[runners]]: 这是GitLab Runner配置的起始点,表示一个GitLab Runner的配置块。通常,你可以有多个不同的[[runners]]块来配置不同的Runner。

  2. environment: 这里可以指定一些环境变量,它们以形式"键=值"存在,会在每个执行job中均初始化此处环境变量信息

  3. cache_dir: 指定了缓存的目录,缓存是用于存储构建和依赖的数据以加速构建过程的工具。默认缓存目录即为/cache

  4. [runners.cache]: 这个块包含了关于缓存的详细配置 。

    1. Type: 指定了缓存类型,这里设置为"s3",表示使用Amazon S3作为缓存后端(minio兼容s3)。目前支持s3, gcs, azure三种分布式外部缓存配置。配置详见 Gitlab Runner Advanced configuration
    2. Path: 指定了缓存的路径,这里设置为"/cache"。
    3. Shared: 是否在不同的runner之间共享缓存,设置为false,表示不共享缓存。
    4. [runners.cache.s3]: 这个块包含了S3(minio)缓存的详细配置。
      1. ServerAddress: 设置minio服务器的地址为"minio-w1hko6-svc:9000"。该地址为minio服务地址
      2. AccessKey 和 SecretKey 分别是minio服务器的访问密钥和密钥。
      3. BucketName: 指定S3存储桶的名称为"runners-cache"。
      4. BucketLocation: 设置存储桶的位置为"cn-hb-wh-1"。测试不配置也可以
      5. Insecure 设置为true,表示允许不安全的HTTP连接到minio服务器。
    5. [runners.kubernetes]: 这个块包含了GitLab Runner在Kubernetes中的配置。
      1. namespace: 使用Helm模板{{.Release.Namespace}}来动态获取Runner所属的Kubernetes命名空间。
      2. image: 设置要用于默认运行作业的容器镜像,这里是"ubuntu:22.04"。
    6. [[runners.kubernetes.host_aliases]]: 这里定义了主机别名,指定了一个IP地址(“192.168.10.128”)和一个主机名(“lb.kubesphere.local”)。这可以用于在Runner容器内解析主机名到指定的IP地址。这个主要用来后续运行kubectl命令做准备,将master节点ip进行配置
    7. [[runners.kubernetes.volumes.config_map]]: 这个部分定义了一个挂载卷,将名为"runner-config"的ConfigMap挂载到容器中的"/runner-config"路径。自定义configmap,将各类需要在job调用的sh脚本进行配置。后续会详细讲解此处配置文件
    8. [[runners.kubernetes.volumes.pvc]]: 这里定义了一个挂载卷,将名为"gitlab-runner-local-pvc"的持久卷声明(PVC)挂载到容器中的"/root/.m2/repository"路径。由于用于构建的pods均为临时pods,运行后会销毁, 因此需要配置cache或者挂载持久卷对maven下载的包进行保存
    9. [[runners.kubernetes.volumes.host_path]]: 这个部分定义了一个挂载卷,将主机的"/var/run/docker.sock"文件挂载到容器中的"/var/run/docker.sock"路径。这是用于与主机上的Docker守护进程通信的典型设置。由于需要使用docker build及docker push命令,因此此处挂载docker.sock文件, 后续会详细讲解为何使用此种方式以及还有哪几种其他方式。

3.2 minio部署(非必选)

minio是部署分布式缓存的选择, 可以使用gitlab自带的缓存配置

3.2.1 配置minio仓库

gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第6张图片与gitlab仓库类似, 将charts.min.io 到应用仓库中


新建应用,版本随意选择,我选择了最新版本

主要需要修改的参数

  1. rootUser: 默认账号
  2. rootPassword: 默认密码
  3. replicas: 3, 副本数, 我选择了3;1无法启动
  4. persistence.enabled: true, 持久化
  5. persistence.existingClaim: 已经存在的持久卷声明

3.3 配置.gitlab-ci.yml脚本文件

该脚本是该文章重点内容

dfsb

如图所示该流程一共五个阶段,目前每个阶段均只有一个job。

  1. pre阶段:该阶段主要为预备阶段,首先是生成动态环境变量,其次是获取到本次提交的内容是属于那些子模块,获取到CHANGE_MODULES,为后续push及deploy阶段做准备工作
  2. build阶段: 该阶段为mavn 构建阶段,将maven构建制品放入缓存(注: 制品存储可以直接使用artifact, 我由于外部原因,只能使用cache缓存代替)
  3. push阶段: 构建docker镜像以及将镜像推送到镜像库
  4. deploy: 将微服务通过kubectl调度容器组镜像信息
  5. clear: 由于minio存储空间及其有限,因此最后手动进行了清理
stages:
  - pre
  - build
  - push
  - deploy
  - clear

# 公共配置
.common: &common
  # 触发流程的分支
  only:
    - dev
    # 调试用
    - litao-dev

variables:
  TZ: Asia/Shanghai
  # 测试环境
  NAMESPACE: crm2
  # 监听待发布服务列表
  DEPLOY_MODULES: admin,authorization,bi,examine,gateway

# 预检查,查看待发布服务列表
pre-checking:
  <<: *common
  image:  bitnami/git
  stage: pre
  before_script:
    # 复制获取变化文件列表模型
    - cp /runner-config/change_modules.sh .
    - chmod +x change_modules.sh
  script:
    - export CHANGE_MODULES=$(sh change_modules.sh $CI_COMMIT_SHA $DEPLOY_MODULES)
    - export BUILD_START_TIME=$(date +%Y%m%d%H%M%S)
    # 存储环境变量
    - echo "BUILD_START_TIME=$BUILD_START_TIME" >> share.env
    - echo "CHANGE_MODULES=$CHANGE_MODULES" >> share.env
  artifacts:
    paths:
      # job间共享环境变量
      - share.env

# maven构建
building:
  <<: *common
  image: maven:3.6.3-jdk-8
  stage: build
  dependencies:
    - pre-checking
  cache:
    key: build-cache
    paths:
      # 存储变更打包的制品
      - target
  #aliyun mvn配置文件准备,提高速度
  before_script:
    # 读取共享环境变量信息
    - source share.env
    - if [ -z "$CHANGE_MODULES" ]; then
      echo "微服务未发生变动,跳过部署";
      exit 0;
      fi
    # 将自定义阿里云xml复制到镜像中
    - echo `ls $MAVEN_HOME/conf`
    - cp -f /runner-config/setting.xml  $MAVEN_HOME/conf/settings.xml
  script:
    - echo "=============== 开始编译源码,在target目录生成jar文件 ==============="
    - mvn clean compile package -Dmaven.test.skip=true
    - echo "=============== 完成源码编译打包 ==============="
    # 将需要缓存的文件复制到target文件夹中
    - cp /runner-config/copy_artifacts.sh .
    - chmod +x copy_artifacts.sh
    - echo $CHANGE_MODULES
    - sh copy_artifacts.sh target $CHANGE_MODULES
    - ls -lh target
  artifacts:
    paths:
      # job间共享环境变量
      - share.env

################-----push-----##########################

# push模块公共组件
push-service:
  <<: *common
  image: docker:latest
  stage: push
  dependencies:
    - building
  cache:
    key: build-cache
    policy: pull
    paths:
      - target/*tar.gz
  before_script:
    - cat share.env
    - source share.env
    # 提前登陆镜像库
    - echo "password" | docker login -u "username" --password-stdin registry.cn-hangzhou.aliyuncs.com
  # CHANGE_MODULES 变量不为空,执行构建操作
  # 生成镜像名称
  # 使用 $module 进行 Docker 构建操作
  # CHANGE_MODULES 变量为空,跳过构建
  script:
    - |
      if [ -n "$CHANGE_MODULES" ]; then
        modules=$(echo "$CHANGE_MODULES" | tr ',' '\n')
        for module in $modules; do
          image_name="registry.cn-hangzhou.aliyuncs.com/quadimodo/crm-${module}:${CI_PIPELINE_IID}-${BUILD_START_TIME}"
          docker build -t "$image_name" --build-arg SERVER_NAME="$module" .
          docker push "$image_name"
        done
      else
        echo "CHANGE_MODULES is empty, skipping build."
      fi
  artifacts:
    paths:
      # job间共享环境变量
      - share.env

################-----push-----##########################

###############------deploy-----########################

# 部署公共模块
deploy-service:
  <<: *common
  image: bitnami/kubectl:latest
  stage: deploy
  dependencies:
    - push-service
  before_script:
    - cat /runner-config/config.yml | base64 -d > ./config
    # 获取环境变量信息
    - source share.env
  script:
    - |
      if [ -n "$CHANGE_MODULES" ]; then
        modules=$(echo "$CHANGE_MODULES" | tr ',' '\n')
        for module in $modules; do
          image_name="registry.cn-hangzhou.aliyuncs.com/quadimodo/crm-${module}:${CI_PIPELINE_IID}-${BUILD_START_TIME}"
          K8S_SERVER_NAME="crm-${module}-v1"
          kubectl set image deployment ${K8S_SERVER_NAME} *=${image_name} --kubeconfig ./config --namespace $NAMESPACE
        done
      else
        echo "CHANGE_MODULES is empty, skipping deploy."
      fi
  artifacts:
    paths:
      # job间共享环境变量
      - share.env

###############------deploy-----########################

# 清除缓存信息
clear-cache:
  <<: *common
  image:
    name: minio/mc
    entrypoint: [ '' ]
  stage: clear
  after_script:
     # 删除缓存
    - mc rm --recursive --force minio/runners-cache/cache/runner
  before_script:
    # 对缓存进行配置
    - export MINIO_HOST=$(cat /runner-config/MINIO_HOST)
    - export MINIO_ACCESS_KEY=$(cat /runner-config/MINIO_ACCESS_KEY)
    - export MINIO_SECRET_KEY=$(cat /runner-config/MINIO_SECRET_KEY)
    - mc alias set minio $MINIO_HOST $MINIO_ACCESS_KEY $MINIO_SECRET_KEY
  script:
    # 删除所有文件, 避免再次缓存
    - rm -rf */target/*tar.gz

逐段解释分析

  1. stages: 定义了CI/CD流程的不同阶段,包括"pre"(预检查)、“build”(构建)、“push”(推送)、“deploy”(部署)、“clear”(清除缓存)。
  2. .common: 这是一个YAML锚点,用于定义公共配置,这些配置可以在不同的任务中共享。在此锚点下,定义了一些公共变量和触发条件。
  3. variables: 在这里定义了一些环境变量,如时区、Kubernetes命名空间、待发布服务列表等。待发布服务列表是该springboot项目中所有可以发布成微服务的子模块列表
  4. pre-checking: 这是一个预检查阶段,用于检查待发布的服务列表。
    • 它继承了.common的配置,包括环境变量和触发条件。
    • 使用GitLab Runner中的bitnami/git镜像执行任务。使用自定义git镜像, 在change_modules.sh脚本中配置git脚本获取提交文件中发生文件变更的微服务,后续会对各个脚本进行详细说明。
    • 在before_script中,将用于获取变更文件列表的脚本change_modules.sh复制到工作目录,并设置其可执行权限。
    • 在script中,运行脚本来获取变更的服务列表,并存储在环境变量中。
    • 使用artifacts部分,将共享环境变量文件share.env保存为构件工件。使用缓存进行保存也可以
  5. building: 这是构建阶段,用于构建应用程序。
    • 继承了.common中的配置,包括环境变量和触发条件。
    • 使用maven:3.6.3-jdk-8镜像执行任务,用于Maven构建。
    • 依赖于pre-checking阶段。
    • 使用缓存用于传递打包完成的压缩包。artifact默认有100M限制,我的项目打一个包就超过了100M, 可以修改系统对artifact的大小限制,但是gitlab我没有管理员权限,因此我选择使用外部minio作为缓存用来存储压缩包,更加可控
    • 在before_script中,读取共享环境变量,并设置Maven的阿里云配置文件。
    • 在script中,执行Maven构建,然后将构建的制品复制到目标目录,并保存共享环境变量。
  6. push-service: 这是推送镜像的阶段,用于构建和推送Docker镜像。
    • 继承了.common中的配置,包括环境变量和触发条件。
    • 使用docker:latest镜像执行任务,用于Docker构建和推送。
    • 依赖于building阶段。
    • 使用缓存获取build阶段中的压缩包文件。
    • 在before_script中,登录到Docker镜像库。此处使用明文不太安全,可以考虑更换为configmap, 然后挂载到执行pods上, 此处可以读取挂载的configmap文件以提高安全性
    • 在script中,根据变更的服务列表构建并推送Docker镜像。先前本来配置为一个微服务就配置一个push job,因此到了push阶段会同时出现大量push pods,占用大量计算资源,对集群有较大压力,因此换成了只有一个push job, 同时脚本使用if + for循环的配置来构建及推送镜像降低短时集群资源消耗
    • 使用artifacts保存共享环境变量。
  7. deploy-service: 这是部署阶段,用于更新Kubernetes中的部署以使用新的镜像。
    • 继承了.common中的配置,包括环境变量和触发条件。
    • 使用bitnami/kubectl:latest镜像执行任务,用于使用kubectl更新Kubernetes部署。
    • 依赖于push-service阶段。
    • 在before_script中,解码Kubernetes配置文件并获取环境变量。
    • 在script中,根据变更的服务列表更新Kubernetes部署以使用新的Docker镜像。
    • 使用artifacts保存共享环境变量。
  8. clear-cache: 这是清除缓存的阶段,用于删除GitLab Runner的缓存。由于minio分配的比较克制的存储空间,因此添加单次对缓存的清理
    • 继承了.common中的配置,包括环境变量和触发条件。
    • 使用minio/mc镜像执行任务,用于删除缓存文件。
    • 依赖于building阶段。
    • 在before_script中,配置Minio/MC以连接到Minio服务器,并获取环境变量。
    • 在script中,删除Minio服务器上的缓存文件。
    • 使用after_script中的命令,删除本地的构建缓存文件。

3.3.1 k8s挂载配置文件及环境变量

在3.1.2.1 runner配置中, 添加了将configmap键值对挂载到工作pods指定目录/runner-config 下, 用于保存待执行的shell脚本及部分配置文件以及不方便放在gitlab脚本中的保密文件
在这里插入图片描述

3.3.1.1 configmap配置列表
  • MINIO_ACCESS_KEY: minio配置
  • MINIO_HOST: minio配置
  • MINIO_SECRET_KEY: minio配置
  • change_modules.sh: 使用git命令获取比对产生变化的模块列表用于发布
  • config.yml: k8s配置信息
  • copy_artifacts.sh: 复制maven制品到指定文件夹
  • setting.xml: maven配置文件,用于加速下载
3.1.1.1 change_modules.sh
#!/bin/bash

# 接受两参数:Git提交的SHA和子模块列表
commit_sha=$1
submodules=$2

# 检查是否提供了足够的参数
if [ -z "$commit_sha" ] || [ -z "$submodules" ]; then
    echo "Usage: $0  "
    exit 1
fi

# 分割子模块列表为数组
# IFS=',' read -ra submodule_list <<< "$submodules"
submodule_list=$(echo "$submodules" | tr ',' '\n')

# 初始化变更的子模块列表
changed_submodules=""

# 使用Git命令获取指定提交与上一次提交之间的文件更改
changed_files=$(git diff-tree -r --name-only --no-commit-id --pretty=format:"%H %P %an %ad" $commit_sha| grep -v ".*\.\(swp\|bak\)")
# 检查每个文件是否以指定的文件夹前缀开头
for file in $changed_files; do
    for submodule in $submodule_list; do
          case "$file" in
                "$submodule"*)
                  if [ -z "$changed_submodules" ]; then
                      changed_submodules="$submodule"
                  else
                      changed_submodules="$changed_submodules,$submodule"
                  fi
                break ;;
          esac
    done
done


# 使用 awk 去除重复的前缀
changed_submodules=$(echo "$changed_submodules" | tr ',' '\n' | awk '!seen[$0]++' | tr '\n' ',' | sed 's/,$//')

# 输出变更的子模块列表
echo "$changed_submodules"
3.1.1.2 copy_artifacts.sh
#!/bin/bash

# 检查是否提供了正确数量的参数
if [ $# -lt 2 ]; then
  echo "Usage: $0  "
  exit 1
fi

# 第一个参数是目标文件夹路径
target_dir="$1"

# 第二个参数是逗号分隔的源文件夹路径字符串,可以包含环境变量
source_dirs="$2"

# 创建目标文件夹,如果它不存在
mkdir -p "$target_dir"

# 使用逗号分隔符分割源文件夹字符串为数组
# IFS=',' read -ra source_dirs_array <<< "$source_dirs"
source_dirs_array=$(echo "$source_dirs" | tr ',' '\n')


# 循环遍历每个源文件夹
for source_dir in $source_dirs_array; do
    target_dir_in_source="$source_dir/target"
done

  # 检查source_dir/target目录是否存在,如果不存在则创建
  if [ ! -d "$target_dir_in_source" ]; then
    mkdir -p "$target_dir_in_source"
  fi

  # 使用find命令查找指定目录下的所有.tar.gz文件并复制到目标文件夹
  find "$target_dir_in_source" -type f -name "*.tar.gz" -exec cp {} "$target_dir" \;

echo "复制完成"
3.1.1.3 settings.xml
  
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="         http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">  
      
      
    <mirrors>  
          
        <mirror>  
            <id>nexus-aliyunid>  
            <mirrorOf>centralmirrorOf>  
            <name>Nexus aliyunname>  
            <url>http://maven.aliyun.com/nexus/content/groups/public/url>  
        mirror>  
        <mirror>  
            <id>net-cnid>  
            <mirrorOf>centralmirrorOf>  
            <name>Nexus netname>  
            <url>http://maven.net.cn/content/groups/public/url>  
        mirror>  
    mirrors>  
  
    <profiles>  
        <profile>  
            
            <repositories>  
                <repository>  
                    <id>nexusid>  
                    <name>local private nexusname>  
                    <url>http://maven.aliyun.com/nexus/content/groups/public/url>  
                    <releases>  
                        <enabled>trueenabled>  
                    releases>  
                    <snapshots>  
                        <enabled>falseenabled>  
                    snapshots>  
                repository>  
            repositories>  
            <pluginRepositories>  
                <pluginRepository>  
                    <id>nexusid>  
                    <name>local private nexusname>  
                    <url>http://maven.aliyun.com/nexus/content/groups/public/url>  
                    <releases>  
                        <enabled>trueenabled>  
                    releases>  
                    <snapshots>  
                        <enabled>falseenabled>  
                    snapshots>  
                pluginRepository>  
            pluginRepositories>  
        profile>  
    profiles>  
      
    <activeProfiles>  
        <activeProfile>nexusactiveProfile>  
    activeProfiles>  
settings>
3.1.1.4 config.yml

gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第7张图片
gitlab ci + k8s(kubesphere) + springcloud微服务部署及使用经验_第8张图片
将以上config的yml文件base64后存储到config.yml中。也可以不经过base64,修改一下shell脚本内容即可,不过转换base64,可能会更安全一点
在这里插入图片描述

3.4 小结

以上流程均为自己经过N次尝试后能够完成需求及性能比较过得去的方案, 肯定不是最佳解决方案。比如, cache如此麻烦,是artifact大小限制问题, 可以直接修改artifact大小限制而不用cache配置及minio搭建。 又比如可以直接升级gitlab的版本,可以解锁一些高级特性,如 rules, only:changes 。不仅要看官网教程,同时也要对照本地gitlab 的help文档看,这样可以知道本地gitlab版本支持语法的界限,可以避免走很多坑

碰到的问题

低版本gitlab不支持高版本语法内容

gitlab11 已知没有的特性

  1. rules
  2. only:changes

具体可以点击如下链接查看
gitlab-ci yml关键字列表

不同类型runner对编写脚本的影响

在k8srunner中, 每次执行一个job都会启动一个新的指定镜像的容器组,因此job之间的信息共享和其他runner存在差异。

  1. 共享文件夹挂载或环境变量挂载
    需要在[runners.kubernetes] 中进行指定配置, 在此配置的configmap或volumes都会在job 容器组初始化时进行挂载
  2. 环境变量分享
    在job或者全局配置variables作为job中的环境变量, 在同一个job读取或者变更都没有任何问题。但是修改后不会传递到下一个job,因此k8s环境下variables实际上均只能在job内生效, 我的做法是将环境变量存储到文件(share.env),通过缓存的方式做到job之间共享环境变量信息,即在下一个job 的before_script中执行 source share.env 读取到pods中

执行docker build的类型方式

我通过挂载docker.sock的方式相对来说是最不安全也是最low的方式,但是我尝试另外两种方式都失败了。花了很长时间搜索错误还是没有头绪,无奈只能放弃
k8s using docker in builds

  1. expose /var/run/docker.sock
  2. docker:dind
  3. use kaniko to build docker images

大家可以点击以上链接自行尝试另外两种可以执行docker build操作的方式

参考资料

我将上文中出现的链接都放在此处进行统一展示

k8s using docker in builds
gitlab-ci yml关键字列表

你可能感兴趣的:(gitlab,ci/cd,kubernetes,spring,boot,spring,cloud)