彌補MySQL和Redis短板:看HBase怎么確保高可用
HBase是一個基于Hadoop面向列的非關系型分布式數(shù)據(jù)庫(NoSQL),設計概念來源于谷歌的BigTable模型,面向實時讀寫、隨機訪問大規(guī)模數(shù)據(jù)集的場景,是一個高可靠性、高性能、高伸縮的分布式存儲系統(tǒng),在大數(shù)據(jù)相關領域應用廣泛。
HBase系統(tǒng)支持對所存儲的數(shù)據(jù)進行透明切分,從而使得系統(tǒng)的存儲以及計算具有良好的水平擴展性。
知乎從2017年起開始逐漸采用HBase系統(tǒng)存儲各類在線業(yè)務數(shù)據(jù),并在HBase服務之上構建各類應用模型以及數(shù)據(jù)計算任務。
- 伴隨著知乎這兩年的發(fā)展,知乎核心架構團隊基于開源容器調度平臺Kubernetes打造了一整套HBase服務平臺管理系統(tǒng);
- 經(jīng)過近兩年的研發(fā)迭代,目前已經(jīng)形成了一套較為完整的HBase自動化運維服務體系,能夠完成HBase集群的快捷部署、平滑擴縮容、HBase組件細粒度監(jiān)控、故障跟蹤等功能。
背景
知乎對HBase的使用經(jīng)驗不算太長,在2017年初的時候,HBase服務主要用于離線算法、推薦、反作弊,還有基礎數(shù)據(jù)倉庫數(shù)據(jù)的存儲計算,通過MapReduce和Spark來進行訪問。而在當時知乎的在線存儲主要采用MySQL和Redis系統(tǒng),其中:
- MySQL:支持大部分的業(yè)務數(shù)據(jù)存儲,當數(shù)據(jù)規(guī)模增大后有一些需要進行擴容的表,分表會帶來一定的復雜性,有些業(yè)務希望能屏蔽這個事情,還有一些是因為歷史原因在表設計的時候用rmsdb的形式存了一些本該由列存儲的數(shù)據(jù),希望做一下遷移。此外MySQL基于SSD,雖然性能很好,花銷也比較大;
- Redis:可以提供大規(guī)模的緩存,也可以提供一定的存儲支持。Redis性能極好,主要的局限是做數(shù)據(jù)Resharding較為繁瑣,其次是內存成本較高。
針對以上兩種在線存儲所存在的一些問題,我們希望建立一套在線存儲NoSQL服務,對以上兩種存儲作為一個補充。
選型期間我們也考慮過Cassandra,早期一些業(yè)務曾嘗試使用Cassandra作為存儲,隔壁團隊在運維了一段時間的Cassandra系統(tǒng)之后,遇到不少的問題,Cassandra系統(tǒng)可操作性沒有達到預期,目前除了Tracing相關的系統(tǒng),其他業(yè)務已經(jīng)放棄使用Cassandra。
我們從已有的離線存儲系統(tǒng)出發(fā),在衡量了穩(wěn)定性、性能、代碼成熟度、上下游系統(tǒng)承接、業(yè)界使用場景以及社區(qū)活躍度等方面之后,選擇了HBase,作為知乎在線存儲的支撐組件之一。
一、HBase On Kubernetes
- 初期知乎只有一套進行離線計算的集群,所有業(yè)務都跑在一個集群上,并且HBase集群和其他離線計算yarn以及Impala混合部署,HBase的日常離線計算和數(shù)據(jù)讀寫都嚴重受到其他系統(tǒng)影響;
- 并且HBase的監(jiān)控都只停留在主機層面的監(jiān)控,出現(xiàn)運行問題時,進行排查很困難,系統(tǒng)恢復服務時間較長,這種狀態(tài)下,我們需要重新構建一套適用于在線服務的系統(tǒng)。
在這樣的場景下,我們對在線HBase服務的需求是明確的:
隔離性
- 從業(yè)務方的視角來說,希望相關的服務做到環(huán)境隔離,權限收歸業(yè)務,避免誤操作和業(yè)務相互影響;
- 對于響應時間,服務的可用性,都可以根據(jù)業(yè)務的需要指定SLA;
- 對于資源的分配和blockcache等參數(shù)的配置也能夠更加有適應性,提供業(yè)務級別的監(jiān)控和報警,快速定位和響應問題;
資源利用率:從運維的角度,資源的分配要合理,盡可能的提升主機cpu,內存包括磁盤的有效利用率;
成本控制:團隊用最小的成本去得到相對較大的運維收益,所以需要提供便捷的調用接口,能夠靈活的進行HBase集群的申請、擴容、管理、監(jiān)控。同時成本包括機器資源,還有工程師。當時我們線上的這套系統(tǒng)是由一位工程師獨立去進行維護。
綜合以上需求,參考我們團隊之前對基礎設施平臺化的經(jīng)驗,最終的目標是把HBase服務做成基礎組件服務平臺向提供給上游業(yè)務,這個也是知乎技術平臺部門工作思路之一,盡可能的把所有的組件對業(yè)務都黑盒化,接口化,服務化。同時在使用和監(jiān)控的粒度上盡可能的準確,細致,全面。這是我們構建在線HBase管理運維系統(tǒng)的一個初衷。
二、Why Kubernetes?
前文說到我們希望將整個HBase系統(tǒng)平臺服務化,那就涉及到如何管理和運維HBase系統(tǒng),知乎在微服務和容器方面的工作積累和經(jīng)驗是相當豐富的。
- 在當時我們所有的在線業(yè)務都已經(jīng)完成了容器化的遷移工作,超萬級別的業(yè)務容器平穩(wěn)運行在基于mesos的容器管理平臺Bay上(參見[1]);
- 與此同時,團隊也在積極的做著Infrastructure容器化的嘗試,已經(jīng)成功將基礎消息隊列組件Kafka容器化運行于Kubernetes系統(tǒng)之上(參見[2]),因此我們決定也將HBase通過Kubernetes來進行資源的管理調度。
Kubernetes[3]是谷歌開源的容器集群管理系統(tǒng),是Google多年大規(guī)模容器管理技術Borg的開源版本。Kubernetes提供各種維度組件的資源管理和調度方案,隔離容器的資源使用,各個組件的HA工作,同時還有較為完善的網(wǎng)絡方案。
Kubernetes被設計作為構建組件和工具的生態(tài)系統(tǒng)平臺,可以輕松地部署、擴展和管理應用程序。有著Kubernetes大法的加持,我們很快有了最初的落地版本([4])。
三、初代
最初的落地版本架構見下圖,平臺在共享的物理集群上通過Kubernetes(以下簡稱K8S)API建立了多套邏輯上隔離的HBase集群,每套集群由一組Master和若干個Regionserver(以下簡稱RS)構成,集群共享一套HDFS存儲集群,各自依賴的Zookeeper集群獨立;集群通過一套管理系統(tǒng)Kubas服務來進行管理([4])。
初代架構
模塊定義
在K8S中如何去構建HBase集群,首先需要用K8S本身的基礎組件去描述HBase的構成;K8S的資源組件有以下幾種:
- Node:定義主機節(jié)點,可以是物理機,也可以是虛擬機;
- Pod:一組緊密關聯(lián)的容器集合,是K8S調度的基本單位;
- ReplicationController:一組pod的控制器,通過其能夠確保pod的運行數(shù)量和健康,并能夠彈性伸縮。
結合之前Kafka on K8S的經(jīng)驗,出于高可用和擴展性的考慮,我們沒有采用一個Pod里帶多個容器的部署方式,統(tǒng)一用一個ReplicationController定義一類HBase組件,就是上圖中的Master,Regionserver還有按需創(chuàng)建的Thriftserver;通過以上概念,我們在K8S上就可以這樣定義一套最小HBase集群:
- 2*MasterReplicationController;
- 3*RegionserverReplicationController;
- 2*ThriftserverReplicationController(可選);
四、高可用以及故障恢復
作為面向在線業(yè)務服務的系統(tǒng),高可用和故障轉移是必需在設計就要考慮的事情,在整體設計中,我們分別考慮組件級別、集群級別和數(shù)據(jù)存儲級別的可用性和故障恢復問題。
1、組件級別
HBase本身已經(jīng)考慮了很多故障切換和恢復的方案:
- Zookeeper集群:自身設計保證了可用性;
- Master:通過多個Master注冊在Zookeeper集群上來進行主節(jié)點的HA和更新;
- RegionServer:本身就是無狀態(tài)的,節(jié)點失效下線以后會把上面的Region自動遷走,對服務可用性不會有太大影響;
- Thriftserver:當時業(yè)務大多數(shù)是Python和Golang,通過用Thrift對HBase的進行,Thriftserver本身是單點的,這里我們通過HAProxy來代理一組Thriftserver服務;
- HDFS:本身又由Namenode和DataNode節(jié)點組成,Namenode我們開啟HA功能,保證了HDFS的集群可用性;
2、集群級別
- Pod容器失效:Pod是通過Replication Controller維護的,K8S的Controller Manager會在它的存儲etcd去監(jiān)聽組件的失效情況,如果副本少于預設值會自動新的Pod容器來進行服務;
- Kubernetes集群崩潰:該場景曾經(jīng)在生產(chǎn)環(huán)境中出現(xiàn)過,針對這種情況,我們對SLA要求較高的業(yè)務采用了少量物理機搭配容器的方式進行混合部署,極端場景出現(xiàn)時,可以保證重要業(yè)務收到的影響可控;
3、數(shù)據(jù)級別
所有在K8S上構建的HBase集群都共享了一套HDFS集群,數(shù)據(jù)的可用性由HDFS集群的多副本來提供。
五、實現(xiàn)細節(jié)
1、資源分配
初期物理節(jié)點統(tǒng)一采用2*12核心的cpu,128G內存和4T的磁盤,其中磁盤用于搭建服務的HDFS,CPU和內存則在K8S環(huán)境中用于建立HBase相關服務的節(jié)點。
Master組件的功能主要是管理HBase集群,Thriftserver組件主要承擔代理的角色,所以這兩個組件資源都按照固定額度分配。
在對Regionserver組件進行資源分配設計的時候,考慮兩種方式去定義資源:
資源分配方式
按照業(yè)務需求分配:
- 根據(jù)業(yè)務方對自身服務的描述,對相關的QPS以及SLA進行評估,為業(yè)務專門配置參數(shù),包含blockcache,region大小以及數(shù)量等;
- 優(yōu)點是針對業(yè)務優(yōu)化,能夠充分的利用資源,降低業(yè)務的資源占用成本;
- 管理成本增加,需要對每一個業(yè)務進行評估,對平臺維護人員非常不友好,同時需要業(yè)務同學本身對HBase有理解;
統(tǒng)一規(guī)格的資源分配:
- CPU以及MEM都按照預先設定好的配額來分配,提供多檔的配置,將CPU和MEM的配置套餐化;
- 方便之處在于業(yè)務擴容時直接增加Regionserver的個數(shù),配置穩(wěn)定,運維成本較低,遇到問題時排障方便;
- 針對某些有特有訪問方式的業(yè)務有局限性,如CPU計算型,大KV存儲,或者有MOB需求的業(yè)務,需要特殊的定制;
- 介于當時考慮接入的在線業(yè)務并不多,所以采用了按業(yè)務定制的方式去配置Regionserver,正式環(huán)境同一業(yè)務采用統(tǒng)一配置的一組Regionserver,不存在混合配置的Regionserver組。
2、參數(shù)配置
基礎鏡像基于cdh5.5.0-hbase1.0.0構建:
- # Example for hbase dockerfile
- # install cdh5.5.0-hbase1.0.0
- ADD hdfs-site.xml /usr/lib/hbase/conf/
- ADD core-site.xml /usr/lib/hbase/conf/
- ADD env-init.py /usr/lib/hbase/bin/
- ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
- ENV HBASE_HOME /usr/lib/hbase
- ENV HADOOP_PREFIX /usr/lib/hadoop
- ADD env-init.py /usr/lib/hbase/bin/
- ADD hadoop_xml_conf.sh /usr/lib/hbase/bin/
- 固定的環(huán)境變量,如JDK_HOME,HBASE_HOME,都通過ENV注入到容器鏡像中;
- 與HDFS相關的環(huán)境變量,如hdfs-site.xml和core-site.xml預先加入Docker鏡像中,構建的過程中就放入了HBase的相關目錄中,用以確保HBase服務能夠通過對應配置訪問到HDFS;
- 與HBase相關的配置信息,如組件啟動依賴的Zookeeper集群地址,HDFS數(shù)據(jù)目錄路徑,堆內存以及GC參數(shù)等,這些配置都需要根據(jù)傳入KubasService的信息進行對應變量的修改,一個典型的傳入?yún)?shù)示例。
- REQUEST_DATA = {
- "name": 'test-cluster',
- "rootdir": "hdfs://namenode01:8020/tmp/hbase/test-cluster",
- "zkparent": "/test-cluster",
- "zkhost": "zookeeper01,zookeeper02,zookeeper03",
- "zkport": 2181,
- "regionserver_num": '3',
- "codecs": "snappy",
- "client_type": "java",
- "cpu": '1',
- "memory": '30',
- "status": "running",
- }
通過上面的參數(shù)KubasService啟動Docker時,在啟動命令中利用hadoop_xml_conf.sh和env-init.py修改hbase-site.xml和hbase-env.sh來完成配置注入,如下所示:
- source /usr/lib/hbase/bin/hadoop_xml_conf.sh
- && put_config --file /etc/hbase/conf/hbase-site.xml --property hbase.regionserver.codecs --value snappy
- && put_config --file /etc/hbase/conf/hbase-site.xml --property zookeeper.znode.parent --value /test-cluster
- && put_config --file /etc/hbase/conf/hbase-site.xml --property hbase.rootdir --value hdfs://namenode01:8020/tmp/hbase/test-cluster
- && put_config --file /etc/hbase/conf/hbase-site.xml --property hbase.zookeeper.quorum --value zookeeper01,zookeeper02,zookeeper03
- && put_config --file /etc/hbase/conf/hbase-site.xml --property hbase.zookeeper.property.clientPort --value 2181
- && service hbase-regionserver start && tail -f /var/log/hbase/hbase-hbase-regionserver.log
3、網(wǎng)絡通信
網(wǎng)絡方面,采用了Kubernetes上原生的網(wǎng)絡模式,每一個Pod都有自己的IP地址,容器之間可以直接通信,同時在Kubernetes集群中添加了DNS自動注冊和反注冊功能,以Pod的標識名字作為域名,在Pod創(chuàng)建和重啟和銷毀時將相關信息同步全局DNS。
在這個地方我們遇到過問題,當時我們的DNS解析不能在Docker網(wǎng)絡環(huán)境中通過IP反解出對應的容器域名,這就使得Regionserver在啟動之后向Master注冊和向Zookeeper集群注冊的服務名字不一致,導致Master中對同一個Regionserver登記兩次,造成Master與Regionserver無法正常通信,整個集群無法正常提供服務。
經(jīng)過我們對源碼的研究和實驗之后,我們在容器啟動Regionserver服務之前修改/etc/hosts文件,將Kubernetes對注入的hostname信息屏蔽。
這樣的修改讓容器啟動的HBase集群能夠順利啟動并初始化成功,但是也給運維提升了復雜度,因為現(xiàn)在HBase提供的Master頁現(xiàn)在看到的Regionserver都是IP形式的記錄,給監(jiān)控和故障處理帶來了諸多不便。
六、存在問題
初代架構順利落地,在成功接入了近十個集群業(yè)務之后,這套架構面臨了以下幾個問題:
管理操作業(yè)務HBase集群較為繁瑣
- 需要手動提前確定HDFS集群的存儲,以及申請獨立Zookeeper集群,早期為了省事直接多套HBase共享了一套Zookeeper集群,這和我們設計的初衷不符合;
- 容器標識符和HBaseMaster里注冊的regionserver地址不一致,影響故障定位;
- 單Regionserver運行在一個單獨的ReplicationController(以下簡稱RC),但是擴容縮容為充分利用RC的特性,粗暴的采用增加或減少RC的方式進行擴容縮容。
HBase配置
- 最初的設計缺乏靈活性,與HBase服務配置有關的hbase-site.xml以及hbase-env.sh固化在DockerImage里,這種情況下,如果需要更新大量配置,則需要重新build鏡像;
- 由于最初設計是共享一套HDFS集群作為多HBase集群的存儲,所以與HDFS有關的hdfs-site.xml和core-site.xml配置文件也被直接配置進了鏡像。如果需要在Kubasservice中上線依賴其他HDFS集群的HBase,也需要重新構建鏡像。
HDFS隔離
- 隨著接入HBase集群的增多,不同的HBase集群業(yè)務對HDFS的IO消耗有不同的要求,因此有了分離HBase依賴的HDFS集群的需求;
- 主要問題源自Docker鏡像對相關配置文件的固化,與HDFS有關的hdfs-site.xml和core-site.xml配置文件與相關Docker鏡像對應,而不同Docker鏡像的版本完全由研發(fā)人員自己管理,最初版本的實現(xiàn)并未考慮到這些問題。
監(jiān)控運維
- 指標數(shù)據(jù)不充分,堆內堆外內存變化,region以及table的訪問信息都未有提取或聚合;
- Region熱點定位較慢,無法在短時間內定位到熱點Region;
- 新增或者下線組件只能通過掃KubasService的數(shù)據(jù)庫來發(fā)現(xiàn)相關變更,組件的異常如RegionServer掉線或重啟,Master切換等不能及時反饋;
七、重構
為了進一步解決初版架構存在的問題,優(yōu)化HBase的管控流程,我們重新審視了已有的架構,并結合Kubernetes的新特性,對原有的架構進行升級改造,重新用Golang重寫了整個Kubas管理系統(tǒng)的服務(初版使用了Python進行開發(fā))。
并在Kubas管理系統(tǒng)的基礎上,開發(fā)了多個用于監(jiān)控和運維的基礎微服務,提高了在Kubernetes上進行HBase集群部署的靈活性,架構如下圖所示:
二代架構圖
1、Deployment&ConfigMap
Deployment
- Deployment(部署)是Kubernetes中的一個概念,是Pod或者ReplicaSet的一組更新對象描述,用于取代之前的ReplicationController。Deployment繼承了ReplicationController的所有功能,并擁有更多的管理新特性;
- 在新的Kubas管理系統(tǒng)中,新設計用Deployment代替Replication Controller做Pod的管理,使用一個Deployment部署一組Region Servers的方式來代替單Regionserver對應一個Replication Controller的設計,提升集群部署擴縮容管理的靈活性;
- 每一組Deployment都會注入各類信息維度的標簽,如相關集群的信息就,服務類型,所屬應用等。
Deployment部署
ConfigMap
- ConfigMap是Kubernetes用來存儲配置文件的資源對象,通過ConfigMap可以將外部配置在啟動容器之前掛載到容器中的指定位置,并以此為容器中運行的程序提供配置信息;
- 重構之后管理系統(tǒng)中,所有HBase的組件配置都存放至ConfigMap之中,系統(tǒng)管理人員會根據(jù)需-要預先生成若干HBase的配置模板存放到K8S系統(tǒng)的ConfigMap中;
- 在業(yè)務方提供出HBase服務申請時,管理人員通過業(yè)務資源的需求結合配置模板,為申請的HBase集群組件渲染具體的hbase-site。xml以及hbase-env。sh等HBase配置相關的文件再存放到ConfigMap中;
- 在容器啟動時,k8s會根據(jù)deployment將ConfigMap中的配置文件Mount到配置中指定的路徑中;
- 和Deployment的操作類似,每一份ConfigMap也都會標記上標簽,將相關的ConfigMap和對應的集群和應用關聯(lián)上。
ConfigMap存檔
2、組件參數(shù)配置
在引入了ConfigMap功能之后,之前創(chuàng)建集群的請求信息也隨之改變。
- RequestData
- {
- "name": "performance-test-rmwl",
- "namespace": "online",
- "app": "kubas",
- "config_template": "online-example-base.v1",
- "status": "Ready",
- "properties": {
- "hbase.regionserver.codecs": "snappy",
- "hbase.rootdir": "hdfs://zhihu-example-online:8020/user/online-tsn/performance-test-rmwl",
- "hbase.zookeeper.property.clientPort": "2181",
- "hbase.zookeeper.quorum": "zookeeper01,zookeeper02,zookeeper03",
- "zookeeper.znode.parent": "/performance-test-rmwl"
- },
- "client_type": "java",
- "cluster_uid": "k8s-example-hbase---performance-test-rmwl---example"
- }
其中config_template指定了該集群使用的配置信息模板,之后所有和該HBase集群有關的組件配置都由該配置模板渲染出具體配置。
config_template中還預先約定了HBase組件的基礎運行配置信息,如組件類型,使用的啟動命令,采用的鏡像文件,初始的副本數(shù)等。
- servers:
- {
- "master": {
- "servertype": "master",
- "command": "service hbase-master start && tail -f /var/log/hbase/hbase-hbase-master.log",
- "replicas": 1,
- "image": "dockerimage.zhihu.example/apps/example-master:v1.1",
- "requests": {
- "cpu": "500m",
- "memory": "5Gi"
- },
- "limits": {
- "cpu": "4000m"
- }
- },
- }
Docker鏡像文件配合ConfigMap功能,在預先約定的路徑方式存放配置文件信息,同時在真正的HBase配置路徑中加入軟鏈文件。
- RUN mkdir -p /data/hbase/hbase-site
- RUN mv /etc/hbase/conf/hbase-site.xml /data/hbase/hbase-site/hbase-site.xml
- RUN ln -s /data/hbase/hbase-site/hbase-site.xml /etc/hbase/conf/hbase-site.xml
- RUN mkdir -p /data/hbase/hbase-env
- RUN mv /etc/hbase/conf/hbase-env.sh /data/hbase/hbase-env/hbase-env.sh
- RUN ln -s /data/hbase/hbase-env/hbase-env.sh /etc/hbase/conf/hbase-env.sh
3、構建流程
結合之前對Deployment以及ConfigMap的引入,以及對Dockerfile的修改,整個HBase構建流程也有了改進:
HBaseonKubernetes構建流程
- 編制相關的Dockerfile并構建基礎的HBase組件鏡像;
- 為將要創(chuàng)建的HBase構建基礎屬性配置模板,訂制基礎資源,這部分可以通過KubasAPI在Kubernetes集群中創(chuàng)建ConfigMap;
- 具體創(chuàng)建部署集群時,通過調用KubasAPI,結合之前構建的ConfigMap模板,渲染出HBase集群中各類組件的詳細ConfigMap,然后在Kubernetes集群中構建Deployment;
- 最終通過之前構建好的鏡像加載組件ConfigMap中的配置,完成在KubernetesNode中運行的一個HBase組件容器。
通過結合K8S的ConfigMap功能的配置模板,以及KubasAPI調用,我們就可以在短時間部署出一套可用的HBase最小集群(2Master + 3Region Server + 2Thriftserver),在所有宿主機Host都已經(jīng)緩存Docker鏡像文件的場景下,部署并啟動一整套HBase集群的時間不超過15秒。
同時在缺少專屬前端控制臺的情況下,可以完全依托Kubernetesdashboard完成HBase集群組件的擴容縮容,以及組件配置的查詢修改更新以及重新部署。
八、資源控制
在完成重構之后,HBase服務面向知乎內部業(yè)務進行開放,短期內知乎HBase集群上升超過30+集群,伴隨著HBase集群數(shù)量的增多,有兩個問題逐漸顯現(xiàn):
- 運維成本增高:需要運維的集群逐漸增高;
- 資源浪費:這是因為很多業(yè)務的業(yè)務量并不高,但是為了保證HBase的高可用,我們至少需要提供2個Master+3個RegionServer,而往往Master的負載都非常低,這就造成了資源浪費。
為了解決如上的兩個問題,同時又不能打破資源隔離的需求,我們將HBaseRSGroup功能加入到了HBase平臺的管理系統(tǒng)中。
優(yōu)化后的架構如下:
RSGroup的使用
由于平臺方對業(yè)務HBase集群的管理本身就具有隔離性,所以在進行更進一步資源管理的時候,平臺方采用的是降級的方式來管理HBase集群。
通過監(jiān)聽每個單獨集群的指標,如果業(yè)務集群的負載在上線一段時間后低于閾值,平臺方就會配合業(yè)務方,將該HBase集群遷移到一套MixedHBase集群上。
同時如果在MixedHBase集群中運行的某個HBase業(yè)務負載增加,并持續(xù)一段時間超過閾值后,平臺方就會考慮將相關業(yè)務提升至單獨的集群。
九、多IDC優(yōu)化
隨著知乎業(yè)務的發(fā)展和擴大,知乎的基礎架構逐漸升級至多機房架構,知乎HBase平臺管理方式也在這個過程中進行了進一步升級,開始構建多機房管理的管理方式;基本架構如下圖所示:
多IDC訪問方式
- 業(yè)務HBase集群分別在多個IDC上運行,由業(yè)務確定IDC機房的主從方式,業(yè)務的從IDC集群數(shù)據(jù)通過平臺方的數(shù)據(jù)同步組件進行數(shù)據(jù)同步;
- 各IDC的Kubas服務主要負責對本地Kubernetes集群的具體操作,包括HBase集群的創(chuàng)建刪除管理,regionserver的擴容等HBase組件的管理操作,Kubas服務部署與機房相關,僅對接部署所在機房的K8S集群;
- 各IDC的Kubas服務向集群發(fā)現(xiàn)服務上報本機房集群信息,同時更新相關集群主從相關信息;
- 業(yè)務方通過平臺方封裝的ClientSDK對多機房的HBase集群進行訪問,客戶端通過集群發(fā)現(xiàn)服務可以確定HBase集群的主從關系,從而將相關的讀寫操作分離,寫入修改訪問可以通過客戶端指向主IDC的集群;
- 跨機房間的數(shù)據(jù)同步采用了自研的HBaseReplicationWALTransfer來提供增量數(shù)據(jù)的同步。
十、數(shù)據(jù)同步
在各類業(yè)務場景中,都存在跨HBase集群的數(shù)據(jù)同步的需求,比如數(shù)據(jù)在離線HBase集群和在線集群同步、多IDC集群數(shù)據(jù)同步等,對于HBase的數(shù)據(jù)同步來說,分為全量復制和增量復制兩種方式。
HBase數(shù)據(jù)同步
在知乎HBase平臺中,我們采用兩種方式進行HBase集群間的數(shù)據(jù)同步:
HBase Snapshot
全量數(shù)據(jù)復制我們采用了HBaseSnapshot的方式進行;主要應用在離線數(shù)據(jù)同步在線數(shù)據(jù)的場景;
WALTransfer
主要用于HBase集群之間的的增量數(shù)據(jù)同步;增量復制我們沒有采用HBaseReplication,相關同步方式我們通過自研的WALTransfer組件來對HBase數(shù)據(jù)進行增量同步;
WALTransfer通過讀取源數(shù)據(jù)HBase集群提供WAL文件列表,于HDFS集群中定位對應的WAL文件,將HBase的增量數(shù)據(jù)按序寫入到目的集群,相關的細節(jié)我們會在以后的文章中詳細解析。
十一、監(jiān)控
從之前重構后的架構圖上我們可以看到,在Kubas服務中我們添加了很多模塊,這些模塊基本屬于HBase平臺的監(jiān)控管理模塊。
1、Kubas-Monitor組件
基本的監(jiān)控模塊,采用輪詢的方式發(fā)現(xiàn)新增HBase集群,通過訂閱Zookeeper集群發(fā)現(xiàn)HBase集群Master以及Regionserver組。
采集Regionserver Metric中的數(shù)據(jù),主要采集數(shù)據(jù)包括:
- Region的信息,上線region數(shù)量,store的數(shù)量、storefile的大小、storefileindex的大小,讀取時memstore缺失次數(shù);
- blockcache的信息,例如blockcache中使用多少、空閑多少、累計的缺失率等;
- 讀寫請求的統(tǒng)計信息,例如讀寫響應時間,讀寫的表分布、讀寫數(shù)據(jù)量、讀寫失敗次數(shù)等;
- compact與split的操作信息,例如隊列的長度、操作次數(shù)和時間等;
- handler的信息,例如隊列長度、處于活躍handler的數(shù)量以及活躍的reader數(shù)量。
其他維度的指標如容器CPU以及Mem占用來自Kubernetes平臺監(jiān)控,磁盤IO,磁盤占用等來自主機監(jiān)控:
HBase部分監(jiān)控
2、Kubas-Region-Inspector組件
- 采集HBase表Region信息,通過HBaseAPI接口,獲取每個HBaseRegion的數(shù)據(jù)統(tǒng)計信息,并將Region數(shù)據(jù)聚合成數(shù)據(jù)表信息;
- 通過調用開源組件形成HBase集群Region分布的圖表,對Region熱點進行定位;
HBaseRegion分布監(jiān)控
通過以上模塊采集的監(jiān)控信息,基本可以描述在Kubernetes上運行的HBase集群的狀態(tài)信息,并能夠輔助運維管理人員對故障進行定位排除。
十二、Future Work
隨著公司業(yè)務的快速發(fā)展,知乎的HBase平臺業(yè)務同時也在不斷的迭代優(yōu)化,短期內我們會從以下幾個方向進一步提升知乎HBase平臺的管理服務能力:
- 提升集群安全穩(wěn)定性。加入HBase權限支持,進一步提升多租戶訪問下的安全隔離性;
- 用戶集群構建定制化。通過提供用戶數(shù)據(jù)管理系統(tǒng),向業(yè)務用戶開放HBase構建接口,這樣業(yè)務用戶可以自行構建HBase集群,添加Phoniex等插件的支持;
- 運維檢測自動化。自動對集群擴容,自動熱點檢測以及轉移等;
參考
[1]知乎基于Kubernetes的Kafka平臺的設計和實現(xiàn)
https://zhuanlan.zhihu.com/ p/36366473
[2]知乎容器平臺演進及與大數(shù)據(jù)融合實踐
[3]Kubernetes
http://link.zhihu.com/?target=https%3A//kubernetes.io/
[4]Building online hbase cluster of zhihu based on kubernetes