2017-04-09 50 views
0

我有这样一段代码可以从一个Hadoop文件系统获取的文件。我在单个节点上设置hadoop,并从本地机器运行此代码,以查看它是否能够从该节点上的HDFS设置中获取文件。有效。如何访问以编程方式启用Kerberos的hadoop群集?

package com.hdfs.test.hdfs_util; 
/* Copy file from hdfs to local disk without hadoop installation 
* 
* params are something like 
* hdfs://node01.sindice.net:8020 /user/bob/file.zip file.zip 
* 
*/ 

import java.io.IOException; 

import org.apache.hadoop.conf.Configuration; 

import org.apache.hadoop.fs.FileSystem; 

import org.apache.hadoop.fs.Path; 

public class HDFSdownloader{ 

public static void main(String[] args) throws Exception { 

    System.getProperty("java.classpath"); 
    if (args.length != 3) { 

     System.out.println("use: HDFSdownloader hdfs src dst"); 

     System.exit(1); 

    } 

    System.out.println(HDFSdownloader.class.getName()); 
    HDFSdownloader dw = new HDFSdownloader(); 

    dw.copy2local(args[0], args[1], args[2]); 

} 

private void copy2local(String hdfs, String src, String dst) throws IOException { 

    System.out.println("!! Entering function !!"); 
    Configuration conf = new Configuration(); 
    conf.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName()); 
    conf.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName()); 


    conf.set("fs.default.name", hdfs); 

    FileSystem.get(conf).copyToLocalFile(new Path(src), new Path(dst)); 

    System.out.println("!! copytoLocalFile Reached!!"); 

} 

} 

现在我把相同的代码捆绑在一个jar中,并试图在另一个节点(比如说B)上运行它。这次代码必须从适当的分布式Hadoop集群中获取文件。该群集中启用了Kerberos。

的代码运行,但给了一个例外:

Exception in thread "main" org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS] 
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
at org.apache.hadoop.ipc.RemoteException.instantiateException(RemoteException.java:106) 
at org.apache.hadoop.ipc.RemoteException.unwrapRemoteException(RemoteException.java:73) 
at org.apache.hadoop.hdfs.DFSClient.getFileInfo(DFSClient.java:2115) 
at org.apache.hadoop.hdfs.DistributedFileSystem$22.doCall(DistributedFileSystem.java:1305) 
at org.apache.hadoop.hdfs.DistributedFileSystem$22.doCall(DistributedFileSystem.java:1301) 
at org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81) 
at org.apache.hadoop.hdfs.DistributedFileSystem.getFileStatus(DistributedFileSystem.java:1317) 
at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:337) 
at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:289) 
at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:2030) 
at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:1999) 
at org.apache.hadoop.fs.FileSystem.copyToLocalFile(FileSystem.java:1975) 
at com.hdfs.test.hdfs_util.HDFSdownloader.copy2local(HDFSdownloader.java:49) 
at com.hdfs.test.hdfs_util.HDFSdownloader.main(HDFSdownloader.java:35) 

有没有办法来编程使此代码运行。出于某种原因,我无法在源节点上安装kinit。

+0

是的,有一种方法。搜索'UserGroupInformation'类(或简称UGI)和'loginUserFromKeytab()'方法。 –

+0

感谢您的帮助。我继续使用它。我收到一个错误:javax.security.auth.login.LoginException:KDC不支持加密类型(14) - BAD_ENCRYPTION_TYPE。对此有何想法? – ak0817

+0

你为什么不谷歌那条消息?既然你不关心,何况你正在运行的平台,Java版本,Kerberos服务(如OpenLDAP的,微软的Active Directory,MIT Kerberos的)的类型,Kerberos客户端配置您正在使用(如:'/等/ KRB5 .conf'),那么你是自己的。相信我,这很复杂。 –

回答

2

这里的代码片段在你上面,即所描述编程访问启用了Kerberos的集群方案工作。要点需要注意的是

  • 在UserGroupInformation提供密钥表文件位置
  • 在JVM参数提供Kerberos领域的细节 - krb5.conf文件
  • 定义Hadoop的安全认证方式为Kerberos的

    import org.apache.hadoop.conf.Configuration; 
    import org.apache.hadoop.fs.FileStatus; 
    import org.apache.hadoop.fs.FileSystem; 
    import org.apache.hadoop.fs.Path; 
    import org.apache.hadoop.security.UserGroupInformation; 
    
    public class KerberosHDFSIO { 
    
    public static void main(String[] args) throws IOException { 
    
        Configuration conf = new Configuration(); 
        //The following property is enough for a non-kerberized setup 
        //  conf.set("fs.defaultFS", "localhost:9000"); 
    
        //need following set of properties to access a kerberized cluster 
        conf.set("fs.defaultFS", "hdfs://devha:8020"); 
        conf.set("hadoop.security.authentication", "kerberos"); 
    
        //The location of krb5.conf file needs to be provided in the VM arguments for the JVM 
        //-Djava.security.krb5.conf=/Users/user/Desktop/utils/cluster/dev/krb5.conf 
    
        UserGroupInformation.setConfiguration(conf); 
        UserGroupInformation.loginUserFromKeytab("[email protected]_DEV.ABC.COM", 
          "/Users/user/Desktop/utils/cluster/dev/.user.keytab"); 
    
        try (FileSystem fs = FileSystem.get(conf);) { 
         FileStatus[] fileStatuses = fs.listStatus(new Path("/user/username/dropoff")); 
         for (FileStatus fileStatus : fileStatuses) { 
          System.out.println(fileStatus.getPath().getName()); 
         } 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
    } 
    

    }

+0

感谢您的回答@saurabh。假设我需要每小时从Hadoop集群获取一个文件。然后我将安排上面的代码每小时运行一次。但是,我是否需要重复执行“kinit -kt principal keytab_path”命令(以编程方式或其他方式)才能使其工作? – ak0817

+0

@ ak0817这种方法不需要你运行kinit,因为你在程序本身提供了keytab文件。所以,每当试图获取文件时都会考虑自己的身份验证。至于需要运行kinit否则,如果您在linux系统上,请尝试使用crontab。 –

相关问题