Lambda(golang)에서 Fargate Spot의 종료 알림을 받는 ECS 작업을 NLB에서 중단합니다.
개시하다
나는 생산기술부에서 제품 검사 공정을 책임지는 엔지니어다.이번에는 Fargate spot에서 ECS가 중단 통지를 받았을 때 ELB에 대한 Deregister Target 수행을 장담할 수 없는 과제에 대해 노력했다.
Fargate Spot의 목적은 다음과 같이 비용을 절감할 수 있다는 것입니다.
또 팜게이트에서 시작된 ECS의 캐피티 프로바이더에 팜게이트와 팜게이트 스팟을 함께 사용함으로써 시스템의 안정성과 비용 절감을 양립하는 구조를 구현했다.
Capacity Provider 가져오기
설치 참조:
Cluster의 기본값, 서비스에서 실제로 사용되는 Capacity Provider를 설정합니다.기본은 최소 실행 작업 수를 나타냅니다. 다음 예에서 두 작업은 Fargate로 실행됩니다.Weight는 전체 작업 수행 횟수에 대한 상대적 비율을 나타내며, 크기를 조절하더라도 Fargate 및 Fargate Spot에서 작업을 1대1로 구성합니다.AWS 콘솔에서 각 임무의 설정을 확인하면 어떤 것을 사용했는지 확인할 수 있다.
이 서비스에서는 Capacity Provider Strategy와 LaunchType을 동시에 설정할 수 없습니다.
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: ecs
CapacityProviders:
- FARGATE
- FARGATE_SPOT
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Base: 2
Weight: 1
- CapacityProvider: FARGATE_SPOT
Base: 0
Weight: 1
Service:
Type: AWS::ECS::Service
Properties:
CapacityProviderStrategy:
- CapacityProvider: FARGATE
Base: 2
Weight: 1
- CapacityProvider: FARGATE_SPOT
Base: 0
Weight: 1
기본적으로 SIGTERM의 30초 후에 SIGKILL이 시작되며 StopTimeout 설정을 통해 120초로 변경할 수 있습니다. TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Name: logstash
StopTimeout: 120
Lambda로 Fargate Spot의 종료 알림 처리
설치 참조:
Event Bridge에서 종료 통지를 받고 NLB 대상에서 객체 작업을 해제합니다.
type NetworkInterface struct {
PrivateIpv4Address string `json:"privateIpv4Address"`
}
type Container struct {
NetworkInterfaces []NetworkInterface
Name string `json:"name"`
}
type EcsEvent struct {
StopCode string `json:"stopCode"`
Containers []Container
}
func HandleLambdaEvent(_ context.Context, event events.CloudWatchEvent) {
// 1. Event Bridgeからイベントを受け取る
var ecsEvent EcsEvent
if err := json.Unmarshal(event.Detail, &ecsEvent); err != nil {
os.Exit(1)
}
// 2. 終了通知かチェック
fmt.Printf("stopCode = %s\n", ecsEvent.StopCode)
if ecsEvent.StopCode != "TerminationNotice" {
return
}
// 3. 対象タスクのIP取得
var ecsIp string
for _, contaier := range ecsEvent.Containers {
if contaier.Name == "logstash" {
for _, ni := range contaier.NetworkInterfaces {
ecsIp = ni.PrivateIpv4Address
}
}
}
fmt.Printf("ip v4 = %s\n", ecsIp)
// 4. 環境変数取得
nlbId := os.Getenv("NlbId")
nlbTargetGroupId := os.Getenv("NlbTargetGroupId")
fmt.Printf("GET ENV AlbId: %s AlbTargetGroupId: %s\n", nlbId, nlbTargetGroupId)
// 5. 初期設定
svc := Init()
// 6. 指定したLoadbalancerを取得
lb := GetSpecifiedLoadbalancer(svc, nlbId)
fmt.Printf("GET LoadbalancerName: %s LoadbalancerArn: %s\n", *lb.LoadBalancerName, *lb.LoadBalancerArn)
// 7. 指定したLoadbalancerのTargetGroupを取得
tg := GetSpecifiedTargetGroup(svc, lb, nlbTargetGroupId)
fmt.Printf("GET TargetGroupName: %s TargetGroupArn: %s\n", *tg.TargetGroupName, *tg.TargetGroupArn)
// 8. TargetGroupからTargetの登録を解除
if HasTarget(svc, tg, ecsIp) {
const tcpPort = 5044
DeregisterSpecifiedTarget(svc, tg, ecsIp, tcpPort)
fmt.Println("DEREGISTER")
}
}
Cloudformation에 Lambda, Event Bridge 규칙 추가
설치 참조:
ECS 문서에 기재된 대로 규칙을 설정합니다.
EventRule:
Type: AWS::Events::Rule
Properties:
Description: detach ecs task that received terminate notification from nlb
Name: detach-task-to-be-terminated-from-nlb
EventPattern:
source:
- aws.ecs
detail-type:
- ECS Task State Change
detail:
clusterArn:
- !Ref ClusterId
State: ENABLED
Targets:
- Arn: !GetAtt Function.Arn
Id: lambda
최후
Lambda 테스트를 사용하여 대상 작업이 NLB에서 제거됨을 확인했습니다.ECS에서 실행되는 응용 프로그램의Graceful Shutdown에 대해서는 사용하는 응용 프로그램의 문서를 참조하여 처리하는 것이 좋다.이번에 사용한 Logo stash는 아래에 기재되어 있습니다.
Reference
이 문제에 관하여(Lambda(golang)에서 Fargate Spot의 종료 알림을 받는 ECS 작업을 NLB에서 중단합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/s_tomoyuki/articles/0003-aws-fargate-spot텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)