我正在尝试将我的CloudFormation模板部署到其他区域进行测试。我的模板通过Boto3与us-east-1很好地配合使用,但如果它尝试其他区域,我不会得到错误输出。
在尝试不同的地区时,我意外地收到一封电子邮件,说加拿大地区已经过验证,但由于通过Boto3尝试,一直没有成功。(计费控制台显示所有地区现已激活(
我正在从Lambda(无专有网络(运行Boto3,它已使用Zappa部署到us-east-1。它的IAM策略没有指定特定的地区。
Python:
cf_client = boto3.client(
'cloudformation', region_name=request.POST['region'])
cf_client.create_stack(
StackName=stack_name,
TemplateURL='https://s3.amazonaws.com/#######/build_instance.yaml',
Parameters=[
{"ParameterKey": "FQDN",
"ParameterValue": instance_domain},
{"ParameterKey": "BucketName",
"ParameterValue": bucket_name},
{"ParameterKey": "CreateSubdomain",
"ParameterValue": create_subdomain},
{"ParameterKey": "CustomerEmail",
"ParameterValue": request.user.email},
{"ParameterKey": "Region",
"ParameterValue": request.POST['region']},
],
Capabilities=['CAPABILITY_NAMED_IAM'],
Tags=[
{
'Key': 'Name',
'Value': instance_domain
},
{
'Key': 'env',
'Value': "prod"
}, ],
EnableTerminationProtection=True
)
;
CF:
---
AWSTemplateFormatVersion: "2010-09-09"
Description: ""
Parameters:
FQDN:
Type: String
Description: Instance FQDN
BucketName:
Type: String
Description: Name of S3 bucket
CreateSubdomain:
Type: String
Default: false
AllowedValues: [true, false]
Description: Does the customer want to use our sub-domain?
CustomerEmail:
Type: String
Description: Customer email to deliver credentials
Region:
Type: String
Description: Customer region
Mappings:
RegionMap:
us-east-1:
AMI: "ami-0affd4508a5d2481b"
us-west-1:
AMI: "ami-03ba3948f6c37a4b0"
ca-central-1:
AMI: "ami-0d0eaed20348a3389"
eu-west-2:
AMI: " ami-006a0174c6c25ac06"
Conditions:
ShouldCreateSubDomain: !Equals [true, !Ref CreateSubdomain]
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
MetricsConfigurations:
- Id: EntireBucket
LifecycleConfiguration:
Rules:
- Id: IntelligentTieringTransition
Status: Enabled
Transitions:
- TransitionInDays: 30
StorageClass: INTELLIGENT_TIERING
PublicAccessBlockConfiguration:
BlockPublicAcls: true
IgnorePublicAcls: false
BlockPublicPolicy: true
RestrictPublicBuckets: true
User:
Type: AWS::IAM::User
Properties:
UserName:
Ref: FQDN
Groups: ["Customers"]
DependsOn: Bucket
Key:
Type: AWS::IAM::AccessKey
Properties:
UserName:
Ref: User
DependsOn: User
BucketPolicy:
Type: "AWS::S3::BucketPolicy"
Properties:
Bucket: !Ref BucketName
PolicyDocument:
Version: "2012-10-17"
Statement:
- Principal:
AWS: !GetAtt User.Arn
Action: "s3:*"
Effect: Allow
Resource:
- !GetAtt Bucket.Arn
- !Sub "${Bucket.Arn}/*"
DependsOn: Key
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
KeyName: aws-master
InstanceType: t3.micro
DisableApiTermination: true
SecurityGroups: ["nextcloud-security"]
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeSize: 10
DeleteOnTermination: false
Tags:
- Key: "Name"
Value: !Ref FQDN
- Key: "env"
Value: "prod"
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
curl -s ####### | /bin/bash
git clone #######
cd nextcloud
sed -i 's/# fqdn = nc.example.org/fqdn = ${FQDN}/g' inventory
sed -i "s/ssl_certificate_type = 'selfsigned'/#ssl_certificate_type = 'selfsigned'/g" inventory
sed -i "s/# ssl_certificate_type = 'letsencrypt'/ssl_certificate_type = 'letsencrypt'/g" inventory
sed -i 's/# cert_email = nc@example.org/cert_email = ####/g' inventory
sed -i "s/# nc_db_type = 'mysql'/nc_db_type = 'mysql'/g" inventory
sed -i "s/nc_db_type = 'pgsql'/#nc_db_type = 'pgsql'/g" inventory
sed -i 's/nc_configure_mail = false/nc_configure_mail = true/g' inventory
sed -i 's/nc_mail_from =/nc_mail_from = contact/g' inventory
sed -i 's/nc_mail_domain =/nc_mail_domain = ######/g' inventory
sed -i 's/nc_mail_smtpname =/nc_mail_smtpname = #######/g' inventory
sed -i 's/nc_mail_smtphost =/nc_mail_smtphost = smtp.gmail.com/g' inventory
sed -i 's/nc_mail_smtppwd =/nc_mail_smtppwd = #####/g' inventory
sed -i 's/s3_key =/s3_key = ${Key}/g' inventory
sed -i 's|s3_secret =|s3_secret = ${Key.SecretAccessKey}|g' inventory
sed -i 's/s3_bucket =/s3_bucket = ${BucketName}/g' inventory
sed -i 's/s3_region =/s3_region = ${Region}/g' inventory
sed -i 's/talk_install = false/talk_install = true/g' inventory
./nextcloud.yml
IPAddress:
Type: AWS::EC2::EIP
Properties:
Tags:
- Key: "Name"
Value: !Ref FQDN
- Key: "env"
Value: "prod"
IPAssoc:
Type: AWS::EC2::EIPAssociation
Properties:
InstanceId: !Ref "EC2Instance"
EIP: !Ref "IPAddress"
Route53Record:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: "########"
Name: !Join ["", [!Ref FQDN, "."]]
Type: A
TTL: "300"
ResourceRecords:
- !Ref "IPAddress"
Condition: ShouldCreateSubDomain
Outputs:
InstanceId:
Description: InstanceId of the newly created EC2 instance
Value: !Ref "EC2Instance"
InstanceIPAddress:
Description: IP address of the newly created EC2 instance
Value: !Ref "IPAddress"
IAM:
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeAddresses",
"ec2:DescribeTags",
"ec2:CreateTags",
"ec2:RunInstances",
"ec2:DescribeKeyPairs",
"ec2:AssociateAddress",
"ec2:AllocateAddress"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"iam:AddUserToGroup",
"cloudformation:CreateStack",
"route53:ChangeResourceRecordSets",
"iam:GetUser",
"iam:CreateUser",
"iam:CreateAccessKey"
],
"Resource": [
"arn:aws:iam::*:user/*",
"arn:aws:iam::#######:group/Customers",
"arn:aws:cloudformation:*:*:stack/*/*",
"arn:aws:route53:::hostedzone/#####"
]
}
]
}
从选择堆栈模板-AWS CloudFormation:
Amazon S3 URL:URL必须指向一个最大大小为460800字节的模板,该模板存储在您有读取权限的S3存储桶中,并且与堆栈位于同一区域。
我怀疑您的堆栈失败了,因为模板位于AmazonS3存储桶中,而该存储桶与启动堆栈的区域不同。您需要将模板复制到同一区域的bucket中,然后在create_stack()
命令中提供它。
您可以使用AWS控制台启动模板来测试这一点,而不必通过boto3。