问题描述
我正在尝试为 S3 上的基本 get/put/delete/list 操作编写一个 python 脚本。我使用的是 cloudian S3 对象存储而不是 AWS。要设置 boto3 资源,我像这样设置端点和键 -
URL = 'http://ip:80'
s3_resource = boto3.resource ('s3',endpoint_url=URL,aws_access_key_id = ACCESS_KEY,aws_secret_access_key = SECRET_KEY,region_name='region1')
我手动创建了一些具有以下名称的测试存储桶,这些名称通过了有效的 S3 存储桶名称约束:
- test-bucket-0
- test-bucket-1
- 样品桶
- 测试桶
但是,当我尝试从 python 代码创建存储桶时,我反复收到以下错误 -
# >>> client.list_buckets()
# Traceback (most recent call last):
# File "<stdin>",line 1,in <module>
# File "/usr/local/lib/python3.8/site-packages/botocore/client.py",line 357,in _api_call
# return self._make_api_call(operation_name,kwargs)
# File "/usr/local/lib/python3.8/site-packages/botocore/client.py",line 676,in _make_api_call
# raise error_class(parsed_response,operation_name)
# botocore.exceptions.ClientError: An error occurred (InvalidBucketName) when calling the ListBuckets operation: The specified bucket is not valid.
作为 boto3 的新手,我真的不确定 boto3 会期待什么。我尝试了各种组合来创建与 S3 服务的连接,例如使用 client
而不是 resource
,但问题是一致的。
我尝试过的其他一些 S3 连接如下:
s3 = boto3.resource('s3',endpoint_url='http://10.43.235.193:80',aws_access_key_id = 'aaa',aws_secret_access_key = 'sss',config=Config(signature_version='s3v4'),region_name='region1')
conn = boto3.connect_s3(
aws_access_key_id = 'aaa',host = '10.43.235.193',port = 80,is_secure = False,)
from boto3.session import Session
session = Session(
aws_access_key_id='aaa',aws_secret_access_key='sss',region_name='region1'
)
s3 = session.resource('s3')
client = session.client('s3',endpoint_url='http://10.43.235.193:80') # s3-region1.example.com
s3_client = boto3.client ('s3',endpoint_url=s3_endpoint,region_name='region1')
python 脚本在容器内运行,并且与运行 s3 容器的 pod 相同。因此,IP 可以从一个容器访问到另一个容器。我该如何解决这个问题?
解决方法
我的发现很奇怪。尽管 InvalidBucketName
出现错误是非常具有误导性的,我在 boto3 github 上发现了很多关于此的线程。但事实证明,大多数用户使用的是 AWS,而不是本地私有云 S3,因此并没有太大帮助。
对我来说,拥有 IP 前。创建 s3_client 时,10.50.32.5 作为配置中的 S3 端点不起作用。因此有这样的端点设置 -
s3_client = boto3.client ('s3',endpoint_url='http://10.50.32.5:80',aws_access_key_id = 'AAA',aws_secret_access_key = 'SSS',region_name='region1')
失败了。
我是如何解决这个问题的?
我在 /etc/hosts 中添加了一个 DNS 条目;即像这样的 IP 和 S3 端点 URL 的映射 -
10.50.32.5 s3-region1.example.com
然后像这样使用 boto 创建了一个 S3 客户端 -
s3_client = boto3.client ('s3',endpoint_url=s3_endpoint,aws_secret_access_key = 'BBB',region_name='region1')
它奏效了。