Kerberos 初始化
管理员可以使用集群成员服务器上的keytab 进行 kerberos 认证,从而获得集群管理员权限,用户需要先进行 kerberos 认证才能对集群进行操作。
在命令行中输入如下命令即可完成kerberos 认证:
klist -kt /etc/security/keytabs/<user>.keytab | awk '{print $4}' | grep -e '<user>.*@.*' | head -1 | xargs kinit -kt /etc/security/keytabs/<user>.keytab也可以将klist 和 kinit 命令分开使用:
1、输入 klist -kt /etc/security/keytabs/<user>.keytab 获取 principal;
2、输入 kinit -kt /etc/security/keytabs/<user>.keytab <principal> 完成认证。
两种认证方式案例如下:
连接beeline
beeline 连接串形式如下(zk_host_name、EXAMPLE.COM 等请替换为实际集群信息):
"jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi"连接串参数说明:
1、principal 后面的内容是启动 kyuubi 服务配置,配置在 /usr/local/kyuubi/kyuubi-defaults.conf 里面,这个需要根据具体的 principal 进行修改,主机名都使用 _HOST 替代;
2、这里的 namespace 是 /usr/local/kyuubi/kyuubi-defaults.conf 里的参数 kyuubi.ha.namespace 配置的,默认是 kyuubi,如果改成了其他的,连接串也要改成相应的名字。
进入beeline 有如下两种方式:
1、beeline 后面跟连接串,案例如下:
beeline -u "jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi"2、先进入 beeline,再通过 !connect 连接,案例如下:
beeline
!connect jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi连接串追加参数
连接串可以追加kyuubi 或 spark 参数。在上述连接串的最后面增加 ;# 再加 kyuubi 参数,后面再加参数就用分号分隔,连接串单独增加 spark 参数时在最后面增加问号再加参数。下面以改变引擎的级别为例:
追加一个kyuubi 参数(kyuubi.engine.share.level=CONNECTION),案例如下:
jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi;#kyuubi.engine.share.level=CONNECTION追加两个及以上kyuubi 参数,案例如下:
jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi;#kyuubi.engine.share.level=USER;kyuubi.engine.share.level.subdomain=test1连接串追加一个spark 参数:第一个参数在连接串后面使用问号分割然后增加参数,追加两个及以上参数在第一个参数后面增加分号分隔。这里以指定 application name 为例:
jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/default;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi?spark.app.name=my_test;相关参数说明
Kyuubi 常用连接参数如下表所示:
| 参数 | 默认值 | 参数说明 |
|---|---|---|
| kyuubi.engine.share.level | USER | 包含CONNECTION、USER、GROUP、SERVER 四个选项,一般会用 CONNECTION、USER 选项,翼MR默认是 USER。CONNECTION:每个 jdbc 连接串会启动一个 spark 的 application,执行结束后马上退出;USER:默认是一个用户启动一个 application,只是 session 不一样,例如 keytab 都用的 hdfs,在 host1 机器使用这个连接串会启动一个 application-1,只要这个 application-1 还没退出,在 host2 机器使用这个连接串还是复用这个 application-1 |
| kyuubi.engine.share.level.subdomain | 无 | 如果要一个用户启动不同的application,那么增加参数 kyuubi.engine.share.level.subdomain,后面的值随便定义,不同的值启动不同的 application,例如:kyuubi.engine.share.level.subdomain=test1 |
| ___username___.spark参数 | 无 | kyuubi 可以根据不同的用户自定义 spark 参数,配置在 kyuubi-defaults.conf(修改了这里的配置需要重启 kyuubi 服务),参考配置如下:修改配置 hdfs 用户的默认 driver 内存 ___hdfs___.spark.driver.memory=4g |
其他kyuubi 参数可以参考官网。
SQL 语法
集群Kyuubi 当前集成的是 spark-sql 语法,这里简单的提供下面 sql 示例,详细的可以参见 spark 使用手册或者参见官网 sql 语法:
drop database if exists spark_test cascade;
create database if not exists spark_test;
drop table if exists spark_test.test_spark_orc;
drop table if exists spark_test.test_spark_txt;
create table spark_test.test_spark_orc(k string,v int);
insert into table spark_test.test_spark_orc values ('k1',1),('k2',2),('k3',3);
create table spark_test.test_spark_txt(k string,v int) stored as textfile;
insert into table spark_test.test_spark_txt values ('k1',1),('k2',2),('k3',3);
select count(*) from spark_test.test_spark_orc t1 inner join spark_test.test_spark_txt t2 on t1.k=t2.k;Java SDK 接口
可以使用kyuubi 的 jdbc 进行开发,也可以使用 hive 的 jdbc 进行开发。
使用kyuubi 的 jdbc 进行开发,pom 里需要加入如下依赖:
<dependency>
<groupId>org.apache.kyuubi</groupId>
<artifactId>kyuubi-hive-jdbc-shaded</artifactId>
<version>1.8.2</version>
</dependency>说明
这个版本号根据自己集群的具体kyuubi 版本选择。
连接代码示例如下(url 中的 zk_host_name、EXAMPLE.COM 等请替换为实际集群信息):
package cn.com.chinatelecom;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.sql.*;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
public class TestKyuubi {
//kyuubi驱动
private static String driverName = "org.apache.kyuubi.jdbc.KyuubiHiveDriver";
//kyuubi连接串
private static String url = "jdbc:hive2://zk_host_name1:2181,zk_host_name2:2181,zk_host_name3:2181/;principal=hive/_HOST@EXAMPLE.COM;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi";
private static Connection conn = null;
private static Statement state = null;
private static ResultSet rs = null;
private static String principal = null;//执行这个jdbc的使用的keytab的principal
private static String keytab = null;//执行这个jdbc的keytab文件路径
private static String user = null;
private static String useType = null;//使用类型,包括ldap和kerberos两种
private static String passwd = null;//使用ldap时的密码
public static void getConnect() throws Exception {
Configuration conf = new Configuration();
//kyuubi只使用了Kerberos时走如下代码
if (useType.equalsIgnoreCase("kerberos")) {
conf.set("hadoop.security.authentication","kerberos");
System.out.println("use: " + user + "------- url: " + url + "---------keytab:" + keytab + "----------principal: " + principal);
UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab(principal,keytab);//keytab内容
Class.forName(driverName);
UserGroupInformation ugi = UserGroupInformation.getLoginUser();
conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
@Override
public Connection run() throws SQLException {
return DriverManager.getConnection(url,user,"");
}
});
} else if (useType.equalsIgnoreCase("ldap")) {//kyuubi使用了Kerberos同时有集成了ldap就走如下代码
Class.forName(driverName);
conn = DriverManager.getConnection(url,user,passwd);
} else {
System.out.println("please input authentication type(kerberos or ldap)");
return;
}
state = conn.createStatement();
}
public static void showDatabases() throws SQLException {
System.out.println("-------show databases -----");
rs = state.executeQuery("show databases");
while (rs.next()) {
System.out.println(rs.getString(1));
}
}
public static void close() throws SQLException {
if (rs != null) state.close();
if (state != null) state.close();
if (conn !=null) conn.close();
}
public static void main(String args[]) throws Exception {
if (args.length >= 4) {
if (args[0]!=null && !args[0].isEmpty()) {
url = args [0];
}
if (args[1]!=null && !args[1].isEmpty()) {
useType = args [1];
}
if (args[2]!=null && !args[2].isEmpty()) {
user = args [2];
}
if (useType.equalsIgnoreCase("ldap") && args[3]!=null && !args[3].isEmpty()) {
passwd = args [3];
} else if (useType.equalsIgnoreCase("kerberos")) {
if (args[3]!=null && !args[3].isEmpty()) {
keytab = args [3];
}
if (args[4]!=null && !args[4].isEmpty()) {
principal = args [4];
}
}
}
getConnect();
showDatabases();
close();
}
}使用hive 的 jdbc 进行开发,pom 里需要加入如下依赖:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.2</version>
</dependency>注意
这个hive-jdbc 包必须使用翼MR提供的,不能使用社区的(由于集群集成了 ranger,会在 ZK 上增加 ranger 的 znode 节点,导致出现连接失败的情况,自研版本解决了这个问题)。