溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Kubernetes的架構(gòu)怎么使用

發(fā)布時(shí)間:2021-12-20 09:52:25 來(lái)源:億速云 閱讀:140 作者:iii 欄目:云計(jì)算

這篇文章主要講解了“Kubernetes的架構(gòu)怎么使用”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Kubernetes的架構(gòu)怎么使用”吧!

分布式TensorFlow

TensorFlow是一個(gè)使用數(shù)據(jù)流圖進(jìn)行數(shù)值計(jì)算的開(kāi)源軟件庫(kù)。圖中的節(jié)點(diǎn)代表數(shù)學(xué)運(yùn)算,而圖中的邊則代表在這些節(jié)點(diǎn)之間傳遞的多維數(shù)組(張量)。這種靈活的架構(gòu)可讓您使用一個(gè) API 將計(jì)算工作部署到桌面設(shè)備、服務(wù)器或者移動(dòng)設(shè)備中的一個(gè)或多個(gè) CPU 或 GPU。 關(guān)于TensorFlow的基礎(chǔ)概念,我就不多介紹了。

單機(jī)TensorFlow

下面是一個(gè)單機(jī)式TensorFlow訓(xùn)練示意圖,通過(guò)Client提交Session,定義這個(gè)worker要用哪個(gè)cpu/gpu做什么事。

Kubernetes的架構(gòu)怎么使用

分布式TensorFlow

2016年4月TensorFlow發(fā)布了0.8版本宣布支持分布式計(jì)算,我們稱之為Distributed TensorFlow。這是非常重要的一個(gè)特性,因?yàn)樵贏I的世界里,訓(xùn)練的數(shù)據(jù)量和模型參數(shù)通常會(huì)非常大。比如Google Brain實(shí)驗(yàn)室今年發(fā)表的論文OUTRAGEOUSLY LARGE NEURAL NETWORKS: THE SPARSELY-GATED MIXTURE-OF-EXPERTS LAYER中提到一個(gè)680億個(gè)Parameters的模型,如果只能單機(jī)訓(xùn)練,那耗時(shí)難于接受。通過(guò)Distributed TensorFlow,可以利用大量服務(wù)器構(gòu)建分布式TensorFlow集群來(lái)提高訓(xùn)練效率,減少訓(xùn)練時(shí)間。

通過(guò)TensorFlow Replcation機(jī)制,用戶可以將SubGraph分布到不同的服務(wù)器中進(jìn)行分布式計(jì)算。TensorFlow的副本機(jī)制又分為兩種,In-graph和Between-graph。

In-graph Replication簡(jiǎn)單來(lái)講,就是通過(guò)單個(gè)client session定義這個(gè)TensorFlow集群的所有task的工作。

Kubernetes的架構(gòu)怎么使用

與之相對(duì)地,Between-graph Replication就是每個(gè)worker都有獨(dú)立的client來(lái)定義自己的工作。

Kubernetes的架構(gòu)怎么使用

下面是抽象出來(lái)的分布式TensorFlow Framework如下:

Kubernetes的架構(gòu)怎么使用

我們先來(lái)了解里面的幾個(gè)概念:

  • Cluster

一個(gè)TensorFlow Cluster有一個(gè)或多個(gè)jobs組成,每個(gè)job又由一個(gè)或多個(gè)tasks構(gòu)成。Cluster的定義是通過(guò)tf.train.ClusterSpec來(lái)定義的。比如,定義一個(gè)由3個(gè)worker和2個(gè)ps的TensorFlow Cluster的ClusterSpec如下:

tf.train.ClusterSpec({
    "worker": [
        "worker0.example.com:2222",  //主機(jī)名也可以使用IP
        "worker1.example.com:2222",
        "worker2.example.com:2222"
    ],
    "ps": [
        "ps0.example.com:2222",
        "ps1.example.com:2222"
    ]})
  • Client

Client用來(lái)build一個(gè)TensorFlow Graph,并構(gòu)建一個(gè)tensorflow::Session用來(lái)與集群通信。一個(gè)Client可以與多個(gè)TensorFlow Server交互,一個(gè)Server能服務(wù)多個(gè)Client。

  • Job

一個(gè)Job由tasks list組成,Job分ps和worker兩種類型。ps即parameter server,用來(lái)存儲(chǔ)和更新variables的,而worker可以認(rèn)為是無(wú)狀態(tài)的,用來(lái)作為計(jì)算任務(wù)的。workers中,一般都會(huì)選擇一個(gè)chief worker(通常是worker0),用來(lái)做訓(xùn)練狀態(tài)的checkpoint,如果有worker故障,那么可以從最新checkpoint中restore。

  • Task

每個(gè)Task對(duì)應(yīng)一個(gè)TensorFlow Server,對(duì)應(yīng)一個(gè)單獨(dú)的進(jìn)程。一個(gè)Task屬于某個(gè)Job,通過(guò)一個(gè)index來(lái)標(biāo)記它在對(duì)應(yīng)Job的tasks中的位置。每個(gè)TensorFlow均實(shí)現(xiàn)了Master service和Worker service。Master service用來(lái)與集群內(nèi)的worker services進(jìn)行g(shù)rpc交互。Worker service則是用local device來(lái)計(jì)算subgraph。

關(guān)于Distributed TensorFlow的更多內(nèi)容,請(qǐng)參考官方內(nèi)容www.tensorflow.org/deplopy/distributed

分布式TensorFlow的缺陷

分布式TensorFlow能利用數(shù)據(jù)中心所有服務(wù)器構(gòu)成的資源池,讓大量ps和worker能分布在不同的服務(wù)器進(jìn)行參數(shù)存儲(chǔ)和訓(xùn)練,這無(wú)疑是TensorFlow能否在企業(yè)落地的關(guān)鍵點(diǎn)。然而,這還不夠,它還存在一下先天不足:

  • 訓(xùn)練時(shí)TensorFlow各個(gè)Task資源無(wú)法隔離,很有可能會(huì)導(dǎo)致任務(wù)間因資源搶占互相影響。

  • 缺乏調(diào)度能力,需要用戶手動(dòng)配置和管理任務(wù)的計(jì)算資源。

  • 集群規(guī)模大時(shí),訓(xùn)練任務(wù)的管理很麻煩,要跟蹤和管理每個(gè)任務(wù)的狀態(tài),需要在上層做大量開(kāi)發(fā)。

  • 用戶要查看各個(gè)Task的訓(xùn)練日志需要找出對(duì)應(yīng)的服務(wù)器,并ssh過(guò)去,非常不方便。

  • TensorFlow原生支持的后端文件系統(tǒng)只支持:標(biāo)準(zhǔn)Posix文件系統(tǒng)(比如NFS)、HDFS、GCS、memory-mapped-file。大多數(shù)企業(yè)中數(shù)據(jù)都是存在大數(shù)據(jù)平臺(tái),因此以HDFS為主。然而,HDFS的Read性能并不是很好。

  • 當(dāng)你試著去創(chuàng)建一個(gè)大規(guī)模TensorFlow集群時(shí),發(fā)現(xiàn)并不輕松;

TensorFlow on Kubernetes架構(gòu)與原理

TensorFlow的這些不足,正好是Kubernetes的強(qiáng)項(xiàng):

  • 提供ResourceQuota, LimitRanger等多種資源管理機(jī)制,能做到任務(wù)之間很好的資源隔離。

  • 支持任務(wù)的計(jì)算資源的配置和調(diào)度。

  • 訓(xùn)練任務(wù)以容器方式運(yùn)行,Kubernetes提供全套的容器PLEG接口,因此任務(wù)狀態(tài)的管理很方便。

  • 輕松對(duì)接EFK/ELK等日志方案,用戶能方便的查看任務(wù)日志。

  • 支持Read性能更優(yōu)秀的分布式存儲(chǔ)(Glusterfs),但目前我們也還沒(méi)對(duì)接Glusterfs,有計(jì)劃但沒(méi)人力。

  • 通過(guò)聲明式文件實(shí)現(xiàn)輕松快捷的創(chuàng)建一個(gè)大規(guī)模TensorFlow集群。

TensorFlow on Kubernetes架構(gòu)

Kubernetes的架構(gòu)怎么使用

TensorFlow on Kubernetes原理

在我們的TensorFlow on Kubernetes方案中,主要用到以下的Kubernetes對(duì)象:

  • Kubernetes Job

我們用Kubernetes Job來(lái)部署TensorFlow Worker,Worker訓(xùn)練正常完成退出,就不會(huì)再重啟容器了。注意Job中的Pod Template restartPolicy只能為Never或者OnFailure,不能為Always,這里我們?cè)O(shè)定restartPolicy為OnFailure,worker一旦異常退出,都會(huì)自動(dòng)重啟。但是要注意,要保證worker重啟后訓(xùn)練能從checkpoint restore,不然worker重啟后又從step 0開(kāi)始,可能跑了幾天的訓(xùn)練就白費(fèi)了。如果你使用TensorFlow高級(jí)API寫(xiě)的算法,默認(rèn)都實(shí)現(xiàn)了這點(diǎn),但是如果你是使用底層core API,一定要注意自己實(shí)現(xiàn)。

kind: Job
apiVersion: batch/v1
metadata:
  name: {{ name }}-{{ task_type }}-{{ i }}
  namespace: {{ name }}
spec:
  template:
    metadata:
      labels:
        name: {{ name }}
        job: {{ task_type }}
        task: "{{ i }}"
    spec:
      imagePullSecrets:
      - name: harborsecret
      containers:
      - name: {{ name }}-{{ task_type }}-{{ i }}
        image: {{ image }}
        resources:
          requests:
            memory: "4Gi"
            cpu: "500m"
        ports:
        - containerPort: 2222
        command: ["/bin/sh", "-c", "export CLASSPATH=.:/usr/lib/jvm/java-1.8.0/lib/tools.jar:$(/usr/lib/hadoop-2.6.1/bin/hadoop classpath --glob); wget -r -nH  -np --cut-dir=1 -R 'index.html*,*gif'  {{ script }}; cd ./{{ name }}; sh ./run.sh {{ ps_hosts() }} {{ worker_hosts() }} {{ task_type }} {{ i }} {{ ps_replicas }} {{ worker_replicas }}"]
      restartPolicy: OnFailure
  • Kubernetes Deployment

TensorFlow PS用Kubernetes Deployment來(lái)部署。為什么不像worker一樣,也使用Job來(lái)部署呢?其實(shí)也未嘗不可,但是考慮到PS進(jìn)程并不會(huì)等所有worker訓(xùn)練完成時(shí)自動(dòng)退出(一直掛起),所以使用Job部署沒(méi)什么意義。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: {{ name }}-{{ task_type }}-{{ i }}
  namespace: {{ name }}
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: {{ name }}
        job: {{ task_type }}
        task: "{{ i }}"
    spec:
      imagePullSecrets:
      - name: harborsecret
      containers:
      - name: {{ name }}-{{ task_type }}-{{ i }}
        image: {{ image }}
        resources:
          requests:
            memory: "4Gi"
            cpu: "500m"
        ports:
        - containerPort: 2222
        command: ["/bin/sh", "-c","export CLASSPATH=.:/usr/lib/jvm/java-1.8.0/lib/tools.jar:$(/usr/lib/hadoop-2.6.1/bin/hadoop classpath --glob); wget -r -nH  -np --cut-dir=1 -R 'index.html*,*gif'  {{ script }}; cd ./{{ name }}; sh ./run.sh {{ ps_hosts() }} {{ worker_hosts() }} {{ task_type }} {{ i }} {{ ps_replicas }} {{ worker_replicas }}"]
      restartPolicy: Always

關(guān)于TensorFlow PS進(jìn)程掛起的問(wèn)題,請(qǐng)參考https://github.com/tensorflow/tensorflow/issues/4713.我們是這么解決的,開(kāi)發(fā)了一個(gè)模塊,watch每個(gè)TensorFlow集群的所有worker狀態(tài),當(dāng)所有worker對(duì)應(yīng)Job都Completed時(shí),就會(huì)自動(dòng)去刪除PS對(duì)應(yīng)的Deployment,從而kill PS進(jìn)程釋放資源。

  • Kubernetes Headless Service

Headless Service通常用來(lái)解決Kubernetes里面部署的應(yīng)用集群之間的內(nèi)部通信。在這里,我們也是這么用的,我們會(huì)為每個(gè)TensorFlow對(duì)應(yīng)的Job和Deployment對(duì)象都創(chuàng)建一個(gè)Headless Service作為worker和ps的通信代理。

kind: Service
apiVersion: v1
metadata:
  name: {{ name }}-{{ task_type }}-{{ i }}
  namespace: {{ name }}
spec:
  clusterIP: None
  selector:
    name: {{ name }}
    job: {{ task_type }}
    task: "{{ i }}"
  ports:
  - port: {{ port }}
    targetPort: 2222

用Headless Service的好處,就是在KubeDNS中,Service Name的域名解析直接對(duì)應(yīng)到PodIp,而沒(méi)有service VIP這一層,這就不依賴于kube-proxy去創(chuàng)建iptables規(guī)則了。少了kube-proxy的iptables這一層,帶來(lái)的是性能的提升。

Kubernetes的架構(gòu)怎么使用

在TensorFlow場(chǎng)景中,這是不可小覷的,因?yàn)橐粋€(gè)TensorFlow Task都會(huì)創(chuàng)建一個(gè)service,幾萬(wàn)個(gè)service是很正常的事,如果使用Normal Service,iptables規(guī)則就幾十萬(wàn)上百萬(wàn)條了,增刪一條iptabels規(guī)則耗時(shí)幾個(gè)小時(shí)甚至幾天,集群早已奔潰。關(guān)于kube-proxy iptables模式的性能測(cè)試數(shù)據(jù),請(qǐng)參考華為PaaS團(tuán)隊(duì)的相關(guān)分享。

  • KubeDNS Autoscaler

前面提到,每個(gè)TensorFlow Task都會(huì)創(chuàng)建一個(gè)service,都會(huì)在KubeDNS中有一條對(duì)應(yīng)的解析規(guī)則,但service數(shù)量太多的時(shí)候,我們發(fā)現(xiàn)有些worker的域名解析失敗概率很大,十幾次才能成功解析一次。這樣會(huì)影響TensorFlow集群內(nèi)各個(gè)task的session建立,可能導(dǎo)致TensorFlow集群起不來(lái)。

為了解決這個(gè)問(wèn)題,我們引入了Kubernetes的孵化項(xiàng)目kubernetes-incubator/cluster-proportional-autoscaler來(lái)對(duì)KubeDNS進(jìn)行動(dòng)態(tài)伸縮。關(guān)于這個(gè)問(wèn)題的具體的細(xì)節(jié),有興趣的同學(xué)可以查看我的博文https://my.oschina.net/jxcdwangtao/blog/1581879。

TensorFlow on Kubernetes實(shí)踐

基于上面的方案,我們開(kāi)發(fā)一個(gè)TaaS平臺(tái),已經(jīng)實(shí)現(xiàn)了基本的功能,包括算法管理、訓(xùn)練集群的創(chuàng)建和管理、模型的管理、模型上線(TensorFlow Serving)、一鍵創(chuàng)建TensorBoard服務(wù)、任務(wù)資源監(jiān)控、集群資源監(jiān)控、定時(shí)訓(xùn)練管理、任務(wù)日志在線查看和批量打包下載等等,這部分內(nèi)容可以參考之前在DockOne上分享的文章http://dockone.io/article/3036。

這只是剛開(kāi)始,我正在做下面的特性:

  • 支持基于訓(xùn)練優(yōu)先級(jí)的任務(wù)搶占式調(diào)度: 用戶在TaaS上創(chuàng)建TensorFlow訓(xùn)練項(xiàng)目時(shí),可以指定項(xiàng)目的優(yōu)先級(jí)為生產(chǎn)(Production)、迭代(Iteration)、調(diào)研(PTR),默認(rèn)為迭代。優(yōu)先級(jí)從高到低依次為**Production --> Iteration --> PTR**。但集群資源不足時(shí),按照任務(wù)優(yōu)先級(jí)進(jìn)行搶占式調(diào)度。

  • 提供像Yarn形式的資源分配視圖,讓用戶對(duì)自己的所有訓(xùn)練項(xiàng)目的資源占用情況變得清晰。

  • 訓(xùn)練和預(yù)測(cè)的混合部署,提供數(shù)據(jù)中心資源利用率。

  • ...

經(jīng)驗(yàn)和坑

整個(gè)過(guò)程中,遇到了很多坑,有TensorFlow的,也有Kubernetes的,不過(guò)問(wèn)題最多的還是我們用的CNI網(wǎng)絡(luò)插件contiv netplugin,每次大問(wèn)題基本都是這個(gè)網(wǎng)絡(luò)插件造成的。Kubernetes是問(wèn)題最少的,它的穩(wěn)定性比我預(yù)期還要好。

  • contiv netplugin的問(wèn)題,在DevOps環(huán)境中還是穩(wěn)定的,在大規(guī)模高并發(fā)的AI場(chǎng)景,問(wèn)題就層出不窮了,產(chǎn)生大量垃圾IP和Openflow流表,直接把Node都成NotReady了,具體的不多說(shuō),因?yàn)閾?jù)我了解,現(xiàn)在用這個(gè)插件的公司已經(jīng)很少了,想了解的私下找我。

  • 在我們的方案中,一個(gè)TensorFlow訓(xùn)練集群就對(duì)應(yīng)一個(gè)Kubernetes Namespace,項(xiàng)目初期我們并沒(méi)有對(duì)及時(shí)清理垃圾Namespace,到后來(lái)集群里上萬(wàn)Namespace的時(shí)候,整個(gè)Kubernetes集群的相關(guān)API性能非常差了,導(dǎo)致TaaS的用戶體驗(yàn)非常差。

  • TensorFlow grpc性能差,上千個(gè)worker的訓(xùn)練集群,概率性的出現(xiàn)這樣的報(bào)錯(cuò)grpc_chttp2_stream request on server; last grpc_chttp2_stream id=xxx, new grpc_chttp2_stream id=xxx,這是TensorFlow底層grpc的性能問(wèn)題,低版本的grpc的Handlergrpc還是單線程的,只能嘗試通過(guò)升級(jí)TensorFlow來(lái)升級(jí)grpc了,或者編譯TensorFlow時(shí)單獨(dú)升級(jí)grpc版本。如果升級(jí)TensorFlow版本的話,你的算法可能還要做API適配。目前我們通過(guò)增加單個(gè)worker的計(jì)算負(fù)載來(lái)減少worker數(shù)量的方法,減少grpc壓力。

  • 還有TensorFlow 自身OOM機(jī)制的問(wèn)題等等

感謝各位的閱讀,以上就是“Kubernetes的架構(gòu)怎么使用”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Kubernetes的架構(gòu)怎么使用這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI