kudu環境搭建和基本使用(centos-7)

注:本文只記錄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

https://github.com/cloudera/kudu/tree/master/examples

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章