注:本文只記錄kudu的安裝,不涉及其它工具或組件
一、前言
安裝 kudu有多種方式,本文介紹使用yum源在線安裝的方式(kudu不像CM那樣安裝包很大,在線安裝不會有什麼問題)。博主當前準備四個節點:192.168.0.198、192.168.0.210、192.168.0.211、192.168.0.212。
現做如下規劃(tserver節點數量得是奇數):
節點 | 角色 |
192.168.0.198 | tserver |
192.168.0.210 | tserver |
192.168.0.211 | master |
192.168.0.212 | tserver |
我們先配置一個master節點,等安裝完成後再演示一下如何擴展更多的master節點,正常情況master節點數量是要大於1的。
二、安裝
2.1 環境準備
爲了方便,直接將每臺機器的hostname都設置爲對應的ip,修改對應的/etc/hostname即可。
2.1 準備repo文件
根據服務器版本到http://archive.cloudera.com/kudu下載對應的cloudera-kudu.repo文件,博主當前環境爲64位centos-7,所以下載的文件爲:
http://archive.cloudera.com/kudu/redhat/7/x86_64/kudu/cloudera-kudu.repo
然後將下載的文件放到每臺機器對應的源目錄,不同的系統目錄有差異,博主的centos環境對應的目錄爲:/etc/yum.repos.d
2.2 引入 RPM-GPG-KEY
這個key用於驗證軟件版權,在每臺機器上執行以下命令即可引入(url參照2.1步驟repo文件的路徑):
>sudo rpm --import https://archive.cloudera.com/kudu/redhat/7/x86_64/kudu/RPM-GPG-KEY-cloudera
2.3 安裝
注:在安裝開始之前,我們要規劃好哪些機器用作master節點,哪些機器用作tserver節點,當然前面已經做了說明。
首先要在集羣中的每臺機器上都安裝kudu公共組件:
>yum -y install kudu
2.3.1 安裝kudu-master
在master機器(192.168.0.211)上安裝kudu-master:
>yum -y install kudu-master
安裝完成之後,會自動在/etc/kudu/conf目錄生成master對應的配置文件:master.gflagfile,內容如下(更多配置項可以參考官方文檔):
# Do not modify these two lines. If you wish to change these variables,
# modify them in /etc/default/kudu-master.
--fromenv=rpc_bind_addresses
--fromenv=log_dir
--fs_wal_dir=/var/lib/kudu/master
--fs_data_dirs=/var/lib/kudu/master
# 當前只有一個節點,暫時可以不用配置
--master_addresses=192.168.0.211:7051
文件內容中有清晰的註釋,--fromenv配置來源於:/etc/default/kudu-master,如果要修改該配置,不要直接在gflagfile中修改,更新kudu-master文件即可,我修改了rpc_bind_addresses爲本機ip+7051:
export FLAGS_log_dir=/var/log/kudu
export FLAGS_rpc_bind_addresses=192.168.0.211:7051
2.3.2 安裝kudu-tserver
在tserver機器(192.168.0.198,192.168.0.210,192.168.0.212)上安裝kudu-tserver,流程和安裝master類似:
>yum -y install kudu-tserver
安裝完成之後,也會在/etc/kudu/conf目錄生成tserver對應的配置文件:tserver.gflagfile,稍作修改,內容如下:
# Do not modify these two lines. If you wish to change these variables,
# modify them in /etc/default/kudu-tserver.
--fromenv=rpc_bind_addresses
--fromenv=log_dir
--fs_wal_dir=/var/lib/kudu/tserver
--fs_data_dirs=/var/lib/kudu/tserver
# master節點地址,逗號分隔,就是master中的FLAGS_rpc_bind_addresses配置
# 我們當前只有一個master節點
--tserver_master_addrs=192.168.0.211:7051
和master節點類似,--fromenv參數依賴/etc/default/kudu-tserver文件,如果需要更新,修改該文件即可(ip爲本機ip):
export FLAGS_log_dir=/var/log/kudu
export FLAGS_rpc_bind_addresses=192.168.0.198:7050
博主當前有三個tserver節點,所以在192.168.0.212和192.168.0.210節點上重複該步驟即可。
注:kudu-client0和kudu-client-devel並不是必須的,如果需要C++客戶端開發庫或者kudu SDK,則需要安裝,安裝比較簡單,直接在節點上執行以下命令即可:
>yum -y install kudu-client0
>yum -y install kudu-client-devel
2.4 配置服務自動啓動(可選)
master節點:
>chkconfig kudu-master on
tserver節點:
>chkconfig kudu-tserver on
2.5 啓動服務
master節點:
>systemctl start kudu-master
tserver節點:
>systemctl start kudu-tserver
三、驗證
通過ps命令可以查看是否啓動成功:
master節點:
tserver節點:
如果沒有啓動成功,查看對應的日誌輸出即可,默認日誌目錄爲:/var/log/kudu
啓動成功後,可以通過瀏覽器進入對應的UI界面:
master地址爲: <hostName>:8051,博主的環境爲:192.168.0.211:8051,界面顯示如下:
上面顯示了基本的版本信息,kudu版本爲1.4。
tserver地址爲:<hostName>:8050,我們進入:192.168.0.198:8050,界面顯示如下:
當然,端口信息,包括用戶名和密碼等等都是可以配置的。
四、擴展master節點(停機)
我們目前只有一個192.168.0.211作爲master節點,現在將192.168.0.210節點擴展爲master節點。
4.1 首先停止集羣中的所有kudu服務
>systemctl stop kudu-master
>systemctl stop kudu-tserver
4.2 安裝kudu-master
這個上面已經介紹過了,我們在新節點192.168.0.210上執行 yum -y install kudu-master即可,安裝完畢之後會在對應的目錄生成好默認配置文件。
4.3 初始化新節點的 fs_wal_dir
在新節點192.168.0.210上執行以下命令初始化目錄:
>kudu fs format --fs_wal_dir=<master_data_dir>
其中master_data_dir默認爲/var/lib/kudu/master,如果自定義了新路徑,照着修改就行。當前環境直接執行:
>kudu fs format --fs_wal_dir=/var/lib/kudu/master
執行該命令後,會初始化好標準的/var/lib/kudu/master目錄:
注:consensus-meta目錄初始爲空,在我們後面的步驟處理。
初始化好之後我們需要獲取一個標識master節點的uuid,將其記錄下來,後面會使用,使用以下命令輸出uuid:
>kudu fs dump uuid --fs_wal_dir=<master_data_dir> 2>/dev/null
其中的master_data_dir和前一個步驟一樣,輸出示例如下:
注:需要記錄每個master節點的uuid,我們的環境就是192.168.0.211和192.168.0.210兩個節點,命令都是一樣的
4.4 更新raft配置
更新配置用到的命令(在非新的master節點上執行,當前爲192.168.0.211)如下:
>kudu local_replica cmeta rewrite_raft_config --fs_wal_dir=<master_data_dir> <tablet_id> <all_masters>
其中:
fs_wal_dir:和前面命令提到的一樣,默認爲/var/lib/kudu/master;
tablet_id:固定爲00000000000000000000000000000000
(32個0);
all_masters:爲擴展之後的所有master節點列表,格式爲uuid:ip:port,多個節點空格分隔,uuid就是我們前面記錄下來的數據。
在我們的環境中,命令是這樣的:
>kudu local_replica cmeta rewrite_raft_config --fs_wal_dir=/var/lib/kudu/master 00000000000000000000000000000000 a3f3fb4e7aba4f559bae12f6aa50a96a:192.168.0.211:7051 453df4dcbb2d41c7b672e2cef99c6c45:192.168.0.210:7051
執行該命令後,/var/lib/kudu/master/consensus-meta/目錄會生成一個新的00000000000000000000000000000000
文件,
同時之前的文件會添加.pre_rewrite.timestamp後綴作爲一個備份:
4.5 同步配置
將上述步驟生成的新的00000000000000000000000000000000文件拷貝到其它機器上,kudu提供了copy_from_remote指令,由於我暫時沒有去配置免密登錄,所有直接使用scp命令,將192.168.0.211最新的00000000000000000000000000000000文件發送到新的節點192.168.0.210:
>cd /var/lib/kudu/master/consensus-meta
>scp 00000000000000000000000000000000 [email protected]:/var/lib/kudu/master/consensus-meta
在192.168.0.210節點確認文件:
但是這樣生成的00000000000000000000000000000000文件不歸kudu:kudu用戶所有,在啓動的時候可能會出現Permission denied (error 13)的異常信息,所以我們修改00000000000000000000000000000000文件的歸屬:
>chown -R kudu:kudu /var/lib/kudu/master/consensus-meta00000000000000000000000000000000
最後,新舊節點(192.168.0.210和192.168.0.211)的配置文件:master.gflagfile也都要完整配置master節點列表:
# Do not modify these two lines. If you wish to change these variables,
# modify them in /etc/default/kudu-master.
--fromenv=rpc_bind_addresses
--fromenv=log_dir
--fs_wal_dir=/var/lib/kudu/master
--fs_data_dirs=/var/lib/kudu/master
# 現在是兩個master節點
--master_addresses=192.168.0.211:7051,192.168.0.210:7051
到這裏master擴展已經完成了,我們還需要修改所有tserver節點的tserver.gflagfile文件的tserver_master_addrs配置,增加新的master節點192.168.0.210,以190.168.0.210爲例(210也是一個tserver節點):
--fromenv=rpc_bind_addresses
--fromenv=log_dir
--fs_wal_dir=/var/lib/kudu/tserver
--fs_data_dirs=/var/lib/kudu/tserver
# 增加192.168.0.210節點
--tserver_master_addrs=192.168.0.211:7051,192.168.0.210:7051
在192.168.0.198和192.168.0.212節點做出同樣修改即可。現在我們的210節點同時充當master和tserver的角色。
4.6 驗證
重新啓動所有master和tserver節點,進入WEB頁面查看狀態信息,首先查看master信息:
我們看到,已經有兩個master節點了,210爲leader,211爲follower。
查看tablets信息:
我們看到,有三個tserver節點,分別爲198、210、212。
4.7 總結
整個新增master節點的步驟可以簡單歸納爲:
>1.新節點安裝kudu-master
>2.在舊節點使用kudu提供的命令更新00000000000000000000000000000000文件
>3.同步最新的00000000000000000000000000000000文件到其它master節點(修改文件權限)
>4.修改每個master節點的master.gflagfile,完善--master_addresses配置
>5.修改每個tserver節點的tserver.gflagfile文件,完善--tserver_master_addrs配置
>6.啓動
五、使用
這裏簡單使用java操作一下kudu,代碼來源於github:kudu/examples。
import java.util.ArrayList;
import java.util.List;
import org.apache.kudu.ColumnSchema;
import org.apache.kudu.Schema;
import org.apache.kudu.Type;
import org.apache.kudu.client.*;
/**
* Author huangzhilin
* Date 2019/5/14
*/
public class Example {
private static final String KUDU_MASTERS = "192.168.0.211:7051,192.168.0.210:7051";
static void createExampleTable(KuduClient client, String tableName) throws KuduException {
// Set up a simple schema.
List<ColumnSchema> columns = new ArrayList<>(2);
columns.add(new ColumnSchema.ColumnSchemaBuilder("key", Type.INT32)
.key(true)
.build());
columns.add(new ColumnSchema.ColumnSchemaBuilder("value", Type.STRING).nullable(true)
.build());
Schema schema = new Schema(columns);
// Set up the partition schema, which distributes rows to different tablets by hash.
// Kudu also supports partitioning by key range. Hash and range partitioning can be combined.
// For more information, see http://kudu.apache.org/docs/schema_design.html.
CreateTableOptions cto = new CreateTableOptions();
List<String> hashKeys = new ArrayList<>(1);
hashKeys.add("key");
int numBuckets = 2;
cto.addHashPartitions(hashKeys, numBuckets);
// Create the table.
client.createTable(tableName, schema, cto);
System.out.println("Created table " + tableName);
}
static void insertRows(KuduClient client, String tableName, int numRows) throws KuduException {
// Open the newly-created table and create a KuduSession.
KuduTable table = client.openTable(tableName);
KuduSession session = client.newSession();
for (int i = 0; i < numRows; i++) {
Insert insert = table.newInsert();
PartialRow row = insert.getRow();
row.addInt("key", i);
// Make even-keyed row have a null 'value'.
if (i % 2 == 0) {
row.setNull("value");
} else {
row.addString("value", "value " + i);
}
session.apply(insert);
}
// Call session.close() to end the session and ensure the rows are
// flushed and errors are returned.
// You can also call session.flush() to do the same without ending the session.
// When flushing in AUTO_FLUSH_BACKGROUND mode (the default mode recommended
// for most workloads, you must check the pending errors as shown below, since
// write operations are flushed to Kudu in background threads.
session.close();
if (session.countPendingErrors() != 0) {
System.out.println("errors inserting rows");
org.apache.kudu.client.RowErrorsAndOverflowStatus roStatus = session.getPendingErrors();
org.apache.kudu.client.RowError[] errs = roStatus.getRowErrors();
int numErrs = Math.min(errs.length, 5);
System.out.println("there were errors inserting rows to Kudu");
System.out.println("the first few errors follow:");
for (int i = 0; i < numErrs; i++) {
System.out.println(errs[i]);
}
if (roStatus.isOverflowed()) {
System.out.println("error buffer overflowed: some errors were discarded");
}
throw new RuntimeException("error inserting rows to Kudu");
}
System.out.println("Inserted " + numRows + " rows");
}
public static void main(String[] args) {
System.out.println("-----------------------------------------------");
System.out.println("Will try to connect to Kudu master(s) at " + KUDU_MASTERS);
System.out.println("Run with -DkuduMasters=master-0:port,master-1:port,... to override.");
System.out.println("-----------------------------------------------");
String tableName = "java_example-" + System.currentTimeMillis();
KuduClient client = new KuduClient.KuduClientBuilder(KUDU_MASTERS).build();
try {
createExampleTable(client, tableName);
int numRows = 150;
insertRows(client, tableName, numRows);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
client.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上述代碼創建了一個table,設置的2個分區,並且插入了150條數據。
這裏要注意一點,使用的kudu-client版本最好和集羣版本一致,不然可能會出現各種異常情況,我們當前安裝的是1.4的kudu。
創建成功之後,進入tables標籤查看:
我們已經能看到該表了, 表名爲java_example-1557818213749,並且有個tableId,點進去可以看到該table的詳細信息:
參考:
https://www.cloudera.com/documentation/kudu/5-12-x/topics/kudu_installation.html