ECS Fargate(Nginx+gRPC) 구성의 상태 확인 설정

10779 단어 gRPCFargateECSAWS
이 기사는 ZOZO Technologies #2 Advent Calendar 2019 24일째 기사가 됩니다.
어제는 @ 츠루미씨의 「 변경 데이터(CDC)를 이용한 데이터 동기화 검토 」였습니다.

또한 올해에는 총 5개의 Advent Calendar가 공개됩니다.

ZOZO 테크놀로지스 #1 Advent Calendar 2019
ZOZO 테크놀로지스 #2 Advent Calendar 2019
ZOZO 테크놀로지스 #3 Advent Calendar 2019
ZOZO 테크놀로지스 #4 Advent Calendar 2019
ZOZO 테크놀로지스 #5 Advent Calendar 2019

소개



본 기사는 @gold-kou 씨의 ECS + Fargate 환경에서 gRPC 서버의 상태 확인을 위해 다양한 노력 에서 소개되고 있는 gRPC 헬스 체크의 인프라면의 설정의 이야기가 됩니다.
전제나 이 구성에 이른 배경에 대해서는 상기의 기사에 정중하게 정리하고 있기 때문에 확인해 주시면 좋겠습니다.

구성



타이틀대로입니다만, NLB와 ECS Fargate의 구성이 되고, Fargate의 태스크에서는 Nginx와 gRPC 어플리케이션이 가동하는 구성이 되고 있습니다.



이번은 내부 통신의 요건이었기 때문에, 평문으로 통신하고 있습니다. HTTP/2로 TLS 종단하려고 하면, NLB는 ALPN에 대응하고 있지 않기 때문에 문제가 될 수 있습니다만, 이번은 평문 통신 때문에 이 문제는 회피할 수 있었습니다.

건강 검사 문제



이 구성에서 문제가 되는 것이 헬스 체크입니다.
이번은 평문의 gRPC를 채용하고 있기 때문에 타겟 그룹의 프로토콜은 TCP를 선택할 필요가 있습니다만, 이 경우, 헬스 체크로 사용할 수 있는 옵션은 TCP, HTTP, HTTPS의 3개만입니다. HTTP, HTTPS는 gRPC 메서드를 호출할 수 없으며 TCP는 포트 모니터링만 하며 응용 프로그램의 사활 모니터링을 수행할 수 없습니다.

ECS의 HEALTHCHECK 기능



위의 문제가 있기 때문에, ECS의 HEALTHCHECK 기능 을 이용해, 헬스 체크를 실시하기로 했습니다.
Nginx 컨테이너 내에 grpc-health-probe를 설치하고 ECS의 HEALTHCHECK 기능으로 Nginx 컨테이너에서 grpc-health-probe를 실행하도록 했습니다.
CFn으로 설정하는 경우는 다음과 같습니다.

  ECSTaskDefinition:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      Family: !Sub ${Prefix}-${Environment}
      RequiresCompatibilities:
        - 'FARGATE'
      Cpu: 1024
      Memory: 2048
      NetworkMode: 'awsvpc'
      ExecutionRoleArn: !GetAtt IAMRoleECSTaskExecution.Arn
      TaskRoleArn: !GetAtt IAMRoleAPI.Arn
      ContainerDefinitions:
        - Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepositoryNginx}:latest
          Name: 'nginx'
          Cpu: 256
          MemoryReservation: 512
          PortMappings:
            - ContainerPort: 10080
              HostPort: 10080
              Protocol: 'tcp'
          # ここがHealthCheckの設定。指定したbashコマンドを実行できる。
          HealthCheck:
            Command: 
              - 'CMD-SHELL'
              - 'grpc-health-probe -addr=localhost:10080 -rpc-timeout 2s'
            Interval: 5
            Retries: 2
            StartPeriod: 10
            Timeout: 3
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Sub /ecs/${ECRRepositoryNginx}
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'ecs'
              awslogs-create-group: true
        - Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepositorygRPC}:latest
          Name: 'grpc'
          Cpu: 256
          MemoryReservation: 512
          PortMappings:
            - ContainerPort: 8080
              HostPort: 8080
              Protocol: 'tcp'
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Sub /ecs/${ECRRepositorygRPC}
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: 'ecs'
              awslogs-create-group: true
          Essential: true
          Environment:
            - Name: 'AWS_DEFAULT_REGION'
              Value: !Ref AWS::Region

이 기능과 NLB의 TCP 포트 감시를 조합함으로써, 이상이 있는 태스크가 NLB로부터 적절히 분리되는 거동이 될 것을 기대했습니다.

실제 거동



실제로 검증해 보았더니, 예상대로 움직였습니다.
헬스 체크의 실패로부터 태스크의 리타이어까지의 흐름으로서는 다음과 같이 됩니다.

1. gRPC 애플리케이션이 응답 불가 상태에 빠짐





2. Nginx 컨테이너에서 실행중인 상태 확인에 실패하고 해당 작업이 Unhealthy 상태가됩니다.





3. NLB의 TCP 포트 상태 확인에 실패하고 Unhealthy 작업이 분리됨





4. 탈퇴한 작업 대신 새 작업이 시작됩니다.





사이고에게



조금 고전했지만, 결과적으로 헬스 체크를 설정할 수 있었습니다. 하나의 기능이 부족하지 않아도 다른 기능으로 보전할 수 있으며, 궁리하면 어떻게 든 점에는 AWS에 고마움을 느끼고 있습니다.
다만, AWS에서 gRPC를 사용하는 경우는, 아직 아직 기능이 갖추어지지 않았다고 느끼는 케이스가 적지 않기 때문에, 좀 더 기능이 충실해 오면 고맙다고 생각했습니다.

당기사의 내용으로서는 이상이 됩니다!

25일간의 어드벤트 캘린더도 내일로 마지막이 됩니다! !
당사에서는 어드벤트 캘린더가 제5탄까지 있으므로, 5 * 25(일간)로 총 125 기사가 됩니다.
꼭 다른 기사에도 눈을 통해 주실 수 있으면 다행입니다!

좋은 웹페이지 즐겨찾기