简体   繁体   English

如何使用 AWS CDK 获取伪参数用户数据?

[英]How to obtain pseudo-parameters user data with AWS CDK?

I would like to convert this working CloudFormation Code into a proper Python AWS CDK version.我想将此工作 CloudFormation 代码转换为合适的 Python AWS CDK 版本。 The EC2 shall be launched within a VPC. EC2 应在 VPC 内启动。 The user data are used to install apps.用户数据用于安装应用程序。 After completion, I need a call back to Cloudformation.完成后,我需要回调 Cloudformation。

UserData:
        Fn::Base64: !Sub |
          <script>
          cfn-signal.exe --exit-code 0 --stack ${AWS::StackId} --resource EC2Instance --region ${AWS::Region}
          </script>

I tried to use the direct way with aws_cdk.core.Fn.base64 which is not working with regard to pseudo-parameters declaration within the EC2 the user data.我尝试对aws_cdk.core.Fn.base64使用直接方式,该方式aws_cdk.core.Fn.base64用于 EC2 用户数据中的伪参数声明。

This is my current state:这是我目前的状态:

EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
   "cfn-signal.exe --exit-code 0 ",
   "--stack ",
   VpcStack.stack_id(XXX, e.g. self?), # not working
   " --resource ",
   VpcStack.get_logical_id(XXX, e.g. self?), # not working
   " --region ",
   VpcStack.region(XXX, e.g. self?) # not working
)

Method 1:方法一:

Pros:优点:

  • Can take in any amount of variables, such as those defined in the context, not just those in the core.Aws object such as Region or Account ID.可以接受任意数量的变量,例如上下文中定义的变量,而不仅仅是core.Aws对象中的变量,例如区域或账户 ID。

Cons:缺点:

  • You will need to prefix references to all regular variables in the user_data.sh script with $!{ rather than just ${ .您将需要使用$!{而不仅仅是${user_data.sh脚本中的所有常规变量的引用添加前缀。

Steps脚步

Use a mappings dict and parse it into the Fn.sub function.使用映射字典并将其解析为Fn.sub函数。 Personally I like these declared at the top of my user_data.sh script rather than substituted throughout so use a double underscore as a prefix and as a suffix.我个人喜欢在我的user_data.sh脚本顶部声明的这些,而不是整个替换,因此使用双下划线作为前缀和后缀。 Note that you still need to consider the mappings as variables rather than strings.请注意,您仍然需要将映射视为变量而不是字符串。

ie IE

$cat user_data.sh
ACCOUNT_ID="${__ACCOUNT_ID__}"
REGION="${__REGION__}"

## Updates
yum update -y

## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime

## ECR Repo
ECR_REPO="${!ACCOUNT_ID}.dkr.ecr.${!REGION}.amazonaws.com/"
...

In my stack declaration I then place the following dict:在我的堆栈声明中,我然后放置以下字典:

mappings = {"__ACCOUNT_ID__": self.account,
            "__REGION__": self.region}

And read the user_data.sh into the sub function, with the mappings dict as the second parameter并将user_data.sh读入子函数,映射dict作为第二个参数

with open("user_data/user_data.sh", 'r') as user_data_h:
    # Use a substitution
    user_data_sub = core.Fn.sub(user_data_h.read(), mappings)

Then use the custom attribute from the UserData module.然后使用 UserData 模块中的自定义属性

# Import substitution object into user_data set
user_data = ec2.UserData.custom(user_data_sub)

Method 2方法二

Pros:优点:

  • No need to change bash syntax无需更改 bash 语法

Cons:缺点:

  • Token variables are hard to read, and restricted to attributes of the core.Aws object.令牌变量难以阅读,并且仅限于core.Aws对象的属性。 Such as AccountID and Region.例如 AccountID 和 Region。

Steps脚步

You can run print statements inside the cdk workflow to assist you in determining what the variables such as core.Aws.ACCOUNT_ID and core.Aws.REGION are evaluated to and use these inside the user_data script.您可以在 cdk 工作流中运行打印语句,以帮助您确定诸如core.Aws.ACCOUNT_IDcore.Aws.REGION类的变量的评估结果,并在 user_data 脚本中使用这些变量。 (I'm writing my deployment in python and have based it from the ec2 on an existing VPC from the aws official examples repo . (我正在用 python 编写我的部署,并将它从 ec2 基于来自aws 官方示例 repo的现有 VPC。

ie: IE:

host = ec2.Instance(...)
print(core.aws.ACCOUNT_ID)
print(core.Aws.REGION)

I then run cdk synth which yields:然后我运行cdk synth产生:

${Token[AWS::AccountId.0]}
${Token[AWS::Region.4]}
Resources:...

From here I can use these in my user_data script: ie从这里我可以在我的 user_data 脚本中使用这些:即

#!/bin/bash
ACCOUNT_ID="${Token[AWS::AccountId.0]}"
REGION="${Token[AWS::Region.4]}"

## Updates
yum update -y

## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime

Note now when re-running cdk synth these are recognised as special by the yaml constructor (The yaml double spacing is a known cdk bug):现在请注意,当重新运行cdk synth ,yaml 构造函数会将它们识别为特殊的(yaml 双间距是已知的 cdk 错误):

...
UserData:
        Fn::Base64:
          Fn::Join:
            - ""
            - - >-
                #!/bin/bash


                # AWS vars:

                ACCOUNT_ID="
              - Ref: AWS::AccountId
              - >-
                "

                REGION="
              - Ref: AWS::Region
              - >-
                "

                ## Updates
                yum update -y

                ## Fix time
                ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime

                ## ECR Repo
                EC2_REPO="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/"
...

I found the following to work with python我发现以下内容可以与 python 一起使用

from aws_cdk import (
  aws_ec2,
  core
)

host = aws_ec2.Instance(...)

host.add_user_data('', join([
  'yum install -y aws-cfn-bootstrap\n',
  f'/opt/aws/bin/cfn-init -v -s {core.Aws.STACK_NAME} -r {host.node.default_child.logical_id}\n'
])

meta_data = {
  'config': {
    'packages': {...},
    'files': {...},
     ...
    }
}

# for adding the meta data in a way that gets synth
host.node.default_child.add_overide('Metadata.AWS::CloudFormation::Init', meta_data)

This is using the CfnInstance object you get from host.node.default_child这是使用您从host.node.default_child获得的CfnInstance对象

You can access those pseudo-params by using the core module:您可以使用核心模块访问这些伪参数:

from aws_cdk import core

# other code...

EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
   "cfn-signal.exe --exit-code 0 ",
   f"--stack {core.Aws.STACK_ID}",
   f" --resource {EC2Instance}",  # Without more context, I'm not sure if this is exactly what you're wanting
   f" --region {core.Aws.REGION}",
)

# other code ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM