# ZooKeeper
分布式 Apache HBase 安裝依賴于正在運行的 ZooKeeper 集群。所有參與節點和客戶端都需要能夠訪問正在運行的 ZooKeeper 集合。 Apache HBase 默認為您管理 ZooKeeper“集群”。它將啟動和停止 ZooKeeper 集合作為 HBase 啟動/停止過程的一部分。您還可以獨立于 HBase 管理 ZooKeeper 集合,只需將 HBase 指向它應該使用的集群。要切換 ZooKeeper 的 HBase 管理,請使用 _conf / hbase-env.sh_ 中的`HBASE_MANAGES_ZK`變量。此變量默認為`true`,告訴 HBase 是否啟動/停止 ZooKeeper 整體服務器作為 HBase 啟動/停止的一部分。
當 HBase 管理 ZooKeeper 集合時,您可以直接在 _conf / hbase-site.xml_ 中指定 ZooKeeper 配置。通過在 ZooKeeper 選項名稱前加上`hbase.zookeeper.property`,可以將 ZooKeeper 配置選項設置為 HBase _hbase-site.xml_ XML 配置文件中的屬性。例如,可以通過設置`hbase.zookeeper.property.clientPort`屬性來更改 ZooKeeper 中的`clientPort`設置。對于 HBase 使用的所有默認值,包括 ZooKeeper 配置,請參見 [hbase 默認配置](#hbase_default_configurations)。查找`hbase.zookeeper.property`前綴。有關 ZooKeeper 配置的完整列表,請參閱 ZooKeeper 的 _zoo.cfg_ 。 HBase 不附帶 _zoo.cfg_ ,因此您需要在的 ZooKeeper 下載中瀏覽 _conf_ 目錄。
您必須至少使用`hbase.zookeeper.quorum`屬性列出 _hbase-site.xml_ 中的整體服務器。此屬性默認為`localhost`上的單個集合成員,它不適用于完全分布式 HBase。 (它僅綁定到本地計算機,遠程客戶端將無法連接)。
> 我應該運行多少 ZooKeepers?
>
> 您可以運行僅包含 1 個節點的 ZooKeeper 集合,但在生產環境中,建議您運行 3 個,5 個或 7 個機器的 ZooKeeper 集合;一個集群的成員越多,對主機失敗的容錯度就越高。此外,運行奇數臺機器。在 ZooKeeper 中,支持偶數個對等體,但通常不使用它,因為偶數大小的集合比奇數大小的集合所需要更多的對等點來支持合法集群數量。例如,具有 4 個對等體的集合需要 3 來形成仲裁,而具有 5 的集合也需要 3 來形成仲裁。因此,5 的集合允許 2 個對等體失敗,因此比 4 的集合更容錯,而不是僅允許 1 個服務器崩潰。
>
> 為每個 ZooKeeper 服務器提供大約 1GB 的 RAM,如果可能的話,給它自己的專用磁盤(專用磁盤是確保高性能 ZooKeeper 集合的最佳方法)。對于負載很重的集群,在 RegionServers(DataNodes 和 TaskTrackers)的不同機器上運行 ZooKeeper 服務器。
例如,讓 HBase 管理節點 _rs {1,2,3,4,5} .example.com_ 上的 ZooKeeper 仲裁,綁定到端口 2222(默認為 2181),確保`HBASE_MANAGE_ZK`為在 _conf / hbase-env.sh_ 中注釋掉或設置為`true`,然后編輯 _conf / hbase-site.xml_ 并設置`hbase.zookeeper.property.clientPort`和`hbase.zookeeper.quorum`。您還應該將`hbase.zookeeper.property.dataDir`設置為默認值以外的值,因為默認情況下 ZooKeeper 會在 _/ tmp_ 下保留數據,這通常會在系統重啟時清除。在下面的示例中,我們將 ZooKeeper 持久保存到 _/ user / local / zookeeper_ 。
```
<configuration>
...
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2222</value>
<description>Property from ZooKeeper's config zoo.cfg.
The port at which the clients will connect.
</description>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>rs1.example.com,rs2.example.com,rs3.example.com,rs4.example.com,rs5.example.com</value>
<description>Comma separated list of servers in the ZooKeeper Quorum.
For example, "host1.mydomain.com,host2.mydomain.com,host3.mydomain.com".
By default this is set to localhost for local and pseudo-distributed modes
of operation. For a fully-distributed setup, this should be set to a full
list of ZooKeeper quorum servers. If HBASE_MANAGES_ZK is set in hbase-env.sh
this is the list of servers which we will start/stop ZooKeeper on.
</description>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/usr/local/zookeeper</value>
<description>Property from ZooKeeper's config zoo.cfg.
The directory where the snapshot is stored.
</description>
</property>
...
</configuration>
```
> 我應該使用什么版本的 ZooKeeper
>
> 新版本越好。從 HBase 1.0.0 開始,ZooKeeper 3.4.x 是必需的
>
> ZooKeeper 維護
>
> 務必設置 [ZooKeeper 維護](https://zookeeper.apache.org/doc/r3.1.2/zookeeperAdmin.html#sc_maintenance)中描述的數據目錄清理器,否則您可能會在幾個月內遇到“有趣”問題;例如,如果zookeeper必須運行成千上萬的日志目錄,zookeeper就可以刪除會話,而這種情況在領導者重新選舉時間周圍不會執行 - 這個過程很少見,但有時會運行,無論是因為機器掉落還是間接性耽誤,這個都會運行。
## 196.使用現有的 ZooKeeper 集合
要將 HBase 指向現有的 ZooKeeper 集群(不受 HBase 管理的集群),請將 _conf / hbase-env.sh_ 中的`HBASE_MANAGES_ZK`設置為 false
```
...
# Tell HBase whether it should manage its own instance of ZooKeeper or not.
export HBASE_MANAGES_ZK=false
```
接下來在 _hbase-site.xml_ 中設置集合位置和客戶端端口(如果是非標準的)。
當 HBase 管理 ZooKeeper 時,它將啟動/停止 ZooKeeper 服務器作為常規啟動/停止腳本的一部分。如果您想自己運行 ZooKeeper,獨立于 HBase 啟動/停止,您將執行以下操作
```
${HBASE_HOME}/bin/hbase-daemons.sh {start,stop} zookeeper
```
請注意,您可以使用hbase以這種方式啟動與 HBase 無關的 ZooKeeper 集群。只要確保將`HBASE_MANAGES_ZK`設置為`false`,如果希望它在 HBase 重啟時保持不變,那么當 HBase 關閉時,它不會使 ZooKeeper 失效。
有關運行不同 ZooKeeper 集群的更多信息,請參閱 ZooKeeper [入門指南](https://hadoop.apache.org/zookeeper/docs/current/zookeeperStarted.html)。另外,有關 ZooKeeper 大小調整的更多信息,請參閱 [ZooKeeper Wiki](https://wiki.apache.org/hadoop/ZooKeeper/FAQ#A7) 或 [ZooKeeper 文檔](https://zookeeper.apache.org/doc/r3.3.3/zookeeperAdmin.html#sc_zkMulitServerSetup)。
## 197.使用 ZooKeeper 進行 SASL 身份驗證
較新版本的 Apache HBase(&gt; = 0.92)將支持連接到支持 SASL 身份驗證的 ZooKeeper Quorum(可在 ZooKeeper 版本 3.4.0 或更高版本中使用)。
介紹如何設置 HBase 與 ZooKeeper Quorum 進行相互認證。 ZooKeeper / HBase 相互認證( [HBASE-2418](https://issues.apache.org/jira/browse/HBASE-2418) )是完整安全 HBase 配置( [HBASE-3025](https://issues.apache.org/jira/browse/HBASE-3025) )的一部分。為簡化說明,本節忽略了所需的其他配置(安全 HDFS 和協處理器配置)。建議首先使用 HBase 管理的 ZooKeeper 配置(而不是獨立的 ZooKeeper 配置),以便于學習。
### 197.1。操作系統先決條件
您需要有一個有效的 Kerberos KDC 設置。對于將運行 ZooKeeper 服務器的每個`$HOST`,您應該具有`zookeeper/$HOST`原則。對于每個這樣的主機,為`zookeeper/$HOST`添加一個服務密鑰(使用`kadmin`或`kadmin.local`工具的`ktadd`命令)并將此文件復制到`$HOST`,并使其僅對將在`$HOST`上運行 zookeeper 的用戶可讀。請注意此文件的位置,我們將在下面使用它作為 _ $ PATH_TO_ZOOKEEPER _KEYTAB_ 。
同理,對于將運行 HBase 服務器(主服務器或區域服務器)的每個`$HOST`,您應該有一個原則:`hbase/$HOST`。對于每個主機,添加一個名為 _hbase.keytab_ 的密鑰表文件,其中包含`hbase/$HOST`的服務密鑰,將此文件復制到`$HOST`,并使其僅對將`$HOST`運行 HBase 服務的用戶可讀。注意這個文件的位置,我們將在下面使用它作為 _ $ PATH_TO_HBASE _KEYTAB_ 。
每個將成為 HBase 客戶端的用戶也應獲得 Kerberos 主體。此主體通常應該為其分配密碼(與 HBase 服務器相反,密鑰表文件),只有該用戶知道。應設置客戶端的主體`maxrenewlife`,以便可以對其進行足夠的續訂,以便用戶可以完成其 HBase 客戶端進程。例如,如果用戶運行長達 3 天的長期運行 HBase 客戶端進程,我們可以在`kadmin`中創建此用戶的主體:`addprinc -maxrenewlife 3days`。 ZooKeeper 客戶端和服務器庫通過運行定期喚醒以執行刷新的線程來管理自己的票證更新。
在將運行 HBase 客戶端的每臺主機上(例如`hbase shell`),將以下文件添加到 HBase 主目錄的 _conf_ 目錄中:
```
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=false
useTicketCache=true;
};
```
我們將此 JAAS 配置文件稱為 _ $ CLIENT _CONF_ 。
### 197.2。 HBase 管理的 ZooKeeper 配置
在將運行 zookeeper,master 或 regionserver 的每個節點上,在節點的 _HBASE _HOME_ 目錄的 conf 目錄中創建一個 [JAAS](http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html) 配置文件,如下所示:
```
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="$PATH_TO_ZOOKEEPER_KEYTAB"
storeKey=true
useTicketCache=false
principal="zookeeper/$HOST";
};
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
keyTab="$PATH_TO_HBASE_KEYTAB"
principal="hbase/$HOST";
};
```
其中 _ $ PATH_TO_HBASE _KEYTAB_ 和 _ $ PATH_TO_ZOOKEEPER _KEYTAB_ 文件是您在上面創建的文件,`$HOST`是該節點的主機名。
`Server`部分將由 ZooKeeper 獨立服務器使用,而`Client`部分將由 HBase 主服務器和區域服務器使用。此文件的路徑應替換下面 _hbase-env.sh_ 列表中的文本 _ $ HBASE_SERVER _CONF_ 。
此文件的路徑應替換下面 _hbase-env.sh_ 列表中的文本 _ $ CLIENT _CONF_ 。
修改 _hbase-env.sh_ 以包含以下內容:
```
export HBASE_OPTS="-Djava.security.auth.login.config=$CLIENT_CONF"
export HBASE_MANAGES_ZK=true
export HBASE_ZOOKEEPER_OPTS="-Djava.security.auth.login.config=$HBASE_SERVER_CONF"
export HBASE_MASTER_OPTS="-Djava.security.auth.login.config=$HBASE_SERVER_CONF"
export HBASE_REGIONSERVER_OPTS="-Djava.security.auth.login.config=$HBASE_SERVER_CONF"
```
其中 _ $ HBASE_SERVER _CONF_ 和 _ $ CLIENT _CONF_ 是上面創建的 JAAS 配置文件的完整路徑。
在將運行 zookeeper,master 或 regionserver 的每個節點上修改 _hbase-site.xml_ 以包含:
```
<configuration>
<property>
<name>hbase.zookeeper.quorum</name>
<value>$ZK_NODES</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.property.authProvider.1</name>
<value>org.apache.zookeeper.server.auth.SASLAuthenticationProvider</value>
</property>
<property>
<name>hbase.zookeeper.property.kerberos.removeHostFromPrincipal</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.property.kerberos.removeRealmFromPrincipal</name>
<value>true</value>
</property>
</configuration>
```
其中`$ZK_NODES`是 ZooKeeper Quorum 主機的逗號分隔的主機名列表。
通過在適當的主機上運行以下一組或多組命令來啟動 hbase 群集:
```
bin/hbase zookeeper start
bin/hbase master start
bin/hbase regionserver start
```
### 197.3。外部 ZooKeeper 配置
添加一個類似于的 JAAS 配置文件:
```
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
keyTab="$PATH_TO_HBASE_KEYTAB"
principal="hbase/$HOST";
};
```
其中 _ $ PATH_TO_HBASE _KEYTAB_ 是上面創建的 HBase 服務在此主機上運行的密鑰表,`$HOST`是該節點的主機名。把它放在 HBase home 的配置目錄中。我們將此文件的完整路徑名稱稱為 _ $ HBASE_SERVER _CONF_ 。
修改您的 hbase-env.sh 以包含以下內容:
```
export HBASE_OPTS="-Djava.security.auth.login.config=$CLIENT_CONF"
export HBASE_MANAGES_ZK=false
export HBASE_MASTER_OPTS="-Djava.security.auth.login.config=$HBASE_SERVER_CONF"
export HBASE_REGIONSERVER_OPTS="-Djava.security.auth.login.config=$HBASE_SERVER_CONF"
```
在將運行 master 或 regionserver 的每個節點上修改 _hbase-site.xml_ 以包含:
```
<configuration>
<property>
<name>hbase.zookeeper.quorum</name>
<value>$ZK_NODES</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.property.authProvider.1</name>
<value>org.apache.zookeeper.server.auth.SASLAuthenticationProvider</value>
</property>
<property>
<name>hbase.zookeeper.property.kerberos.removeHostFromPrincipal</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.property.kerberos.removeRealmFromPrincipal</name>
<value>true</value>
</property>
</configuration>
```
其中`$ZK_NODES`是 ZooKeeper Quorum 主機的逗號分隔的主機名列表。
同樣在每個主機上,創建一個 JAAS 配置文件,其中包含:
```
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="$PATH_TO_ZOOKEEPER_KEYTAB"
storeKey=true
useTicketCache=false
principal="zookeeper/$HOST";
};
```
其中`$HOST`是每個 Quorum 主機的主機名。我們將此文件的完整路徑名稱為 _ $ ZK_SERVER _CONF_ 。
使用以下命令在每個 ZooKeeper Quorum 主機上啟動 ZooKeepers:
```
SERVER_JVMFLAGS="-Djava.security.auth.login.config=$ZK_SERVER_CONF" bin/zkServer start
```
通過在相應節點上運行以下一組或多組命令來啟動 HBase 集群:
```
bin/hbase master start
bin/hbase regionserver start
```
### 197.4。 ZooKeeper 服務器身份驗證日志輸出
如果上面的配置成功,您應該在 ZooKeeper 服務器日志中看到類似于以下內容的內容:
```
11/12/05 22:43:39 INFO zookeeper.Login: successfully logged in.
11/12/05 22:43:39 INFO server.NIOServerCnxnFactory: binding to port 0.0.0.0/0.0.0.0:2181
11/12/05 22:43:39 INFO zookeeper.Login: TGT refresh thread started.
11/12/05 22:43:39 INFO zookeeper.Login: TGT valid starting at: Mon Dec 05 22:43:39 UTC 2011
11/12/05 22:43:39 INFO zookeeper.Login: TGT expires: Tue Dec 06 22:43:39 UTC 2011
11/12/05 22:43:39 INFO zookeeper.Login: TGT refresh sleeping until: Tue Dec 06 18:36:42 UTC 2011
..
11/12/05 22:43:59 INFO auth.SaslServerCallbackHandler:
Successfully authenticated client: authenticationID=hbase/ip-10-166-175-249.us-west-1.compute.internal@HADOOP.LOCALDOMAIN;
authorizationID=hbase/ip-10-166-175-249.us-west-1.compute.internal@HADOOP.LOCALDOMAIN.
11/12/05 22:43:59 INFO auth.SaslServerCallbackHandler: Setting authorizedID: hbase
11/12/05 22:43:59 INFO server.ZooKeeperServer: adding SASL authorization for authorizationID: hbase
```
### 197.5。 ZooKeeper 客戶端身份驗證日志輸出
在 ZooKeeper 客戶端(HBase 主服務器或區域服務器)上,您應該看到類似于以下內容的內容:
```
11/12/05 22:43:59 INFO zookeeper.ZooKeeper: Initiating client connection, connectString=ip-10-166-175-249.us-west-1.compute.internal:2181 sessionTimeout=180000 watcher=master:60000
11/12/05 22:43:59 INFO zookeeper.ClientCnxn: Opening socket connection to server /10.166.175.249:2181
11/12/05 22:43:59 INFO zookeeper.RecoverableZooKeeper: The identifier of this process is 14851@ip-10-166-175-249
11/12/05 22:43:59 INFO zookeeper.Login: successfully logged in.
11/12/05 22:43:59 INFO client.ZooKeeperSaslClient: Client will use GSSAPI as SASL mechanism.
11/12/05 22:43:59 INFO zookeeper.Login: TGT refresh thread started.
11/12/05 22:43:59 INFO zookeeper.ClientCnxn: Socket connection established to ip-10-166-175-249.us-west-1.compute.internal/10.166.175.249:2181, initiating session
11/12/05 22:43:59 INFO zookeeper.Login: TGT valid starting at: Mon Dec 05 22:43:59 UTC 2011
11/12/05 22:43:59 INFO zookeeper.Login: TGT expires: Tue Dec 06 22:43:59 UTC 2011
11/12/05 22:43:59 INFO zookeeper.Login: TGT refresh sleeping until: Tue Dec 06 18:30:37 UTC 2011
11/12/05 22:43:59 INFO zookeeper.ClientCnxn: Session establishment complete on server ip-10-166-175-249.us-west-1.compute.internal/10.166.175.249:2181, sessionid = 0x134106594320000, negotiated timeout = 180000
```
### 197.6。從 Scratch 配置
這已經在當前的標準 Amazon Linux AMI 上進行了測試。首先如上所述設置 KDC 和主體。下一個檢查代碼并運行完整性檢查。
```
git clone https://gitbox.apache.org/repos/asf/hbase.git
cd hbase
mvn clean test -Dtest=TestZooKeeperACL
```
然后如上所述配置 HBase。手動編輯 target / cached_classpath.txt(見下文):
```
bin/hbase zookeeper &
bin/hbase master &
bin/hbase regionserver &
```
### 197.7。未來的改進
#### 197.7.1。修復 target / cached_classpath.txt
您必須使用包含 HADOOP-7070 修復程序的版本覆蓋`target/cached_classpath.txt`文件中的標準 hadoop-core jar 文件。您可以使用以下腳本執行此操作:
```
echo `find ~/.m2 -name "*hadoop-core*7070*SNAPSHOT.jar"` ':' `cat target/cached_classpath.txt` | sed 's/ //g' > target/tmp.txt
mv target/tmp.txt target/cached_classpath.txt
```
#### 197.7.2。以編程方式設置 JAAS 配置
這將避免需要一個單獨的 Hadoop jar 來修復 [HADOOP-7070](https://issues.apache.org/jira/browse/HADOOP-7070) 。
#### 197.7.3。消除`kerberos.removeHostFromPrincipal`和`kerberos.removeRealmFromPrincipal`
- HBase? 中文參考指南 3.0
- Preface
- Getting Started
- Apache HBase Configuration
- Upgrading
- The Apache HBase Shell
- Data Model
- HBase and Schema Design
- RegionServer Sizing Rules of Thumb
- HBase and MapReduce
- Securing Apache HBase
- Architecture
- In-memory Compaction
- Backup and Restore
- Synchronous Replication
- Apache HBase APIs
- Apache HBase External APIs
- Thrift API and Filter Language
- HBase and Spark
- Apache HBase Coprocessors
- Apache HBase Performance Tuning
- Troubleshooting and Debugging Apache HBase
- Apache HBase Case Studies
- Apache HBase Operational Management
- Building and Developing Apache HBase
- Unit Testing HBase Applications
- Protobuf in HBase
- Procedure Framework (Pv2): HBASE-12439
- AMv2 Description for Devs
- ZooKeeper
- Community
- Appendix