Hadoop 使用Kerberos在映射器内连接到Accumulo

Hadoop 使用Kerberos在映射器内连接到Accumulo,hadoop,kerberos,accumulo,Hadoop,Kerberos,Accumulo,我正在将一些软件从一个旧的Hadoop集群(使用用户名/密码身份验证)移动到一个新的集群,2.6.0-cdh5.12.0,该集群启用了Kerberos身份验证 我已经能够使用AccumuloInput/OutputFormat类中设置的DelegationToken使许多使用Accumulo进行输入和/或输出的现有Map/Reduce作业正常工作 但是,我有一个作业,它使用AccumuloInput/OutputFormat进行输入和输出,但在其Mapper.setup()方法中,它通过Zook

我正在将一些软件从一个旧的Hadoop集群(使用用户名/密码身份验证)移动到一个新的集群,2.6.0-cdh5.12.0,该集群启用了Kerberos身份验证

我已经能够使用AccumuloInput/OutputFormat类中设置的DelegationToken使许多使用Accumulo进行输入和/或输出的现有Map/Reduce作业正常工作

但是,我有一个作业,它使用AccumuloInput/OutputFormat进行输入和输出,但在其Mapper.setup()方法中,它通过Zookeeper连接到Accumulo,以便在Mapper.map()方法中,它可以将正在处理的每个键/值与Mapper.map()和另一个Accumulo表中的条目进行比较。

我在下面包含了相关代码,其中显示了setup()方法连接Zookeeper用户一个PasswordToken,然后创建一个Accumulo表格扫描仪,然后在mapper方法中使用该扫描仪

因此,问题是如何在Mapper.setup()方法中用KerberosToken代替PasswordToken来设置Accumulo扫描仪?我无法找到“获取”我设置的AccumuloInput/OutputFormat类使用的DelegationToken的方法

我尝试了context.getCredentials().getAllTokens()并查找类型为org.apache.accumulo.code.client.security.tokens.AuthenticationToken的令牌——这里返回的所有令牌的类型都是org.apache.hadoop.security.token.token

请注意,当代码在未连接到internet的网络上运行时,我在中键入了代码片段,而不是剪切/粘贴-也就是说,可能有输入错误。:)

//****************************
//M/R驱动程序中的代码
//****************************
ClientConfiguration accumuloCfg=ClientConfiguration.loadDefault().withInstance(“Accumulo1”).withZkHosts(“zookeeper1”);
ZooKeeperInstance inst=新的ZooKeeperInstance(accumuloCfg);
AuthenticationToken dt=conn.securityOperations().getDelegationToken(新DelagationTokenConfig());
setConnectorInfo(作业、用户名、dt);
setConnectorInfo(作业、用户名、dt);
//其他作业设置,然后
作业。等待完成(true)
//****************************
//这在M/R作业的Mapper类中
//****************************
专用扫描器;索引扫描器;
公共无效设置(上下文){
Configuration cfg=context.getConfiguration();
//从M/R驱动程序设置和传递的属性
字符串username=cfg.get(“用户名”);
字符串密码=cfg.get(“密码”);
字符串accumuloInstName=cfg.get(“InstanceName”);
字符串zooweers=cfg.get(“zooweers”);
字符串tableName=cfg.get(“tableName”);
实例inst=新的ZooKeeperInstance(accumuloInstName,zookeepers);
试一试{
AuthenticationToken passwordToken=新的passwordToken(密码);
连接器conn=inst.getConnector(用户名、密码令牌);
index_scanner=conn.createScanner(表名,conn.securityOperations().getUserAuthorizations(用户名));
}捕获(例外e){
e、 printStackTrace();
}
}
公共void映射(键、值、上下文上下文)引发IOException、InterruptedException{
字符串uuid=key.getRow().toString();
索引_scanner.clearColumns();
索引_scanner.setRange(范围精确(uuid));
用于(条目:索引\扫描仪){
//在这里做一些处理
}
}
提供了一种方法,可以使用
Accumulo*putFormat.setConnectorInfo(作业、原理、令牌)
在作业配置中设置令牌。您还可以使用和使用接受文件名的
setConnectorInfo
方法的版本在HDFS中序列化文件中的令牌

如果传入KerberosToken,作业将创建一个要使用的DelegationToken,如果传入一个DelegationToken,它将只使用它

提供的
AccumuloInputFormat
应处理其自己的扫描仪,因此,通常情况下,如果已正确设置配置,则不必在映射器中执行此操作。但是,如果您在Mapper中进行二次扫描(例如连接),您可以查看提供的
AccumuloInputFormat
的RecordReader源代码,以获取如何检索配置和构造扫描仪的示例。

还可以查看其中包含的信息与Christopher所述的相同。
//****************************
// code in the M/R driver
//****************************
ClientConfiguration accumuloCfg = ClientConfiguration.loadDefault().withInstance("Accumulo1").withZkHosts("zookeeper1");
ZooKeeperInstance inst = new ZooKeeperInstance(accumuloCfg);
AuthenticationToken dt = conn.securityOperations().getDelegationToken(new DelagationTokenConfig());
AccumuloInputFormat.setConnectorInfo(job, username, dt);
AccumuloOutputFormat.setConnectorInfo(job, username, dt);
// other job setup and then
job.waitForCompletion(true)



//****************************
// this is inside the Mapper class of the M/R job
//****************************
private Scanner index_scanner;

public void setup(Context context) {
    Configuration cfg = context.getConfiguration();

    // properties set and passed from M/R Driver program
    String username = cfg.get("UserName");
    String password = cfg.get("Password");
    String accumuloInstName = cfg.get("InstanceName");
    String zookeepers = cfg.get("Zookeepers");
    String tableName = cfg.get("TableName");
    Instance inst = new ZooKeeperInstance(accumuloInstName, zookeepers);
    try {
      AuthenticationToken passwordToken = new PasswordToken(password);

      Connector conn = inst.getConnector(username, passwordToken);

      index_scanner = conn.createScanner(tableName, conn.securityOperations().getUserAuthorizations(username));
    } catch(Exception e) {
       e.printStackTrace();
    }
}

public void map(Key key, Value value, Context context) throws IOException, InterruptedException {
    String uuid = key.getRow().toString();
    index_scanner.clearColumns();
    index_scanner.setRange(Range.exact(uuid));
    for(Entry<Key, Value> entry : index_scanner) {
        // do some processing in here
    }
}