BLOG
AWS CloudFormation은 스택을 고객이 단일 유닛으로 관리할 수 있는 AWS 리소스의 모음으로 간주합니다. 스택을 시작한 후에는 AWS CloudFormation 콘솔, API 또는 AWS CLI를 사용하여 스택의 리소스를 업데이트할 수 있습니다. CloudFormation 외부에서 리소스 스택을 변경하면 안 됩니다. 우리가 리소스 이동이라고 부르기 때문입니다. 리소스 이동은 CloudFormation 관리 리소스를 대역 외로 변경하는 경우 발생하며, 나중에 스택을 업데이트하거나 삭제할 경우 오류가 발생할 수 있습니다.
이 블로그 게시물에서는 UPDATE_ROLLBACK_FAILED 와 같은 상태에서 스택을 복구하는 방법에 대한 예시를 살펴봅니다. AWS 지원 팀의 개입 없이 CloudFormation을 사용하여 추가 업데이트를 수행하기 위해 스택 제어를 다시 되찾는 방법을 보여줍니다.
UPDATE_ROLLBACK_FAILED
CloudFormation의 리소스를 실수로 변경하는 조직이 새로 생겨난 경우에는 대역 외 변경이 쉽게 이루어질 수 있습니다. 이러한 변경은 서비스에 대한 인식이 부족한 다른 팀의 멤버들에 의해서도 이루어질 수 있습니다. 대역 외 변경은 CloudFormation 스택이 더 이상 스택을 수정할 수 없는 상태가 되게 합니다. UPDATE_ROLLBACK_FAILED에 스택이 도달하면 CloudFormation 스택이 업데이트 작업을 시도하고 있었으며 작업이 실패하고 rollback을 시작했다는 것을 의미합니다. rollback 중에 CloudFormation이 이전의 “양호”상태로 돌아가지 않도록 하는 문제가 발생했다고 가정해 봅시다. 스택은 업데이트할 수 없고 roll back할 수 없으므로 이러한 중간 상태를 가정합니다. 그러면 API가 ContinueUpdateRollback및 DeleteStack을 제외한 스택의 추가 작업을 중지합니다.
ContinueUpdateRollback
ContinueUpdateRollback API작업은 고객에게 UPDATE_ROLLBACK_FAILED 상태의 스택에 대해 무효화를 제공합니다. 이는 CloudFormation이 rollback 절차를 계속하도록 만듭니다. 이 작업은 문제 해결에만 사용하시길 바랍니다. 장애가 발생하고 스택이 UPDATE_ROLLBACK_FAILED상태로 전환되면 API작업은 rollback만 계속하게 됩니다. 그러나 이는 근본적인 문제에 대한 해결책을 제공하지 못합니다. 예를 들어, 계정 제한으로 인해 rollback에 실패했는지에 대한 기본적인 문제는 해결되지 않습니다. 이 계정 제한을 해결하지 않으면 ContinueUpdateRollback이 다시 rollback을 시도하고 다시 한번 실패하게 됩니다. 하지만 기본 문제는 별도로 해결해야 하며, AWS CloudFormation 외부에서 모범 사례를 어긴 경우에도 해결해야 합니다.
사례 예시
UPDATE_ROLLBACK_FAILED상태로 전환되는 스택과 Auto Scaling서비스의 사용을 포함하는 시나리오를 안내해드리겠습니다. 이제 CloudFormation 템플릿에 대해 살펴보겠습니다.
참고 :이 템플릿은 시작 시 유효한 HVM이 호환되는 AMI (Amazon Machine Image)를 지정하는 모든 지역에 배포할 수 있습니다. 또는 현재 출시하려면 유럽(런던)(EU-웨스트-2)지역을 사용하십시오.
AWSTemplateFormatVersion: “2010-09-09”
Description: “A template used to illustrate the use of ContinueUpdateRollback API when recovering CloudFormation stacks from Update Rollback Failed”
Parameters:
pAMI:
Type: “AWS::EC2::Image::Id”
Description: “Pick any HVM compatible AMI-ID for the AutoScaling group, the default works in eu-west-2 only”
Default: “ami-1a7f6d7e”
Resources:
ASG:
Type: “AWS::AutoScaling::AutoScalingGroup”
Properties:
AvailabilityZones:
– !Select
– 0
– Fn::GetAZs: !Ref ‘AWS::Region’
DesiredCapacity: 1
LaunchConfigurationName: !Ref “LC”
MaxSize: 1
MinSize: 1
LC:
Type: “AWS::AutoScaling::LaunchConfiguration”
Properties:
ImageId: !Ref “pAMI”
InstanceType: “t2.micro”
보시다시피, 시작 구성으로 Auto Scaling그룹을 생성하면 스택이 예상대로 생성됩니다.
혼돈이 발생합니다
가상의 작업을 계속하기 위해서, AWS 인증 솔루션 아키텍트 Associate 시험을 통과한 운영 팀의 새로운 구성원인 지미를 고용하는 것으로 가정해 보겠습니다. 어느 날, 사용자가 자리를 비운 동안 개발 팀에서 지미에게 Auto Scaling그룹의 인스턴스 유형 크기를 줄이도록 요청합니다. 그는 실행 중인 Auto Scaling그룹에 대해 시작 구성을 새롭게 생성하고 새 시작 구성을 그룹에 할당하는 것이 가장 좋다고 결정합니다.
aws autoscaling create-launch-configuration –launch-configuration-name Jimmys_new_LC –image-id ami-1a7f6d7e –instance-type t2.nano –region eu-west-2
ASName=`aws cloudformation describe-stack-resources –stack-name <stack-name> –logical-resource-id ASG –output text –query StackResources[0].PhysicalResourceId –region eu-west-2`
aws autoscaling update-auto-scaling-group –auto-scaling-group-name $ASName –launch-configuration-name Jimmys_new_LC –region eu-west-2
물론, 그는 적절한 조치를 위해 이전의 AutoScaling 시작 구성을 정리하기로 결정합니다.
(쉽게 복제할 수 있도록 아래 첫번째 줄을 포함하여 이전 템플릿에서 생성한 런칭 구성의 물리적 ID를 가져옵니다.)
LCName=`aws cloudformation describe–stack–resources —stack–name <stack–name> —logical–resource–id LC —output text —query StackResources[0].PhysicalResourceId —region eu–west–2`
aws autoscaling delete–launch–configuration —launch–configuration–name $LCName —region eu–west–2
오 지미…우린 그런 큰 기대를 하고 있었어..
Rollback과 안정화
대부분의 테스트에서 AWS CloudFormation은 빠르게 실패합니다. 예를 들어 값이 올바르지 않은 상태에서 상태 점검 유형을 추가하면 초기 API호출이 실패하고 스택이 rollback됩니다. 그러나 CloudFormation이 대상 리소스를 교체하거나 성공적으로 변경하지 않았기 때문에 rollback하기 위해 API 호출이 필요하지 않다는 것을 정확히 가정합니다.
rollback은 일정 시간이 지난 후 이전 구성을 다시 적용하도록 촉발시킬 수 있습니다. CloudFormation은 이를 안정화라고 합니다. CloudFormation은 사용자를 대신하여 API 호출을 수행하며, 또한 리소스가 생성완료라고 표시되고 리소스가 원하는 상태로 실행되고 있는지 확인합니다. 예를 들어 Auto Scaling에서 Auto Scaling 그룹 생성 API호출을 전송한 다음 그룹에 Min/Max가 정의되고 템플릿에 원하는 개수가 될 때까지 Auto Scaling 그룹 형성을 시도합니다. 그렇지 않은 경우에는 CloudFormation을 이전 구성으로 다시 적용해야 합니다.
Rollback 강요하기
예를 들어, Auto Scaling그룹의 용량을 온디맨드 인스턴스 실행에 대한 계정 제한을 초과하도록 늘려서 이러한 유형의 장애를 강제로 발생시킬 수 있습니다. 그러면 안정화가 실패하고 rollback이 시작됩니다. 이때 CloudFormation은 이전에 정의된 시작 구성을 찾을 수 없으며 스택이 UPDATE_ROLLBACK_FAILED상태가 됩니다. 하지만, 이것은 사용하지 않는 인스턴스들을 시작하는 것을 포함할 것이고, 그렇게 하는 것은 그리 경제적이지 않을 것입니다. 대신, CloudFormation 대기 상태 리소스를 사용하여 오류를 시뮬레이션하고 rollback을 강제 적용할 수 있습니다.
다음은 CloudFormation 템플릿을 업데이트하는 방법입니다.
AWSTemplateFormatVersion: “2010-09-09”
Description: “A template used to illustrate the use of ContinueUpdateRollback API when recovering CloudFormation stacks from Update Rollback Failed”
Parameters:
pAMI:
Type: “AWS::EC2::Image::Id”
Description: “Pick any HVM compatible AMI-ID for the AutoScaling group, the default works in eu-west-2 only”
Default: “ami-1a7f6d7e”
Resources:
ASG:
Type: “AWS::AutoScaling::AutoScalingGroup”
Properties:
AvailabilityZones:
– !Select
– 0
– Fn::GetAZs: !Ref ‘AWS::Region’
DesiredCapacity: 1
LaunchConfigurationName: !Ref “LC”
MaxSize: 1
MinSize: 1
LC:
Type: “AWS::AutoScaling::LaunchConfiguration”
Properties:
ImageId: !Ref “pAMI”
InstanceType: “t2.large”
WaitCondition:
Type: “AWS::CloudFormation::WaitCondition”
DependsOn: ASG
CreationPolicy:
ResourceSignal:
Count: 1
Timeout: PT1M
보시다시피, 템플릿은 t2.large인스턴스를 사용하도록 시작 구성을 업데이트합니다. 하지만, 우리는 결코 대기 상태를 알려주지 않기 때문에, 그 스택은 rollback 할 것입니다. 이때, CloudFormation에서 시작 구성을 다시 적용합니다. 하지만, 우리가 앞에서 본 바와 같이, 지미가 출시 계획을 지웠습니다. 따라서 Auto Scaling그룹을 업데이트하고 rollback을 촉발시키는 스택의 업데이트는 실패합니다.
고착된 스택 복구에 대한 일반 지침
UPDATE_ROLLBACK_FAILED상태로 전환된 CloudFormation 스택의 문제를 해결하는 방법은 다음과 같습니다.
1. 스택을 삭제합니다. 어떤 이유로든 삭제가 실패하면 삭제에 실패한 리소스를 나열하는 RetainResources 옵션을 사용하여 DeleteStack API작업을 사용할 수 있습니다.
2. 기본 계정 변경 사항을 수동으로 생성 스택의 범위를 확장하여 스택을 다시 동기화한 다음 ContinueUpdateRollback을 수행합니다.
3. 기본 스택 리소스로 문제를 해결하는 경우 리소스 기술 지원 옵션과 함께 ContinueUpdateRollback을 사용할 수 있습니다. CloudFormation은 문제가 되거나 실패한 리소스를 업데이트 완료로 표시하고 나머지 rollback 작업을 계속합니다.
궁지를 벗어나다
이제 지미의 실수를 처리하기 위해서 경험을 통해 우리는 Cloudformation이 소유권을 추적하는 리소스 이름이나 ID에 의존한다는 것을 알고 있습니다. 런칭 구성을 통해 서비스에서 StackName, Logicalld및 랜덤 문자열의 조합을 사용하여 런칭 구성의 이름을 지정하고 있음을 알 수 있습니다.
이전 것의 정확한 이름을 사용하여 새로운 시작 구성을 만들 수 있습니다. 이전과 같이 스택을 설명한 후 ContinueUpdateRollback을 진행하면 이 이름을 알 수 있습니다.
LCName=`aws cloudformation describe-stack-resources –stack-name <stack-name> –logical-resource-id LC –output text –query StackResources[0].PhysicalResourceId`
aws autoscaling create-launch-configuration –launch-configuration-name $LCName –image-id ami-1a7f6d7e –instance-type t2.micro –region eu-west-2
aws cloudformation continue-update-rollback –stack-name <stack-name> –region eu-west-2
이제 스택이 UPDATE_ROLLBACK_COMPLETE상태로 돌아가 업데이트를 다시 수행할 준비가 되어야 합니다.
aws cloudformation describe-stacks –stack-name <stack-name> –query Stacks[0].StackStatus –region eu-west-2
“UPDATE_ROLLBACK_COMPLETE”
이 예시에서는 완료되지 않은 대기 조건을 추가하여 rollback을 강제로 적용했습니다. 당신의 경우, 원인은 계정 제한이나 다른 문제들 때문일 수도 있습니다.
교체가 옵션은 아니다
예를 들어 스택에서 예상하는 이름과 동일한 이름의 새 리소스를 명명하여 제거된 리소스를 쉽게 교체할 수 있는 운 좋은 상황이 발생했습니다. 사용자 지정 이름이 없는 리소스가 삭제된 상황을 살펴보겠습니다.
다음 Cloudformation템플릿을 고려하십시오
AWSTemplateFormatVersion: “2010-09-09”
Description: “A template used to illustrate the use of ContinueUpdateRollback API when recovering CloudFormation stacks from Update Rollback Failed”
Parameters:
pAMI:
Type: “AWS::EC2::Image::Id”
Description: “Pick any HVM compatible AMI-ID for the AutoScaling group, the default works in eu-west-2 only”
Default: “ami-1a7f6d7e”
pVPC:
Type: “AWS::EC2::VPC::Id”
Description: “Please use your *default* VPC security group so that the steps that follow are successful”
pSubnet:
Type: “AWS::EC2::Subnet::Id”
Description: “A Subnet within the VPC provided”
Resources:
Instance:
Type: “AWS::EC2::Instance”
Properties:
ImageId: !Ref pAMI
SubnetId: !Ref pSubnet
SecurityGroupIds:
– !Ref InstanceSecurityGroup
InstanceType: t2.micro
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref pVPC
GroupDescription: Allow http to client host
SecurityGroupIngress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
이 템플릿에서는 인스턴스와 보안그룹을 생성합니다. 우리의 오래 된 친구 지미가 EC2 인스턴스를 변경하고 기본 VPC 보안 그룹을 참조하라는 지시를 받았다고 가정하겠습니다.
defaultSecGroup=`aws ec2 describe-security-groups –group-name default –query SecurityGroups[0].GroupId –output text –region eu-west-2`
stackSecGroup=`aws cloudformation describe-stack-resources –stack-name <stack-name> –logical-resource-id InstanceSecurityGroup –output text –query StackResources[0].PhysicalResourceId –region eu-west-2`
instance=`aws cloudformation describe-stack-resources –stack-name <stack-name> –logical-resource-id Instance –output text –query StackResources[0].PhysicalResourceId –region eu-west-2`
aws ec2 modify-instance-attribute –instance-id $instance –group $defaultSecGroup –region eu-west-2
aws ec2 delete-security-group –group-id $stackSecGroup –region eu-west-2
그리고 다시 한번 실패한 대기 조건으로 스택을 업데이트하여 장애를 시뮬레이션하고 rollback을 시작합니다.
AWSTemplateFormatVersion: “2010-09-09”
Description: “A template used to illustrate the use of ContinueUpdateRollback API when recovering CloudFormation stacks from Update Rollback Failed”
Parameters:
pAMI:
Type: “AWS::EC2::Image::Id”
Description: “Pick any HVM compatible AMI-ID for the AutoScaling group, the default works in eu-west-2 only”
Default: “ami-1a7f6d7e”
pVPC:
Type: “AWS::EC2::VPC::Id”
Description: “Any VPC with at least 1 available subnet”
pSubnet:
Type: “AWS::EC2::Subnet::Id”
Description: “A Subnet within the VPC provided”
Resources:
Instance:
Type: “AWS::EC2::Instance”
Properties:
ImageId: !Ref pAMI
SubnetId: !Ref pSubnet
InstanceType: t2.micro
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref pVPC
GroupDescription: Allow http to client host
SecurityGroupIngress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
WaitCondition:
Type: “AWS::CloudFormation::WaitCondition”
DependsOn: Instance
CreationPolicy:
ResourceSignal:
Count: 1
Timeout: PT1M
스택이 ‘인스턴스’리소스를 rollback할 수 없어서 다음과 같은 오류가 발생하여 UPDATE_ROLLBACK_FAILED상태입니다.
보안그룹에 ‘sg-xxxxxxx’가 존재하지 않습니다.
이번에 복구하려면 정확한 ID로 sg-xxxxxxx를 재생성할 수 없기 때문에 rollback을 계속하고 스택을 수정하며 작동 중인 동기화 상태로 되돌리려면 인스턴스를 스킵해야합니다.
첫번째 단계에서는 리소스를 건너뛰면서 ContinueUpdateRollback을 수행합니다.
aws cloudformation continue–update–rollback —resources–to–skip Instance —region eu–west–2
스택이 이제 UPDATE_ROLLBACK_COMPLETE상태가 됩니다. 그러나 스택의 상태가 더 이상 기본 리소스의 상태와 일치하지 않습니다. 이 인스턴스는 계속 실행되는 동안 우리가 스택에서 정의한 보안그룹 대신에 지미에 의해 기본 EC2 보안그룹이 할당됩니다. 이를 수정하기 위해서는 인스턴스가 다른 보안그룹 ID로 업데이트되도록 템플릿을 수정해야 합니다. 또한 이제 삭제된 이전 그룹에 대한 참조를 템플릿에서 제거하고 새 그룹으로 사용할 수도 있습니다.
AWSTemplateFormatVersion: “2010-09-09”
Description: “A template used to illustrate the use of ContinueUpdateRollback API when recovering CloudFormation stacks from Update Rollback Failed”
Parameters:
pAMI:
Type: “AWS::EC2::Image::Id”
Description: “Pick any HVM compatible AMI-ID for the AutoScaling group, the default works in eu-west-2 only”
Default: “ami-1a7f6d7e”
pVPC:
Type: “AWS::EC2::VPC::Id”
Description: “Any VPC with at least 1 available subnet”
pSubnet:
Type: “AWS::EC2::Subnet::Id”
Description: “A Subnet within the VPC provided”
Resources:
Instance:
Type: “AWS::EC2::Instance”
Properties:
ImageId: !Ref pAMI
SubnetId: !Ref pSubnet
InstanceType: t2.micro
SecurityGroupIds:
– InstanceSecurityGroup2
InstanceSecurityGroup2:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref pVPC
GroupDescription: Allow http to client host
SecurityGroupIngress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
– IpProtocol: tcp
FromPort: ’80’
ToPort: ’80’
CidrIp: 0.0.0.0/0
이제 스택이 기본 리소스와 동기화되어 있고 해당 스택을 이후 실행될 추가적인 수정을 허용하는 상태로 돌아와야 합니다.
결론
이 블로그를 통해 rollback, 안정화 및 ContinueUpdateRollback작업과 같은 다양한 Cloudformation개념에 대해 배웠습니다. 고착된 상태에서 스택을 복구하기 위해 ContinueUpdateRollback을 사용하는 두 가지 예시를 보여 주었습니다. 첫 번째 예시에서는 기본 값을 변경한 다음 API호출을 수행하였습니다. 두 번째 예시에서는 문제가 있는 리소스를 건너뛰어야 합니다(사용자 정의 값 대신 고유 ID를 사용하기 때문입니다.).
원문 URL: https://aws.amazon.com/ko/blogs/mt/recovering-aws-cloudformation-stacks-using-continueupdaterollback/
** 메가존 TechBlog는 AWS BLOG 영문 게재글중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.