boto3 client NoRegionError:只能在某些时候指定区域错误

我有一个boto3客户端:

boto3.client('kms')

但这发生在新机器上,它们动态地打开和关闭。

    if endpoint is None:
if region_name is None:
# Raise a more specific error message that will give
# better guidance to the user what needs to happen.
raise NoRegionError()

为什么会这样?为什么只是部分时间?

347397 次浏览

不管怎样,你必须告诉boto3你希望在哪个区域创建kms客户端。这可以显式地使用region_name参数来完成,如下所示:

kms = boto3.client('kms', region_name='us-west-2')

或者你可以在~/.aws/config文件中有一个与你的配置文件相关联的默认区域,如下所示:

[default]
region=us-west-2

或者你可以使用环境变量,如下所示:

export AWS_DEFAULT_REGION=us-west-2

但是您需要告诉boto3使用哪个区域。

我相信,默认情况下,boto选择在aws cli中设置的区域。您可以运行命令#aws configure并按enter(它会显示您在aws cli with region中设置的信用)两次来确认您的区域。

您还可以在脚本本身中设置环境变量,而不是传递region_name参数

os.environ['AWS_DEFAULT_REGION'] = 'your_region_name'

大小写敏感性可能很重要。

os.environ['AWS_DEFAULT_REGION'] = 'your_region_name'

对我来说,敏感很重要。

对于Python 2,我发现boto3库不从~/.aws/config中获取区域,如果该区域定义在与默认配置文件不同的配置文件中。 所以你必须在会话创建中定义它
session = boto3.Session(
profile_name='NotDefault',
region_name='ap-southeast-2'
)


print(session.available_profiles)


client = session.client(
'ec2'
)

我的~/.aws/config文件是这样的:

[default]
region=ap-southeast-2


[NotDefault]
region=ap-southeast-2

我这样做是因为我使用不同的配置文件登录AWS,个人和工作。

对于那些使用CloudFormation模板。可以使用UserData和AWS::Region设置环境变量AWS_DEFAULT_REGION。例如,

MyInstance1:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-04b9e92b5572fa0d1 #ubuntu
InstanceType: t2.micro
UserData:
Fn::Base64: !Sub |
#!/bin/bash -x


echo "export AWS_DEFAULT_REGION=${AWS::Region}" >> /etc/profile

您也可以运行以下命令(aws cli)

aws configure --profile $PROFILE_NAME

它会提示您输入区域。

注意在~/.aws/config中它是:

[default]
region = ap-southeast-1
output = json


[profile prod]
region = ap-southeast-1
output = json

[配置文件配置文件名称]在方括号中

如果您正在使用lambda,那么您可能希望使用部署lambda的区域。 您可以使用下面的

import boto3
import json
import os


def lambda_handler(event, context):
region = os.environ['AWS_REGION']
print('Lambda region: ', region)
kms = boto3.client('kms', region_name=region)

我们将配置好的区域存储在~/中。aws /配置文件。下面是一个纯python的方法,根据配置文件名称从这个文件中读取正确的区域:

def get_aws_region(profile_name: str) -> str:
config = configparser.ConfigParser()
config.read(f"{os.environ['HOME']}/.aws/config")
profile_section = config[f"profile {profile_name}"]
return profile_section["region"]

regions = [
'eu-north-1', 'ap-south-1', 'eu-west-3', 'eu-west-2',
'eu-west-1', 'ap-northeast-3', 'ap-northeast-2'
'ap-northeast-1', 'sa-east-1', 'ca-central-1',
'ap-southeast-2', 'eu-central-1', 'us-east-1', 'us-east-2',
'us-west-1', 'us-west-2']
for r in regions:
kms = boto3.client('kms', region_name= r)

如果您使用AWS Lambda,您的代码将在部署时工作, 因为Lambda被部署在特定的区域

如果你愿意,你可以总是将它设置为EC2所在的相同区域。这是用bash,但你可以很容易地在python中重现:

EC2_AVAIL_ZONE=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
EC2_REGION="`echo $EC2_AVAIL_ZONE | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"
# if unset, set it:
export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-$EC2_REGION}"

python:

import os
import re
from subprocess import check_output


EC2_AVAIL_ZONE = check_output(["curl", "-s", "http://169.254.169.254/latest/meta-data/placement/availability-zone"]).decode().strip()
EC2_REGION = re.sub(r"^(\w{2}-\w{3,10}-[0-9][0-9]*)[a-z]*$", r"\1", EC2_AVAIL_ZONE)
# if unset, set it:
os.environ["AWS_DEFAULT_REGION"] = os.getenv("AWS_DEFAULT_REGION", EC2_REGION)