본문 바로가기

DevOps/Jenkins

[AWS CLI] ECS 서비스 우선순위 기반 Task 분배 자동화

스크립트 작성 배경

AWS ECS에는 Auto Scaling 기능이 있다. 

하지만 때로는 다수의 서비스가 n개의 task 수를 적절히 나눠가져야 할 때가 생긴다..,

그러나 기본 Auto Scaling으로는 안 된다. 그래서 Jenkins에서 AWS CLI로 오토스케일링을 구현했다.

 

스크립트

우리의 목표!! svc-high-priority SQS에 있는 메시지를 우선처리 해야한다!!

- total은 31개 유지하기

svc-high-priority가 svc-low-priority 보다 우선순위가 높다.

- svc-high-priority sqs 잔여 메시지가 1000개 이상일 때 max capacity를 30으로 조정하고, desired count를 30으로 조정

- svc-high-priority sqs 잔여 메시지가 3000개 이하일 때 svc-low-priority의 max capacity를 30으로 조정하고, desired count를 30으로 조정 (잔여 처리 메시지가 얼마 안 남았을 때 low 서비스 미리 scale out하여 전환 시점의 처리 지연도 없애기)

- svc-high-priority sqs 잔여 메시지가 없다면 1로 scale in 된다

위와 같은 방식으로 우선순위에 맞게 task를 몰아주는 스크립트이다.

#!/bin/bash

# ================================
# 공통 환경 설정
# ================================
export AWS_ACCOUNT=123456789012
export AWS_DEFAULT_REGION=ap-northeast-2

CLUSTER_NAME="sample-cluster"
LOW_SERVICE_NAME="low-service"
HIGH_SERVICE_NAME="high-service"

TOTAL_DESIRED_COUNT=31
DOWN_TRIGGER_COUNT=3000
UP_TRIGGER_COUNT=1000

HIGH_SQS_URL="https://sqs.ap-northeast-2.amazonaws.com/$AWS_ACCOUNT/$HIGH_SERVICE_NAME"

# ================================
# Step 1. LOW 서비스 Scale-Out (HIGH 서비스 메시지가 적을 때)
# ================================
echo "=== Step 1: LOW 서비스 스케일 조정 ==="

HIGH_SQS_VISIBLE=$(aws sqs get-queue-attributes \
    --queue-url $HIGH_SQS_URL \
    --attribute-names ApproximateNumberOfMessages \
    --query "Attributes.ApproximateNumberOfMessages" \
    --output text)

echo "HIGH 서비스 SQS 대기 메시지 수: $HIGH_SQS_VISIBLE"

if [ "$HIGH_SQS_VISIBLE" -le "$DOWN_TRIGGER_COUNT" ]; then
    echo "$DOWN_TRIGGER_COUNT 이하일 경우 LOW 서비스 확장 시작"

    LOW_MAX_CAPACITY=$((TOTAL_DESIRED_COUNT - 1))

    SETTED_LOW_MAX_CAPACITY=$(aws application-autoscaling describe-scalable-targets \
        --service-namespace ecs \
        --resource-id service/$CLUSTER_NAME/$LOW_SERVICE_NAME \
        --scalable-dimension ecs:service:DesiredCount \
        --query "ScalableTargets[0].MaxCapacity" \
        --output text)

    if [ "$SETTED_LOW_MAX_CAPACITY" -eq "$LOW_MAX_CAPACITY" ]; then
        echo "LOW 서비스는 이미 확장 설정 완료 ($SETTED_LOW_MAX_CAPACITY)"
    else
        aws application-autoscaling register-scalable-target \
            --service-namespace ecs \
            --resource-id service/$CLUSTER_NAME/$LOW_SERVICE_NAME \
            --scalable-dimension ecs:service:DesiredCount \
            --min-capacity 1 \
            --max-capacity $LOW_MAX_CAPACITY

        echo "LOW 서비스 확장 적용 대기 중..."
        for i in {1..10}; do
            CURRENT_MAX=$(aws application-autoscaling describe-scalable-targets \
                --service-namespace ecs \
                --resource-id service/$CLUSTER_NAME/$LOW_SERVICE_NAME \
                --scalable-dimension ecs:service:DesiredCount \
                --query "ScalableTargets[0].MaxCapacity" \
                --output text)

            if [ "$CURRENT_MAX" -eq "$LOW_MAX_CAPACITY" ]; then
                echo "LOW 서비스 확장 적용 완료"
                break
            fi
            sleep 2
        done

        aws ecs update-service \
            --cluster $CLUSTER_NAME \
            --service $LOW_SERVICE_NAME \
            --desired-count $LOW_MAX_CAPACITY
    fi
else
    echo "LOW 서비스 확장 조건 미충족 (PASS)"
fi

# ================================
# Step 2. HIGH 서비스 Scale-Out (메시지 수 1000 초과 시)
# ================================
echo "=== Step 2: HIGH 서비스 스케일 조정 ==="

HIGH_SQS_VISIBLE=$(aws sqs get-queue-attributes \
    --queue-url $HIGH_SQS_URL \
    --attribute-names ApproximateNumberOfMessages \
    --query "Attributes.ApproximateNumberOfMessages" \
    --output text 2>/dev/null)
HIGH_SQS_VISIBLE=${HIGH_SQS_VISIBLE:-0}

echo "HIGH 서비스 SQS 대기 메시지 수: $HIGH_SQS_VISIBLE"

if [ "$HIGH_SQS_VISIBLE" -gt "$UP_TRIGGER_COUNT" ]; then
    HIGH_DESIRED_COUNT=$((TOTAL_DESIRED_COUNT - 1))
    echo "$UP_TRIGGER_COUNT 초과 - HIGH 서비스 desired count를 $HIGH_DESIRED_COUNT로 설정"

    CURRENT_HIGH_DESIRED=$(aws ecs describe-services \
        --cluster $CLUSTER_NAME \
        --service $HIGH_SERVICE_NAME \
        --query "services[0].desiredCount" \
        --output text 2>/dev/null)
    CURRENT_HIGH_DESIRED=${CURRENT_HIGH_DESIRED:-0}

    echo "현재 HIGH 서비스 desired count: $CURRENT_HIGH_DESIRED"

    if [ "$CURRENT_HIGH_DESIRED" -ne "$HIGH_DESIRED_COUNT" ]; then
        echo "HIGH 서비스 desired count 변경 ($CURRENT_HIGH_DESIRED -> $HIGH_DESIRED_COUNT)"

        aws application-autoscaling register-scalable-target \
            --service-namespace ecs \
            --resource-id service/$CLUSTER_NAME/$HIGH_SERVICE_NAME \
            --scalable-dimension ecs:service:DesiredCount \
            --min-capacity 1 \
            --max-capacity $HIGH_DESIRED_COUNT

        echo "HIGH 서비스 확장 적용 대기 중..."
        for i in {1..10}; do
            CURRENT_MAX=$(aws application-autoscaling describe-scalable-targets \
                --service-namespace ecs \
                --resource-id service/$CLUSTER_NAME/$HIGH_SERVICE_NAME \
                --scalable-dimension ecs:service:DesiredCount \
                --query "ScalableTargets[0].MaxCapacity" \
                --output text)

            if [ "$CURRENT_MAX" -eq "$HIGH_DESIRED_COUNT" ]; then
                echo "HIGH 서비스 확장 적용 완료"
                break
            fi
            sleep 2
        done

        aws ecs update-service \
            --cluster $CLUSTER_NAME \
            --service $HIGH_SERVICE_NAME \
            --desired-count $HIGH_DESIRED_COUNT

        # LOW 서비스는 max-capacity를 1로 줄임
        aws application-autoscaling register-scalable-target \
            --service-namespace ecs \
            --resource-id service/$CLUSTER_NAME/$LOW_SERVICE_NAME \
            --scalable-dimension ecs:service:DesiredCount \
            --min-capacity 1 \
            --max-capacity 1
    else
        echo "HIGH 서비스 desired count는 이미 일치"
    fi
else
    echo "HIGH 서비스 확장 조건 미충족 (PASS)"
fi

 

 

max capacity 수정 후 sleep 로직에 대한 내용은 아래 포스팅으로 이어집니다.

https://juyeonee826.tistory.com/205

 

[AWS CLI] ECS Task Scale out 빠르게 하기

https://juyeonee826.tistory.com/199 [AWS CLI] ECS 서비스 우선순위 기반 Task 분배 자동화스크립트 작성 배경AWS ECS에는 Auto Scaling 기능이 있다. 하지만 때로는 다수의 서비스가 n개의 task 수를 적절히 나눠가

juyeonee826.tistory.com