首页 > 解决方案 > 无服务器模板上 EC2 元数据上的 !Sub 和 !GetAtt 问题

问题描述

我在使用!Sub!GetAtt函数从我的 EC2 元数据 configSet 块中获取一些 RDS 实例属性时遇到问题。

因此,在我的 serverless.yml 文件中的资源键中,我(除其他外)有一个 EC2 实例(OASInstance)和一个 RDS 实例(OASRDSInstance)。我正在尝试为托管在 RDS 上的数据库构建连接字符串,为此,我在 EC2 实例定义的元数据块上的文件定义中使用!Sub!GetAtt函数。

我已经尝试了多种方法,使用短语法格式和长语法格式,但我确保这个方法适用于 CloudFormation 模板:

- Fn::Sub:
  - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
  - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}

我尝试部署此模板时遇到的错误是:

Serverless Error ---------------------------------------   
Invalid variable reference syntax for variable RDSEndpointURL. You can only reference env vars, options, & files. You can check our docs for more info.

但是,如果我在 CloudFormation 模板的相同位置使用相同的代码块,则它可以完美运行。

我的猜测是,无服务器将 {RDSEndpointURL} 和 {RDSEndpointPort} 与本地模板变量混淆了,并且没有意识到这些只是用于 !Sub 上下文。

模板非常大(尤其是 EC2 元数据部分),所以我在这里只发布相关部分并将“...”放在不相关的部分中。

这是您应该检查的路径: 小路

...
resources:
  Resources:
    OASRDSInstance:
      Type: 'AWS::RDS::DBInstance'
      Properties:
        AllocatedStorage: 20
        BackupRetentionPeriod: 0
        CopyTagsToSnapshot: True
        DBInstanceClass: db.m5.xlarge
        DBInstanceIdentifier: oas-rcu-central
        DBName: ORCL
        DBParameterGroupName: default.oracle-ee-19
        DBSubnetGroupName: default-vpc
        Engine: oracle-ee
        EngineVersion: 19.0.0.0.ru-2020-07.rur-2020-07.r1
        KmsKeyId: arn:aws:kms:us-east-1:1111111111:key/aaaa-bbbb-cccc-eeee-dddd
        LicenseModel: bring-your-own-license
        MasterUserPassword: ${self:custom.rcuSysDBPassword}
        MasterUsername: admin
        OptionGroupName: default:oracle-ee-19
        Port: 1521
        StorageEncrypted : True
        StorageType : gp2
    OASInstance:
      Type: 'AWS::EC2::Instance'
      DependsOn: OASRDSInstance
      Metadata:
        'AWS::CloudFormation::Init':
          configSets:
            InstallAndRun:
              - OsRequirements
              - AddSwap
              - InstallJDK
              - PrepareFolders
              - PreOracleInventory
              - OracleInventory
              - PreInstallWLS
              - InstallWLS
              - PrePatchWLS
              - PatchWLS
              - PreInstallOAS
              - InstallOAS
              - CreateRCU
              - ConfigureOAS
              - RunOAS
          OsRequirements: ...
          AddSwap: ...
          InstallJDK: ...
          PrepareFolders: ...
          PreOracleInventory: ...
          OracleInventory: ...
          PreInstallWLS: ...
          InstallWLS: ...
          PrePatchWLS: ...
          PatchWLS: ...
          InstallOAS: ...
          CreateRCU:
            commands:
              cmd00:
                command: echo 'Create RCU' >> /tmp/OASsetup.log
              cmd01_01:
                command: !Join 
                  - ''
                  - - sudo -u oracle sh -c '(echo "
                    - !Ref RcuSysDBPassword
                    - '"; echo "'
                    - !Ref RcuSchemasDBPassword
                    - '") > /home/oracle/rcu_password.dat'''
              cmd02_01:
                command: !Join 
                  - ''
                  - - 'sudo -u oracle '
                    - !FindInMap 
                      - TemplateParams
                      - paths
                      - OracleHome
                    - '/oracle_common/bin/rcu '
                    - '-silent '
                    - '-createRepository '
                    - '-schemaPrefix '
                    - !Ref RcuDBPrefix
                    - ' '
                    - '-useSamePasswordForAllSchemaUsers true '
                    - '-connectString '
                    - Fn::Sub:
                      - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
                      - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}
                    - ' '
                    - '-dbUser '
                    - !Ref RcuSysDBUser
                    - ' '
                    - '-databaseType ORACLE '
                    - '-dbRole Normal '
                    - '-honorOMF '
                    - >-
                      -component STB -component MDS -component WLS -component OPSS
                      -component BIPLATFORM -component IAU -component IAU_APPEND
                      -component IAU_VIEWER 
                    - '-f < /home/oracle/rcu_password.dat'
              cmd03_01:
                command: rm /home/oracle/rcu_password.dat
          ConfigureOAS: ...
          RunOAS: ...
      Properties:
        IamInstanceProfile: dev-k12-oas-InstanceRole
        ImageId: !FindInMap 
          - AWSRegionArch2AMI
          - !Ref 'AWS::Region'
          - !FindInMap 
            - AWSInstanceType2Arch
            - !Ref InstanceType
            - Arch
        InstanceType: !Ref InstanceType
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              VolumeSize: 25
              VolumeType: gp2
        NetworkInterfaces:
          - AssociatePublicIpAddress: false
            DeviceIndex: '0'
            GroupSet:
              - !Ref OASSecurityGroup
            SubnetId: subnet-aaaaaaaaaaaaaaaa
        KeyName: !Ref KeyName
        Tags:
        - Key: "Name"
          Value: !Ref "AWS::StackName"
        UserData: !Base64 
          'Fn::Join':
            - ''
            - - |
                #!/bin/bash -xe
              - |
                yum update -y aws-cfn-bootstrap
              - |
                # Install the files and packages from the metadata
              - '/opt/aws/bin/cfn-init -v '
              - '         --stack '
              - !Ref 'AWS::StackName'
              - '         --resource OASInstance '
              - '         --configsets InstallAndRun '
              - '         --region '
              - !Ref 'AWS::Region'
              - |+

              - |
                # Signal the status from cfn-init
              - '/opt/aws/bin/cfn-signal -e $? '
              - '         --stack '
              - !Ref 'AWS::StackName'
              - '         --resource OASInstance '
              - '         --region '
              - !Ref 'AWS::Region'
              - |+

      CreationPolicy:
        ResourceSignal:
          Timeout: PT45M
    OASSecurityGroup: ...
    OASLoadBalancerSG: ...
    OASTargetGroup: ...
    OASLoadBalancer: ...
    OASHttpLoadBalancerListener: ...
    OASLoadBalancerListener: ...
    PrivateDNSRecord: ...
...

我应该怎么办?

谢谢

标签: amazon-web-servicesamazon-ec2amazon-cloudformationserverless-frameworkserverless

解决方案


好吧,我找到了解决方法。

我将!Sub替换为!Join

这就是我所拥有的:

- Fn::Sub:
  - "${RDSEndpointURL}:${RDSEndpointPort}:ORCL"
  - {RDSEndpointURL: !GetAtt OASRDSInstance.Endpoint.Address, RDSEndpointPort: !GetAtt OASRDSInstance.Endpoint.Port}

这是替换:

- !Join 
  - ''
  - - !GetAtt OASRDSInstance.Endpoint.Address
    - ':'
    - !GetAtt OASRDSInstance.Endpoint.Port
    - ':'
    - ${self:custom.RDSDbName}

但是,我想知道是否有更好的方法。


推荐阅读