歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~
本文首發在雲+社群,未經許可,不得轉載。
自我介紹
我是知乎的技術中臺工程師,現在是負責知乎的儲存相關元件。我的分享主要基於三個,一個是簡單介紹一下Kafka在知乎是的應用,另外一個是為什麼做基於Kubernetes的Kafka平臺,還有我們如何去實現了基於Kubernetes平臺
Kafka在知乎的應用
Kafka一個是非常優秀的,訊息或者是資料流的元件,在知乎承載了日誌,資料收集,訊息佇列的服務日誌,顯而易見就包括業務,包括執行的DEBUG日誌關鍵性日誌。
資料傳輸,比如我們在瀏覽知乎的時候,有些使用者行為或者內容特徵,通過我們這個平臺做資料的流失處理。
另外一個是Kafka實現對訊息服務。簡單地,就是我關注的A使用者,我是不是應該基於關注使用者行為上做很多事情,這是一個訊息佇列的服務。我們那個平臺現在是部署超過有40個Kafka叢集,這些叢集都是獨立的。另外上面有超過一千個topic,我們的Broker數有超過有兩千個Kafka。平臺從上線到現在已經執行有兩年了,承載的資料量都是百TB級的,我們現在這個設計是Kafka叢集,我們要實現多叢集。因為是對於公司內部的平臺,我們要保證高可用,平臺架構底層其實是廣大Broker管理員,上層是抽象出來的。Kafka的叢集對業務其實也無感,。另外就是一個管理平臺管理,我建立topic,去建立分割槽,或者做故障處理。第一,上層只可能有管理平臺和客戶端是對R業務有感,客戶端我們要對客戶端進行收斂,有一個客戶端是原生支援的——Java。不同客端會有不同的表現,現在我們需要去收斂這個詞,
為什麼採用Kubernetes?
因為我們遇到的問題在早期的時候,知乎的Kafka是一個單叢集,在大家使用率不高,或者在資料量增長不爆炸的時候,單叢集大家用得還OK時有天發現有一個Broker掛了,等到大家都掛了,這時候才發現其實是一條路是不可以常走的。因此我們覺得我們認為叢集和大型社科系統單點,大家會依賴集權,不管任何的業務,我寫日誌也好,發訊息也好,或者我去做資料傳輸也好,這是不可以的。對於Kafka來,我們有一個開發,有各國的Top的概念,其實發生到業務來,每個topic都代表了不同的一個業務的場景,我們覺得對業務場景在內部要做分級,比如我重要的資料,我要做分析,我們的業務與Kafka的深耦合。當我先做了規劃,去梳理一下發現為什麼我會這麼多,它topic為什麼集中掛掉之後有人還沒事,還非常的憤怒,覺得簡單就是天災。
那時候我們發現,其實我們的日誌裡面topic有很多型別,抽樣出來,一種是日誌,一種是資料和訊息。資料,比如在做一個離線計算的時候,收集了使用者資料或者我在APP裡有埋點,這些資料可以通過開發管道或者spa或者我們的計算任務。另外一個是訊息剛才也提到,比如我使用者去做了一次關注或者點贊,觸發後面一系列處理流程,很顯然看出他們其實是有分級的。我們要把Kafka叢集在內部要做成多叢集的方式,然而根據我們套配合做出劃分。
同型別的topic做不同叢集的管理和配置。其實最簡單的法是Kafka有分片,我們是做高可用,日誌的分片可以少。訊息容量是小的,對於資料大家都做,比如用Kafka做資料分析,肯定知道在離線技術,在資料分析時候看一下資料量是跟線上的時候應該是千倍萬倍的這種關係,那就會出現一個問題——我們去規劃一個設計就去實施的,最後結果我們的需求會變的非常多,比如一個A業務,我認為非常的重要,去做一個但是承載了一個,我每天有幾百幾十T的資料,那我是不是可以申請一個新的Broker。新的叢集,別人不要跟我摻到一起,我提供的是基礎資料,這樣的話我們遇到問題是叢集會越來越多,事實上現在很多已經是超過四十億四十個了。伺服器資源怎麼去使用?因為早期部署的時候肯定單機部署,但又不是,比如我有一個普通的,比如我做了一個G,承載的數量有四個T,這樣的話我部署一個訊息任務是不是有點浪費?那不數數任務它是有點就太太小,其實我們提供一個提高資源利用率,希望從單機上部署更多的Broker,並且能夠做到它們之間的相互的影響降到最低。實際上在我們實驗實踐中,磁碟其實是Kafka一個繞不開的問題。
首先磁碟不可以做資料持久化,但是我們遇到了很多的問題,有量突增的或者流量大的時候,磁碟首先容量會有問題,比如我有申請了1T的磁碟,那可能我現在寫一天給我寫兩天就已經寫到了3T。
另外一個問題就是磁碟的LUTOC其實IOPS過高這種問題出現的話,開發的效能是有很大的下降的。既然Broker可以做到多部署,那我們就在磁碟層面上做隔離,先在保證這種不要互相影響,就是比如資料和訊息,Broker在磁碟這個層面要做好,做到互相不影響,因此我們想到的方法就是磁碟是不是可以分開,在物理層面就分開,並且開它本身又有副本。
這種物理存在分開是可以接受的,而且如果出現故障,完全是在可控範圍之內的,而是可期的。因此我覺得把分開,我們當時選伺服器,正好黑石這邊也提供了一種叫高效能的伺服器,其實非常滿足我們需求,它有12個高效能的磁碟,是單盤的,他不做瑞的,每個盤就是容量還不小。它的CPU和記憶體上面其實有優勢的,因為Kafka是對記憶體是有要求的,比如走的檔案快取,記憶體是滿足我需求的CPU,現在英特爾的CPU效能還蠻。我們就採用了黑色這款高效能伺服器,現在我們的平臺都主要部署在這種伺服器。底層的伺服器想好了,資源劃分想好了,就是怎麼去管理它?
我們先講一個有意思的,我們平臺之前有一個開發的管理平臺是自寫自演的,實現了部署Broker,包括渲染配置,去做遷移的,這個平臺比較私有,而且在運維上面或者管理上面不是很方便,而且觀眾很高興來同事都要從程式碼層面學習,從那一套我們的平臺學習影響,或者是有一個更好的方案來去解決。如果激情數增加到了保證的不可數增加,並且是伺服器如果壞掉了,你看我們如何感染管理他,排程的時候我們如何去考慮到按照磁碟這個維度做排程。因此我們想到QQ那鐵絲,因為之前我們有很多的一個在容器化方面的實踐,早期在開發上QQ來此之前其實知乎在ks上部署了很多計算任務,在這上面有很多積累,所以我們想利用它的管理功能和容器的技術進行資源管理。另外一個是應用程式管理。
Kafka on Kubernetes
首先解決問題設計Kafka容器,無非就是四個問題——記憶體,CPU,網路和儲存。另外一個問題是我們怎麼實現具體排程Kafka容器。
首先是記憶體和CPU。其實CPU是比較難以預估的,因為根據諮詢型別不同,對於記憶體和CPU消耗是不同的,Kafka本身是不強,依賴於CPU。但是在實際使用中還是有些問題的,比如我們們Kafka不是做批量,但很多時候有時候大家對它比較理解得透的時候,會把批量會得很小,比如我降低延遲,要保證每一條訊息都確切的投放過去,把Brokers收得很小,這時候會造成一個什麼問題?CPU會高,但是很這種問題我們可以通過調高CPU來解決。如果不出現這種大流量的話,一般記憶體是不會超過八個G的,而且一般使用會更低,所以我們的基準的容器會設定成8G根據實際使用時間長,經常會做調整,這個調整可以在IT市場很容易改。
另外網路方面就是我們對外服務,採用的是一種獨立的內網ip方式,比如我每一個Broker都有一個獨立的ip,實際上因為我們的單機上會部署很多容器,所以每個都有IP,並且將這個ip註冊在內網DNS上面,這樣照好處是對於使用者來說,不需要知道具體容器的ip。這個是網路又有一個很好的方式——可以做單機的多ip網路設計,至少可以滿足我們的需求,這是容器方面的設計。預設支援的磁碟的掛載方式是HostParh Volume,這種方式是最優的,因為Kafka在本地磁碟效能最好的,而且能夠充分利用到本地的這種高效的檔案快取,我們本身的磁碟效能也是非常棒的,至少我可以滿足我的需求。
因此我們就應該是本地的目錄一個cosplay,也就到K2起來之後是給他的,請求的配置掛載到伺服器的磁碟,黑色框是我們的一個容器,開發目錄指向的藍色框是伺服器上的一個磁碟或者伺服器上的目錄。雖然我們的叢集看來就是這個樣子的,每一個方塊代表網上有很多的部署的Broker。業務上面可以反過來看,每個藍色的地方代表Broker。
第一,CPU和記憶體並不是問題,網路其實已過測試過的,伺服器網路是二世紀的20G頻寬,每個盤我們經過測試,是有一點幾個G效能,即便把每個盤所有人都跑滿,其實這是災難情況,他只有不會超過20個G,因此我們不在考慮範圍之內,我們考慮的是磁碟的高可用目標,讓單個叢集的Broker在節點要儘量做到分散。
第二是節點上的儲存使用盡量均勻。
演算法是根據伺服器磁碟狀態計算分數,分數高者被排程。另外就是磁碟的使用情況,如果有更多的可用盤,我們傾向於把Broker掛在了上面。其實它用了一個簡單的方式,假設建立一個紅色叢集,實際上A和C都可以,但C是最優的,因為C上面的Broker數比較少。如果要建立一個藍色叢集,那顯然是A是最優的。另外,在實際使用情況下要更復雜,因為得考慮到分片的高可用。按照演算法去實現會遇到了一個實際性的問題——用HostPat是有很大侷限性,一致性不好,比如需要去管理要排程的節點,因為如果用class的話需要去註冊一個本身選擇的word,或者其實我是不知道被調到哪個節點上。另外主機上要去掛載的目錄其實是沒有人管理的。這是我們遇到的問題,當時我們希望是既要利用到HostPath,只有掛在本地的磁碟這種特性來提高我們的效能管理。
而且我要能夠選出合理節點,並且能夠管理到這個儲存。因此我們在當時對Kubernetes做改造,實現磁碟和排程器的演算法,可以實現實時更新磁碟資訊。但是實現方式是通過假設建立例項.
本地磁碟管理
如果Broker已經在裝置上建立起來,磁碟也被用了,那如何去管理它?事實上磁碟管理只能進入第三方的Agent。
故障處理和提升資源利用時會預留空間,比如為了快速處理故障不做簽署,首先就是成本太高,現在做的是快速恢復,因此我們會預留1到2個盤,即快速處理盤,因此只要把軟體指向這個容器,就可以馬上啟用,並且不會有太大的網路開銷。另外就是在主機層面,即把分片在主機層面是做分開,做到高可用。
但我們遇到一個問題——需要把客戶端統一,因為技術平臺化。那如何把客戶端做到統一?我們的看這裡,客戶端可以去讀Consul資訊,檢查topic是不是有用。還有個好處是,如果做遷移的時候,因為事情使了很多方,生產和消費方式是很多的,而且一般流程是先於生產方,消費方就過來,大家可能有業務,可能大家如果按照這種註冊方式的話,其實遷移過程是可以同步的。在這個地方更改資訊,整個這個生產所生產的消費,都可以感受到,就是另外就是易用性會提高。且用這種方式有好處是有一個叢集比如我整個叢集全部斷掉了,雖然事沒發生過,但是作為一個備用的方式的話,我們會有一個災備叢集把所有的客戶端都可以直接遷移過去。
Q/A
Q: 你好,麻煩問一下,一個叢集裡面可能有很多topic,不同的使用者消費topic的時候,使用者之間是怎麼隔離的?會不會消費到其他的topic資料?想問一下有沒有什麼隔離的好的辦法?你一個叢集裡有多少套?叢集裡有多個topic,資料我就不想讓別人看到嗎?當然我如果提供一個客戶端給他,他就能把所有的資料看得到,有沒有什麼好的辦法。
A:其實是這樣的,就是在我們的一個情況稱,如果這個進群它有多少Broker,假如在這個會相互影響,我們還是建議把它不是相互影響,因為叢集面不可能只給一個使用者只提供一個叢集,就是我們一個大的叢集,會有很多使用者在使用他的資料,都是不同的topic進來的嗎?他消費的時候如果我沒有隔離的話,我只要給他客戶端,它所有的資料都看得到嗎?只能通過我在前面去做提供什麼API服務來這種方式,有沒有?Kafka本身有沒有什麼好的辦法去本身應該是有認證。
更多詳細資料,請戳下面的連結:
知乎基於Kubernetes的Kafka平臺的設計和實現.pdf
問答
apache kafka vs apache storm如何使用?
相關閱讀
陳新宇:CKafka在人臉識別PASS中的應用
楊原:騰訊雲Kafka自動化運營實踐
饒軍:Apache Kafka的過去,現在,和未來
此文已由作者授權騰訊雲+社群釋出,原文連結:https://cloud.tencent.com/dev…