EC2用户数据无法通过python boto命令工作

时间:2017-05-25 22:08:52

标签: python amazon-ec2 user-data

我正在尝试启动一个实例,在第一次作为userdata的一部分启动时运行脚本。使用了以下代码(python boto3库):

import boto3
ec2 = boto3.resource('ec2')
instance = ec2.create_instances(DryRun=False, ImageId='ami-abcd1234', MinCount=1, MaxCount=1, KeyName='tde', Placement={'AvailabilityZone': 'us-west-2a'}, SecurityGroupIds=['sg-abcd1234'], UserData=user_data, InstanceType='c3.xlarge', SubnetId='subnet-abcd1234')

我一直在使用user_data并且没有成功。我一直在尝试将一些字符串回显到现有目录中的新文件。以下是我尝试的最新版本。

user_data = '''
    #!/bin/bash
    echo 'test' > /home/ec2/test.txt
    '''

ami是基于CentOS的私人AMI。我已经在服务器上本地测试了命令并让它们工作。但是当我在userdata上放置相同的命令(略微调整以匹配userdata格式)时,它不起作用。实例成功启动但我指定的文件不存在。

我查看了其他示例(https://github.com/coresoftwaregroup/boto-examples/blob/master/32-create-instance-enhanced-with-user-data.py),甚至复制了他们的命令。

非常感谢您的帮助!谢谢:))

3 个答案:

答案 0 :(得分:5)

要将用户数据识别为脚本,第一个字符必须是#!(至少对于Linux实例)。

但是,您的user_data变量定义为:

"\n    #!/bin/bash\n    echo 'test' > /home/ec2/test.txt\n    "

您应该像这样定义:

user_data = '''#!/bin/bash
echo 'test' > /tmp/hello'''

产生:

"#!/bin/bash\necho 'test' > /tmp/hello"

这是正常的。

所以,这是最终产品:

import boto3

ec2 = boto3.resource('ec2')

user_data = '''#!/bin/bash
echo 'test' > /tmp/hello'''

instance = ec2.create_instances(ImageId='ami-abcd1234', MinCount=1, MaxCount=1, KeyName='my-key', SecurityGroupIds=['sg-abcd1234'], UserData=user_data, InstanceType='t2.nano', SubnetId='subnet-abcd1234')

登录后:

[ec2-user@ip-172-31-2-151 ~]$ ls /tmp
hello  hsperfdata_root

答案 1 :(得分:0)

也许您的脚本不起作用,因为您键入了错误的用户路径。

正确的用户路径是SELECT * FROM ( SELECT n.name AS actress_name , AVG(r.avg_rating) AS actress_avg_rating, SUM(r.total_votes) AS total_votes, COUNT(r.movie_id) AS movie_count, RANK() OVER ( PARTITION BY n.name ORDER BY COUNT(r.movie_id) DESC) AS actress_rank FROM names AS n JOIN role_mapping AS rm ON n.id = rm.name_id JOIN movie AS m ON rm.name_id = m.id JOIN ratings AS r ON m.id = r.movie_id JOIN genre AS g ON g.movie_id = r.movie_id WHERE r.avg_rating > 8 AND g.genre = 'Drama' AND rm.category ='actress' GROUP BY actress_name ) q WHERE actress_rank <= 3 ,而不是脚本中假定的/home/ec2-user

尝试作为用户数据:

/home/ec2

答案 2 :(得分:0)

我相信您需要指定一个实例配置文件。请查看此页面:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-api-cli

进行此操作的步骤包括:

  • 创建一个角色
  • 将适当的策略文档附加到该角色(注意:在示例中使用的 AmazonEC2FullAccess 策略可能不是,我只是找不到更好的替代方案)
  • 创建一个实例配置文件
  • 将角色附加到实例配置文件
  • 使用实例配置文件创建实例

另外,如其他答案所述,请以

#!/bin/bash

开始您的用户数据。这是我正在使用的“简化”代码片段,跳过了其他初始化步骤,如选择机器镜像和设置安全组等。

iam_client = boto3.client('iam')

# 创建假定角色策略文档
assume_role_policy_document = json.dumps({
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
})

# 创建 ec2 全面访问角色
role_response = iam_client.create_role(
    RoleName='ec2_full_access_role',
    AssumeRolePolicyDocument=assume_role_policy_document,
    Description='AmazonEC2FullAccess',
    MaxSessionDuration=3600,
)

# 获取策略 arm
policy_arn = policies_df[policies_df.PolicyName=='AmazonEC2FullAccess'].Arn.iloc[0]

# 附加策略
role_attach_response = iam_client.attach_role_policy(
    RoleName='ec2_full_access_role',
    PolicyArn=policy_arn
)

# 创建实例配置文件
instance_profile_response = iam_client.create_instance_profile(
    InstanceProfileName='ec2_instance_profile',
)

# 将角色附加到实例配置文件
attach_role_response = iam_client.add_role_to_instance_profile(
    InstanceProfileName='ec2_instance_profile',
    RoleName='ec2_full_access_role'
)

# 定义用户数据
user_data = """#!/bin/bash
touch test.txt
"""

# 创建实例
instance_params = {
    'ImageId': image_id,
    'InstanceType': instance_type,
    'KeyName': key_name,
    'SecurityGroups': (sg_name, ),
    'UserData': user_data,
    'IamInstanceProfile':{'Name': 'ec2_instance_profile'},
    'MinCount': 1,
    'MaxCount': 1
}
instances = ec2_res.create_instances(**instance_params)