Azure DevOps 中 Dapr项目自动部署流程实践

  • A+
所属分类:.NET技术
摘要

注:本文中主要讨论 .NET6.0项目在 k8s 中运行的 Dapr 的持续集成流程, 但实际上不是Dapr的项目部署到K8s也是相同流程,只是k8s的yaml配置文件有所不同

注:本文中主要讨论 .NET6.0项目在 k8s 中运行的 Dapr 的持续集成流程, 但实际上不是Dapr的项目部署到K8s也是相同流程,只是k8s的yaml配置文件有所不同

流程选择

基于 Dapr 的项目持续集成包含以下流程

  1. 编译并打包项目
  2. 构建 Dockerfile,并推送镜像push image至私有仓库
  3. 准备 k8s 部署的配置文件
  4. 通过 kubectl 部署镜像至 k8s 中

这里面有多种方案

- Pipeline的操作 Publish的操作 优点 缺点
1. 直接BuildImage并发布 1. 直接使用 Docker Build Image 2. push image 3.复制Yaml至Artifacts K8s 直接发布 对应版本的yaml + 指定Image 直接,操作简单 1. 产生大量不必要的Image 2.持续集成消耗时间较长3.每次持续集成都有Image产生
2. Publish时再进行Build 1. 仅 dotnet publish zip 1. Build Image / Push Image (可选 )2. K8S 部署+指定Image 单次部署减慢,多次增快 部署过程会比直接接取镜像慢
3. 仅发布 Zip,并Build一个使用Volume的专署镜像 仅 dotnet publish zip 使用编译好的镜像修改Volume参数 跨环境部署时会导致对于文件系统依赖过重

鉴于以上优缺点,最终我选择了第二种折衷方案,这种方案既不影响持续集成的速度,也不会产生过多的镜像,只是在部署时会产生多余的镜像构建时间。

项目结构

  • 每个要发布的API的 project 文件夹中增加以下文件
    • dapr.yaml
    • Dockerfile

dapr.yaml

kind: Deployment apiVersion: apps/v1 metadata:   name: demo   namespace: dapr-api   labels:     app: .api     service: demo spec:   replicas: 1   selector:     matchLabels:       service: demo   template:     metadata:       labels:         app: .api         service: demo       annotations:         dapr.io/enabled: "true"         dapr.io/app-id: "demo-api"         dapr.io/app-port: "80"         dapr.io/log-as-json: "true"     spec:       containers:         - name: demo-api           image: 仓库地址/镜像名:220310.13           ports:             - name: http               containerPort: 80               protocol: TCP           imagePullPolicy: IfNotPresent --- kind: Service apiVersion: v1 metadata:   name: demo-api   namespace: dapr-api   labels:     app: .api     service: demo spec:   type: NodePort   selector:     service: demo   ports:   - protocol: TCP     port: 80     targetPort: 80     nodePort: 30004  

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final WORKDIR /app EXPOSE 80 COPY ["./projectfolder", "/app"] ENTRYPOINT ["dotnet", "projectdll.dll"] 

这两个文件需要每个项目不同,后面在编译和部署流程中会用到。

Pipelines 持续集成的配置文件

trigger:   batch: true  pool:   name: Default name: $(Date:yy)$(Date:MM)$(Date:dd)$(Rev:.r)  variables:     BuildConfiguration: 'Release' steps: - task: UseDotNet@2   displayName: 'Check and Install .NET SDK 6.0'   inputs:     version: '6.0.x'     includePreviewVersions: false  - task: DotNetCoreCLI@2   displayName: 'Publish to zip'   inputs:     command: publish     publishWebProjects: false     projects: './src/projectfolder/project.csproj'     arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory) -v n'     zipAfterPublish: false     workingDirectory: '$(Build.SourcesDirectory)/src' ## 复制上文中的两个文件到 Artifact - task: CopyFiles@2   displayName: 'Copy dapr.yaml to: $(build.artifactstagingdirectory)'   inputs:     SourceFolder: './src/${{ parameters.project }}/'     Contents: |       Dockerfile       dapr.yaml     TargetFolder: '$(build.artifactstagingdirectory)'  - task: PublishBuildArtifacts@1   displayName: 'Publish Artifact'   inputs:     PathtoPublish: '$(build.artifactstagingdirectory)' 

Release 发布流程配置文件

发布流程新建两个作业
Azure DevOps 中 Dapr项目自动部署流程实践

作业1 Build Image

variables:   image: '自定义镜像名'  steps: - task: Docker@2   displayName: buildAndPush   inputs:     containerRegistry: harbor     repository: '$(image)'     Dockerfile: '$(System.DefaultWorkingDirectory)/_dapr-demo/drop/Dockerfile'     tags: '$(Build.BuildNumber)'  

作业2 KubeDeploy

variables:   image: '自定义镜像名,与上文须一致'  steps: - task: KubernetesManifest@0   displayName: deploy   inputs:     kubernetesServiceConnection: online     namespace: '$(ns)' ## k8s的部署目标命名空间     strategy: canary ## 灰度部署策略     percentage: 50     manifests: '$(System.DefaultWorkingDirectory)/_dapr-demo/drop/dapr.yaml'     containers: '$(harborUrl)/$(image):$(Build.BuildNumber)'  

这样,在首次部署时执行全部管道。
Azure DevOps 中 Dapr项目自动部署流程实践

后期回滚版本只,手动执行第二个管理即KubeDeploy即可
Azure DevOps 中 Dapr项目自动部署流程实践

其它流程

本流程全部依赖 Azure DevOps 自身的配置,并不依赖 Agent 环境配置,如果依赖 Agent 环境的话有更多做法。