Kubernetes api微服务开发之jupyter模型创建
目标:完成模型开发功能中的Model创建,返回jupyter notebook
访问信息
概述
人工智能服务中模型开发功能的实现主要参考金山云方案,提供一个tensorflow
容器,并通过jupyter notebook
编写代码,实现模型开发。
本文使用容器镜像为jupyter/tensorflow-notebook
Replication Controller功能修改
DevK8sApiService.java在原有rc创建代码的基础上,增加cpu与memory设定的功能:
//创建Replication Controller
public ReplicationController createRC(String rcName, String nsName, String lbkey, String lbvalue,
int replicas, String ctName, String imName, int cnPort,
String cpuRes, String memRes, String cpuLim, String memLim) {
Quantity cpuQn = new QuantityBuilder()
.withAmount(cpuRes)
.build();
Quantity memQn = new QuantityBuilder()
.withAmount(memRes)
.build();
Quantity cpuliQn = new QuantityBuilder()
.withAmount(cpuLim)
.build();
Quantity memliQn = new QuantityBuilder()
.withAmount(memLim)
.build();
ReplicationController rc = new ReplicationControllerBuilder()
.withApiVersion("v1")
.withKind("ReplicationController")
.withNewMetadata()
.withName(rcName)
.withNamespace(nsName)
.addToLabels(lbkey, lbvalue)
.endMetadata()
.withNewSpec()
.withReplicas(replicas)
.addToSelector(lbkey, lbvalue)
.withNewTemplate()
.withNewMetadata()
.addToLabels(lbkey, lbvalue)
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName(ctName)
.withImage(imName)
.addNewPort()
.withContainerPort(cnPort)
.endPort()
.withNewResources()
.addToRequests("cpu", cpuQn)
.addToRequests("memory", memQn)
.addToLimits("cpu", cpuliQn)
.addToLimits("memory", memliQn)
.endResources()
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
try {
kubernetesClient.replicationControllers().create(rc);
System.out.println("replication controller create success");
} catch (Exception e) {
System.out.println("replication controller create failed");
}
return rc;
}
其中request为初始运行时占用的资源值,limit为最大能使用的资源值。
将新增参数加入DevK8sApiController.java
//k8s rc create
@RequestMapping(value = "/createRCWithinQuantity", method = RequestMethod.POST)
public ReplicationController createK8sRC(@RequestParam(value = "ReplicationControllerName") String rcName,
@RequestParam(value = "NamespaceName") String nsName,
@RequestParam(value = "LabelKey") String lbkey,
@RequestParam(value = "LabelValue") String lbvalue,
@RequestParam(value = "Replicas") int replicas,
@RequestParam(value = "ContainerName") String ctName,
@RequestParam(value = "ImageName") String imName,
@RequestParam(value = "ContainerPort") int cnPort,
@RequestParam(value = "CpuR") String cpurName,
@RequestParam(value = "MemR") String memrName,
@RequestParam(value = "CpuL") String cpulName,
@RequestParam(value = "MemL") String memlName) {
return devK8sApiService.createRC(rcName, nsName, lbkey, lbvalue, replicas, ctName, imName, cnPort, cpurName, memrName, cpulName, memlName);
}
TensorFlow Jupyter Notebook应用创建
修改完成后重新构建项目,启动应用
创建replication controller
POST
: http://127.0.0.1:8080/k8s/createRCWithinQuantity
Content-Type
: application/x-www-form-urlencoded
Body
: {"NameSpaceName":"appblog", "ReplicationControllerName":"tf-nb-rc", "LabelKey":"name", "LabelValue":"tf-nb", "Replicas":"1", "ContainerName":"tf-nb", "ImageName":"jupyter/tensorflow-notebook", "ContainerPort":"8888", "CpuR":"1", "MemR":"1Gi", "CpuL":"1", "MemL":"2Gi"}
注:
jupyter/tensorflow-notebook
的ContainerPort
必须为8888
{
"apiVersion": "v1",
"kind": "ReplicationController",
"metadata": {
"annotations": {},
"labels": {
"name": "tf-nb"
},
"name": "tf-nb-rc",
"namespace": "appblog"
},
"spec": {
"replicas": 1,
"selector": {
"name": "tf-nb"
},
"template": {
"metadata": {
"annotations": {},
"labels": {
"name": "tf-nb"
}
},
"spec": {
"containers": [
{
"image": "jupyter/tensorflow-notebook",
"name": "tf-nb",
"ports": [
{
"containerPort": 8888
}
],
"resources": {
"limits": {
"cpu": "1",
"memory": "2Gi"
},
"requests": {
"cpu": "1",
"memory": "1Gi"
}
}
}
],
"nodeSelector": {}
}
}
}
}
在master节点上查看rc信息:
[root@k8s-master ~]# kubectl get pods -n appblog
NAME READY STATUS RESTARTS AGE
tf-nb-rc-vs52b 1/1 Running 0 9m2s
[root@k8s-master ~]# kubectl describe rc tf-nb-rc -n appblog
Name: tf-nb-rc
Namespace: appblog
Selector: name=tf-nb
Labels: name=tf-nb
Annotations: <none>
Replicas: 1 current / 1 desired
Pods Status: 0 Running / 1 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: name=tf-nb
Containers:
tf-nb:
Image: jupyter/tensorflow-notebook
Port: 8888/TCP
Host Port: 0/TCP
Limits:
cpu: 2
memory: 2Gi
Requests:
cpu: 1
memory: 1Gi
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 10s replication-controller Created pod: tf-nb-rc-vs52b
创建service
POST
: http://127.0.0.1:8080/k8s/createService
Content-Type
: application/x-www-form-urlencoded
Body
: {"ServiceName":"tf-nb-service", "NameSpaceName":"appblog", "LabelKey":"name", "LabelValue":"tf-nb", "ContainerPort":"80", "NodePort":"30050"}
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {},
"labels": {
"name": "tf-nb"
},
"name": "tf-nb-service",
"namespace": "appblog"
},
"spec": {
"ports": [
{
"nodePort": 30050,
"port": 8888
}
],
"selector": {
"name": "tf-nb"
},
"type": "NodePort"
}
}
在master节点上查看service信息:
[root@k8s-master ~]# kubectl get service tf-nb-service -n appblog
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tf-nb-service NodePort 10.98.57.109 <none> 8888:30050/TCP 24s
访问:http://NodeIP:30050
需要获取notebook的token才能访问。
获取notebook token
编写token获取方法:
//token查询
public Map<String, String> readToken(String nsName, String rcName, String lbKey, String lbValue) {
Map<String, String> resourceInfo = new HashMap<String, String>();
try {
//ExecWatch tokenResult = kubernetesClient.pods().inNamespace(nsName).withName(rcName).exec("jupyter notebook list");
PodList podList = kubernetesClient.pods().inNamespace(nsName).withLabel(lbKey, lbValue).list();
for (Pod pod : podList.getItems()) {
String podName = pod.getMetadata().getName();
String podLog = kubernetesClient.pods().inNamespace(nsName).withName(podName).getLog();
resourceInfo.put(podName + "token: ", podLog);
}
//resourceInfo.put("token: ", tokenResult.toString());
log.error("model token get success");
} catch (Exception e) {
log.error("model token get failed");
log.error("", e);
}
return resourceInfo;
}
因执行exec会有认证的问题,此处使用getLog的方法获取启动日志,在日志中查询token。
同时修改DevK8sApiController.java
//token read
@RequestMapping(value = "/readToken", method = RequestMethod.GET)
public Map<String, String> readJNtoken(@RequestParam(value = "NamespaceName") String nsName,
@RequestParam(value = "ReplicationControllerName") String rcName,
@RequestParam(value = "LabelKey") String lbkey,
@RequestParam(value = "LabelValue") String lbvalue) {
return devK8sApiService.readToken(nsName, rcName, lbkey, lbvalue);
}
因为rc创建的pod都会随机生成5位字符串,所以通过Label查询pod名称,并获取日志。
{
"tf-nb-rc-gzz5jtoken: ": "Executing the command: jupyter notebook\n[I 01:25:06.115 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret\n[I 01:25:07.998 NotebookApp] JupyterLab extension loaded from /opt/conda/lib/python3.7/site-packages/jupyterlab\n[I 01:25:07.998 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab\n[I 01:25:08.000 NotebookApp] Serving notebooks from local directory: /home/jovyan\n[I 01:25:08.000 NotebookApp] The Jupyter Notebook is running at:\n[I 01:25:08.000 NotebookApp] http://(tf-nb-rc-gzz5j or 127.0.0.1):8888/?token=f94b3960fb6a1b50f06d07b1211f41b38c26a3a3ec3e9173\n[I 01:25:08.000 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).\n[C 01:25:08.005 NotebookApp] \n \n To access the notebook, open this file in a browser:\n file:///home/jovyan/.local/share/jupyter/runtime/nbserver-6-open.html\n Or copy and paste one of these URLs:\n http://(tf-nb-rc-gzz5j or 127.0.0.1):8888/?token=f94b3960fb6a1b50f06d07b1211f41b38c26a3a3ec3e9173\n[I 01:28:48.071 NotebookApp] 302 GET / (192.168.0.10) 0.66ms\n[I 01:28:48.124 NotebookApp] 302 GET /tree? (192.168.0.10) 4.00ms\n"
}
token信息:token=f94b3960fb6a1b50f06d07b1211f41b38c26a3a3ec3e9173
访问jupyter notebook并测试
输入上一节中的token并登录:
编写tensorflow测试程序:
import tensorflow as tf
hello = tf.Variable('Hello TF')
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
sess.run(hello)
运行代码:
以上,开发模型创建完成。
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/23/jupyter-model-creation-for-kubernetes-api-microservice-development/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论