情景
我创建一个名为“my role”的aws iam角色,将ec2指定为受信任实体,即使用信任关系策略文档:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
角色具有以下策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetBucketAcl",
"s3:GetBucketCORS",
"s3:GetBucketLocation",
"s3:GetBucketLogging",
"s3:GetBucketNotification",
"s3:GetBucketPolicy",
"s3:GetBucketRequestPayment",
"s3:GetBucketTagging",
"s3:GetBucketVersioning",
"s3:GetBucketWebsite",
"s3:GetLifecycleConfiguration",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectTorrent",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTorrent",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:ListBucketVersions",
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl",
"s3:RestoreObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
}
]
}
我使用awscli从命令行启动了一个ec2示例(amazonlinux2014.09.1),将“我的角色”指定为示例概要文件,一切正常。我通过运行以下命令来验证示例是否有效地承担了“我的角色”: curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
查询示例元数据,从中得到响应 my-role
; curl http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role
我从中获得与“我的角色”关联的临时凭据。
此类凭证检索响应的示例如下:
{
"Code" : "Success",
"LastUpdated" : "2015-01-19T10:37:35Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "an-access-key-id",
"SecretAccessKey" : "a-secret-access-key",
"Token" : "a-token",
"Expiration" : "2015-01-19T16:47:09Z"
}
``` `aws s3 ls s3://my-bucket/` 从中我正确地得到了一个包含“我的桶”下的第一个子目录的列表(启动此ami时,默认情况下会安装和配置aws cli。ec2示例和s3 bucket在同一个aws帐户中)
我在这个示例上运行/安装了一个tomcat7服务器和容器,在这个示例上部署了一个j2ee1.7servlet,没有任何问题。
这样的servlet应该在本地文件系统上从s3 bucket下载一个文件,特别是从 `s3://my-bucket/custom-path/file.tar.gz` 使用hadoop java API(请注意,我尝试了hadoop公共工件2.4.x、2.5.x、2.6.x,但没有任何积极的结果。我将在下面发布使用2.5.x时遇到的异常)
在servlet中,我从上面提到的示例元数据url中检索新的凭据,并使用它们配置我的hadoop java api示例:
...
Path path = new Path("s3n://my-bucket/");
Configuration conf = new Configuration();
conf.set("fs.defaultFS", path.toString());
conf.set("fs.s3n.awsAccessKeyId", myAwsAccessKeyId);
conf.set("fs.s3n.awsSecretAccessKey", myAwsSecretAccessKey);
conf.set("fs.s3n.awsSessionToken", mySessionToken);
...
显然, `myAwsAccessKeyId` , `myAwsSecretAccessKey` ,和 `mySessionToken` 是我之前用实际值设置的java变量。然后,我有效地获得一个文件系统示例,使用:
FileSystem fs = path.getFileSystem(conf);
我能够检索与文件系统(fs.getconf().get(key name))相关的所有配置,并验证所有配置都是按照假设的那样配置的。
### 问题
我不能下载 `s3://my-bucket/custom-path/file.tar.gz` 使用:
...
fs.copyToLocalFile(false, new Path(path.toString()+"custom-path/file.tar.gz"), outputLocalPath);
...
如果我使用hadoopcommon2.5.x,我会得到 `IOException` :
org.apache.hadoop.security.accesscontrolexception:权限被拒绝:s3n://my bucket/custom path/file.tar.gz位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.processexception(jets3tnativefilesystemstore)。java:449)位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.processexception(jets3tnativefilesystemstore)。java:427)在org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.handleexception(jets3tnativefilesystemstore)。java:411)位于org.apache.hadoop.fs.s3native.jets3tnativefilesystemstore.retrievemetadata(jets3tnativefilesystemstore)。java:181)位于sun.reflect.nativemethodaccessorimpl.invoke0(本机方法)sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl。java:57)在sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl。java:43)在java.lang.reflect.method.invoke(方法。java:606)在org.apache.hadoop.io.retry.retryinvocationhandler.invokemethod(retryinvocationhandler。java:187)在org.apache.hadoop.io.retry.retryinvocationhandler.invoke(retryinvocationhandler。java:102)org.apache.hadoop.fs.s3native.$proxy12.retrievemetadata(未知源),org.apache.hadoop.fs.s3native.natives3filesystem.getfilestatus(natives3filesystem)。java:467)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:337)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:289)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1968)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1937) ...
如果我使用hadoopcommon2.4.x,我会得到一个 `NullPointerException` :
org.apache.hadoop.fs.s3native.natives3filesystem.getfilestatus(natives3filesystem)上的java.lang.nullpointerexception。java:433)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:337)在org.apache.hadoop.fs.fileutil.copy(fileutil。java:289)在org.apache.hadoop.fs.filesystem.copytolocalfile(filesystem。java:1968)在org.apache.hadoop.fs.filesystem.copytolocalfile(文件系统)。java:1937) ...
只是为了记录,如果不设置任何aws凭据,我会得到:
aws access key id和secret access key必须分别指定为s3n url的用户名或密码,或者通过设置fs.s3n.awsaccesskeyid或fs.s3n.awssecretaccesskey属性来指定。
### 期末笔记
如果我尝试从示例中使用awscli命令从完全相同的uri(但用s3代替s3n)下载该文件,则完全没有问题。
如果我尝试下载hadoop发行版(如2.4.1)https://archive.apache.org/dist/hadoop/core/hadoop-2.4.1/),解压缩它,从示例元数据url检索临时aws凭据并尝试运行 `<hadoop-dir>/bin/hadoop fs -cp s3n://<aws-access-key-id>:<aws-secret-access-key>@my-bucket/custom-path/file.tar.gz .` 我又一次得到了npe:
位于org.apache.hadoop.fs.s3native.natives3filesystem.liststatus(natives3filesystem)的致命内部错误java.lang.nullpointerexception。java:479)在org.apache.hadoop.fs.shell.pathdata.getdirectorycontents(路径数据。java:268)在org.apache.hadoop.fs.shell.command.recursepath(command。java:347)在org.apache.hadoop.fs.shell.ls.processpathargument(ls。java:96)在org.apache.hadoop.fs.shell.command.processargument(command。java:260)在org.apache.hadoop.fs.shell.command.processarguments(command。java:244)在org.apache.hadoop.fs.shell.command.processrawarguments(command。java:190)在org.apache.hadoop.fs.shell.command.run(command。java:154)在org.apache.hadoop.fs.fsshell.run(fsshell。java:255)在org.apache.hadoop.util.toolrunner.run(toolrunner。java:70)在org.apache.hadoop.util.toolrunner.run(toolrunner。java:84)在org.apache.hadoop.fs.fsshell.main(fsshell。java:308)
抱歉发了这么长的帖子,我只是尽量详细。谢谢你的帮助。
1条答案
按热度按时间2w3rbyxf1#
您正在使用sts/临时aws凭据;这些似乎目前不受
s3
或者s3n
FileSystem
hadoop中的实现。awssts/临时凭证不仅包括一个(访问密钥、密钥),还包括一个会话令牌。hadoop
s3
以及s3n
FileSystem
(s) 还不支持包含会话令牌(即您的fs.s3n.awsSessionToken
不受支持且被s3n
FileSystem
.从amazons3-hadoop wiki。。。
(注:未提及
fs.s3.awsSessionToken
):配置为使用s3/s3n文件系统
编辑您的
core-site.xml
包含s3密钥的文件如果您在github.com上查看apache/hadoop中的s3credentials.java,就会注意到s3凭证的表示中完全没有会话令牌的概念。
提交了一个补丁来解决这个限制(这里详细说明);然而,它还没有被整合。
如果您使用的是aws iam示例角色,则可能需要探索使用新的
s3a
FileSystem
这是hadoop2.6.0中添加的。它声称支持基于iam角色的身份验证(即,根本不必显式指定密钥)。hadoop jira票证描述了如何配置
s3a
FileSystem
:从https://issues.apache.org/jira/browse/hadoop-10400 :
fs.s3a.access.key
-您的aws访问密钥id(角色身份验证时省略)fs.s3a.secret.key
-您的aws密钥(角色身份验证时省略)