EC2 루트 볼륨과 추가 볼륨의 삭제 옵션에 대하여

EC2의 루트 볼륨과 추가 볼륨의 삭제 옵션에 관해 간단한 테스트를 적은 글입니다.
2021.05.22

이번에 작업을 하며 EC2에 추가한 EBS 볼륨을 삭제하지 않은 일이 있었습니다.
이 일을 계기로 조사를 해보니 EC2의 볼륨이 루트 볼륨인지 아닌지에 따라 인스턴스를 삭제할 때 함께 볼륨이 남기도 한다는 것을 알게 되었습니다.
그리고 작성한 방법과 옵션에 따라 적용이 다르게 된다는 것도 알게 되었습니다.
물론 DeleteOnTermination을 특정한다면 딱히 고민할 필요가 없는 문제이지만
호기심이 생겨 간단한 테스트를 해보았고 이를 공유하고자 합니다.

공통 기본값은?

DeleteOnTermination 속성의 기본값은 볼륨이 인스턴스의 루트 볼륨인지 아니면 인스턴스에 연결된 루트 외 볼륨인지에 따라 다릅니다.

공식 문서에 따르면 루트 볼륨의 DeleteOnTermination의 기본값은 true이고, 루트 외 볼륨의 경우엔 false로 지정되어 있습니다.
그럼 실제로는 어떻게 적용되는지 확인해보겠습니다.

테스트

AWS CLI로 테스트를 해보겠습니다. 이어서 CloudFormation에서도 동일하게 적용되는지 확인해봅니다.

우선 결과부터

설명으로 글이 길어지니 우선 결과부터 말하자면

  • AWS CLI로 작성하면 방법에 따라 삭제 옵션이 다르게 적용된다.
  • CloudFormation으로 작성하더라도 CLI와 똑같은 규칙이 적용된다.
    하지만 위의 기본값은 인스턴스의 삭제에만 한정되기 때문에 스택을 삭제하면 VolumeAttach로 작성한 볼륨은 삭제된다.

였습니다.

AWS CLI로 테스트

인스턴스에 추가 볼륨을 작성하는 방법으로는

  • run-instances 명령어에 --block-device-mappings 옵션을 추가
  • attach-volume 명령어 사용

등이 있습니다.

테스트는 다음과 같은 방법으로 진행하였습니다.

  • 단순히 run-instances 명령어에 --block-device-mappings 옵션 사용
  • --block-device-mappings 옵션에 DeleteOnTermination 를 특정
  • attach-volume 명령어 사용

우선 --block-device-mappings 옵션을 사용한 방법으로 작성해보겠습니다.
사용한 스크립트는 다음과 같습니다.

# 사용하는 AMI에 따라 루트 볼륨의 이름이 달라짐
# 스크립트에선 Amazon Linux 2 를 사용
aws ec2 run-instances \
    --image-id ami-0ca38c7440de1749a \
    --instance-type t2.micro \
    --block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs":{"VolumeSize":50}},{"DeviceName":"/dev/sde","Ebs":{"VolumeSize":8}}]' \
    --key-name publicTestKey

루트 볼륨 1개와 추가 볼륨 1개를 가진 인스턴스가 생성되었습니다.

볼륨 목록에서도 이를 확인할 수 있습니다.

describe-instances명령어로 인스턴스의 설정값을 확인해보겠습니다.

aws ec2 describe-instances --instance-ids i-05eadaa67e78d50bd

# result
----
"BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2021-05-22T09:28:42+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-0727684da83e83e16"
                            }
                        },
                        {
                            "DeviceName": "/dev/sde",
                            "Ebs": {
                                "AttachTime": "2021-05-22T09:28:42+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-0bf9ee0f38c2a1102"
                            }
                        }
                    ],
----

예상과는 다르게 추가 볼륨인 sde의 DeleteOnTermination이 true로 설정되어 있습니다.
실제로 인스턴스를 삭제하면 볼륨도 함께 사라집니다.

찾아보니 BlockDeviceMappings 옵션은 DeleteOnTermination을 다르게 적용하고 있었습니다.

인스턴스 종료 시 볼륨 삭제 여부(true 또는 false). 기본값은 루트 디바이스 볼륨은 true이고 연결된 볼륨은 false입니다 AMI를 생성하면 그 블록 디바이스 매핑이 인스턴스에서 이 설정을 내려 받습니다. 인스턴스를 시작하면 AMI에서 이 설정을 내려 받습니다.

즉, AMI의 기본 설정에 따라 추가 볼륨의 취급도 달라진다는 뜻입니다.
실제로 AMI의 설정값을 확인해보니 BlockDeviceMappings의 옵션값이 true로 되어 있습니다.

# 사용한 AMI(Amazon Linux 2)의 설정값 확인
aws ec2 describe-images --image-ids ami-0ca38c7440de1749a

# 결과
----
"BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/xvda",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "SnapshotId": "snap-003b466f2f65000b0",
                        "VolumeSize": 8,
                        "VolumeType": "gp2",
                        "Encrypted": false
                    }
                }
            ],
----

만약 BlockDeviceMappings으로 볼륨을 추가한다면 ebs 파라미터의 DeleteOnTermination을 특정해주어야 합니다.

이어서 DeleteOnTerminationattach-volume을 쓰는 방법으로 2개의 추가 볼륨을 작성해보겠습니다.

aws ec2 run-instances \
    --image-id ami-0ca38c7440de1749a \
    --instance-type t2.micro \
    --block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs":{"VolumeSize":50}},{"DeviceName":"/dev/sde","Ebs":{"DeleteOnTermination":false, "VolumeSize":8}}]' \
    --key-name publicTestKey

# 볼륨 생성
aws ec2 create-volume \
--size 8 \
--availability-zone ap-northeast-1a
# 볼륨 연결
aws ec2 attach-volume \
--instance-id {생성한 인스턴스 id} \
--volume-id {생성한 볼륨 id} \
--device /dev/sdh

연결을 완료한 후 인스턴스의 정보를 확인해보겠습니다.

----
"BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2021-05-22T13:15:05+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-035175b43ea9cb27f"
                            }
                        },
                        {
                            "DeviceName": "/dev/sde",
                            "Ebs": {
                                "AttachTime": "2021-05-22T13:15:05+00:00",
                                "DeleteOnTermination": false,
                                "Status": "attached",
                                "VolumeId": "vol-008218eb85553d2c7"
                            }
                        },
                        {
                            "DeviceName": "/dev/sdh",
                            "Ebs": {
                                "AttachTime": "2021-05-22T13:18:41+00:00",
                                "DeleteOnTermination": false,
                                "Status": "attached",
                                "VolumeId": "vol-0796ef4d6ef545145"
                            }
                        }
                    ],
----

DeleteOnTermination를 특정한 볼륨은 당연하게도 삭제 옵션이 false로 되어 있습니다.
그리고 attach-volume로 연결한 볼륨은 다른 지정이 없어도 공통 기본값에 따라 삭제 옵션이 false로 설정됩니다.
실제로 인스턴스를 삭제한 후 볼륨 목록을 확인하면 2개의 볼륨은 삭제되지 않고 남아있습니다.

CloudFormation로 테스트

AWS CLI로 작성하며 각 옵션이 어떻게 적용되는지 확인할 수 있었습니다.
그리고 CloudFormation으로 작성하더라도 DeleteOnTermination는 공통 기본값으로 설정될 것입니다.
그렇다면 다음과 같은 결과가 나올 것이라 예상됩니다.

  • 우선 AMI의 설정에 따른다
  • DeleteOnTermination 을 특정하였다면 함께 삭제되지 않는다
  • 볼륨을 따로 생성하여 연결한다면 함께 삭제되지 않는다(기본값이 false이기 때문)

그렇다면 위의 가정을 모두 포함한 템플릿을 만들어 실제로 테스트해봅시다.
가정대로라면 xvda와 sdc는 삭제되고 sdd와 sdh는 삭제되지 않을 것입니다.

AWSTemplateFormatVersion: 2010-09-09
Description: TEST EC2 Environment

Resources:
  EC2:
    Type: "AWS::EC2::Instance"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      KeyName: publicTestKey
      ImageId: ami-0ca38c7440de1749a
      InstanceType: t2.micro
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 50
        - DeviceName: /dev/sdc
          Ebs:
            VolumeSize: 8
        - DeviceName: /dev/sdd
          Ebs:
            VolumeSize: 8
            DeleteOnTermination: false
  NewVolume:
    Type: AWS::EC2::Volume
    Properties:
      Size: 8
      AvailabilityZone: "ap-northeast-1a"

  AttachVolume:
    Type: AWS::EC2::VolumeAttachment
    Properties:
      InstanceId: !Ref EC2
      VolumeId: !Ref NewVolume
      Device: /dev/sdh

스택 생성이 완료된 후 인스턴스의 설정값을 확인해 봅시다.

aws ec2 describe-instances --instance-ids i-0d138e84db5772538
----
"BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xvda",
                            "Ebs": {
                                "AttachTime": "2021-05-22T14:29:16+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-09b1f046afa7b24d5"
                            }
                        },
                        {
                            "DeviceName": "/dev/sdc",
                            "Ebs": {
                                "AttachTime": "2021-05-22T14:29:16+00:00",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-05e1b21cbe5380cc2"
                            }
                        },
                        {
                            "DeviceName": "/dev/sdd",
                            "Ebs": {
                                "AttachTime": "2021-05-22T14:29:16+00:00",
                                "DeleteOnTermination": false,
                                "Status": "attached",
                                "VolumeId": "vol-0dc98cd7455d75b3f"
                            }
                        },
                        {
                            "DeviceName": "/dev/sdh",
                            "Ebs": {
                                "AttachTime": "2021-05-22T14:30:10+00:00",
                                "DeleteOnTermination": false,
                                "Status": "attached",
                                "VolumeId": "vol-0bcc5937885929018"
                            }
                        }
                    ],
----

예상대로 CLI와 똑같은 결과가 나왔습니다.
실제로 인스턴스를 직접 삭제한다면 2개의 추가 볼륨은 삭제되지 않습니다.
하지만 인스턴스를 따로 삭제하지않고 CloudFormation에서 스택을 삭제하면
DeleteOnTermination을 지정한 볼륨만 남아있습니다.
(인스턴스를 종료한 후에 스택을 삭제하여도 같은 결과입니다)

생성한 스택의 리소스를 보면 Type: AWS::EC2::Volume으로 작성한 볼륨은 리소스에 포함되어 있지만
DeviceName: /dev/sdd로 작성한 볼륨은 포함되어 있지 않기 때문입니다.
(만약 Type: AWS::EC2::Volume으로 작성된 볼륨을 삭제하고 싶지 않다면
"DeletionPolicy" : "Snapshot" 을 지정하면 됩니다. 상세한 내용은 문서를 참고해주세요.)

마무리

앞서 얘기했듯이 DeleteOnTermination 옵션을 의식하고 항상 설정한다면 크게 문제되지 않을 내용입니다.
하지만 BlockDeviceMappings 을 사용하는게 신경쓸게 더 있다는 점을 알 수 있었습니다.

끝으로 Trusted Advisor를 습관처럼 한번씩 확인한다면 AWS의 모범사례는 물론
본인도 모르게 남겨버린 볼륨을 확인할 수 있으니 한번씩 확인해보시기를 추천하며 글을 마칩니다.

내용의 피드백 및 오탈자 제보는 언제나 환영합니다! must01940(G메일) 으로 보내주시길 바랍니다.
긴 글 읽어주셔서 감사합니다!