(五)自动化MLOps部署到Kubernetes

目录

开发Python脚本

运行脚本

结论


在这里,我们为我们的CI/CD MLOps管道开发了一个半自动化的生产部署。

之前的系列文章中,我们解释了如何编写要在我们的Docker容器组中执行的脚本作为 CI/CD  MLOps管道的一部分。在本系列中,我们将设置一个Google Kubernetes Engine( GKE )集群来部署这些容器。

本系列文章假设您熟悉深度学习、DevOpsJenkinsKubernetes基础知识。

在本系列的前一篇文章中,我们构建了四个自动化的Jenkins工作流。在本文(本系列的最后一篇)中,我们将为我们的CI/CD MLOps管道开发一个半自动化的生产部署。它是半自动化的,因为您作为产品所有者通常希望在部署到生产之前检查单元测试结果——以避免服务失败。部署到生产可以手动完成,但需要自动化才能实现Google MLOps 成熟度模型目标。

下图显示了我们在项目架构中的位置。

部署到生产包括:

  • 单元测试结束后,将模型文件从GCS测试注册表复制到生产版本
  • 清理已完成的Kubernetes作业
  • 启动预测服务Pod的系统关闭(如果相应的工作流已经执行),这会迫使Kubernetes启动新的,以零服务停机时间加载新模型

开发Python脚本

我们一直在与JenkinsKubernetes合作来构建我们的CI/CD解决方案。下一个脚本将向您展示如何使用PythonJenkinsKubernetes交互,从而自动化部署到生产任务。我们的Python 脚本将在本地运行。

让我们深入研究代码。首先,我们导入所需的库并定义变量:

from kubernetes import client, config
from google.cloud import storage
import jenkins
import time
import os
 
bucket_name = 'automatictrainingcicd-aiplatform'
model_name = 'best_model.hdf5'

接下来,我们声明清除集群中已完成作业的函数:

def clean_jobs():
    config.load_kube_config()
 
    api_instance=client.BatchV1Api()
    print("Listing jobs:")
    api_response = api_instance.list_job_for_all_namespaces()
    jobs = []
    print('job-name  job-namespace  active  succeeded  failed  start-time  completion-time')
    for i in api_response.items:
        jobs.append([i.metadata.name,i.metadata.namespace])
        print("%s  %s  %s  %s  %s  %s  %s" % (i.metadata.name,i.metadata.namespace,i.status.active,i.status.succeeded,i.status.failed,i.status.start_time,i.status.completion_time))
    print('Deleting jobs...')
    if len(jobs) > 0:
        for i in range(len(jobs)):
            api_instance.delete_namespaced_job(jobs[i][0],jobs[i][1])
        print("Jobs deleted.")
    else:
        print("No jobs found.")
return

将模型从GCS测试注册表复制到生产注册表的功能如下:

def model_to_production():
    storage_client = storage.Client.from_service_account_json('AutomaticTrainingCICD-68f56bfa992e.json')
    bucket = storage_client.bucket(bucket_name)
    status = storage.Blob(bucket=bucket, name='{}/{}'.format('testing',model_name)).exists(storage_client)
    if status == True:
        print('Copying model...')
        source_blob = bucket.blob('{}/{}'.format('testing',model_name))
        destination_blob_name = '{}/{}'.format('production',model_name)
        blob_copy = bucket.copy_blob(source_blob, bucket, destination_blob_name)
        print('Model from testing registry has been copied to production registry.')
    else:
        print('No model found at testing registry.')
    return

下一个函数检查预测服务是否处于活动状态。如果是,则启动系统pod关闭;否则,将触发AutomaticTraining-PredictionAPI Jenkins工作流:

def check_services():
    api_instance = client.CoreV1Api()
    api_response = api_instance.list_service_for_all_namespaces()
    print('Listing services:')
    print('service-namespace  service-name')
    services = []
    for i in api_response.items:
        print("%s  %s" % (i.metadata.namespace, i.metadata.name))
        services.append(i.metadata.name)
    if True in (t.startswith('gke-api') for t in services):
        print('gke-api service is active. Proceeding to systematically shutdown its pods...')
        shutdown_pods()
        return
    else:
        jenkins_build()
        return

如果预测服务处于活动状态,则以下函数负责Pod关闭:

def shutdown_pods():
    config.load_kube_config()
    api_instance = client.CoreV1Api()
    print("Listing pods:")
    api_response = api_instance.list_pod_for_all_namespaces(watch=False)
    pods = []
    print('pod-ip-address  pod-namespace  pod-name')
    for i in api_response.items:
        print("%s  %s  %s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
        pods.append([i.metadata.name, i.metadata.namespace])
    print('Shutting down pods...')
    print('Deleting only gke-api pods...')
    if len(pods) > 0:
        for i in range(len(pods)):
            if pods[i][0].startswith('gke-api') == True:
                api_instance.delete_namespaced_pod(pods[i][0],pods[i][1])
                print("Pod '{}' shut down.".format(pods[i][0]))
                time.sleep(120)
        print("All pods have been shut down.")
    else:
        print("No pods found.")
   return

如果预测服务未激活,则会触发以下功能。它部署了预测服务:

def jenkins_build():
    print('gke-api service is not active. Proceeding to build AutomaticTraining-PredictionAPI job at Jenkins.')
    server = jenkins.Jenkins('http://localhost:8080', username='your_username', password='your_password')
    server.build_job('AutomaticTraining-PredictionAPI')
    print('AutomaticTraining-PredictionAPI job has been triggered, check Jenkins logs for more information.')
    return

最后是main函数;它按要求的顺序执行整个脚本:

def main():
    clean_jobs()
    model_to_production()
    check_services()
 
if __name__ == '__main__':
    main()

运行脚本

运行我们开发的Python脚本文件后,您应该得到以下响应:

所有旧的、已完成的作业都将被删除,模型复制到生产注册表,并且Pod成功终止。要仔细检查您是否获得了新的pod,请在脚本执行前后运行kubectl get pods。您应该会看到不同的pod标识符:

要查看最终产品的外观(包括界面奖励),请查看此内容。接口的公共IP地址是我们访问服务的地方:

服务接口如下所示:

最后,这是您提交图像后显示的预测:

结论

我们的系列到此结束。我们希望您喜欢这个系列,并且在处理具有挑战性的ML任务时,您将利用它来获取知识!

Automating MLOps Deployment to Kubernetes - CodeProject

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值