ML.NET机器学习、API容器化与Azure DevOps实践(四):持续集成与k8s持续部署

通过上文所介绍的内容,我们已经完成了RESTful API的开发,现在,就可以使用Azure DevOps来进行持续集成(CI)和k8s持续部署(CD)了。本文我会对使用Azure DevOps进行CI/CD的过程中需要注意的地方进行详细介绍,而对于Azure DevOps配置的详细步骤,我不会做太多注解,大家可以参考我前面写的《ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署》系列文章。

在使用Azure DevOps进行CI/CD之前,首先来了解一下整个开发部署的架构拓扑,下图展示了基于Azure DevOps进行持续集成和持续部署的架构拓扑:

image

我们首先使用Visual Studio 2019来开发ML.NET模型训练的项目,用以生成训练模型,并使用Visual Studio 2019开发了基于ASP.NET Core的RESTful API,这些代码都由Azure DevOps Repo进行托管。然后,Azure DevOps Build Pipeline会对源代码进行编译,将RESTful API应用程序编译成docker镜像然后推送到Azure Container Registry上,并执行模型训练程序,产生训练模型ZIP文件,并由Release Pipeline将训练模型保存到Azure Blob Storage中。Release Pipeline的另一个任务就是通过定义好的Kubernetes部署文件,将RESTful API部署到Azure Kubernetes Services集群。运行于ASP.NET Core中的RESTful API在启动的时候,会访问Azure Blob Storage读取训练模型,同时向客户端提供API端点。整套CI/CD体系,包括代码托管,包括容器注册表,包括容器集群等,全部都由Microsoft Azure提供。不过,出于费用方面的考虑,我没有使用Azure Container Registry,而是使用docker hub,在代码托管方面,也没有使用Azure Repo,而是使用的Github。

总结起来,Build Pipeline和Release Pipeline的任务如下:

  • Build Pipeline:从代码库下载代码,编译并运行训练程序,生成训练模型文件;将ASP.NET Core RESTful API编译成docker镜像并推送到docker hub;最后,将训练模型文件以及用于k8s部署的配置文件进行存档,以供Release Pipeline使用
  • Release Pipeline:读取Build Pipeline所保存的训练模型文件,将其保存到Azure Blob Storage;然后读取Build Pipeline所保存的k8s配置文件,将RESTful API容器镜像部署到k8s环境运行

下面,我简要介绍一下这两个部分的配置过程以及注意事项。

Build Pipeline的配置

以下是本案例的Build Pipeline的配置:

image

在Build Pipeline里,我定义了两个Agent job:Build Training Model以及Build Web API。前者运行在Hosted VS2017的Agent pool中,后者运行在Hosted Ubuntu 1604的Agent pool中。两者可以并行执行,因为互相并没有依赖。Build Training Model会下载训练程序,在.NET Core下编译并执行这个训练程序,并产生训练模型文件,通过Publish Artifact: Trained Model任务,将训练模型保存起来。而Publish Artifact: Drop k8s deployment script任务则比较简单了,仅仅是将代码库中预先写好的k8s配置文件保存下来,仅此而已。

在Build Web API这个job里,会将ASP.NET Core RESTful API编译成docker容器镜像,并推送到docker hub中,详细配置步骤都比较简单,也就不多说明了。

Release Pipeline的配置

以下是本案例的Release Pipeline的配置:

image

在Artifacts设置中,会从Build Pipeline将训练模型文件和部署文件复制过来,接下来,在Publish Model to Azure Blob stage中,会将训练模型复制到Azure Blob Storage中,这里使用的是Azure File Copy任务,我们只需要将Azure Subscription的信息以及Azure Blob Storage的连接信息填入即可。

image

在Kubernetes Deployment job中,使用Deploy to Kubernetes任务,即可快速方便地将ASP.NET Core RESTful API方便地部署到Azure Kubernetes Services托管的k8s集群中。需要注意的是,由于RESTful API需要访问Azure Blob Storage来读取机器学习的训练模型(这一点在上一讲已经提到过),因此,在这里就要将访问Blob Storage的连接信息通过ConfigMap配置到k8s集群中:

image

从k8s.deploy.yml文件可以看到,环境变量是如何通过ConfigMap设置到集群中的服务上的:

apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
    name: mlnet-webapi-deployment
  spec:
    replicas: 2
    template:
      metadata:
        labels:
          app.name: mlnet
      spec:
        containers:
          - image: daxnet/mlnet_webapi
            name: mlnet-webapi
            ports:
            - containerPort: 80
            env:
            - name: BLOB_DEFAULT_ENDPOINTS_PROTOCOL
              valueFrom:
                configMapKeyRef:
                  name: mlnet-config
                  key: BLOB_DEFAULT_ENDPOINTS_PROTOCOL
            - name: BLOB_ACCOUNT_NAME
              valueFrom:
                configMapKeyRef:
                  name: mlnet-config
                  key: BLOB_ACCOUNT_NAME
            - name: BLOB_ACCOUNT_KEY
              valueFrom:
                configMapKeyRef:
                  name: mlnet-config
                  key: BLOB_ACCOUNT_KEY
            - name: BLOB_ENDPOINT_SUFFIX
              valueFrom:
                configMapKeyRef:
                  name: mlnet-config
                  key: BLOB_ENDPOINT_SUFFIX
        restartPolicy: Always
- apiVersion: v1
  kind: Service
  metadata:
    labels:
      app.name: mlnet
    name: mlnet-webapi-service
  spec:
    type: LoadBalancer
    ports:
      - name: "expose-80"
        port: 80
        targetPort: 80
    selector:
      app.name: mlnet
kind: List
metadata: {}

测试已部署的RESTful API

通过kubectl客户端命令,可以查看我们的API是否已经部署成功:

image

然后,使用mlnet-webapi-service服务的EXTERNAL-IP地址,对API进行测试:

image

已经得到预测结果,API部署和调用成功。

总结

本系列文章一共四个部分,首先介绍了机器学习的基本概念,然后介绍了基于ML.NET的机器学习案例以及训练模型生成、RESTful API的开发,最后简要介绍了基于Azure DevOps实现持续集成、持续部署以及Azure Kubernetes Service k8s集群部署的过程。本系列文章也是我在Microsoft Global Azure Bootcamp 2019上海站活动中所分享的内容。整个案例的源代码可以从Github下载:https://github.com/daxnet/mlnet-trainer

posted @ 2019-05-15 21:56  dax.net  阅读(355)  评论(0编辑  收藏  举报