【问题标题】:Dynamically create n number of ec2 instances with Troposphere使用 Troposphere 动态创建 n 个 ec2 实例
【发布时间】:2016-10-20 02:08:55
【问题描述】:

我刚刚进入 EC2、CloudFormation(和对流层)等。我正在尝试从一个简单的 Selenium Grid 开始,以便在夜间运行。现在,我们在需要时使用了 12 个 selenium 节点(每个节点都有自己的 EC2 实例)。这些堆栈一次只能上升几个小时。将来我们很可能需要更多,所以我没有静态设置节点数,而是尝试设置它,以便 Jenkins 可以动态增加节点数。

现在,我有一个简单的 for 循环,看起来应该可以正常工作 - 特别是在查看了一堆示例之后:

for i in range(numNodes):
    instance = ec2.Instance("Node{}".format(str(i)))
    instance.ImageId = Ref(Image)
    instance.UserData = Base64(Join("", userData))
    instance.InstanceType = Ref(NodeSize)
    instance.KeyName = Ref(SSHKey)
    instance.SecurityGroups = [Ref("NodeSecurityGroup")]
    instance.IamInstanceProfile = "SeleniumNode"
    template.add_resource(instance)

完整的堆栈跟踪:

        Traceback (most recent call last):
  File "C:/dev/source/admin/scripts/troposphere/seleniumGrid.py", line 171, in <module>
    print(template.to_json())
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 543, in to_json
    sort_keys=sort_keys, separators=separators)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 200, in encode
    chunks = list(chunks)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 429, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 436, in _iterencode
    o = _default(o)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 440, in default
    return obj.JSONrepr()
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 223, in JSONrepr
    "Resource %s required in type %s" % (k, rtype))
ValueError: Resource ImageId required in type AWS::EC2::Instance

我的图片参数如下:

Image = template.add_parameter(Parameter(
"Image",
    Type="AWS::EC2::Image::Id",  # I even tried setting this to "String"
    Description="AMI To use for all windows grid instances.",
    Default="ami-c06b24a0"  
))

我什至尝试将所有内容都传递给构造函数。

for i in range(numNodes):
    instance = ec2.Instance("Node{}".format(str(i)),
                            ImageId=Ref(Image),
                            UserData=Base64(Join("", userData)),
                            InstanceType=Ref(NodeSize),
                            KeyName=Ref(SSHKey),
                            SecurityGroups=[Ref("NodeSecurityGroup")],
                            DependsOn=["NodeSecurityGroup", "WindowsHub"],
                            IamInstanceProfile="SeleniumNode")
    template.add_resource(instance)

但我仍然遇到同样的错误。我敢肯定这很愚蠢,但它变得非常烦人。有什么想法吗?

另外,我在尝试打印 JSON 模板时遇到了错误。

print(template.to_json())

对流层 1.8.2

Python 3.5.2

【问题讨论】:

    标签: amazon-ec2 amazon-cloudformation troposphere


    【解决方案1】:

    对流层维护者在这里。您在什么时候收到 ValueError?你能分享完整的堆栈跟踪吗?

    可能无法解决此问题的一件事,但我想我要指出的是,您不需要在创建对象后指定实例的每个单独属性。相反,您通常会使用以下代码:

    for i in range(numNodes):
        instance = ec2.Instance(
            "Node{}".format(str(i)),
            ImageId=Ref(Image)
            UserData=Base64(Join("", userData)),
            InstanceType=Ref(NodeSize),
            KeyName=Ref(SSHKey),
            SecurityGroups=[Ref("NodeSecurityGroup")],
            IamInstanceProfile="SeleniumNode",
        )
        template.add_resource(instance)
    

    您甚至可以将其缩短为:

    for i in range(numNodes):
        instance = template.add_resource(
            ec2.Instance(
                "Node{}".format(str(i)),
                ImageId=Ref(Image)
                UserData=Base64(Join("", userData)),
                InstanceType=Ref(NodeSize),
                KeyName=Ref(SSHKey),
                SecurityGroups=[Ref("NodeSecurityGroup")],
                IamInstanceProfile="SeleniumNode",
            )
        )
    

    无论如何,这似乎不是您的问题 - 因此,如果您可以分享完整的堆栈跟踪以了解有帮助的错误,以及您正在使用的 python 和对流层的版本。

    【讨论】:

    • 我实际上尝试缩短它并将其传递给构造函数,但我仍然得到同样的错误。
    • 抱歉,点击返回太早了。我用您要求的信息更新了问题。
    【解决方案2】:

    好吧,一旦我发现我是个傻瓜,我就打算删除这个问题......但是关于为了全人类而删除“已回答的问题”的小消息,yadda yadda yadda让我感到内疚。希望其他人可以从我的错误中吸取教训。

    至于答案……

    结果证明对流层没有任何问题(我认为这是我的错)。我完全忘记了 Selenium Hub,它是它自己的实例,但不是根据所需节点的数量动态设置的。我只为集线器添加了部分资源。你猜对了——我忘了​​指定 ImageId kwarg。一旦我添加了它(和其他一些 kwargs),一切都完美无缺。

    向@phobologic 和所有其他对流层维护者大喊。因为有你,我能够将 2500+ 行 JSON 对象转换为更易于维护的 ~175 行 python 脚本!

    【讨论】:

    • 哦,太好了,很高兴你知道了。我现在真的想知道,如果有办法让那个异常指出导致问题的对象的标题(如果它有一个),那肯定会帮助你解决这个问题。我去看看,谢谢你的好话:)
    • 顺便说一句,我继续创建了一个 PR,应该可以更轻松地解决这些问题:github.com/cloudtools/troposphere/pull/597
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-16
    • 2011-06-27
    • 1970-01-01
    • 2014-05-29
    • 2015-12-28
    • 2019-11-21
    • 1970-01-01
    相关资源
    最近更新 更多