Zookeeper 入门实战(4)-

Zookeeper 入门实战(4)-

本主要介绍在 Zookeeper 中如何配置 Kerberos 认证,文中所使用到的软件版本:Java 1.8.0_191、Zookeeper 3.6.3、Kerberos 1.15.1。

1、Kerberos 安装

要使用 Kerberos 服务,需先安装 Kerberos,安装方法可参考:Kerberos 入门实战(2)--Kerberos 安装及使用。

2、Client-Server 的 Kerberos 认证

Client-Server 的 Kerberos 认证主要用于客户端与 Zookeeper 服务端的相互认证。

2.1、单节点 Client-Server 的 Kerberos 认证

2.1.1、创建 keytab

在安装 Kerberos 的机器上进入 kadmin(Kerberos 服务端上使用 kadmin.local,安装了 Kerberos Client 的机器上可以使用 kadmin),然后执行如下命令分别创建服务端和客户端的 keytab:

kadmin.local:  add_principal -randkey zk-server/pxc2@ABC.COM   #pxc2 为安装 Zookeeper 的主机名
kadmin.local:  add_principal -randkey zk-client@ABC.COM
kadmin.local:  xst -k /root/zk-server.keytab zk-server/pxc2@ABC.COM
kadmin.local:  xst -k /root/zk-client.keytab zk-client@ABC.COM

2.1.2、配置

A、拷贝 krb5.conf 及 keytab 文件到安装 Zookeeper 的机器,这里把文件都放到 Zookeeper 的 conf 目录下。

B、修改 zoo.cfg,增加如下配置:

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
sessionRequireClientSASLAuth=true #客户端必须 SASL 认证

C、新建 jaas.conf 文件,该文件也放到 Zookeeper 的 conf 目录下。

Server {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-server.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-server/pxc2@ABC.COM";
};

#客户端配置,方便 zkCli.sh 使用
Client {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-client.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-client@ABC.COM";
};

D、新建 java.env 文件;该文件主要用于指定 jaas 文件位置,也放到 Zookeeper 的 conf 目录下。

export SERVER_JVMFLAGS="-Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf"
export CLIENT_JVMFLAGS="${CLIENT_JVMFLAGS} -Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf -Dzookeeper.server.principal=zk-server/pxc2@ABC.COM"

SERVER_JVMFLAGS 是服务端(zkServer.sh)的配置
CLIENT_JVMFLAGS 是客户端(zkClis.sh)的配置,zookeeper.server.principal 参数用于配置服务端 principal(默认为 zookeeper/localhost@{realm},可能不存在)

2.1.3、启动并测试

配置完成后就可以启动 Zookeeper 了:

bin/zkServer.sh start

启动完成后可以使用 zkCli.sh 来测试:

bin/zkCli.sh

2.1.4、java 程序连接 Zookeeper

java 可以使用 JAAS 来进行 Kerberos 认证,需要 JAAS 配置文件、keytab 文件及 Kerberos 配置文件。

A、配置文件

JAAS 配置文件(zk-client-jaas.conf):

Client {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-client@ABC.COM";
};

keytab 文件:

从 Kerberos 服务器上拷贝到目标机器,拷贝路径即为 JAAS 配置中间配置的路径:D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client.keytab。

Kerberos 配置文件(krb5.conf):

从 Kerberos 服务器上拷贝 /etc/krb5.conf 到目标机器即可。

B、引入依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.3</version>
</dependency>

C、样例程序

package com.inspur.demo.general.zookeeper;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * Zookeeper 客户端 Kerberos 认证
 */
public class ZookeeperKerberosCase {
    private static String connectString = "10.49.196.11:2181";
    private static int sessionTimeout = 200 * 1000;

    private ZooKeeper zooKeeper;

    @Before
    public void before() {
        System.setProperty("java.security.auth.login.config", "D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client-jaas.conf");
        System.setProperty("java.security.krb5.conf", "D:\workspaceidea\demo\demo\src\main\resources\kerberos\krb5.conf");
        System.setProperty("zookeeper.server.principal", "zk-server/pxc2@ABC.COM"); //设置 Zookeeper 的 principal

        try {
            zooKeeper =  new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {

                }
            });
            System.out.println(zooKeeper.getState());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After
    public void after() throws Exception {
        zooKeeper.close();
    }

    @Test
    public void getData() throws Exception {
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/javatest/node1", false, stat);
        System.out.println(new String(data));
        System.out.println(stat);
    }
}

2.2、集群 Client-Server 的 Kerberos 认证

假设 Zookeeper 集群的机器信息如下:

ip 主机名
10.49.196.10 pxc1
10.49.196.11 pxc2
10.49.196.12 pxc3

2.2.1、创建 keytab

在安装 Kerberos 的机器上进入 kadmin(Kerberos 服务端上使用 kadmin.local,安装了 Kerberos Client 的机器上可以使用 kadmin),然后执行如下命令分别创建服务端和客户端的 keytab:

kadmin.local:  add_principal -randkey zk-server/pxc1@ABC.COM
kadmin.local:  add_principal -randkey zk-server/pxc2@ABC.COM
kadmin.local:  add_principal -randkey zk-server/pxc3@ABC.COM
kadmin.local:  add_principal -randkey zk-client@ABC.COM
kadmin.local:  xst -k /root/zk-server.keytab zk-server/pxc1@ABC.COM
kadmin.local:  xst -k /root/zk-server.keytab zk-server/pxc2@ABC.COM
kadmin.local:  xst -k /root/zk-server.keytab zk-server/pxc3@ABC.COM
kadmin.local:  xst -k /root/zk-client.keytab zk-client@ABC.COM

2.2.2、配置

A、拷贝 krb5.conf 及 keytab 文件到所有安装 Zookeeper 的机器,这里把文件都放到 Zookeeper 的 conf 目录下。

B、修改 zoo.cfg,增加如下配置:

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
sessionRequireClientSASLAuth=true #客户端必须 SASL 认证

C、新建 jaas.conf 文件,该文件也放到 Zookeeper 的 conf 目录下。

Server {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-server.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-server/pxc1@ABC.COM";   #这里不同的主机上,需修改为本机的主机名
};

#客户端配置,方便 zkCli.sh 使用
Client {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-client.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-client@ABC.COM";
};

D、新建 java.env 文件;该文件主要用于指定 jaas 文件位置,也放到 Zookeeper 的 conf 目录下。

export SERVER_JVMFLAGS="-Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf"
export CLIENT_JVMFLAGS="${CLIENT_JVMFLAGS} -Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf -Dzookeeper.server.principal=zk-server/pxc1@ABC.COM" #这里不同的主机上,需修改为本机的主机名

SERVER_JVMFLAGS 是服务端(zkServer.sh)的配置
CLIENT_JVMFLAGS 是客户端(zkClis.sh)的配置,zookeeper.server.principal 参数用于配置服务端 principal(默认为 zookeeper/localhost@{realm},可能不存在)

2.2.3、启动并测试

配置完成后就可以启动 Zookeeper 集群了:

bin/zkServer.sh start

启动完成后可以使用 zkCli.sh 来测试:

bin/zkCli.sh

2.2.4、java 程序连接 Zookeeper

java 可以使用 JAAS 来进行 Kerberos 认证,需要 JAAS 配置文件、keytab 文件及 Kerberos 配置文件。

A、配置文件

JAAS 配置文件(zk-client-jaas.conf):

Client {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   keyTab="D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client.keytab"
   storeKey=true
   useTicketCache=false
   principal="zk-client@ABC.COM";
};

keytab 文件:

从 Kerberos 服务器上拷贝到目标机器,拷贝路径即为 JAAS 配置中间配置的路径:D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client.keytab。

Kerberos 配置文件(krb5.conf):

从 Kerberos 服务器上拷贝 /etc/krb5.conf 到目标机器即可。

B、配置 hosts 文件

在 hosts 文件中添加:

10.49.196.10    pxc1
10.49.196.11    pxc2
10.49.196.12    pxc3

C、引入依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.3</version>
</dependency>

D、样例程序

package com.inspur.demo.general.zookeeper;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**
 * Zookeeper 客户端 Kerberos 认证
 */
public class ZookeeperKerberosCase {
    /**
     * 使用ip访问也可以:10.49.196.10:2181,10.49.196.11:2181,10.49.196.12:2181。
     * 但 hosts 文件还是要配置的,Zookeeper 客户端会查找 ip 对应的主机名作为 Zookeeper 服务的 principal 的 instance 部分,
     * 如果找不到对应的主机名就使用 ip 代替,这会导致找不到对应的 principal。
     */
    private static String connectString = "pxc1:2181,pxc2:2181,pxc3:2181";
    private static int sessionTimeout = 200 * 1000;

    private ZooKeeper zooKeeper;

    @Before
    public void before() {
        System.setProperty("java.security.auth.login.config", "D:\workspaceidea\demo\demo\src\main\resources\kerberos\zk-client-jaas.conf");
        System.setProperty("java.security.krb5.conf", "D:\workspaceidea\demo\demo\src\main\resources\kerberos\krb5.conf");//Zookeeper 服务的 principal 的 primary 部分
        System.setProperty("zookeeper.sasl.client.username", "zk-server");

        try {
            zooKeeper =  new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {

                }
            });
            System.out.println(zooKeeper.getState());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After
    public void after() throws Exception {
        zooKeeper.close();
    }

    @Test
    public void getData() throws Exception {
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/javatest/node1", false, stat);
        System.out.println(new String(data));
        System.out.println(stat);
    }
}

3、Server-Server 的 Kerberos 认证

在主节点选举阶段,集群中的所有服务器都将参与以达到规定的票数;默认情况下,此通信不经过身份验证。Zookeeper 也支持在集群的服务器之间启用 Kerberos 认证,这里就不介绍了,详细说明可参考官网文档:https://cwiki.apache.org/confluence/display/ZOOKEEPER/Server-Server+mutual+authentication。