如何使用Java代碼訪問Kerberos環境下的Kudu

溫馨提示:如果使用電腦查看圖片不清晰,可以使用手機打開文章單擊文中的圖片放大查看高清原圖。

Fayson的github: https://github.com/fayson/cdhproject

提示:代碼塊部分可以左右滑動查看噢

1

文檔編寫目的

前面Fayson介紹了《如何使用Java API訪問CDH的Kudu》,文章是在非安全環境下實現,隨着對集羣安全要求的提高,在Kerberos環境下的使用API訪問Kudu也會有一些變化,本篇文章Fayson主要介紹如何使用Java代碼訪問Kerberos環境下的Kudu。

  • 內容概述

1.環境準備

2.Kerberos環境示例代碼及運行

3.總結

  • 測試環境

1.CDH版本爲5.15.0

2.OS爲Redhat7.2

3.Kudu版本爲1.7.0

  • 前置條件

1.CDH集羣運行正常

2.集羣已啓用Kerberos

2

環境準備

使用IDE工具通過Maven創建一個Java工程,具體創建過程就不詳細描述了。

1.在工程的pom.xml文件中增加如下依賴

<dependency>
    <groupId>org.apache.kudu</groupId>
    <artifactId>kudu-client</artifactId>
    <version>1.7.0-cdh5.15.2</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.6.0-cdh5.15.0</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.6.0-cdh5.15.0</version>
</dependency>

2.集羣爲Kerberos,需要導出一個keytab文件用於訪問HDFS,導出步驟如下

在CMD命令行執行如下命令導出AD中用戶的keytab文件

ktpass -princ hdfs/[email protected]  -mapuser hdfs/admin -pass 123!QAZ -out hdfsadmin.keytab -crypto RC4-HMAC-NT

(可左右滑動)

導出的keytab文件會在當前命令執行目錄。

3.獲取集羣krb5.conf文件,內容如下

[root@cdh4 ~]# more /etc/krb5.conf
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/

includedir /var/lib/sss/pubconf/krb5.include.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = true
 default_realm = FAYSON.COM
 #default_ccache_name = KEYRING:persistent:%{uid}

[realms]
 FAYSON.COM = {
  kdc = adserver.fayson.com
  admin_server = adserver.fayson.com
 }

[domain_realm]
 .fayson.com = FAYSON.COM
 fayson.com = FAYSON.COM

(可左右滑動)

4.配置hosts文件,確保本地開發環境與集羣所有節點通且端口均放通

5.通過Cloudera Manager下載HDFS客戶端配置

6.將上述準備的配置文件及keytab等信息拷貝至本地目錄或工程中,Fayson的工程目錄結構如下:

3

第一標題

1.ClientUtils類主要提供客戶端初始化方法,內容如下:

package com.cloudera.utils;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import java.util.Properties;

/**
 * package: com.cloudera.utils
 * describe: 客戶端工具類
 * creat_user: Fayson
 * email: [email protected]
 * creat_date: 2018/11/14
 * creat_time: 下午10:17
 * 公衆號:Hadoop實操
 */
public class ClientUtils {

    /**
     * 初始化訪問Kerberos訪問
     * @param debug 是否啓用Kerberos的Debug模式
     */
    public static void initKerberosENV(Boolean debug) {
        try {
            Properties properties = new Properties();
            properties.load(ClientUtils.class.getClass().getResourceAsStream("/client.properties
"));

            System.setProperty("java.security.krb5.conf", properties.getProperty("krb5.conf.path"));
            System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
            if (debug) System.setProperty("sun.security.krb5.debug", "true");

            Configuration configuration = new Configuration();
            configuration.addResource(ClientUtils.class.getClass().getResourceAsStream("/hdfs-client-kb/core-site.xml"));
            configuration.addResource(ClientUtils.class.getClass().getResourceAsStream("/hdfs-client-kb/hdfs-site.xml"));
            UserGroupInformation.setConfiguration(configuration);

            UserGroupInformation.loginUserFromKeytab(properties.getProperty("kerberos.user"), properties.getProperty("kerberos.keytab.path"));
            System.out.println(UserGroupInformation.getCurrentUser());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

(可左右滑動)

2.KuduUtils用於操作Kudu的工具類,建表、查詢數據、刪除表等操作

package com.cloudera.utils;

import com.cloudera.RandomUserInfo;
import org.apache.kudu.ColumnSchema;
import org.apache.kudu.Schema;
import org.apache.kudu.Type;
import org.apache.kudu.client.*;
import java.util.ArrayList;
import java.util.List;

/**
 * package: com.cloudera.utils
 * describe: TODO
 * creat_user: Fayson
 * email: [email protected]
 * creat_date: 2018/11/15
 * creat_time: 上午12:31
 * 公衆號:Hadoop實操
 */
public class KuduUtils {

    /**
     * 使用Kudu API創建一個Kudu表
     * @param client
     * @param tableName
     */
    public static void createTable(KuduClient client, String tableName) {
        List<ColumnSchema> columns = new ArrayList<>();
        //在添加列時可以指定每一列的壓縮格式
        columns.add(new ColumnSchema.ColumnSchemaBuilder("id", Type.STRING).key(true).        compressionAlgorithm(ColumnSchema.CompressionAlgorithm.SNAPPY).build());
       …
        Schema schema = new Schema(columns);
        CreateTableOptions createTableOptions = new CreateTableOptions();
        List<String> hashKeys = new ArrayList<>();
        hashKeys.add("id");
        int numBuckets = 8;
        createTableOptions.addHashPartitions(hashKeys, numBuckets);

        try {
            if(!client.tableExists(tableName)) {
                client.createTable(tableName, schema, createTableOptions);
            }
            System.out.println("成功創建Kudu表:" + tableName);
        } catch (KuduException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向指定的Kudu表中upsert數據,數據存在則更新,不存在則新增
     * @param client KuduClient對象
     * @param tableName 表名
     * @param numRows 向表中插入的數據量
     */
    public static void upsert(KuduClient client, String tableName, int numRows ) {
        try {
            KuduTable kuduTable = client.openTable(tableName);
            KuduSession kuduSession = client.newSession();
            //設置Kudu提交數據方式,這裏設置的爲手動刷新,默認爲自動提交
            …
            kuduSession.flush();
            kuduSession.close();
        } catch (KuduException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查看Kudu表中數據
     * @param client
     * @param tableName
     */
    public static void scanerTable(KuduClient client, String tableName) {
        try {
            KuduTable kuduTable = client.openTable(tableName);
            KuduScanner kuduScanner = client.newScannerBuilder(kuduTable).build();
            while(kuduScanner.hasMoreRows()) {
                RowResultIterator rowResultIterator =kuduScanner.nextRows();
                while (rowResultIterator.hasNext()) {
                    RowResult rowResult = rowResultIterator.next();
                    System.out.println(rowResult.getString("id"));
                }
            }
            kuduScanner.close();
        } catch (KuduException e) {
            e.printStackTrace();
        }
    }

    /**
     * 刪除表
     * @param client
     * @param tableName
     */
    public static void dropTable(KuduClient client, String tableName) {
        try {
            client.deleteTable(tableName);
        } catch (KuduException e) {
            e.printStackTrace();
        }
    }

    /**
     * 列出Kudu下所有的表
     * @param client
     */
    public static void tableList(KuduClient client) {
        try {
            ListTablesResponse listTablesResponse = client.getTablesList();
            List<String> tblist = listTablesResponse.getTablesList();
            for(String tableName : tblist) {
                System.out.println(tableName);
            }
        } catch (KuduException e) {
            e.printStackTrace();
        }
    }

}

(可左右滑動)

4

示例代碼及運行

1.KuduKerberosExample爲測試類包含API的調用

package com.cloudera;

import com.cloudera.utils.ClientUtils;
import com.cloudera.utils.KuduUtils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.kudu.client.KuduClient;
import org.apache.kudu.client.KuduException;
import java.io.IOException;
import java.security.PrivilegedExceptionAction;

/**
 * package: com.cloudera
 * describe: 訪問Kerberos環境下的Kudu
 * creat_user: Fayson
 * email: [email protected]
 * creat_date: 2018/11/15
 * creat_time: 上午12:32
 * 公衆號:Hadoop實操
 */
public class KuduKerberosExample {

    public static void main(String[] args) {
        ClientUtils.initKerberosENV(false);
        String kudu_master = System.getProperty("kuduMasters", "cdh1.fayson.com:7051,cdh2.fayson.com:7051,cdh3.fayson.com:7051");
        try {
            KuduClient kuduClient = UserGroupInformation.getLoginUser().doAs(
                    new PrivilegedExceptionAction<KuduClient>() {
                        @Override
                        public KuduClient run() throws Exception {
                            return new KuduClient.KuduClientBuilder(kudu_master).build();
                        }
                    }
            );

            String tableName = "user_info_kudu";
            //刪除Kudu的表
            KuduUtils.dropTable(kuduClient, tableName);
            //創建一個Kudu的表
            KuduUtils.createTable(kuduClient, tableName);
            //列出Kudu下所有的表
            KuduUtils.tableList(kuduClient);
            //向Kudu指定的表中插入數據
            KuduUtils.upsert(kuduClient, tableName, 100);
            //掃描Kudu表中數據
            KuduUtils.scanerTable(kuduClient, tableName);
            try {
                kuduClient.close();
            } catch (KuduException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

(可左右滑動)

2.示例運行

3.訪問Kudu Master的UI界面

點擊“Table Id”進入user_info_kudu表詳細頁面

使用Kudu表提供的Impala建表語句,在Impala上創建外部表

CREATE EXTERNAL TABLE `user_info_kudu` STORED AS KUDU
TBLPROPERTIES(
    'kudu.table_name' = 'user_info_kudu',
    'kudu.master_addresses' = 'cdh1.fayson.com:7051,cdh2.fayson.com:7051,cdh3.fayson.com:7051')

(可左右滑動)

查詢user_info_kudu表數據

5

總結

1.在進行本地開發時,必須將集羣的hostname及IP配置在本地的hosts文件中(如果使用DNS服務則可以不配置hosts文件),否則無法與集羣互通,確保本地客戶端與集羣的端口是放通的。

2.訪問Kerberos環境下的Kudu時,需要使用HDFS API提供的UserGroupInformation類實現Kerberos賬號登錄認證,該API在登錄Kerberos認證後,會啓動一個線程定時的刷新認證。

GitHub源碼地址:

https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/KuduKerberosExample.java

https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/utils/ClientUtils.java

https://github.com/fayson/cdhproject/blob/master/kududemo/src/main/java/com/cloudera/utils/KuduUtils.java

提示:代碼塊部分可以左右滑動查看噢

爲天地立心,爲生民立命,爲往聖繼絕學,爲萬世開太平。 溫馨提示:如果使用電腦查看圖片不清晰,可以使用手機打開文章單擊文中的圖片放大查看高清原圖。

推薦關注Hadoop實操,第一時間,分享更多Hadoop乾貨,歡迎轉發和分享。

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