#!/usr/bin/env python3 """ DMLC submission script by kubernetes One need to make sure kubectl-able. """ from __future__ import absolute_import import os from os import path import sys import uuid import logging from kubernetes import client, config from . import tracker import yaml template_volume = { "name":"" } template_volumemount = { "mountPath":"", "name":"" } template_resouce = { "requests":{}, "limits":{} } sched_port = 9091 def create_svc_manifest(name, port, target_port): spec = client.V1ServiceSpec( selector={"app": name}, ports=[client.V1ServicePort(protocol="TCP", port=port, target_port=target_port)] ) service = client.V1Service( metadata=client.V1ObjectMeta(name=name), spec=spec) return service def create_sched_svc_manifest(name, port): return create_svc_manifest(name, port, port) def create_job_manifest(envs, commands, name, image, template_file): if template_file is not None: with open( template_file ) as f: job=yaml.safe_load(f) job["metadata"]["name"]=name job["spec"]["template"]["metadata"]["labels"]["app"]=name job["spec"]["template"]["spec"]["containers"][0]["image"]=image job["spec"]["template"]["spec"]["containers"][0]["command"]=commands job["spec"]["template"]["spec"]["containers"][0]["name"]=name job["spec"]["template"]["spec"]["containers"][0]["env"]=envs job["spec"]["template"]["spec"]["containers"][0]["command"]=commands else: container=client.V1Container(image=image, command=commands, name=name, env=envs) pod_temp=client.V1PodTemplateSpec( spec=client.V1PodSpec(restart_policy="OnFailure", containers=[container]), metadata=client.V1ObjectMeta(name=name, labels={"app":name}) ) job=client.V1Job( api_version="batch/v1", kind="Job", spec=client.V1JobSpec(template=pod_temp), metadata=client.V1ObjectMeta(name=name) ) return job def create_ps_manifest( ps_id, ps_num, job_name, envs, image, commands, template_file ): envs.append( client.V1EnvVar( name="DMLC_SERVER_ID", value=ps_id )) envs.append( client.V1EnvVar( name="DMLC_ROLE", value="server" )) if job_name is not None: name = "mx-" + job_name + "-server-" + ps_id else: name = "mx-server-" + ps_id return create_job_manifest(envs, commands, name, image, template_file ) def create_wk_manifest( wk_id, wk_num, ps_num, job_name, envs, image, commands, template_file ): envs.append( client.V1EnvVar( name="DMLC_WORKER_ID", value=wk_id )) envs.append( client.V1EnvVar( name="DMLC_SERVER_ID", value="0" )) envs.append( client.V1EnvVar( name="DMLC_ROLE", value="worker" )) if job_name is not None: name = "mx-" + job_name + "-worker-" + wk_id else: name = "mx-worker-" + wk_id return create_job_manifest(envs, commands, name, image, template_file ) def create_sched_job_manifest( wk_num, ps_num, envs, image, commands): envs.append( client.V1EnvVar( name="DMLC_ROLE", value="scheduler" )) name = "" for i in envs: if i.name == "DMLC_PS_ROOT_URI": name = i.value break return create_job_manifest(envs, commands, name, image, None ) def create_env(root_uri, root_port, sv_num, wk_num ): envs = [] envs.append( client.V1EnvVar( name="DMLC_PS_ROOT_URI", value=root_uri)) envs.append( client.V1EnvVar( name="DMLC_PS_ROOT_PORT", value=str(root_port))) envs.append( client.V1EnvVar( name="DMLC_NUM_SERVER", value=str(sv_num))) envs.append( client.V1EnvVar( name="DMLC_NUM_WORKER", value=str(wk_num))) return envs def submit(args): def kubernetes_submit(nworker, nserver, pass_envs): sv_image = args.kube_server_image wk_image = args.kube_worker_image if args.jobname is not None: r_uri = "mx-" + args.jobname + "-sched" else: r_uri = "mx-sched" r_port = 9091 sd_envs = create_env( r_uri, r_port, nserver, nworker ) mn_jobs = [] mn_sh_job = create_sched_job_manifest( str(nworker), str(nserver), sd_envs, sv_image, args.command) mn_sh_svc = create_sched_svc_manifest(r_uri, r_port) for i in range(nserver): envs = create_env( r_uri, r_port, nserver, nworker ) mn_sv = create_ps_manifest( str(i), str(nserver), args.jobname, envs, sv_image, args.command, args.kube_server_template ) mn_jobs.append(mn_sv) for i in range(nworker): envs = create_env( r_uri, r_port, nserver, nworker ) mn_wk = create_wk_manifest( str(i), str(nworker), str(nserver), args.jobname, envs, wk_image, args.command, args.kube_worker_template ) mn_jobs.append(mn_wk) config.load_kube_config() k8s_coreapi = client.CoreV1Api() k8s_batch = client.BatchV1Api() resp = k8s_batch.create_namespaced_job(namespace=args.kube_namespace, body=mn_sh_job) print( resp.kind + " " + resp.metadata.name +" is created." ) resp = k8s_coreapi.create_namespaced_service(namespace="default", body=mn_sh_svc) print( resp.kind + " " + resp.metadata.name +" is created." ) for m in mn_jobs: resp = k8s_batch.create_namespaced_job( body=m, namespace="default") print( resp.kind + " " + resp.metadata.name +" is created." ) return kubernetes_submit tracker.submit(args.num_workers, args.num_servers, fun_submit=kubernetes_submit, pscmd="echo \"To check each log, try 'kubectl logs job/{{role}}-{{jobname}}-{{workerID}}'\"")