Skip to content

Latest commit

 

History

History
194 lines (179 loc) · 10.6 KB

gitlab-ci.yml.md

File metadata and controls

194 lines (179 loc) · 10.6 KB

3.1 配置 gitlab-ci.yml

示例应用搭建 CI/CD 流水线的背景需求

  • 应用测试环境部署在本地k8s平台,生产环境部署在阿里云上k8s平台
  • 应用的多个feature分支可以并行测试
  • 对于即将发布的release分支,本地提供封版测试环境,阿里云上提供UAT测试环境

以下示例配置为个人经验总结,仅供参考,可以根据自己的理解和项目需要不断优化完善;总体来说 gitlab-ci.yml 配置很丰富,基本上能够满足各种个性化的CI/CD流程需要。

$ cat > .ci/gitlab-ci.yml << EOF
variables:                                                               ### 定义全局变量 http://gitlab.test.com/help/ci/variables/README.md
  PROJECT_NS: '$CI_PROJECT_NAMESPACE-$CI_JOB_STAGE'                      # 定义项目命名空间,对应k8s的namespace
  APP_NAME: '$CI_PROJECT_NAME-$CI_COMMIT_REF_SLUG'                       # 使用项目名和git提交信息作为应用名
  IMAGE_NAME: '$CI_PROJECT_NAMESPACE-$CI_PROJECT_NAME:$CI_PIPELINE_ID'   # 定义镜像名称 

stages:                                                                  ### 定义ci各阶段
  - beta-build                                                           # beta环境编译打包
  - beta-deploy                                                          # beta环境部署
  - beta-feature-delete                                                  # beta环境feature分支手动删除
  - prod-build                                                           # prod环境编译打包
  - prod-uat-deploy                                                      # prod-uat环境部署
  - prod-deploy                                                          # prod环境部署
  - prod-rollback                                                        # prod回滚

job_beta_build:
  stage: beta-build                                                      # beta环境编译打包
  tags:
    - build-shell                                                        # 定义带`build-shell`标签的runner可以运行该job
  only:                                                                  # 定义只在如下分支或者tag运行该job 
    - master
    - develop
    - /^feature.*$/
    - release
  #when: manual                                                          # 调试阶段可以先手动,后续可以注释掉以自动运行
  script:                                                                ### runner上运行的脚本
  - bash .ci/config.sh                                                   # 不同环境配置替换,后文详解 config.sh
  - mvn clean install -Dmaven.test.skip=true -U                          # mvn 编译,可以去runner 虚机上手动执行编译测试
  - mv example-web/target/*.jar dockerfiles/                             # 把mvn生成的xxx.jar移动到dockerfiles目录下
  - export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`                     # 转换镜像名,例:mygroup/java/example:172 >> mygroup-java-example:172
  - cd dockerfiles && docker build -t $BETA_HARBOR/example/$IMAGE .      # 创建 docker 镜像
  - docker login -u $BETA_HARBOR_USR -p $BETA_HARBOR_PWD $BETA_HARBOR    # 登录到内部镜像仓库 harbor,并推送
  - docker push $BETA_HARBOR/example/$IMAGE                                          
  - docker logout $BETA_HARBOR

job_push_beta:                                                           ### 推送到beta环境,可以推送不同分支 develop, feature-1, ...>
  stage: beta-deploy                                                     # 可以做到多分支同时测试,甚至最后的release分支也要在beta封版测试
  tags:
    - beta-shell                                                         # 定义带`beta-shell`标签的runner可以运行该job
  only:
    - master
    - develop
    - /^feature.*$/
    - release
  when: manual                                                           # 调试阶段可以先手动,后续可以注释掉以自动运行
  variables:
    BETA_EXP_Domain: '$CI_COMMIT_REF_SLUG.example.test.com'              # job内部变量,指定该应用在beta环境的 ingress 域名
  script:
  - export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`                     # 转换 $IMAGE_NAME 中可能的 / 字符
  - export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`                # 转换命名空间中可能有的 / 字符
  # 替换beta环境的参数配置
  - sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml                     ### app.yaml 即k8s的部署模板文件,详见后面 app.yaml.md 文档,注意这里的变量有的来自>
  - sed -i "s/APP_NAME/$APP_NAME/g" .ci/app.yaml                         # gitlab 系统变量, 有的是在项目 CI/CD 设置里面用户定义的变量
  - sed -i "s/APP_REP/$BETA_APP_REP/g" .ci/app.yaml
  - sed -i "s/AppDomain/$BETA_EXP_Domain/g" .ci/app.yaml
  - sed -i "s/ProjectImage/$BETA_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
  - sed -i "s/DOCKER_KEY/$BETA_KEY/g" .ci/app.yaml                       # DOCKER_KEY 为k8s平台能从镜像仓库pull所需的认证信息,详见harbor文档
  #
  - mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME                             # 在runner:beta-shell虚机本地创建应用配置目录,调试检查用
  - cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
  - kubectl --kubeconfig=/etc/.beta/config apply -f .ci/app.yaml         # 部署应用(runner虚机上预先配置了kubectl权限执行测试k8s平台)

job_delete_beta:                                                         ### 多测试环境并行部署在beta k8s平台,feature分支测试完毕后删除代码分支,
  stage: beta-feature-delete                                             # 同时需要删除该分支在k8s平台上的部署,可以由开发人员自行执行该job删除
  tags:
    - beta-shell
  only:
    - /^feature.*$/
  when: manual
  script:
  - export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
  - kubectl --kubeconfig=/etc/.beta/config delete deploy,svc,ing $APP_NAME -n $PROJECT_NS

job_prod_build:                                                          ### prod环境编译打包,这里prod环境我们使用阿里云上的K8S
  stage: prod-build                                                      # 阿里云k8s平台上运行的uat环境和正式环境都使用本次打包镜像
  tags:
    - build-shell
  only:                                                                  # 仅master和release分支可以执行该job
    - master
    - release
  #when: manual
  script:
  - bash .ci/config.sh                                                   # config.sh 会执行替换生产环境的变量
  - mvn clean install -Dmaven.test.skip=true -U                          # mvn 编译,可以去runner 虚机上手动执行编译测试
  - mv example-web/target/*.jar dockerfiles/                             # 把mvn生成的xxx.jar移动到dockerfiles目录下
  - export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
  - cd dockerfiles && docker build -t $PROD_HARBOR/example/$IMAGE .
  - docker login -u $PROD_HARBOR_USR -p $PROD_HARBOR_PWD $PROD_HARBOR
  - docker push $PROD_HARBOR/example/$IMAGE
  - docker logout $PROD_HARBOR

job_push_prod_uat:                                                       ### 部署至阿里云uat环境
  stage: prod-uat-deploy
  tags:
    - prod-shell
  when: manual
  only:                                                                  # 仅master和release分支可以执行该job
    - master
    - release
  variables:
    PROD_EXP_Domain: 'example-uat.xxxx.com'                              # job内部变量,指定该应用在uat环境的 ingress 域名
  script:
  - export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
  - export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
  # 替换prod环境的参数配置
  - sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml
  - sed -i "s/APP_NAME/$CI_PROJECT_NAME/g" .ci/app.yaml
  - sed -i "s/APP_REP/1/g" .ci/app.yaml
  - sed -i "s/AppDomain/$PROD_EXP_Domain/g" .ci/app.yaml
  - sed -i "s/ProjectImage/$PROD_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
  - sed -i "s/DOCKER_KEY/$PROD_KEY/g" .ci/app.yaml
  #
  - mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME
  - cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
  - kubectl --kubeconfig=/etc/.aliyun/config apply -f .ci/app.yaml

job_push_prod_release:                                                   ### 部署至阿里云正式环境
  stage: prod-deploy
  tags:
    - prod-shell
  when: manual
  only:                                                                  # 仅master和release分支可以执行该job
    - master
    - release
  variables:
    PROD_EXP_Domain: 'example.xxxx.com'                                  # 指定该应用在阿里云正式环境的 ingress 域名
  script:
  - export IMAGE=`echo $IMAGE_NAME | sed 's/\//-/g'`
  - export PROJECT_NS=`echo $PROJECT_NS | sed 's/\//-/g'`
  # 替换prod环境的参数配置
  - sed -i "s/PROJECT_NS/$PROJECT_NS/g" .ci/app.yaml
  - sed -i "s/APP_NAME/$CI_PROJECT_NAME/g" .ci/app.yaml
  - sed -i "s/APP_REP/$PROD_APP_REP/g" .ci/app.yaml
  - sed -i "s/AppDomain/$PROD_EXP_HOST/g" .ci/app.yaml
  - sed -i "s/ProjectImage/$PROD_HARBOR\/example\/$IMAGE/g" .ci/app.yaml
  - sed -i "s/DOCKER_KEY/$PROD_KEY/g" .ci/app.yaml
  #
  - mkdir -p /opt/kube/$PROJECT_NS/$APP_NAME
  - cp -f .ci/app.yaml /opt/kube/$PROJECT_NS/$APP_NAME
  - kubectl --kubeconfig=/etc/.aliyun/config apply -f .ci/app.yaml

1/3 rollback:                                                            ### 定义生产环境回退job  
  stage: prod-rollback
  tags:
    - prod-shell
  when: manual
  only:
    - master
    - /^release.*$/
  variables:
    PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy'                      # 定义job内变量覆盖全局变量设置
  script:
  - kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=1

2/3 rollback:
  stage: prod-rollback
  tags:
    - prod-shell
  when: manual
  only:
    - master
    - /^release.*$/
  variables:
    PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy'                      # 定义job内变量覆盖全局变量设置
  script:
  - kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=2

3/3 rollback:
  stage: prod-rollback
  tags:
    - prod-shell
  when: manual
  only:
    - master
    - /^release.*$/
  variables:
    PROJECT_NS: '$CI_PROJECT_NAMESPACE-prod-deploy'                      # 定义job内变量覆盖全局变量设置
  script:
  - kubectl --kubeconfig=/etc/.aliyun/config -n $PROJECT_NS rollout undo deployment $CI_PROJECT_NAME --to-revision=3
EOF

恭喜终于看完 gitlab-ci.yml 文件,怎么样,是不是一千个人可以写出一万个 CI/CD 流程 :)