Весенняя загрузка Hadoop, Webhdfs и Apache Knox
У меня есть загрузочное приложение Spring, которое обращается к HDFS через Webhdfs, защищенное через Apache Knox, защищенное Kerberos. Я создал свой собственный KnoxWebHdfsFileSystem
с пользовательской схемой (swebhdfsknox) в качестве подкласса WebHdfsFilesystem
который изменяет только URL-адреса, содержащие префикс Knox-прокси. Таким образом, он эффективно перераспределяет запросы из формы:
http://host:port/webhdfs/v1/...
Ноксу:
http://host:port/gateway/default/webhdfs/v1/...
Я делаю это, переопределяя два метода:
public URI getUri()
URL toUrl(Op op, Path fspath, Param<?, ?>... parameters)
Все идет нормально. Я позволил весеннему ботинку создать FsShell
для меня и использовать его для различных операций, таких как список файлов, MKDIR и т. д. Все работает нормально. За исключением copyFromLocal, который согласно документу требует 2 шага и перенаправления. И на последнем шаге, когда файловая система пытается PUT
на последний URL-адрес, полученный в заголовке Location, происходит ошибка:
org.apache.hadoop.security.AccessControlException: Authentication required
at org.apache.hadoop.hdfs.web.WebHdfsFileSystem.validateResponse(WebHdfsFileSystem.java:334) ~[hadoop-hdfs-2.6.0.jar:na]
at org.apache.hadoop.hdfs.web.WebHdfsFileSystem.access$200(WebHdfsFileSystem.java:91) ~[hadoop-hdfs-2.6.0.jar:na]
at org.apache.hadoop.hdfs.web.WebHdfsFileSystem$FsPathOutputStreamRunner$1.close(WebHdfsFileSystem.java:787) ~[hadoop-hdfs-2.6.0.jar:na]
at org.apache.hadoop.io.IOUtils.copyBytes(IOUtils.java:54) ~[hadoop-common-2.6.0.jar:na]
at org.apache.hadoop.io.IOUtils.copyBytes(IOUtils.java:112) ~[hadoop-common-2.6.0.jar:na]
at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:366) ~[hadoop-common-2.6.0.jar:na]
at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:338) ~[hadoop-common-2.6.0.jar:na]
at org.apache.hadoop.fs.FileUtil.copy(FileUtil.java:302) ~[hadoop-common-2.6.0.jar:na]
at org.apache.hadoop.fs.FileSystem.copyFromLocalFile(FileSystem.java:1889) ~[hadoop-common-2.6.0.jar:na]
at org.springframework.data.hadoop.fs.FsShell.copyFromLocal(FsShell.java:265) ~[spring-data-hadoop-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
at org.springframework.data.hadoop.fs.FsShell.copyFromLocal(FsShell.java:254) ~[spring-data-hadoop-core-2.2.0.RELEASE.jar:2.2.0.RELEASE]
Я подозреваю, что проблема заключается в переадресации, но не могу понять, в чем здесь проблема. Если я делаю те же запросы через curl, файл успешно загружается в HDFS.
1 ответ
Это известная проблема, связанная с использованием существующих клиентов Hadoop против Apache Knox с использованием поставщика HadoopAuth для kerberos в Knox. Если бы вы использовали curl или какой-либо другой REST-клиент, он, вероятно, сработал бы для вас. Существующий Java-клиент Hadoop не ожидает вызова SPNEGO от узла DataNode, о котором говорит PUT на этапе отправки. DataNode ожидает присутствия маркера доступа блока / токена делегирования, выданного NameNode на первом этапе. Однако шлюзу Knox потребуется проверка подлинности SPNEGO для каждого запроса к этой топологии.
Это проблема, которая должна быть рассмотрена в дорожной карте, и, вероятно, она станет более горячей, так как интерес будет больше перемещаться внутри кластера, а не только через ресурсы извне.
Следующая JIRA отслеживает этот элемент и, как вы можете видеть из заголовка, относится к DistCp, который является аналогичным вариантом использования: https://issues.apache.org/jira/browse/KNOX-482
Не стесняйтесь взглянуть и помочь с тестированием или разработкой - все это будет приветствоваться!
Другой возможностью было бы изменить Java-клиент Hadoop для решения задачи SPNEGO и для DataNode.