这几天忙着测试批量文件上传通过hdfsclient上传hdfs上,刚到第一步就卡住了,遇到了所有程序员几乎都不可避免遇到的问题
那就是认证问题,这里我的集群的hdfs连接要认证kerberos,kerberos我就不加介绍了,可以去别的博客上看。
当时我是按照跟别的博客一样的写法:
上传本地文件到hdfs上:
结果报了:Exception in thread "main" org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]
看到这个错误之后我就意识到遇到kerberos认证,这个认证还是很麻烦的。
然后我就想到调用认证的SDK,认证需要你提供你集群的accessKeyID和accessKeySC,还有你的ldapurl地址以及freeipa的地址,我就重写了代码
之后以为肯定成功了,结果还是报错,程序员就是不停地与错误打交道,
错误是:java.io.IOException: Failed on local exception: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name;
查看错误可知是hdfs的namenode的principal没有找到,于是我就去hdfs-site.xml里面去找
找到这个配置之后,设置:
后面还要解决很多问题,加油!!!
那就是认证问题,这里我的集群的hdfs连接要认证kerberos,kerberos我就不加介绍了,可以去别的博客上看。
当时我是按照跟别的博客一样的写法:
上传本地文件到hdfs上:
Configuration config=new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.182.121:8020"), config, "root");
Path dst = new Path("/");
Path src = new Path("/user/4.mp3");
fs.copyFromLocalFile(src, dst);
System.out.println("Upload to" + config.get("fs.default.name"));
fs.close();
结果报了:Exception in thread "main" org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]
看到这个错误之后我就意识到遇到kerberos认证,这个认证还是很麻烦的。
然后我就想到调用认证的SDK,认证需要你提供你集群的accessKeyID和accessKeySC,还有你的ldapurl地址以及freeipa的地址,我就重写了代码
private static String akid = "spark";
private static String aksc = "DtDream0209";
static Configuration conf = new Configuration();
private static String ldapUrl = "ldap://你的ladpurl地址:389";
private static String ipaUrl = "https://你的freeipa地址:18443";
private static String keytabDir = "/root/keytab";//你集群的keytab存放路径
private static String ipaRealm = "@DTDREAM.COM";
private static String ldapBasedn = "cn=users,cn=accounts,dc=dtdream,dc=com";
public HDFSClient() {
}
public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException, DataSentryException{
conf.set("fs.default.name", "hdfs://你的hdfs地址:8020");
conf.set("fs.hdfs.impl", DistributedFileSystem.class.getName());
conf.set("fs.file.impl", LocalFileSystem.class.getName());
DataSentryClient dataSentryClient = new DataSentryClient(ldapUrl, keytabDir, ipaRealm, ipaUrl, ldapBasedn);
System.out.println(dataSentryClient.isVaildAK(akid, aksc));
UserGroupInformation userGroupInformation = dataSentryClient.getUGIFromAK(conf, akid, aksc);
System.out.println("produce fs object");
FileSystem fs1 = (FileSystem)userGroupInformation.doAs(new PrivilegedExceptionAction() {
public FileSystem run() throws IOException {
return FileSystem.get(FileSystem.getDefaultUri(HDFSClient.conf), HDFSClient.conf);
}
});
System.out.println("print home directory");
System.out.println(fs1.getHomeDirectory());
//fs1.create(new Path("/llll"));
Path dst = new Path(args[0]);
Path src=new Path(args[1]);
fs1.copyFromLocalFile(src, dst);
System.out.println("success");
fs1.close();
}
}
之后以为肯定成功了,结果还是报错,程序员就是不停地与错误打交道,
错误是:java.io.IOException: Failed on local exception: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name;
查看错误可知是hdfs的namenode的principal没有找到,于是我就去hdfs-site.xml里面去找
<property>
<name>dfs.namenode.kerberos.principal</name>
<value>nn/_HOST@DTDREAM.COM</value>
</property>
找到这个配置之后,设置:
conf.set("dfs.namenode.kerberos.principal", "nn/_HOST@DTDREAM.COM");
之后总算找到了,但是还是报错:
org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category WRITE is not supported in state standby
看到这个错误我就放心了,是我hdfs地址中的namenode是standby的,我把hdfs的地址换成active namenode运行的那台机器的地址,之后就成功了。后面还要解决很多问题,加油!!!