zoukankan      html  css  js  c++  java
  • .NetCore 配合 Gitlab CI&CD 实践

    .NetCore 配合 Gitlab CI&CD 实践 - 单体项目

     

    前言

    上一篇博文 .NetCore 配合 Gitlab CI&CD 实践 - 开篇,主要简单的介绍了一下 GitLab CI 的持续集成以及持续部署,这篇将通过 GitLab CI 发布一个 .net core 项目,来带小伙伴们感受一下自动化的魅力,从此告别手动发布。

    准备工作

    创建一个空MVC项目来进行演示:

    mkdir hello-world
    cd hello-world
    dotnet new sln -n HelloWorld
    mkdir src
    cd src
    dotnet new mvc -n GitLabCIDemo
    cd ../
    dotnet sln add .srcGitLabCIDemoGitLabCIDemo.csproj
    

    完成以上创建后,用 vscode 打开应该是下面这个样子:

    image.png

    项目上传至 GitLab

    在 gitlab 上新建一个 hello-world 的项目,将本地的项目上传。这个按照如下提示操作即可:

    image.png

    项目上传成功后,切一个 dev 分支出来,我这里的策略是,代码提交到 dev 分支是自动发布到开发环境进行验证的,生产环境是通过 master 分支打 tag 进行发布的。

    • 切换到 dev 分支!
    • 切换到 dev 分支!
    • 切换到 dev 分支!

    添加相关脚本

    在 hello-world 文件夹内创建 .build/docker 文件夹,并添加如下脚本以及Dockerfile:

    • build-image.sh
    docker build -f .build/docker/Dockerfile --build-arg PROJECT=$1 --build-arg ASPNETCORE_ENVIRONMENT=$2 -t $3 .
    
    • build-project.sh
    set -e
    for arg in "$@"
    do
        target=$(pwd)/src/$arg
        dotnet restore -v n $target
        dotnet publish -c Release -o $target/publish $target
    done
    
    • push-image.sh
    NEW_TAG="registry.cn-hangzhou.aliyuncs.com/xxx/$1"; // 这里得用你自己命名空间哦
    docker tag $1 $NEW_TAG
    docker push $NEW_TAG
    docker rmi $NEW_TAG
    
    • Dockerfile
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
    ARG PROJECT
    ARG ASPNETCORE_ENVIRONMENT
    ENV ASPNETCORE_ENVIRONMENT ${ASPNETCORE_ENVIRONMENT}
    WORKDIR /app
    COPY src/${PROJECT}/publish .
    RUN echo "#!/bin/bash 
     dotnet ${PROJECT}.dll" > start.sh && chmod +x ./start.sh
    ENTRYPOINT ["./start.sh"]
    

    这里构建镜像所使用 3.1-alpine 构建出来的镜像体积只有其他镜像版本构建出来体积的一半。推荐使用。到此目录结构就成了现在这样:

    image.png

    至此准备工作已经差不多了!我们先简单过一下 CI 的流程:

    提交代码 --> 编译 --> 测试 --> 构建镜像 --> 发布

    编译 -- Build

    在 hello-world 目录下添加 .gitlab-ci.yml 文件,添加 build 任务:

    stages:
      - build
    
    helloworld-build:
      stage: build
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - .build/docker/build-project.sh GitLabCIDemo
      artifacts:
        paths:
          - src/*/bin
          - src/*/publish
    

    这里起一个容器来跑编译任务,具体细节可以看 build-project.sh 脚本,用 artifacts 将发布出来的资源上传,给后面的 构建任务使用,不需要重复 build,节约时间。这里执行会出现如下错误:

    /bin/bash: line 89: .build/docker/build-project.sh: Permission denied
    

    这是因为脚本没有执行权限,通过 chmod 命令可以解决:

    chmod +x build-image.sh build-project.sh push-image.sh
    

    重新提交,触发 build 任务。打开 GitLab CI 界面,执行成功,是不是很开心呢?

    image.png

    测试 -- Test

    现在项目里面没有测试代码,那就新建一个吧。在 hello-world 根目录下:

    mkdir test
    cd test
    dotnet new xunit -n GitLabCIDemo.UnitTests
    

    更新 .gitlab-ci.yml 添加 Test 任务:

    stages:
      - build
      - test
    
    helloworld-build:
      stage: build
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - .build/docker/build-project.sh GitLabCIDemo
      artifacts:
        paths:
          - src/*/bin
          - src/*/publish
    
    helloworld-test:
      stage: test
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - dotnet test -c Release
      dependencies:
        - helloworld-build
    

    等待一会,查看 CI 运行。

    image.png

    构建 Docker 镜像 -- Pack

    我这里使用的是阿里云的镜像仓库,需要现在阿里云上创建对应的命名空间以及镜像名称。我这里给镜像名取名为 hello-world,别忘了修改 push-image.sh 中的命名空间哦!

    image.png

    更新 .gitlab-ci.yml 添加 Pack 任务:

    stages:
      - build
      - test
      - pack
    
    helloworld-build:
      stage: build
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - .build/docker/build-project.sh GitLabCIDemo
      artifacts:
        paths:
          - src/*/bin
          - src/*/publish
    
    helloworld-test:
      stage: test
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - dotnet test -c Release
      dependencies:
        - helloworld-build
    
    helloworld-pack-staging:
      stage: pack
      tags:
        - shell
      script:
        - .build/docker/build-image.sh GitLabCIDemo Staging hello-world:beta
        - .build/docker/push-image.sh hello-world:beta
      dependencies:
        - helloworld-build
      only:
        - dev
    
    • Staging: 用来设置环境变量 ASPNETCORE_ENVIRONMENT,让 .net core 读取对应的配置文件,可以设置Development,Staging,Production 三种,可以在对应的环境设置对应环境变量,使用不同配置。

    • beta: 因为是开发环境,就一直使用同一个 tag 去覆盖之前的镜像,每次 pull 最新的镜像就好了,也可以使用 $CI_COMMIT_SHORT_SHA 使用当前 git 提交的 hash 值作为版本号

    CI 应该执行的差不多,再去瞧瞧呗! 又是全绿,真是开心!额,全绿,怪怪的...

    image.png

    打开阿里云镜像容器服务,查看一下刚刚上传的容器镜像吧!

    image.png

    部署 -- Deploy

    这里我图方便就使用 docker-compose 来做演示了,通常部署环境都是使用集群来部署的,当然单机部署也不是不无可能的,我内网用 k3s 搭建的一个集群,为啥不用 k8s,因为要求资源配置比较高,k3s 刚好够用。但是部署到 k3s 需要写挺多的配置的文件,可以单独写一篇博文介绍。

    作为自动化最后一步,无论你是用 k8s,k3s,docker swarm......,都是拉取对应的镜像,进行部署。思路是一样的,只是部署方式略有不同。这里通过 docker-compose 来发布 hello-world 应用咯。

    在部署的 Linux 服务器上创建文件夹 /deploy ,在目录下添加 docker-compose.yml 文件,添加如下内容:

    version: "3.8"
    services:
      hello-world:
        image: registry.cn-hangzhou.aliyuncs.com/jd-rd/hello-world:beta
        container_name: hello-world
        restart: always
        ports: 
          - 5013:80
        networks:
          - basic_service  
    
    networks:
      basic_service:
    

    更新 .gitlab-ci.yml,添加部署任务:

    stages:
      - build
      - test
      - pack
      - deploy
    
    helloworld-build:
      stage: build
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - .build/docker/build-project.sh GitLabCIDemo
      artifacts:
        paths:
          - src/*/bin
          - src/*/publish
    
    helloworld-test:
      stage: test
      tags:
        - docker
      image: mcr.microsoft.com/dotnet/core/sdk:3.1
      script:
        - dotnet test -c Release
      dependencies:
        - helloworld-build
    
    helloworld-pack-staging:
      stage: pack
      tags:
        - shell
      script:
        - .build/docker/build-image.sh GitLabCIDemo Staging hello-world:beta
        - .build/docker/push-image.sh hello-world:beta
      dependencies:
        - helloworld-build
      only:
        - dev
    
    deploy-staging:
      stage: deploy
      tags:
        - staging
      script:
        - cd /deploy && docker-compose pull && docker-compose up --force-recreate -d && docker ps
      only:
        - dev
    

    等待整个CI跑完,查看 CI 运行结果

    image.png

    通过服务器IP + 5013 访问应用了,就可以看到服务更新

    image.png

    修改一下 Index.cshtml 将 Welcome 修改为 Hello Devops ! ,重新提交一下,稍等片刻,重新访问即可看到变化了。

    image.png

    至此一个简单的 CI 流程已经走完了,各位看官可以根据自己的需求,继续探索。

    题外话

    如果将脚本都放在项目里面的话,将来涉及到脚本变更,需要每个项目都给改过去,这是十分痛苦的事情。这里推荐小伙伴可以通过 git submodule 子模块的方式进行引用,将公共的脚本都给提取出来,项目通过子模块来加载脚本项目,将来脚本变更,每个项目只需要更新一下子模块就好。

    总结

    通过以上一个小案例已经带小伙伴了解了一圈 GitLab-CI 如何来发布一个 .net core 应用,感受了一下 GitLab-ci 的魅力。但是以上方案还是有瑕疵的,对于单体应用来说,没有太大问题,但并不适合微服务项目。在微服务项目中,如果多个服务散落在多个仓库中,需要多个项目代码改动其实是很不方便的,所以现在很多的微服务项目都采用 Mono 仓库风格及将所有的服务都放在一个仓库里面,仓库体积虽然大,但是改动起来更方便。本篇就先到这里了,有关于 GitLab-CI 对于 Mono 仓库风格项目 CI&CD 探索实践,且听下回分解。

  • 相关阅读:
    软件定义网络笔记(PART 1)
    软件架构-可视化
    nginx反向代理配置去除前缀
    年轻就该多尝试,教你20小时Get一项新技能
    LNMP架构部署(附:部署Discuz社区论坛Web应用)
    高级开发进阶:第一章:总篇
    pip和conda添加和删除镜像源
    Micro-PaaS(Docker+K8S)
    云平台概述
    1、Docker学习笔记
  • 原文地址:https://www.cnblogs.com/zengpeng/p/14977889.html
Copyright © 2011-2022 走看看