【问题标题】:AWS Cloudformation Default keypair for ec2ec2 的 AWS Cloudformation 默认密钥对
【发布时间】:2022-01-27 15:41:07
【问题描述】:

我有一个 cloudformation 模板来创建一个 ec2 实例。该模板还会启动一个 httpd 以及一些提供的内容。

我正在使用 Parameter 部分来允许指定或选择一个键 - 请参阅下面的 sn-p:

Parameters:
  paramKeyPair:
    Description: KeyPairName
    Type: AWS::EC2::KeyPair::KeyName

我通过 AWS CLI 调用 ec2-instance,如下所示:

aws cloudformation create-stack --stack-name stack-ec2instance --template-body file://demo-ec2instance --parameters ParameterKey=paramKeyPair,ParameterValue=peterKeyPair

所以可以创建实例,并且可以将密钥对作为参数传递 - 但是 - 坦率地说,我实际上并不关心实例是否可以访问。它只是一个可以向上或向下旋转的 Web 服务器。 SSH 访问很好,但没什么大不了的。

事实上,如果我从 cloudformation 模板中删除了 keypair 参数 - 并在 AWS CLI 调用中删除了关联的引用 - Cloudformation 将很高兴在没有密钥对的情况下启动实例。太好了!

我真正想要的是让 cloudformation 处理密钥对是否存在。 我认为最好的方法是更新代码,以便参数具有默认值“无”(例如),然后可以从 AWS CLI 运行 ec2-instance,如果 keypair 参数不是指定,则 AWS 将知道根本不用担心密钥对。

问题在于,通过将 Type 指定为 AWS::EC2::KeyPair::KeyName,AWS CLI 需要一个实际值。

我没有想法 - 如果其他人已经解决了这个问题 - 我将非常感激。 谢谢 彼得。

【问题讨论】:

    标签: amazon-web-services templates parameter-passing amazon-cloudformation


    【解决方案1】:

    如果我对您的理解正确,您希望能够将参数保留在 Cloudformation 模板中,但仅在您指定值时将密钥对“分配”给实例,否则不要将密钥对分配给 ec2实例资源。您可以使用 AWS::NoValue 伪参数来做到这一点。

    这是一个示例模板:

    
    Description: My EC2 instance
    
    Parameters:
      SSHKeyName:
        Type: String
    
    Conditions:
    
      Has-EC2-Key:
        !Not [ !Equals [ !Ref SSHKeyName, '' ] ]
    
    Resources:
    
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: <InstanceImageID>
          InstanceType: t2.micro
          KeyName: !Ref SSHKeyName
          KeyName:
            Fn::If:
            - Has-EC2-Key
            - Ref: SSHKeyName
            - Ref: AWS::NoValue
          <other properties as required
    

    所以它的作用是检查 SSHKeyName 值是否为空,如果为空则 KeyName 属性将被忽略,如果不为空则它将使用 SSHKeyName 的值。

    【讨论】:

    • 太棒了-感谢您的快速响应-我会尝试一下。
    • 参数验证仍然失败:“参数验证失败:参数名称 KeyName 的参数值不存在。用户请求回滚。”。我假设它在到达条件块之前解析参数。
    • 谢谢@PeterRhodes。修改了我对未来用户的回答。
    【解决方案2】:

    谢谢 WarrenG,您的解决方案有一个小例外,即将参数类型从 AWS::EC2::KeyPair::KeyName 更改为 String。 如果没有你的帮助,我敢肯定我会为此花费更多时间。

    总之,修复是 1:将参数类型改为字符串。

    Parameters:
      SSHKeyName:
        Type: String
    

    2:添加一个判断键是否存在的函数。

    Conditions:
      Has-EC2-Key:
        !Not [ !Equals [ !Ref SSHKeyName, '' ] ]
    
    1. 使用资源部分中的函数。

    KeyName:
      Fn::If:
      - Has-EC2-Key
      - Ref: SSHKeyName
      - Ref: AWS::NoValue

    在我的问题中,为了便于阅读,我将代码 sn-ps 保持在最低限度,但现在我已将其标记为已解决,我添加两个代码块仅用于文档,以防这对其他人有帮助。

    1. 通过 AWS CLI 调用模板的一个示例。

    aws cloudformation create-stack --stack-name stack-ec2instance --template-body file://demo-ec2instance --parameters ParameterKey=paramSubnetId,ParameterValue=$SubnetId ParameterKey=paramKeyPair,ParameterValue=peterKeyPair ParameterKey=paramSecurityGroupIds,ParameterValue=$SecurityGroupId
    1. 创建 EC2 实例的模板。

    AWSTemplateFormatVersion: 2010-09-09
    Parameters:
      SSHKeyName:
        Description: EC2 KeyPair for SSH access.
        Type: String
    
    Conditions:
      Has-EC2-Key:
        !Not [ !Equals [ !Ref SSHKeyName, '' ] ]
    
    Mappings:
      RegionMap:
        eu-west-1:
          AMI: ami-3bfab942
        eu-west-2:
          AMI: ami-098828924dc89ea4a
          
    Resources:
      EC2Instance:
        Type: AWS::EC2::Instance
        Metadata: 
          AWS::CloudFormation::Init:
            config: 
              packages: 
                yum:
                  httpd: []
                  php: []
              files: 
                /var/www/html/index.php:
                  content: !Sub |
                    <?php print "Hello Peter !"; ?>
              services: 
                sysvinit:
                  httpd:
                    enabled: true
                    ensureRunning: true
        Properties:
          InstanceType: t2.micro
          ImageId:
            Fn::FindInMap:
            - RegionMap
            - !Ref AWS::Region
            - AMI
          SecurityGroupIds:
            - !Ref MySecurityGroup
          KeyName:
            Fn::If:
            - Has-EC2-Key
            - Ref: SSHKeyName
            - Ref: AWS::NoValue
          UserData:
            'Fn::Base64': 
              !Sub |
                #!/bin/bash -xe            
                # Ensure AWS CFN Bootstrap is the latest
                yum install -y aws-cfn-bootstrap
                # Install the files and packages from the metadata
                /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2Instance  --region ${AWS::Region}
      MySecurityGroup:
        Type: AWS::EC2::SecurityGroup
        Properties:
          GroupDescription: Open Ports 22 and 80
          SecurityGroupIngress:
          - IpProtocol: tcp
            FromPort: '22'
            ToPort: '22'
            CidrIp: 0.0.0.0/0
          - IpProtocol: tcp
            FromPort: '80'
            ToPort: '80'
            CidrIp: 0.0.0.0/0
    
    Outputs:
      Website:
        Description: The Public DNS for the EC2 Instance
        Value: !Sub 'http://${EC2Instance.PublicDnsName}'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      • 2023-03-28
      • 2018-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      相关资源
      最近更新 更多