AWS 기술 블로그

Amazon ECS 워크로드를 위한 AWS Fault Injection Simulator의 새로운 기능 발표

본 게시물은 AWS Container Blog에 게시된 “Announcing AWS Fault Injection Simulator new features for Amazon ECS workloads” by Jooyoung Kim, Re Alvarez-Pamar을 한국어 번역 및 편집하였습니다.

소개

Amazon Elastic Container Service (Amazon ECS)Amazon Elastic Kubernetes Service (Amazon EKS)에서 실행되는 워크로드에 다양한 오류를 주입할 수 있는 AWS Fault Injection Simulator (FIS)의 새로운 기능을 발표하게 되어 기쁩니다. 이 블로그는 Amazon ECS에서 새로운 AWS FIS 액션을 사용하는 방법을 보여줍니다.

AWS FIS는 오류에 대한 복원력을 위해 애플리케이션을 테스트하는 데 도움이 되는 완전관리형 서비스입니다. AWS FIS는 카오스 엔지니어링 원칙을 따르므로 AWS 환경에서 오류를 시뮬레이션할 수 있습니다. 네트워크 중단, 인프라 오류 및 서비스 중단이 될 수 있습니다. AWS FIS 실험은 잠재적인 문제가 프로덕션 중단을 유발하기 전에 식별하고 해결하는 데 도움이 됩니다.

새로운 Amazon ECS 태스크 액션

AWS FIS는 Amazon ECS 워크로드를 대상으로 하는 6가지 새로운 장애 주입 액션을 추가했습니다. 새로운 Amazon ECS 태스크에는  ECS 태스크의 CPU(중앙 처리 장치stress, I/O stress, 프로세스 종료, 네트워크 블랙홀, 지연 시간, 패킷 손실과 같은 네트워크 작업이 포함됩니다. 이러한 조치를 통해 다양한 장애 시나리오에서 애플리케이션의 안정성과 복원력을 쉽게 평가할 수 있습니다. AWS Fargate를 사용하는 경우 CPU 및 I/O 작업을 수행할 수 있습니다.

Action Identifier Description Applicable Compute Engine
aws:ecs:task-cpu-stress Simulates CPU stress
Configurable parameters are the duration of the CPU stress test, the target CPU load percentage, and the number of CPU stressors
Amazon EC2 and AWS Fargate
aws:ecs:task-io-stress Simulates I/O stress
Configurable parameters are the duration of the I/O stress test, the percentage of free space on the file system to use during the test and the number of mixed I/O stressors to use
Amazon EC2 and AWS Fargate
aws:ecs:task-kill-process Simulates killing certain process
Configurable parameters are the name of the process to stop, the signal to send along with the command
Amazon EC2 only
aws:ecs:task-network-blackhole-port Simulates a discarding network traffic
Configurable parameters are the duration of the network blackhole, the port number and the protocol
Amazon EC2 only
aws:ecs:task-network-latency Simulates a network latency
Configurable parameters are the duration of the network latency, the network interface, the delay/ms, the jitter/ms, and the sources
Amazon EC2 only
aws:ecs:task-network-packet-loss Simulates a network packet loss
Configurable parameters are the duration of the network packet loss, the network interface, the percentage of packet loss and the sources
Amazon EC2 only

Amazon ECS 태스크 액션 내부 동작 원리

다음 다이어그램은 AWS FIS가 Amazon ECS 태스크에 결함을 주입하는 방법을 보여줍니다. AWS FIS는 AWS System Manager  SSM Agent를 사용하여 Amazon ECS 태스크에서 AWS FIS 액션을 실행합니다. SSM Agent 사이드카를 사용하면 AWS FIS에서 결함을 주입하는 데 필요한 Amazon ECS 태스크와 연결된 관리형 인스턴스를 생성할 수 있습니다. 이를 통해 고객은 System Manager Run Command로 문제를 해결하고 인사이트를 얻을 수 있습니다. 워크로드에서 AWS FIS 실험을 수행하려면 작업 정의에 SSM Agent 사이드카 컨테이너를 추가합니다.

실습

다음 섹션에서는 AWS FIS 실험 단계를 안내합니다.

  1. 인프라 설정 및 샘플 앱 배포
  2. Amazon ECS 작업 정의 압출 풀기
  3. 실험을 실행할 수 있는 AWS FIS 권한 부여
  4. CPU Stress를 증가시키는 실험 생성
  5. Amazon ECS Task에서 프로세스를 종료하는 실험 생성

전제 조건

이 연습에는 다음이 필요합니다.

  1. AWS CLI version 2
  2. AWS CDK Toolkit
  3. Working with the AWS CDK in Python
  4. Node.js ≥ 14.15.0
  5. Python ≥ 3.6+

1단계: 기본 인프라 배포

AWS CDK를 사용하여 기본 인프라를 생성할 것이며, 여기에는 Amazon VPC(Amazon Virtual Private Cloud), Amazon ECS 클러스터, AWS IAM(AWS Identity and Access Management) 역할, 두 개의 Amazon EC2 인스턴스, 그리고 AWS FIS 실험을 위한 Amazon ECS 서비스가 포함됩니다. 코드는 ecs-blueprints github 저장소를 사용할 수 있습니다.

샘플 코드 저장소를 복제합니다.

git clone https://github.com/aws-ia/ecs-blueprints.git
cd ecs-blueprints/cdk/examples/fis_service/

환경과 일치하도록 AWS 계정 및 AWS 리전 환경 변수를 설정합니다. 그런 다음 ECS Blueprint CDK 템플릿에서 사용할 .env 파일을 생성합니다. 예를 들어 이 게시물에서는  오레곤 리전(us-west-2)을 사용합니다.

export AWS_ACCOUNT=$(aws sts get-caller-identity --query 'Account' --output text)
export AWS_REGION=${AWS_REGION:=us-west-2}

sed -e "s/<ACCOUNT_NUMBER>/$AWS_ACCOUNT/g" \
-e "s/<REGION>/$AWS_REGION/g" sample.env > .env

다음 단계가 필요합니다.

# manually create a virtualenv: 
python3 -m venv .venv

# activate your virtualenv:
source .venv/bin/activate

# install the required dependencies: 
python -m pip install -r ../../requirements.txt

CDK를 사용하여 인프라를 만드는 것이 처음인 경우 Bootstrap CDK를 실행합니다.

cdk bootstrap aws://${AWS_ACCOUNT}/${AWS_REGION}

CDK를 사용하여 Amazon ECS 클러스터를 생성하고 그 안에서 AWS FIS 작업에 대한 샘플 애플리케이션을 실행합니다. 프로덕션이 아닌 계정에 이 스택을 배포하는 것이 좋습니다.

아래 명령을 사용하여 CDK 스택을 배포합니다.

cdk deploy --all --require-approval never

2단계: 생성된 Amazon ECS 작업 정의 검사

CDK 코드는 Amazon ECS 클러스터, 작업 정의, 2개의 m5.large Amazon EC2 인스턴스 및 로드 밸런서에 연결된 서비스를 생성합니다. 이 작업은 웹 애플리케이션 컨테이너와 사이드카 컨테이너로 실행되는 SSM Agent로 구성됩니다. 사이드카는 작업 정의에서 필수적으로 구성됩니다. 따라서 사이드카가 중지되면 Amazon ECS는 작업을 종료하고 대체 작업을 시작합니다. 사이드카는 활성화 스크립트를 실행하여 Amazon ECS 작업을 AWS Systems Manager에 관리형 인스턴스로 등록합니다.

사이드카는 MANAGED_INSTANCE_ROLE_NAME AWS IAM 역할을 맡아 Amazon ECS 태스크를 AWS Systems Manager에서 관리형 인스턴스로 등록합니다. AWS FIS는 AWS Systems Manager를 사용하여 Amazon ECS 태스크에 결함을 삽입합니다. 이 역할에는 AmazonSSMManagedInstanceCore 정책과 다음 권한이 연결되어 있습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "ssm:DeleteActivation",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "ssm:DeregisterManagedInstance",
            "Resource": "arn:aws:ssm:${AWS_REGION}:${AWS_ACCOUNT}:managed-instance/*",
            "Effect": "Allow"
        }
    ]
}

Amazon ECS 태스크 IAM 역할에는 다음 권한이 있습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::${AWS_ACCOUNT}:role/{MANAGED_INSTANCE_ROLE_NAME}",
            "Effect": "Allow"
        },
        {
            "Action": [
                "ssm:CreateActivation",
                "ssm:AddTagsToResource"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

3단계: 계정에서 실험을 실행할 수 있는 AWS FIS 권한 부여

AWS FIS 서비스는 AWS IAM 역할을 사용하여 고객 계정에서 실험을 수행합니다. AWS FIS의 IAM 역할에 대한 신뢰 정책을 생성합니다.

cat > fis-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                  "fis.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

AWS FIS에 대한 AWS IAM 역할을 생성합니다.

aws iam create-role --role-name ecs-fis-role \
 --assume-role-policy-document file://fis-trust-policy.json

이 실험에서 Amazon ECS 태스크에 오류를 삽입하는 데 필요한 AWS IAM 권한을 추가합니다.

cat > fis-ecs-experiment-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:SendCommand",
                "ssm:ListCommands",
                "ssm:CancelCommand"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
EOF

이 실험에서 Amazon ECS 태스크에 오류를 삽입하는 데 필요한 AWS IAM 권한을 추가합니다.

aws iam put-role-policy --role-name ecs-fis-role \
  --policy-name ecs-fis-policy \
  --policy-document file://fis-ecs-experiment-policy.json

AWS FIS는 실험을 안전하게 실행할 수 있도록 컨트롤과 가드레일을 제공합니다. 경보가 트리거되면 실험을 중지하는 Amazon CloudWatch 경보를 기반으로 중지 조건을 구현할 수 있습니다.

실행 중인 태스크 수를 추적하기 위해 중지 조건을 설정합니다. 샘플 서비스는 기본적으로 세 가지 태스크를 실행합니다. 실험에서 태스크가 충돌하고 태스크 복제본 수가 3개 미만으로 떨어지면 AWS FIS는 추가 서비스 중단을 방지하기 위해 즉시 실험을 종료합니다.

Amazon CloudWatch 경보 생성:

aws cloudwatch put-metric-alarm \
  --alarm-name 'ECS Sample service task count alarm' \
  --actions-enabled \
  --metric-name 'RunningTaskCount' \
  --namespace 'ECS/ContainerInsights' \
  --statistic 'Average' \
  --dimensions '[{"Name":"ServiceName","Value":"fis-service"},{"Name":"ClusterName","Value":"ecs-blueprint-infra"}]' \
  --period 300 \
  --evaluation-periods 1 \
  --datapoints-to-alarm 1 \
  --threshold 3 \
  --comparison-operator 'LessThanThreshold' \
  --treat-missing-data 'missing' \
  --region $AWS_REGION

4단계: 태스크 CPU에 stress를 주는 실험 만들기

CPU Stress 테스트는 CPU 사용량이 많은 애플리케이션의 성능을 분석합니다. 애플리케이션에 CPU 리소스가 부족하면 응답 시간이 늘어납니다. Stress 테스트 CPU는 기본 시스템이 과부하 상태일 때 워크로드의 견고성과 고객 영향을 결정하는 데 도움이 될 수 있습니다. CPU stress 동안 애플리케이션의 동작을 관찰하면 중단 또는 데이터 무결성 문제를 일으킬 수 있는 시스템의 약점을 발견할 수 있습니다.

예를 들어 애플리케이션이 원격 프로시저를 호출하는 경우 CPU stress 이벤트가 발생하는 동안 작업(operation)을 완료하는 데 시간이 더 오래 걸릴 수 있습니다. 결과적으로 제한 시간을 조정하거나 재시도를 구현해야 할 수 있습니다. 애플리케이션이 클라이언트 요청에 응답하는 데 시간이 오래 걸리는 경우 서비스에서 애플리케이션을 확장하여 과도한 시스템 부하를 완화할 수 있습니다.

Amazon ECS 서비스를 지원하는 세 가지 태스크 중 66%(2/3)에서 CPU에 stress를 주는 AWS FIS 실험 템플릿을 생성해 보겠습니다. ARN(Amazon Resource Names), 태그, 필터 및 파라미터를 사용하여 태스크를 대상으로 지정할 수 있습니다.

66%를 선택한 이유는 다음과 같습니다. 이 클러스터는 2개의 Amazon EC2 인스턴스에서 3개의 태스크를 실행합니다. 한 노드의 높은 CPU 사용률은 한 번에 두 태스크에 영향을 미칠 수 있습니다. 클러스터 설정에 따라 중단 비율을 선택하는 것이 좋습니다.

실험 템플릿 만들기:

cat > fis-ecs-experiment-template-cpu-stress.json << EOF
{
  "description": "ecs-task-cpu-stress",
  "targets": {
    "Tasks-Target-1": {
      "resourceType": "aws:ecs:task",
      "parameters": {
        "cluster": "ecs-blueprint-infra",
        "service": "fis-service"
      },
      "selectionMode": "PERCENT(66)"
    }
  },
  "actions": {
    "ecs-task-cpu": {
      "actionId": "aws:ecs:task-cpu-stress",
      "parameters": {
        "duration": "PT5M"
      },
      "targets": {
        "Tasks": "Tasks-Target-1"
      }
    }
  },
  "stopConditions": [
      {
         "source": "aws:cloudwatch:alarm",
         "value": "arn:aws:cloudwatch:${AWS_REGION}:${AWS_ACCOUNT}:alarm:ECS Sample service task count alarm"
       }
  ],
  "roleArn": "arn:aws:iam::${AWS_ACCOUNT}:role/ecs-fis-role",
  "tags": {}
}
EOF

FIS_EXPERIMENT_TEMPLATE_ID=$(aws fis create-experiment-template \
  --region $AWS_REGION \
  --tags Name=ecs-cpu-stress \
  --cli-input-json file://fis-ecs-experiment-template-cpu-stress.json \
  --query 'experimentTemplate.id' \
  --output text)

이 실험은 이전 단계에서 배포된 샘플 서비스에 연결된 모든 태스크를 대상으로 합니다. 실험은 5분간 진행됩니다.

실험 시작:

aws fis start-experiment \
  --experiment-template-id $FIS_EXPERIMENT_TEMPLATE_ID \
  --region $AWS_REGION

Amazon ECS 콘솔로 이동하여 클러스터를 선택하고 ecs-blueprint-infra 클러스터를 선택한 다음 서비스 탭에서 fis-service를 선택하고 ECS 서비스의 상태 및 지표 탭으로 이동합니다.

약 5~10분 내에 CPU 사용률이 증가하는 것을 관찰할 수 있습니다. 그래프에서 업데이트를 보려면 최대 5분을 기다려야 할 수 있습니다.

실험 중에 P95응답 시간이 약 200ms에서 430ms로 증가했습니다. 이러한 이벤트를 처리하기 위해 Amazon EC2 인스턴스의 크기를 늘리거나 작업 집합의 CPU 리소스가 부족한 상태에서 트래픽을 처리할 작업을 더 추가할 수 있습니다.

실험이 완료될 때까지 기다리거나(실험은 5분 동안 실행됨) 다음 단계로 진행하기 전에 실험을 종료하십시오.

5단계: AWS FIS를 사용하여 Amazon ECS 태스크에서 프로세스 종료

다음 실험에서는 AWS FIS를 사용하여 태스크의 프로세스를 종료합니다. 우리가 배포한 샘플 워크로드는 Flask에서 사용하는 웹 애플리케이션을 실행합니다. 웹 애플리케이션 컨테이너는 태스크의 필수 컨테이너입니다. Python 프로세스가 종료되면 Amazon ECS는 태스크를 중지하고 새 태스크를 생성합니다. AWS FIS를 사용하여 웹 애플리케이션 컨테이너에서 Python 프로세스를 종료하여 Amazon ECS가 새 태스크를 생성하도록 합니다.

프로세스를 종료하면 예기치 않게 종료되는 프로세스의 비즈니스 영향을 확인하는 데 도움이 됩니다. 프로세스가 워크로드에 필수적인 경우 Amazon ECS가 실패한 태스크를 대체할 새 태스크를 생성하는 동안 다운스트림 영향도 관찰할 수 있습니다. 복구 시간이 길어지고 비즈니스 중단이 발생하는 경우 예기치 않은 오류를 고려하여 복제본 수를 늘릴 수 있습니다. 프로세스가 필수가 아닌 경우 중단을 최소화하기 위해 워크로드에서 단계적 종료 절차를 구현할 수 있습니다.

샘플 서비스는 세 가지 태스크를 실행합니다. 3개 태스크 중 1개에서 필수 프로세스를 종료합니다. 애플리케이션이 33% 용량으로 작동하고 있으므로 다운스트림 영향은 응답 대기 시간 및 시간 초과 증가로 예상됩니다. (Application Load Balancer의 5xx 오류).

새 실험 템플릿 만들기:

cat > fis-ecs-experiment-template-kill-proc.json << EOF
{
  "description": "ecs-task-kill-process",
  "targets": {
    "Tasks-Target-1": {
      "resourceType": "aws:ecs:task",
      "parameters": {
        "cluster": "ecs-blueprint-infra",
        "service": "fis-service"
      },
      "selectionMode": "COUNT(1)"
    }
  },
  "actions": {
    "ecs-task-kill-proc": {
      "actionId": "aws:ecs:task-kill-process",
      "parameters": {
        "processName": "python"
      },
      "targets": {
        "Tasks": "Tasks-Target-1"
      }
    }
  },
  "stopConditions": [
    {
      "source": "none"
    }
  ],
  "roleArn": "arn:aws:iam::${AWS_ACCOUNT}:role/ecs-fis-role",
  "tags": {}
}
EOF

FIS_EXPERIMENT_ID=$(aws fis create-experiment-template \
  --region $AWS_REGION \
  --tags Name=ECS-kill-process \
  --cli-input-json file://fis-ecs-experiment-template-kill-proc.json \
  --query 'experimentTemplate.id' \
  --output text)

다시 Amazon ECS 콘솔로 이동하여 fis-service라는 Amazon ECS 서비스를 선택하고 태스크 탭으로 이동합니다. 아래와 같이 태스크 목록 필터링 조건을 실행 중인 태스크에서 모든 태스크로 변경합니다. 이 탭을 열어 두십시오. 실험을 시작하면 태스크 중 하나가 실패합니다.

이제 실험을 시작합니다.

aws fis start-experiment \
  --experiment-template-id $FIS_EXPERIMENT_ID \
  --region $AWS_REGION

몇 초 후 Amazon ECS는 AWS FIS가 필수 컨테이너에서 Python 프로세스를 종료하므로 태스크를 중지합니다. AWS FIS 서비스와 연결된 중지된 태스크를 선택합니다. Amazon ECS 콘솔에 아래와 같은 오류 메시지가 표시됩니다.

실험의 영향을 시각화하기 위해 Locust를 사용하여 트래픽을 웹 애플리케이션으로 전송했습니다. 보시다시피 AWS FIS가 필수 프로세스를 종료했을 때 사이트에 액세스하는 동안 사용자가 오류를 경험했을 것입니다. 동시에 요청을 처리할 태스크가 충분하지 않았기 때문에 P95 대기 시간이 급증했습니다.

ALB 지표는 Amazon ECS가 종료된 태스크를 대체하는 동안 5xx 오류의 증가를 보여줍니다.

aws:ecs:task-kill-process 액션을 수행하려면 Amazon ECS 작업 정의에서 PID(Process ID) 모드로 태스크를 설정해야 합니다. Amazon ECS는 기본적으로 프라이빗 네임스페이스에서 컨테이너를 실행합니다. PID 모드로 태스크를 설정하면 태스크 내의 모든 컨테이너가 프로세스 네임스페이스를 공유합니다. 동일한 프로세스 네임스페이스에 있으면 사이드카 컨테이너가 태스크에서 실행 중인 다른 프로세스를 종료할 수 있습니다.

리소스 정리하기

export AWS_PAGER=""
# Get experiment ids
fis_expmt1=$(aws fis list-experiment-templates --query 'experimentTemplates[?description == `ecs-task-kill-process`].id' --output text)
fis_expmt2=$(aws fis list-experiment-templates --query 'experimentTemplates[?description == `ecs-task-cpu-stress`].id' --output text)

# Delete the alarm 
aws cloudwatch delete-alarms --alarm-names 'ECS Sample service task count alarm' --region $AWS_REGION

# Delete experiments
aws fis delete-experiment-template --id $fis_expmt1
aws fis delete-experiment-template --id $fis_expmt2

# Delete ecs-fis IAM role
aws iam delete-role-policy --role-name ecs-fis-role --policy-name ecs-fis-policy
aws iam delete-role --role-name ecs-fis-role

# Destroy CDK stack
cdk destroy --force –all

요금

AWS FIS에서는 사용한 만큼만 비용을 지불합니다. 선불 비용이나 최소 수수료가 없습니다. 액션이 활성화된 기간에 따라 요금이 부과됩니다. 자세한 내용은 AWS Fault Injection Simulator 요금 페이지를 참조하십시오.

aws:ecs:task-kill-process 액션은 기간이 없기 때문에 무료입니다.

기본적으로 AWS FIS 서비스에는 필요한 것보다 더 많은 리소스를 실수로 프로비저닝하는 것을 방지하기 위해 태스크 당 액션 수에 대한 할당량이 있습니다. AWS 콘솔을 통해 이 할당량을 늘리도록 요청할 수 있습니다.

결론

이 게시물에서는 Amazon ECS 고객이 카오스 엔지니어링을 쉽게 수행할 수 있도록 하는 새로운 AWS FIS 액션을 보여 주었습니다. Amazon ECS 태스크에서 CPU stress를 높이는 방법과 프로세스를 종료하는 방법을 보여 주었습니다. AWS FIS는 실험을 완전히 제어할 수 있도록 하여 결함 주입을 단순화합니다. AWS FIS는 특정 조건이 충족되면 실험을 자동으로 롤백하거나 중지하는 등 프로덕션 환경에서 실험을 실행하는 데 필요한 컨트롤과 가드레일을 제공합니다. 새로운 AWS FIS 액션은 다른 방법으로는 찾기 어려울 수 있는 Amazon ECS 클러스터의 애플리케이션 문제를 발견하는 데 필요한 실제 조건을 만드는 데 도움이 됩니다.

Amazon ECS 액션은 이제 AWS GovCloud(US) 리전을 포함하여 AWS FIS를 사용할 수 있는 모든 AWS 리전에서 사용할 수 있습니다.

Seongjin Ahn

Seongjin Ahn

안성진 Solutions Architect는 다양한 고객 인프라 운영 경험을 바탕으로 AWS 서비스의 효율적인 사용을 위해 Startup 고객에게 기술을 지원하는 역할을 합니다.