900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 华为云原生Kubernetes之运行Volcano高性能作业的深度使用和实践

华为云原生Kubernetes之运行Volcano高性能作业的深度使用和实践

时间:2023-12-14 05:15:03

相关推荐

华为云原生Kubernetes之运行Volcano高性能作业的深度使用和实践

一、Volcano 简介

① 什么是 Volcano ?

Volcano 是 CNCF 下首个也是唯一的基于 Kubernetes 的容器批量计算平台,主要用于高性能计算场景,提供了机器学习、深度学习、生物信息学、基因组学及其他大数据应用所需要而 Kubernetes 当前缺失的一系列特性。Volcano 提供高性能任务调度引擎、高性能异构芯片管理、高性能任务运行管理等通用计算能力,通过接入 AI、大数据、基因、渲染等诸多行业计算框架服务终端用户。Volcano 针对计算型应用提供了作业调度、作业管理、队列管理等多项功能,主要特性包括: 丰富的计算框架支持:通过 CRD 提供了批量计算任务的通用 API,通过提供丰富的插件及作业生命周期高级管理,支持 TensorFlow,MPI,Spark 等计算框架容器化运行在 Kubernetes 上; 高级调度:面向批量计算、高性能计算场景提供丰富的高级调度能力,包括成组调度,优先级抢占、装箱、资源预留、任务拓扑关系等; 队列管理:支持分队列调度,提供队列优先级、多级队列等复杂任务调度能力。

② Volcano 的特性

Volcano 支持各种调度策略,包括 Gang-scheduling、Fair-share scheduling、Queue scheduling、Preemption scheduling、Topology-based scheduling、Reclaims、Backfill、Resource Reservation 等,得益于可扩展性的架构设计,Volcano 支持用户自定义 plugin 和 action 以支持更多调度算法;Volcano 提供了增强型的 Job 管理能力以适配高性能计算场景,如多 pod 类型job、增强型的异常处理、可索引 Job;Volcano 提供了基于多种架构的计算资源的混合调度能力:如 x86、ARM、鲲鹏、昇腾、GPU;Volcano 已经支持几乎所有的主流计算框架:Spark、TensorFlow、PyTorch、Flink、Argo、MindSpore、PaddlePaddle、OpenMPI、Horovod、mxnet、Kubeflow、KubeGene、Cromwell 等。

③ Volcano 的系统架构

Volcano 与 Kubernetes 天然兼容,并为高性能计算而生,它遵循 Kubernetes 的设计理念和风格,如下所示: Volcano 由 scheduler、controllermanager、admission 和 vcctl 组成: Scheduler Volcano scheduler 通过一系列的 action 和 plugin 调度Job,并为它找到一个最适合的节点,与 Kubernetes default-scheduler 相比,Volcano 与众不同的地方是它支持针对 Job 的多种调度算法; Controllermanager Volcano controllermanager 管理 CRD 资源的生命周期,它主要由 Queue ControllerManager、 PodGroupControllerManager、 VCJob ControllerManager 构成; Admission Volcano admission 负责对 CRD API 资源进行校验; Vcctl Volcano vcctl 是 Volcano 的命令行客户端工具。

④ Volcano 的应用场景

⑤ Volcano 的安装

(A)通过 Deployment Yaml 安装

Deployment Yaml 安装方式支持 x86_64/arm64 两种架构,在 kubernetes 集群上,执行如下的 kubectl 指令:

For x86_64:kubectl apply -f /volcano-sh/volcano/master/installer/volcano-development.yamlFor arm64:kubectl apply -f /volcano-sh/volcano/master/installer/volcano-development-arm64.yaml

也可以将 master 替换为指定的标签或者分支(比如 release-1.5 分支表示最新的 v1.5.x 版本,v1.5.1 标签表示 v1.5.1 版本)以安装指定的 Volcano 版本。

(B)通过源代码安装

如果没有 kubernetes 集群,可以选择在 github 下载 volcano 源代码压缩包,解压后运行 volcano 的安装脚本,这种安装方式暂时只支持 x86_64 平台:

# git clone /volcano-sh/volcano.git# tar -xvf volcano-{Version}-linux-gnu.tar.gz# cd volcano-{Version}-linux-gnu# ./hack/local-up-volcano.sh

(C)通过 Helm 安装

在集群中下载 Helm,可以根据以下指南安装 Helm:[https://helm.sh/docs/intro/](安装 Helm)(仅当使用 Helm 模式进行安装时需要)。如果想使用 Helm 部署 Volcano,请先确认已经在集群中安装了 Helm。创建一个新的命名空间:

# kubectl create namespace volcano-systemnamespace/volcano-system created

使用 Helm 进行安装:

# helm install helm/chart/volcano --namespace volcano-system --name volcanoNAME: volcanoLAST DEPLOYED: Tue Jul 23 20:07:29 NAMESPACE: volcano-systemSTATUS: DEPLOYEDRESOURCES:==> v1/ClusterRoleNAME AGEvolcano-admission 1svolcano-controllers 1svolcano-scheduler 1s==> v1/ClusterRoleBindingNAME AGEvolcano-admission-role 1svolcano-controllers-role 1svolcano-scheduler-role 1s==> v1/ConfigMapNAMEDATA AGEvolcano-scheduler-configmap 21s==> v1/DeploymentNAME READY UP-TO-DATE AVAILABLE AGEvolcano-admission 0/1 1 01svolcano-controllers 0/1 1 01svolcano-scheduler 0/1 1 01s==> v1/JobNAMECOMPLETIONS DURATION AGEvolcano-admission-init 0/11s 1s==> v1/Pod(related)NAME READY STATUS RESTARTS AGEvolcano-admission-b45b7b76-84jmw0/1 ContainerCreating 0 1svolcano-admission-init-fw47j0/1 ContainerCreating 0 1svolcano-controllers-5f66f8d76c-27584 0/1 ContainerCreating 0 1svolcano-scheduler-bb4467966-z642p0/1 Pending 0 1s==> v1/ServiceNAME TYPE CLUSTER-IPEXTERNAL-IP PORT(S) AGEvolcano-admission-service ClusterIP 10.107.128.208 <none> 443/TCP 1s==> v1/ServiceAccountNAME SECRETS AGEvolcano-admission 1 1svolcano-controllers 1 1svolcano-scheduler 1 1s==> v1beta1/CustomResourceDefinitionNAME AGEpodgroups.scheduling.sigs.dev 1squeues.scheduling.sigs.dev1sNOTES:Thank you for installing volcano.Your release is named volcano.For more information on volcano, visit:https://volcano.sh/

验证 Volcano 组件的状态:

# kubectl get all -n volcano-systemNAME READY STATUSRESTARTS AGEpod/volcano-admission-5bd5756f79-p89tx1/1Running06m10spod/volcano-admission-init-d4dns 0/1Completed 06m10spod/volcano-controllers-687948d9c8-bd28m 1/1Running06m10spod/volcano-scheduler-94998fc64-9df5g1/1Running06m10sNAME TYPE CLUSTER-IPEXTERNAL-IP PORT(S) AGEservice/volcano-admission-service ClusterIP 10.96.140.22 <none> 443/TCP 6m10sNAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/volcano-admission1/11 1 6m10sdeployment.apps/volcano-controllers 1/11 1 6m10sdeployment.apps/volcano-scheduler1/11 1 6m10sNAMEDESIRED CURRENT READY AGEreplicaset.apps/volcano-admission-5bd5756f791 1 1 6m10sreplicaset.apps/volcano-controllers-687948d9c8 1 1 1 6m10sreplicaset.apps/volcano-scheduler-94998fc641 1 1 6m10sNAME COMPLETIONS DURATION AGEjob.batch/volcano-admission-init 1/1 28s 6m10s

⑥ 使用 Volcano CRD 资源

创建一个名为 “test” 的自定义队列:

# cat <<EOF | kubectl apply -f -apiVersion: scheduling.volcano.sh/v1beta1kind: Queuemetadata:name: testspec:weight: 1reclaimable: falsecapability:cpu: 2EOF

创建一个名为 “job-1” 的 Volcano Job:

# cat <<EOF | kubectl apply -f -apiVersion: batch.volcano.sh/v1alpha1kind: Jobmetadata:name: job-1spec:minAvailable: 1schedulerName: volcanoqueue: testpolicies:- event: PodEvictedaction: RestartJobtasks:- replicas: 1name: nginxpolicies:- event: TaskCompletedaction: CompleteJobtemplate:spec:containers:- command:- sleep- 10mimage: nginx:latestname: nginxresources:requests:cpu: 1limits:cpu: 1restartPolicy: NeverEOF

检查自定义 job 的状态:

# kubectl get vcjob job-1 -oyamlapiVersion: batch.volcano.sh/v1alpha1kind: Jobmetadata:creationTimestamp: "-05-18T12:59:37Z"generation: 1managedFields:- apiVersion: batch.volcano.sh/v1alpha1fieldsType: FieldsV1fieldsV1:f:spec:.: {}f:minAvailable: {}f:policies: {}f:queue: {}f:schedulerName: {}manager: kubectloperation: Updatetime: "-05-18T12:59:37Z"- apiVersion: batch.volcano.sh/v1alpha1fieldsType: FieldsV1fieldsV1:f:spec:f:tasks: {}f:status:.: {}f:minAvailable: {}f:running: {}f:state:.: {}f:lastTransitionTime: {}f:phase: {}manager: vc-controller-manageroperation: Updatetime: "-05-18T12:59:45Z"name: job-1namespace: defaultresourceVersion: "850500"selfLink: /apis/batch.volcano.sh/v1alpha1/namespaces/default/jobs/job-1uid: 215409ec-7337-4abf-8bea-e6419defd688spec:minAvailable: 1policies:- action: RestartJobevent: PodEvictedqueue: testschedulerName: volcanotasks:- name: nginxpolicies:- action: CompleteJobevent: TaskCompletedreplicas: 1template:spec:containers:- command:- sleep- 10mimage: nginx:latestname: nginxresources:limits:cpu: 1requests:cpu: 1status:minAvailable: 1running: 1state:lastTransitionTime: "-05-18T12:59:45Z"phase: Running

检查名为 ”job-1“ 的 PodGroup 的状态:

# kubectl get podgroup job-1 -oyamlapiVersion: scheduling.volcano.sh/v1beta1kind: PodGroupmetadata:creationTimestamp: "-05-18T12:59:37Z"generation: 5managedFields:- apiVersion: scheduling.volcano.sh/v1beta1fieldsType: FieldsV1fieldsV1:f:metadata:f:ownerReferences:.: {}k:{"uid":"215409ec-7337-4abf-8bea-e6419defd688"}:.: {}f:apiVersion: {}f:blockOwnerDeletion: {}f:controller: {}f:kind: {}f:name: {}f:uid: {}f:spec:.: {}f:minMember: {}f:minResources:.: {}f:cpu: {}f:queue: {}f:status: {}manager: vc-controller-manageroperation: Updatetime: "-05-18T12:59:37Z"- apiVersion: scheduling.volcano.sh/v1beta1fieldsType: FieldsV1fieldsV1:f:status:f:conditions: {}f:phase: {}f:running: {}manager: vc-scheduleroperation: Updatetime: "-05-18T12:59:45Z"name: job-1namespace: defaultownerReferences:- apiVersion: batch.volcano.sh/v1alpha1blockOwnerDeletion: truecontroller: truekind: Jobname: job-1uid: 215409ec-7337-4abf-8bea-e6419defd688resourceVersion: "850501"selfLink: /apis/scheduling.volcano.sh/v1beta1/namespaces/default/podgroups/job-1uid: ea5b4f87-b750-440b-a41a-5c9944a7ae43spec:minMember: 1minResources:cpu: "1"queue: teststatus:conditions:- lastTransitionTime: "-05-18T12:59:38Z"message: '1/0 tasks in gang unschedulable: pod group is not ready, 1 minAvailable.'reason: NotEnoughResourcesstatus: "True"transitionID: 606145d1-660f-4e01-850d-ed556cebc098type: Unschedulable- lastTransitionTime: "-05-18T12:59:45Z"reason: tasks in gang are ready to be scheduledstatus: "True"transitionID: 57e6ba9e-55cc-47ce-a37e-d8bddd99d54btype: Scheduledphase: Runningrunning: 1

检查队列 “test” 的状态:

# kubectl get queue test -oyamlapiVersion: scheduling.volcano.sh/v1beta1kind: Queuemetadata:creationTimestamp: "-05-18T12:59:30Z"generation: 1managedFields:- apiVersion: scheduling.volcano.sh/v1beta1fieldsType: FieldsV1fieldsV1:f:spec:.: {}f:capability: {}f:reclaimable: {}f:weight: {}manager: kubectloperation: Updatetime: "-05-18T12:59:30Z"- apiVersion: scheduling.volcano.sh/v1beta1fieldsType: FieldsV1fieldsV1:f:spec:f:capability:f:cpu: {}f:status:.: {}f:running: {}f:state: {}manager: vc-controller-manageroperation: Updatetime: "-05-18T12:59:39Z"name: testresourceVersion: "850474"selfLink: /apis/scheduling.volcano.sh/v1beta1/queues/testuid: b9c9ee54-5ef8-4784-9bec-7a665acb1fdespec:capability:cpu: 2reclaimable: falseweight: 1status:running: 1state: Open

二、Kubernetes 运行作业的问题分析及解决方案

① 报错 cannot allocate memory 或者 no space left on device,修复 Kubernetes 内存泄露问题

(A)问题描述和分析

当 Kubernetes 集群运行日久以后,有的 Node 无法再新建 Pod,并且出现如下错误,当重启服务器之后,才可以恢复正常使用,查看 Pod 状态的时候会出现以下报错:

applying cgroup … caused: mkdir …no space left on device或者在 describe pod 的时候出现 cannot allocate memory

这时候 Kubernetes 集群可能就存在内存泄露的问题,当创建的 Pod 越多的时候内存会泄露的越多越快。具体查看是否存在内存泄露:

cat /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo当出现 cat: /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo: Input/output error 则说明不存在内存泄露的情况如果存在内存泄露会出现slabinfo - version: 2.1# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>

(B)解决方案

可以考虑关闭 runc 和 kubelet 的 kmem,因为升级内核的方案改动较大,此处不采用。kmem 导致内存泄露的原因:内核对于每个 cgroup 子系统的的条目数是有限制的,限制的大小定义在 kernel/cgroup.c #L139,当正常在 cgroup 创建一个 group 的目录时,条目数就加 1。我们遇到的情况就是因为开启 kmem accounting 功能,虽然 cgroup 的目录删除,但是条目没有回收,这样后面就无法创建 65535 个 cgroup。也就是说,在当前内核版本下,开启 kmem accounting 功能,会导致 memory cgroup 的条目泄漏无法回收。

(C)具体实现

需要重新编译 runc: 配置 go 语言环境:

wget /go/go1.12.9.linux-amd64.tar.gztar xf go1.12.9.linux-amd64.tar.gz -C /usr/local/写入 bashrcvim ~/.bashrc export GOPATH="/data/Documents"export GOROOT="/usr/local/go"export PATH="$GOROOT/bin:$GOPATH/bin:$PATH"export GO111MODULE=off验证source ~/.bashrc go env

下载 runc 源码:

mkdir -p /data/Documents/src//opencontainers/cd /data/Documents/src//opencontainers/git clone /opencontainers/runccd runc/git checkout v1.0.0-rc9 # 切到 v1.0.0-rc9 tag

编译:

安装编译组件sudo yum install libseccomp-develmake BUILDTAGS='seccomp nokmem'编译完成之后会在当前目录下看到一个runc的可执行文件,等kubelet编译完成之后会将其替换

编译 kubelet: 下载 Kubernetes 源码:

mkdir -p /root/k8s/cd /root/k8s/git clone /kubernetes/kubernetescd kubernetes/git checkout v1.15.3

制作编译环境的镜像 Dockerfile 如下:

FROM centos:centos7.3.1611ENV GOROOT /usr/local/goENV GOPATH /usr/local/gopathENV PATH /usr/local/go/bin:$PATHRUN yum install rpm-build which where rsync gcc gcc-c++ automake autoconf libtool make -y \&& curl -L /dl/golang/go1.12.9.linux-amd64.tar.gz | tar zxvf - -C /usr/local

在制作好的 go 环境镜像中来进行编译 kubelet:

docker run -it --rm -v /root/k8s/kubernetes:/usr/local/gopath/src/k8s.io/kubernetes build-k8s:centos-7.3-go-1.12.9-k8s-1.15.3 bashcd /usr/local/gopath/src/k8s.io/kubernetes# 编译GO111MODULE=off KUBE_GIT_TREE_STATE=clean KUBE_GIT_VERSION=v1.15.3 make kubelet GOFLAGS="-tags=nokmem"

替换原有的 runc 和 kubelet: 将原有 runc 和 kubelet 备份:

mv /usr/bin/kubelet /home/kubeletmv /usr/bin/docker-runc /home/docker-runc

停止 Docker 和 kubelet:

systemctl stop dockersystemctl stop kubelet

将编译好的 runc 和 kubelet 进行替换:

cp kubelet /usr/bin/kubeletcp kubelet /usr/local/bin/kubeletcp runc /usr/bin/docker-runc

检查 kmem 是否关闭前需要将此节点的 Pod 杀掉重启或者重启服务器,当结果为 0 时成功:

cat /sys/fs/cgroup/memory/kubepods/burstable/memory.kmem.usage_in_bytes

是否还存在内存泄露的情况:

cat /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo

② Kubernetes 证书过期问题的解决

(A)问题分析

出现 Kubernetes API 无法调取的现象,使用 kubectl 命令获取资源均返回如下报错:

Unable to connect to the server: x509: certificate has expired or is not yet valid

可以猜测 Kubernetes 集群的证书过期,使用命令排查证书的过期时间:

kubeadm alpha certs check-expiration

(B)问题解决

由于使用 kubeadm 部署的 Kubernetes 集群,所以更新起证书也是比较方便的,默认的证书时间有效期是一年,集群的 Kubernetes 版本是 1.15.3版本是可以使用以下命令来更新证书的,但是一年之后还是会到期,这样就很麻烦,所以需要了解一下 Kubernetes 的证书,然后来生成一个时间很长的证书,这样就可以不用去总更新证书:

kubeadm alpha certs renew all --config=kubeadm.yamlsystemctl restart kubeletkubeadm init phase kubeconfig all --config kubeadm.yaml然后将生成的配置文件替换,重启 kube-apiserver、kube-controller、kube-scheduler、etcd 这 4 个容器即可

另外 kubeadm 会在控制面板升级的时候自动更新所有证书,所以使用 kubeadm 搭建得集群最佳的做法是经常升级集群,这样可以确保集群保持最新状态并保持合理的安全性。但是对于实际的生产环境我们可能并不会去频繁得升级集群,所以这个时候就需要去手动更新证书:

首先在/etc/kubernetes/manifests/kube-controller-manager.yaml文件加入配置spec:containers:- command:- kube-controller-manager# 设置证书有效期为- --experimental-cluster-signing-duration=87600h - --client-ca-file=/etc/kubernetes/pki/ca.crt

修改完成后 kube-controller-manager 会自动重启生效,然后需要使用下面的命令为 Kubernetes 证书 API 创建一个证书签名请求,如果设置例如 cert-manager 等外部签名者,则会自动批准证书签名请求(CSRs)。否者,必须使用 kubectl certificate 命令手动批准证书,以下 kubeadm 命令输出要批准的证书名称,然后等待批准发生。如下所示,通过调用 Kubernetes 的 API 来实现更新一个 10 年的证书:

kubeadm alpha certs renew all --use-api --config kubeadm.yaml &

需要将全部 pending 的证书全部批准,还不能直接重启控制面板的几个组件,这是因为使用 kubeadm 安装的集群对应的 etcd 默认是使用的 /etc/kubernetes/pki/etcd/ca.crt 这个证书进行前面的,而上面用命令 kubectl certificate approve 批准过后的证书是使用的默认的 /etc/kubernetes/pki/ca.crt 证书进行签发的,因此需要替换 etcd 中的 CA 机构证书:

# 先拷贝静态Pod资源清单cp -r /etc/kubernetes/manifests/ /etc/kubernetes/manifests.bakvi /etc/kubernetes/manifests/etcd.yaml......spec:containers:- command:- etcd# 修改为CA文件- --peer-trusted-ca-file=/etc/kubernetes/pki/ca.crt- --trusted-ca-file=/etc/kubernetes/pki/ca.crt......volumeMounts:- mountPath: /var/lib/etcdname: etcd-data- mountPath: /etc/kubernetes/pki # 更改证书目录name: etcd-certsvolumes:- hostPath:path: /etc/kubernetes/pki # 将 pki 目录挂载到etcd中去type: DirectoryOrCreatename: etcd-certs- hostPath:path: /var/lib/etcd type: DirectoryOrCreatename: etcd-data......

由于 kube-apiserver 要连接 etcd 集群,因此也需要重新修改对应的 etcd ca 文件:

vi /etc/kubernetes/manifests/kube-apiserver.yaml......spec:containers:- command:- kube-apiserver# 将etcd ca文件修改为默认的ca.crt文件- --etcd-cafile=/etc/kubernetes/pki/ca.crt......

除此之外还需要替换 requestheader-client-ca-file 文件,默认是 /etc/kubernetes/pki/front-proxy-ca.crt 文件,现在也需要替换成默认的 CA 文件,否则使用聚合 API,比如安装 metrics-server 后执行 kubectl top 命令就会报错:

cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/front-proxy-ca.crtcp /etc/kubernetes/pki/ca.key /etc/kubernetes/pki/front-proxy-ca.key

这样就得到了一个 10 年证书的 Kubernetes 集群,还可以通过重新编译 kubeadm 来实现一个 10 年证书。

三、Volcano 容器在气象行业 HPC 高性能计算场景的应用

① 什么是 HPC ?

HPC 是 High Performance Computing(高性能计算)的缩写,平时提到的 HPC,一般指代高性能计算机群(HPCC),它将大量的计算机软件/硬件整合起来,将大的计算作业分解成一个个小部分,通过并行计算的方式加以解决。HPC 高性能计算在 CAE 仿真、动漫渲染、物理化学、石油勘探、生命科学、气象环境等领域有广泛的应用。一般来说,高性能计算集群(HPCC)包含如下部分: PBS:Protable Batch System,资源管理器,负责管理集群中所有节点的资源,除了 PBS 意外,常用的资源管理系统还有 Slurm,LSF 等; Maui:第三方任务调度器,支持资源预留,支持各种复杂的优先级策略,支持抢占机制等,资源管理器中内置了默认的任务调取器,但功能往往比较简单; OpenMPI:上层通信环境,兼顾通信库,编译,分布式启动任务的功能。 PBS 和 Maui 对于用户来说是完全透明的,用户只需要按照 PBS 提供的方式提交作业即可,不需要了解内部细节,而 OpenMPI 则需要用户进行相关了解,来编写能够并行计算的应用。以 mpirun -np 4 ./mpi_hello_world 为例介绍 mpi 作业是如何运行的: 说明: 调用 openmpi 或者其他 mpi 的库来编写源代码,示例就是输出 hello world 字符串; 使用支持 MPI 的编译器来编译出可执行程序 mpi_hello_world; 将 mpi_hello_world 分发到各个节点,也可以通过共享文件系统来实现对 mpi_hello_world 的访问; 运行 mpirun 来并行执行 mpi_hello_world。

② 什么是 WRF ?

WRF 是 Weather Research and Forecasting Model(天气研究和预报模型)的简称,是一种比较常见的 HPC 应用,WRF 是一种中尺度数值天气预报系统,设计用于大气研究和业务预报应用,可以根据实际的大气条件或理想化的条件进行模拟。由于 WRF 包含多个模块,因此处理流程可能不尽相同,这里仅以 WPS 和 WRF 这两个模块为例介绍一下完整的 WRF 流程: 外部数据源:包含静态地理数据,网络数据等,静态地理数据可以理解为某区域内的地理信息,例如山川,河流,湖泊,森林等等。网络数据是某区域内的气象环境数据,例如气温,风速风向,空气湿度,降雨量等。前处理系统 WRF Pre-processing System:前处理系统用于载入地理和气象数据,对气象数据进行插值,为 WRF 提供输入数据,该部分包含 3 个程序: geogrid.exe:定义模型投影、区域范围,嵌套关系,对地表参数进行插值,处理地形资料和网格数据; ungrib.exe:从 grib 数据中提取所需要的气象参数; metgrid.exe:将气象参数插值到模拟区域。 核心模拟系统(WRF):核心模拟系统对前处理系统生成的气象信息进行模拟和预报,是 WRF 的核心模块,该部分包含 2 个程序: real.exe:初始化实际气象数据; wrf.exe:模拟及预报结果; real.exe 和 wrf.exe 可以通过 mpi 并行运算来提升计算速度,如下所示,wrfinput_d0X 和 wrfbdy_d0X 为 real.exe 的运算结果,wrf.exe 以该结果为输入进行模拟演算,生成最终的气象模拟结果 wrfout_dxx_yyyy-mm-dd_hh:mm:ss,并由后处理系统进行验证展示: 后处理系统用来验证和显示核心模拟系统的计算结果,主要由各种第三方图像和验证工具组成。如下所示展示 Conus 2.5km 算例中各个地区相对湿度的模拟预报结果,Conus 2.5km 是指美国本土气象数据,分辨率为 2.5km(将整个区域分成一个个 2.5km2.5km2.5km 的方格,每个方格中的气象信息被认为是完全一致的):

③ HPC Volcano

如下所示,一个 HPCC 包括资源管理器,调度器和 mpi 并行计算库三部分,其中资源管理器由 Kubernetes 负责,调度器由 Volcano 负责: 在 Kubernetes+Volcano 环境中运行 HPC 应用,本质上就是在容器中运行 HPC 作业,示意图如下: 将运行的容器分为 Master 容器和 Worker 容器两种,Master 容器负责启动 mpirun/mpiexec 命令,Worker 容器负责运行真正的计算作业。因此 Volcano 为了支持 MPI 作业运行,添加了如下功能: Volcano job 支持定义多个 pod 模板,能够同时定义 master pod 和 worker pod; 支持 Gang scheduling,保证作业中所有的 pod 能够同时启动; Master/Worker pod 内部主机 IP 映射; Master/Workerpod 之间 ssh 免密登录; 作业生命周期管理。 Volcano mpi 作业配置 mpi_sample.yaml:

apiVersion: batch.Volcano.sh/v1alpha1kind: Jobmetadata:name: mpi-joblabels:# 根据业务需要设置作业类型"Volcano.sh/job-type": "MPI"spec:# 设置最小需要的服务 (小于总replicas数)# 这里等于mpimaster和mpiworker的总数minAvailable: 3# 指定调度器为VolcanoschedulerName: Volcanoplugins:# 提供 ssh 免密认证ssh: []# 提供运行作业所需要的网络信息,hosts文件,headless service等svc: []# 如果有pod被 杀死,重启整个作业policies:- event: PodEvictedaction: RestartJobtasks:- replicas: 1name: mpimaster# 当 mpiexec 结束,认为整个mpi作业结束policies:- event: TaskCompletedaction: CompleteJobtemplate:spec:# Volcano的信息会统一放到 /etc/Volcano 目录下containers:# master容器中# 1. 启动sshd服务# 2. 通过/etc/Volcano/mpiworker.host获取mpiworker容器列表# 3. 运行mpirun/mpiexec- command:- /bin/sh- -c- |MPI_HOST=`cat /etc/Volcano/mpiworker.host | tr "\n" ","`;mkdir -p /var/run/sshd; /usr/sbin/sshd;mpiexec --allow-run-as-root --host ${MPI_HOST} -np 2 mpi_hello_world;image: Volcanosh/example-mpi:0.0.1imagePullPolicy: IfNotPresentname: mpimasterports:- containerPort: 22name: mpijob-portworkingDir: /homeresources:requests:cpu: "100m"memory: "1024Mi"limits:cpu: "100m"memory: "1024Mi"restartPolicy: OnFailureimagePullSecrets:- name: default-secret- replicas: 2name: mpiworkertemplate:spec:containers:# worker容器中只需要启动sshd服务- command:- /bin/sh- -c- |mkdir -p /var/run/sshd; /usr/sbin/sshd -D;image: Volcanosh/example-mpi:0.0.1imagePullPolicy: IfNotPresentname: mpiworkerports:- containerPort: 22name: mpijob-portworkingDir: /homeresources:requests:cpu: "100m"memory: "2048Mi"limits:cpu: "100m"memory: "2048Mi"restartPolicy: OnFailureimagePullSecrets:- name: default-secret

提交 mpi Volcano job: 作业执行完毕: 查看 master pod 的结果: 通过上述执行结果可以看出,在作业执行结束后,Volcano 只清理 worker pod,保留 master pod,这样用户 kubectl 命令获取执行结果。此外,由于网络构建可能会出现延迟,在作业运行开始时,master pod 会出现连接 worker pod 失败的情况。对于这种情况,Volcano 会自动重启 master pod,保证作业能够正确运行。通过以上示例,可以看出 Volcano 想要运行 WRF 作业的话,理论上需要将其中的 mpi_hello_world 替换为 real.exe/wrf.exe,此外,用户还需要进行如下准备: 自建 docker images,包含完整的 WRF 运行环境; 将计算所需要的数据(原生数据或者中间结果数据)挂载到相应的容器中。 这样就能在 Kubernetes+Volcano 上运行气象模拟作业。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。