我們發(fā)現(xiàn)調(diào)度器端到端的延遲達(dá)到7ms,相當(dāng)于140pod/秒的吞吐量,比我們之前測(cè)試看到的20pod/秒要高出很多。這說(shuō)明瓶頸在調(diào)度器自身以外。
我們繼續(xù)通過(guò)查看性能指標(biāo)和日志來(lái)縮小問(wèn)題的范圍。我們發(fā)現(xiàn)瓶頸在replication controller里??催@里:
我們打印了日志,發(fā)現(xiàn)等到500 CreatePods() 用了25秒。這正好是20pod/秒,但 CreatePods() 的延遲只有1ms。
不久之后,我們?cè)诳蛻舳擞脩衾锇l(fā)現(xiàn)了一個(gè)速率限制。速率限制是用來(lái)保護(hù)API服務(wù)器不被過(guò)度使用。在我們的測(cè)試中,我們并不需要它。 我們提高了限制,想看看調(diào)度速度的邊界。它沒(méi)有完全解決問(wèn)題。
結(jié)果,我們又發(fā)現(xiàn)了一個(gè)速率限制,并且修復(fù)了一個(gè)程序的非有效路徑。在那些變化之后,我們得以看到了最終的提高。在100個(gè)節(jié)點(diǎn)的建立中,平均建立速度從20pod/秒提高到超過(guò)300pod/秒,在50秒中完成,平均pod吞吐量在60pod/秒。
目光轉(zhuǎn)向調(diào)度器
然后我們嘗試在1千個(gè)節(jié)點(diǎn)的集群上進(jìn)行提高。然而,我們這次沒(méi)這么幸運(yùn)??纯聪聢D:
在一千個(gè)節(jié)點(diǎn)的集群上,花了5243秒來(lái)跑3萬(wàn)個(gè)pod,平均吞吐量在5.72pod/秒。Creation rate持續(xù)增加,但running rate一直比較低。
我們?nèi)缓笥诌M(jìn)行了測(cè)試,查看調(diào)度器的性能指標(biāo)。這次,調(diào)度延遲變成了開始時(shí)的60ms,到結(jié)束時(shí)(即3萬(wàn)個(gè)pod)增加到了200ms。結(jié)合我們?cè)谌罩竞蛨D表中所見,我們意識(shí)到以下兩點(diǎn):
60ms的延遲很高。調(diào)度器很可能變成了瓶頸。如果我們能把它降低,這樣就能增加調(diào)度速度,這樣pod的running rate就很有可能變高。 調(diào)度延遲隨著被調(diào)度pod總體數(shù)量的增加而上升,這導(dǎo)致了集群pod的running rate的下降。這在調(diào)度器里面是個(gè)擴(kuò)容問(wèn)題。
調(diào)度器的代碼庫(kù)是很復(fù)雜的,我們需要很細(xì)致的歸檔才能理解調(diào)度器在哪塊花費(fèi)了時(shí)間。但是,在Kubernetes上面重復(fù)同樣的過(guò)程是很耗時(shí)的,我們的測(cè)試用了超過(guò)兩個(gè)小時(shí)才完成。我們想要一個(gè)更加輕便一些的方法來(lái)做調(diào)度器組建測(cè)試,從而集中我們的精力和時(shí)間。這樣,我們就能寫一個(gè)像Go unit test那樣的調(diào)度器的benchmark做基準(zhǔn)工具。這個(gè)工具測(cè)試調(diào)度器作為一個(gè)整體,而不用啟動(dòng)不必要的部件。更多細(xì)節(jié)可以從我們的幻燈片(https://docs.google.com/presentation/d/1HYGDFTWyKjJveAk_t10L6uxoZOWTiRVLLCZj5Zxw5ok/edit?usp=sharing)中找到關(guān)于調(diào)度器性能測(cè)試以及在Kubernetes pull request中看到。
通過(guò)使用benchmarking做基準(zhǔn)的工具,我們高效地工作,打破調(diào)度器在1千個(gè)節(jié)點(diǎn)集群的3萬(wàn)個(gè)pod建立上的瓶頸。
例如,在Kubernetes的issue#18126(https://github.com/kubernetes/kubernetes/issues/18126)中,我們有如下pprof (performance profiling)結(jié)果:
總共的79秒鐘內(nèi),Round()方法只用了18秒。我們覺(jué)得這對(duì)于取整而言是失效的。我們用更加有效的實(shí)現(xiàn)方式調(diào)整了這個(gè)問(wèn)題。結(jié)果,我們把對(duì)1千個(gè)節(jié)點(diǎn)上調(diào)度1千個(gè)pod的平均調(diào)度延遲時(shí)間從53秒降低到23秒。
這樣,我們可以挖掘出更多沒(méi)有效率且成為瓶頸的代碼。在以下的upstream issue中我們進(jìn)行了匯報(bào)并做了提升:
https://github.com/kubernetes/kubernetes/pull/18170 https://github.com/kubernetes/kubernetes/issues/18255 https://github.com/kubernetes/kubernetes/pull/18413 https://github.com/kubernetes/kubernetes/issues/18831