<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • .Net微服務實戰之CI/CD

    系列文章

     相關源碼:https://github.com/SkyChenSky/Sikiro

    地基

      在軟件工程不少的思想、概念來源于建筑工程,大家也喜歡把開發軟件比喻成建房子。那么如果說運維是軟件的地基,那么框架就是承重墻。起房子就是先打地基,再建承重墻。地基打得越穩,房子才能起得更高。也等同于運維技術越扎實,系統才能更加健壯。

      特別在微服務興起得時代,運維越發的現得尤為得重要,DevOps也風靡全球。只要聊起DevOps與微服務,CI/CD總是不能避免的。CI/CD不一定限制于微服務,我認為無論在什么樣風格的架構和怎么樣組織架構的團隊,自動化技術越早使用收效越高。

      我認為IT人員更多是腦力大于體力的勞動者,一些重復的、錯誤率高的、無法對自己有增長的工作應該盡早交給自動化技術處理,節省了不需要浪費的時間與精力,這樣才能更好的去完成有價值、有意義的工作。

      2020-12-1更新,下文之前做的時候是使用了Docker部署Jenkins,在默認情況Jenkins容器是無法與宿主的Docker命令公用的,因此我使用了SSH從Jenkins容器調用宿主的方式解決。后來經過和同行溝通,使用了掛載docker.sock目錄的方式,讓Jenkinis容器調用宿主Docker指令的方式進行構建。為了保持原來文章的整體性,我打算在文章末尾額外加上新的方案。

    部署圖

      以上是我在虛擬機環境的部署圖:

      一共三臺服務器,每臺服務器都裝了Docker,Server B是docker swarm的Manger角色,A和C是worker。

      在Server B裝了Jenkins、Docker Registry、dotnet sdk,Server A裝了Gitlab,Server C裝了私有Nuget。

      那么工作流程是:

    1. 遷入代碼push到Gitlab
    2. Gitlab觸發webhook的push觸發事件并主動通知Jenkins構建
    3. Jenkins在Gitlab獲取源碼并通過配置好的規則與shell腳本進行構建
      • 如果是工具庫則dotnet push到192.168.88.139:8081的私有Nuget
      • 如果是Web應用則通過dockerfile構建docker鏡像并push到192.168.88.141:6000的Docker Registry,然后由docker swarm create多節點

    安裝Docker

    安裝最新版本Docker,并在所有需要使用docker的服務器節點根據以下步驟安裝

    升級yum并安裝基礎組件

    yum upgrade -y
    
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2

    添加安裝源信息

    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    安裝docker-ce

    yum makecache fast
    yum install docker-ce -y
     
    修改鏡像源
    vim /etc/docker/daemon.json
        
    {
      "registry-mirrors" : [
        "http://ovfftd6p.mirror.aliyuncs.com",
        "http://registry.docker-cn.com",
        "http://docker.mirrors.ustc.edu.cn",
        "http://hub-mirror.c.163.com"
      ],
      "insecure-registries" : [
        "registry.docker-cn.com",
        "docker.mirrors.ustc.edu.cn"
      ],
      "debug" : true,
      "experimental" : true
    }

    啟動docker

    systemctl daemon-reload
    systemctl enable docker
    systemctl start docker

    安裝 Docker Registry(私有倉儲)

    選取一個服務器-Server B使用docker安裝Registry

    docker run -d -p 6000:5000 -v /root/docker_registry:/var/lib/registry --name private_registry registry

    開放6000端口

    firewall-cmd --permanent --add-port=6000/tcp
    firewall-cmd --reload

    以上就Registry安裝完成了,但為了正常使用還需要做點配置修改

    編輯所有需要docker registry使用的節點的daemon.json文件,確保能正常訪問

    vim /etc/docker/daemon.json
    
    {
    "insecure-registries":["192.168.88.141:6000"]
    }

    重啟docker

    systemctl daemon-reload
    service docker restart

    如果需要推送鏡像到私庫確保標簽(tag)前綴帶有私庫地址

    docker push 192.168.88.141:6000/testdockerswarm

    docker swarm的初始化

    把相關涉及到docker swarm的節點端口開啟

    firewall-cmd --permanent --zone=public --add-port=2377/tcp
    firewall-cmd --permanent --zone=public --add-port=4789/udp
    firewall-cmd --permanent --zone=public --add-port=7946/udp
    firewall-cmd --reload

    選取Server B作為Manager節點,執行下面的指令后會出現docker swarm join的指令文本,復制保存下來

    docker swarm init --advertise-addr 192.168.88.141

    Server A和Server C為Worker節點,執行剛剛保存下來指令

    docker swarm join --token SWMTKN-1-0odogegq3bwui4o76aq5v05doqqvuycb5jmuckjmvzy4bfmm59-ewht2cz6fo0r39ky44uv00aq5 192.168.88.141:2377
    查看節點信息
    docker node ls

    私有Nuget的安裝

    選擇Server C基于docker的Nuget安裝

    docker run -d \
               -p 8081:80 \
               --env NUGET_API_KEY=chengong \
               -v /root/nuget/database:/var/www/db \
               -v /root/nuget/packages:/var/www/packagefiles \
               --name nuget-server \
               sunside/simple-nuget-server

    開放相關8081端口

    firewall-cmd --permanent --add-port=8081/tcp
    firewall-cmd --reload

    上傳包指令,注意包名有中文會導致上傳出現bad request

    dotnet nuget push --source http://192.168.88.139:8081/ -k chengong TestPackage.1.0.0.nupkg

    刪除包指令

    dotnet nuget delete --source http://192.168.88.139:8081/ -k chengong  TestPackage 1.0.0

    如果在Windowsx系統可以通過工具上傳

    https://github.com/NuGetPackageExplorer/NuGetPackageExplorer

    Gitlab的安裝

    在Server A服務器上基于docker安裝

    sudo docker run -d \
      --hostname 192.168.88.138 \
      -p 443:443 -p 8080:80 -p 2222:22 \
      --name gitlab \
      --restart always \
      -v /root/gitlab/config:/etc/gitlab:Z \
      -v /root/gitlab/logs:/var/log/gitlab:Z \
      -v /root/gitlab/data:/var/opt/gitlab:Z \
      gitlab/gitlab-ce

    開放端口

    firewall-cmd --permanent --add-port=8080/tcp
    firewall-cmd --reload

    第一次啟動會有點慢,需要耐心的等待一下(幾分鐘),初始化完了后進入系統設置root的密碼,登錄進去我們創建兩個項目,一個Web應用,一個工具庫,等會需要用到

    Jenkins的安裝

    在Server B服務器基于docker安裝Jenkins

    mkdir -p /root/jenkins
    setenforce 0
    docker run --name jenkins -u 0 -d  --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /root/jenkins/jenkins_home:/var/jenkins_home -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

    開放端口

    firewall-cmd --permanent --add-port=8080/tcp
    firewall-cmd --reload

    啟動完了后需要等待一會,我們先去查看Jenkins的docker log,我們找到下面那段密碼,在Jenkins歡迎頁輸入,設置好管理員后,選擇Custom Select,如果您對網絡有自信就直接點繼續,如果您對網絡沒自信,避免花了很長的時間還沒安裝好插件就直接啥都不選繼續。(如果出現一個XXX失敗代理的頁面直接跳過)

    docer logs xxx
    Please use the following password to proceed to installation:
    53d4a2880bf8460c8ff61936278855ca

    插件自動下載完后了,終于進去了,如果有沒有安裝成功的都得保證以下三個插件安裝好,Gitlab Hook 、Gitlab、Push Over SSH.

    登錄后,在左側點擊【系統管理】,拖下去點擊 【插件管理】,確保Gitlab Hook 、Gitlab、Push Over SSH成功安裝,如果無法順利安裝則到https://plugins.jenkins.io/下載插件手動上傳。

     

    修改時區,進入Jenkins容器
    docker exec -it 81 /bin/bash
    執行下面命令
    tzselect
    
    4
    9
    1
    1
    
    cp /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime
    
    ##查看時間
    date -R

    在Server B安裝.Net SDK,因為在Server B安裝了Jenkins,因此會基于Server B的環境進行.Net的應用進行打包、發布

    添加下載源:

    rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

    下載安裝:

    sudo yum install dotnet-sdk-3.1
     在Server B添加私有Nuget包源,因為在.Net Core應用 Build和Publish的時候會觸發Restore指令(還原包),默認只有微軟的nuget源,如果缺少了私有Nuget源會還原包失敗
    dotnet nuget add source http://192.168.88.139:8081 -n LocalNugetServer

    列出已有包源

    dotnet nuget list source

    當然可以通過 dotnet restore -s http://192.168.88.139:8081 指令指定還原包源,但是為了避免如果服務地址變動后shell腳本會大面積的修改,還是建議通過dotnet nuget add soure指令。

     

    那么到這里所有的關于Linux的工具安裝、初始化的準備工作都完成了,那么接下來就是講解Jenkins結合Gitlab,把應用與工具包發布到Nuget與Docker。

    Jenkins的使用

    在一切開始之前得把SSH配置好,因為后續會使用到,在【SSH Servers】模塊把服務器地址、賬號密碼填進去保存。

    返回到首頁面板點擊【新建任務】-選擇【構建一個自由風格的軟件項目】(FreeStyle Project)。

    自由風格的項目更多是使用shell腳本結合相應平臺的指令實現自動化,因此建議大家對shell腳本有個初步的認識與學習,雖然Jenkins也提供了對應平臺語言的一些插件,但是只要您熟悉了shell就會發現它的靈活性與便捷性。

    接下來我們只要關注3個模塊,源碼管理、構建觸發器、構建

    源碼構建,填寫您要自動發布的項目的源碼地址,并輸入賬號密碼。

    構建觸發器,這里勾選Build when a chenge ……,把URL 復制記錄下來,等下在Gitlab需要使用到。這里就是與Gitlab webhook做了聯動,可以理解成Jenkins開放了一個接口,讓Gitlab被push代碼后會主動告訴Jenkins做一次自動化構建。

    構建,這里其實就是執行shell腳本完成發布。這里得注意下我是用ssh,因為我的Jenkins是使用了docker安裝的,如果我使用了【構建】模塊里的【執行shell】就會在Jenkins環境里進行編譯、打包,同時也需要安裝相應的環境 例如dotnet sdk等。值得注意的是,我的環境與Jenkins掛載的都是在了Server B這個宿主環境,因此通過Jenkins的SSH Publishers連到Jenkins的宿主服務器(Server B),執行相應的shell腳本從Jenkins掛載的目錄進行構建鏡像。

    當然有同學想在Jenkins環境先打包然后通過SSH的Transfers模塊進行文件傳也是可以的。 

    構建腳本

    這個是工具庫發布到私有Nuget的腳本

    #腳本開始執行
    echo '腳本開始執行'
    
    base_path=/root/jenkins/jenkins_home/workspace/TestNuget
    nuget_url=http://192.168.88.139:8081/
    nuget_api_key=chengong
    
    project_path=$base_path/TestNuget
    package_path=$project_path/bin/Debug
    cd $project_path
    
    rm -rf $package_path/*.nupkg
    
    dotnet pack $project_path &&
        dotnet nuget push --source $nuget_url -k $nuget_api_key $package_path/*.nupkg >/dev/null
    
    if [ $? -eq 0 ]; then
        echo '發布成功:'$project_path''
    else
        echo '發布失敗:'$project_path''
    fi
    
    echo '腳本執行結束'

    下面這個是Web應用發布到單臺服務器的腳本

    #!/bin/bash
    echo '腳本開始執行'
    
    base_path=/root/jenkins/jenkins_home/workspace/TestDockerSwarm
    
    project_name=testdockerswarm
    project_path=$base_path/TestDockerSwarm
    publish_path=$project_path/bin/Release/netcoreapp2.2/publish
    
    cd $project_path
    rm -rf $project_path/bin
    
    dotnet publish -c Release && (
        cd $publish_path &&
            docker stop $project_name
        docker rm $project_name
        docker image rm $project_name
        docker build -t $project_name . &&
            docker run -d -p 5000:80 -e ASPNETCORE_ENVIRONMENT="Development" --name $project_name $project_name &&
            echo '發布成功:'$project_path'' ||
            echo '發布失敗:'$project_path''
    ) || echo '發布失敗:'$project_path''
    
    echo '腳本執行結束'

    下面這個是通過Docker Swarm把Web應用發布到多臺服務器

    #!/bin/bash
    echo '腳本開始執行'
    
    base_path=/root/jenkins/jenkins_home/workspace/TestDockerSwarm
    
    project_name=testdockerswarm
    project_path=$base_path/TestDockerSwarm
    publish_path=$project_path/bin/Release/netcoreapp2.2/publish
    private_registry_url=192.168.88.141:6000
    version=`date "+%Y%m%d%H%M%S"`
    
    cd $project_path
    rm -rf $project_path/bin
    
    dotnet publish -c Release && ( 
        (
            cd $publish_path
            docker service rm testdockerswarm
            docker images | grep $private_registry_url/$project_name | awk '{print $3}' | xargs docker rmi
            docker build -t $private_registry_url/$project_name:$version ./
            docker push $private_registry_url/$project_name:$version
        ) &&
            docker service create -d -p 5000:80 --replicas 2 -e ASPNETCORE_ENVIRONMENT="Development"  --constraint=" node.role==worker"  --name $project_name $private_registry_url/$project_name:$version &&
            echo '發布成功:'$project_path'' ||
            echo '發布失敗:'$project_path''
    ) || echo '發布失敗:'$project_path''
    
    echo '腳本執行結束'

    上面腳本有一處地址得注意下我指定了--constraint=" node.role==worker" 也就是woker節點才會部署應用,因為我定義了ServerA和C是Web服務器。當然各位可以按照自己的需要處理。

    Dockerfile

    FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
    WORKDIR /app
    EXPOSE 80
    
    FROM base AS final
    WORKDIR /app
    COPY ./ /app
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    
    ENTRYPOINT ["dotnet", "TestDockerSwarm.dll"]

    Gitlab的使用

    進入Gitlab,點擊【Admin Area】-【Network】,勾選選項后保存

    進入一個Project,點擊【Setting】-【Webhooks】,把剛剛在Jenkins的復制下來的Url填寫進去,勾選相應的觸發事件后保存。

    結束

       以上就是本篇的內容了,完成了部署后,可以在Jenkins點擊【立刻構建】和在Gitlab遷入一次代碼查看運行效果。Shell腳本作為一個demo,如果對腳本有更好的建議和優化的寫法可以在評論區反饋給我。

    容器調用宿主Docker指令構建方式

    該方案主要三大塊需要額外處理:

    1.Jenkins容器目錄掛載方式

    2.DockerFile使用多段構建

    3.Shell構建腳本的路徑修改,使用的是容器內的路徑(原來是服務器路徑)

    Jenkins的安裝

    其余指令可以參考上文,核心主要把 /usr/bin/docker 與 /var/run/docker.sock目錄掛載出來。這樣就可以在Jenkins容器里調用宿主Docker指令了。

    docker run --name jenkins -u 0 -d --restart always -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /root/jenkins/jenkins_home:/var/jenkins_home -v /root/jenkins/shell:/shell -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

    安裝完成后可以進入Jenkins容器測試下:

    docker exec -it jenkins /bin/bash
    
    docker info

    DockerFile的修改

    FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS builder
    WORKDIR /src
    COPY ./ /src
    
    RUN dotnet nuget add source http://192.168.88.138:8081 -n LocalNugetServer
    RUN dotnet publish -c Release TestDockerSwarm.csproj
    
    
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
    WORKDIR /app
    EXPOSE 80
    
    COPY --from=builder /src/bin/Release/netcoreapp3.1/publish ./
    ENTRYPOINT ["dotnet", "TestDockerSwarm.dll"]

    可以優先到服務器把對應的sdk和runtime鏡像下載下來

    docker pull mcr.microsoft.com/dotnet/core/sdk:3.1
    
    docker pull mcr.microsoft.com/dotnet/core/aspnet:3.1

    Shell構建腳本的修改

    下面只是針對的單個應用的示例,如果是用docker swarm可以參照上面的多應用部署的示例做調整,主要是一些路徑調整,因為現在這種方案是在容器內編譯,因此使用的是容器的路徑。

    #!/bin/bash
    echo '腳本開始執行'
    
    base_path=/var/jenkins_home/workspace/TestDockerSwarm
    
    project_name=testdockerswarm
    project_path=$base_path/TestDockerSwarm
    
    cd $project_path
    
     (
        docker stop $project_name
        docker rm $project_name
        docker image rm $project_name
        docker build -t $project_name . &&
            docker run -d -p 5000:80 -e ASPNETCORE_ENVIRONMENT="Development" --name $project_name $project_name &&
            echo '發布成功:'$project_path'' ||
            echo '發布失敗:'$project_path''
    ) || echo '發布失敗:'$project_path''
    
    echo '腳本執行結束'

     

    posted @ 2020-07-27 14:12  陳珙  閱讀(6493)  評論(24編輯  收藏  舉報
    国产美女a做受大片观看