skip to Main Content

I am associating an elastic IP to an EC2 instance that i am creating via cloudformation. I am attaching it to my EC2 instance via

AWSTemplateFormatVersion: 2010-09-09
Description:
  Testing stuff

Resources:
  myENI:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId: <subnet-id>
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: <ami-id>
      InstanceType: t2.micro
      NetworkInterfaces:
        - NetworkInterfaceId: !Ref myENI
          DeviceIndex: '0'
      Tags:
        - Key: Name
          Value: test-instance-1
  myEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt myEIP.AllocationId
      NetworkInterfaceId: !Ref myENI
    DependsOn: Instance

and i am creating the stack using aws cloudformation create-stack --stack-name ec2-example --template-body file://test-instance.yaml

Which creates my resources including the elastic IP. 35.82.18.137, an instance, EIPAssociation and it’s own ENI.

Now i spin up another EC2 instance by updating my existing stack by changing the value of tags to test-instance-2 using the following command aws cloudformation create-stack --stack-name ec2-example-1 --template-body file://test-instance.yaml

AWSTemplateFormatVersion: 2010-09-09
Description:
  Testing stuff

Resources:
  myENI:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId: <subnet-id>
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: <ami-id>
      InstanceType: t2.micro
      NetworkInterfaces:
        - NetworkInterfaceId: !Ref myENI
          DeviceIndex: '0'
      Tags:
        - Key: Name
          Value: test-instance-2
  myEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt myEIP.AllocationId
      NetworkInterfaceId: !Ref myENI
    DependsOn: Instance

Which creates a new instance and issues a new EIP : 44.229.115.61, an instance, EIPAssociation and it’s own ENI.

How can i switch over the old elastic IP 35.82.18.137 from the old instance to the new instance without deleting the old instance? Is that even possible using cloudformation ( No clickops if possible )? Thank you for the assistance.

2

Answers


  1. You need to tag each IP instance first, and then switch them in the Cloudformation template:

    1. Create an Elastic IP:
      enter image description here

    2. Develop the full deployment template:
      enter image description here

    More details (actually, a tutorial with more explanations) is available at this link.

    Login or Signup to reply.
  2. Yes, it’s possible as outlined in the documentation: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/refactor-stacks.html

    Here’s a demo (all of the code snippets below are run in bash).


    Let’s say we have these two templates (note that the first template must have the deletion policy set to Retain for the EIP):

    template1.yml :

    AWSTemplateFormatVersion: 2010-09-09
    Description:
      Testing stuff
    
    Resources:
      myENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
          SubnetId: <subnet-id>
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: ami-02d7ab1717c7787ce
          InstanceType: t2.micro
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref myENI
              DeviceIndex: '0'
          Tags:
            - Key: Name
              Value: test-instance-1
      myEIP:
        Type: AWS::EC2::EIP
        DeletionPolicy: Retain
        Properties:
          Domain: vpc
      EIPAssociation:
        Type: AWS::EC2::EIPAssociation
        Properties:
          AllocationId: !GetAtt myEIP.AllocationId
          NetworkInterfaceId: !Ref myENI
        DependsOn: Instance
    

    template2.yml:

    AWSTemplateFormatVersion: 2010-09-09
    Description:
      Testing stuff
    
    Resources:
      myENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
          SubnetId: <subnet-id>
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: ami-02d7ab1717c7787ce
          InstanceType: t2.micro
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref myENI
              DeviceIndex: '0'
          Tags:
            - Key: Name
              Value: test-instance-2
    

    then let’s deploy them both:

    $ aws cloudformation deploy --template-file template1.yml --stack-name stack1
    $ aws cloudformation deploy --template-file template2.yml --stack-name stack2
    

    once the stacks have been deployed, we need to fetch the allocation id and the public ip of the elastic ip deployed in the first stack:

    $ EIP_PHYSICAL_RESOURCE_ID=$(aws cloudformation describe-stack-resources --stack-name stack1 --query 'StackResources[?LogicalResourceId == `myEIP`].PhysicalResourceId' --output text)
    $ EIP_ALLOCATION_ID=$(aws ec2 describe-addresses --query "Addresses[?PublicIp == '${EIP_PHYSICAL_RESOURCE_ID}'].AllocationId" --output text)
    

    we can now proceed to remove the EIP and the EIP association from the first stack:

    template1.yml

    AWSTemplateFormatVersion: 2010-09-09
    Description:
      Testing stuff
    
    Resources:
      myENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
          SubnetId: <subnet-id>
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: ami-02d7ab1717c7787ce
          InstanceType: t2.micro
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref myENI
              DeviceIndex: '0'
          Tags:
            - Key: Name
              Value: test-instance-1
    

    and let’s update the first stack:

    $ aws cloudformation update-stack --template-body file://template1.yml --stack-name stack1
    

    now we must modify the second template to include the EIP.

    template2.yml:

    AWSTemplateFormatVersion: 2010-09-09
    Description:
      Testing stuff
    
    Resources:
      myENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
          SubnetId: <subnet-id>
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: ami-02d7ab1717c7787ce
          InstanceType: t2.micro
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref myENI
              DeviceIndex: '0'
          Tags:
            - Key: Name
              Value: test-instance-2
      myEIP:
        Type: AWS::EC2::EIP
        DeletionPolicy: Retain
        Properties:
          Domain: vpc
    

    now let’s create the following file (file.txt) which will be used in the import operation later:

    [
      {
          "ResourceType":"AWS::EC2::EIP",
          "LogicalResourceId":"myEIP",
          "ResourceIdentifier": {
            "AllocationId": "$EIP_ALLOCATION_ID",
            "PublicIp": "$EIP_PHYSICAL_RESOURCE_ID"
          }
      }
    ]
    

    and now let’s populate it (envsubst is a handy way to replace the two variables into the text file, however you can obviously do this in other ways too):

    $ export EIP_PHYSICAL_RESOURCE_ID
    $ export EIP_ALLOCATION_ID
    $ envsubst < file.txt > resourcesToImport.txt
    

    resourcesToImport.txt now contains the allocation id and public ip of the EIP.
    Let’s run the import operation:

    $ aws cloudformation create-change-set 
        --stack-name stack2 --change-set-name ImportChangeSet 
        --change-set-type IMPORT 
        --resources-to-import file://resourcesToImport.txt 
        --template-body file://template2.yml
    $ aws cloudformation execute-change-set --change-set-name ImportChangeSet --stack-name stack2
    

    the second stack now has imported the EIP. Finally, let’s create an association with the existing instance

    template2.yml:

    AWSTemplateFormatVersion: 2010-09-09
    Description:
      Testing stuff
    
    Resources:
      myENI:
        Type: AWS::EC2::NetworkInterface
        Properties:
          SubnetId: <subnet-id>
      Instance:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: ami-02d7ab1717c7787ce
          InstanceType: t2.micro
          NetworkInterfaces:
            - NetworkInterfaceId: !Ref myENI
              DeviceIndex: '0'
          Tags:
            - Key: Name
              Value: test-instance-2
      myEIP:
        Type: AWS::EC2::EIP
        DeletionPolicy: Retain
        Properties:
          Domain: vpc
      EIPAssociation:
        Type: AWS::EC2::EIPAssociation
        Properties:
          AllocationId: !GetAtt myEIP.AllocationId
          NetworkInterfaceId: !Ref myENI
        DependsOn: Instance
    

    and let’s update the stack:

    $ aws cloudformation update-stack --template-body file://template2.yml --stack-name stack2
    

    The EIP which was originally associated with the instance in the first stack is now associated with the instance in the second stack

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search