FastAPI & Nginx 특정 엔드포인트(Health Check) 로그 제거 - ALB Health Check 로그 제외시키기

# 목적

웹서버와 API 서버에 대한 대상 그룹의 헬스체크를 ALB가 수행하는데, 헬스체크 요청에 대한 로그가 계속 쌓이게 되어서 사용자의 요청 로그를 추적하기 불편한 상황이 발생했다.

 

정상적인 운영 및 디버깅을 위해서 특정 엔드포인트로의 요청에 대한 로그를 제외시켜야했음.

 

FastAPI와 Nginx에서 특정 엔드포인트에 대한 Health Check 용도의 엔드포인트에 대하여, 로그가 쌓이지 않도록 설정하는 방법을 공유한다.


# 상태 확인

웹서버와 API 서버가 배포되어있는 환경과 라우팅 조건은 아래와 같았다.

EKS 환경 위에서 웹서버, API 서버를 운영

EKS 환경을 사용했고, Ingress를 통하여 L7 LB 구성을 수행했다.

 

해당 인그레스를 통하여 /* 경로로 접속하는 HTTP 요청은 웹서버로, /api/* 로 접속하는 요청은 API 서버로 전달되도록 구성하였다.

해당 EKS에서 AWS LB Controller를 구성하여 AWS 환경에 해당 인그레스를 바탕으로 자동으로 ALB가 구성되었고, 로드밸런서의 리스너 및 대상 그룹은 아래와 같이 자동으로 구성되었다.

 

EKS 환경에서 ALB를 통한 애플리케이션 배포 방법에 대해선 아래 포스팅에서 자세하게 설명했다.

 

EKS ALB 구성 및 노출 - K8s Ingress 및 AWS LB Controller 사용

# 목적 EKS 및 데이터플레인을 구성할 때 일반적으로 Private Subnets에 속하도록 구성한다. 이럴 경우, 사설 네트워크에 존재하는 파드들을 외부로 서비스하기 위해선 별도로 공인 IP를 할당받던지, N

alive-wong.tistory.com

아무튼 Path 규칙에 대해 구성된 대상 그룹의 기본적인 상태 검사 경로는 아래와 같다.

대상 그룹 > 상태 검사

/ 경로에 헬스체크용 HTTP 요청을 보낸다는 의미인데, 이는 모든 대상 그룹에서 기본적으로 `/` 경로로 요청을 보내므로 실제 API 서버와 Web 서버의 HTTP 요청 로그를 확인하면 각각 아래와 같았다.

Nginx
FastAPI

헬스체크 요청 때문에 로그가 난장판이였다.

 

서비스를 운영하는 환경에서 이런식으로 헬스체크 로그가 계속 찍히게되면, 실제 사용자의 요청을 추적하기에 굉장한 방해가 되기 때문에 이러한 문제 상황을 해결해야했다.

 

이를 위해 수행해야할 점은 총 3가지이다.

  1. 대상 그룹의 Health Check 경로 변경
  2. Nginx의 Healt Check 엔드포인트 로그 수집 제외
  3. FastAPI의 Healt Check 엔드포인트 로그 수집 제외

# AWS Target Group 상태 검사 수정

이에 앞서, 웹서버를 위한 health check 경로는 /health, API 서버를 위한 경로는 /api/health로 설계했다.

AWS 웹콘솔에 접속하여서 EC2 > 로드 밸런싱 > 대상 그룹에 들어가서, 구성되어있는 적용할 대상 그룹을 선택하여 아래의 상태 검사를 탭을 클릭한다.

이후 우상단의 편집을 눌러서 상세 편집을 수행한다.

위의 상태 검사 경로를 사용할 헬스체크 경로로 변경한다.

 

추가로 아래의 고급 상태 검사 설정에 들어가 상태를 정상적으로 확인하는 Response 응답 코드를 지정할 수도 있다(응답 시간, Threshhold 등등 구성 가능).

헬스체크 경로에 아무런 반환을 만들지 않는다면, 404 NotFound로 지정해도 상관없다. 응답이 정상적으로 가는지만 확인하면 된다.

 

아무튼 저런 방식으로 대상 그룹의 헬스체크 경로를 원하는대로 지정하면 된다.

ALB를 수동으로 구성했다면, 대상 그룹의 해당 부분을 수동으로 지정하면 되지만, 만약 AWS LB Controller를 사용하여 대상 그룹이 자동으로 구성되었다면, 손으로 구성해봤자 얼마 지나면 풀린다.

이는 추가적인 annotation으로 ingress 혹은 service 객체에서 health-check 경로를 지정해야지 반영된다. 

해당 정보는 아래의 공식 문서에서 확인 가능하다.

 

Annotations - AWS Load Balancer Controller

Ingress annotations You can add annotations to kubernetes Ingress and Service objects to customize their behavior. Annotation keys and values can only be strings. Advanced format should be encoded as below: boolean: 'true' integer: '42' stringList: s1,s2,s

kubernetes-sigs.github.io

이를 적용한 예시는 아래와 같다.

apiVersion: v1
kind: Service
metadata:
  name: quest-api-service
  namespace: quest
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: /api/health

어노테이션 설정을 ingress에 지정해줘도 되고, 서비스 객체에 지정해도 되지만 본인의 환경에선 헬스체크 경로가 대상 그룹에 따라 달라서 서비스 객체에 지정했다.

아무튼 이를 수행하고 배포하면 대상 그룹의 설정은 정상적으로 완료된다.


# Nginx 설정

웹 서버는 빌드한 React App을 Nginx가 서빙하는 방식으로 구성했으므로, Nginx를 /health 경로의 요청에 대해 로그가 쌓이지 않도록 설정해야 했다.

nginx.conf의 해당 부분은 아래와 같다.

server {
	listen 80;
	server_name quest-nba.com;
	root /usr/share/nginx/html;
	index index.html;
  
	location / {
		try_files $uri /index.html;
	}
	location /health {
		access_log off;
		return 200 'OK';
	}
}

이렇게 구성하면 ALB가 보내는 헬스체크 요청에 대한 로그가 제외된다. (/health 경로의 모든 요청 제외)


# FastAPI 설정

API Server를 FastAPI 프레임워크를 사용했으므로, 이에 대한 구성 방법은 아래와 같다.

Python logging 구조에 대해서 자세히 인지하고 사용하는 것이 아니므로, 구성하는 방법만 확인한다.

import logging

class EndpointFilter(logging.Filter):
	def filter(self, record: logging.LogRecord) -> bool:
		return record.getMessage().find("/api/health") == -1

logging.getLogger("uvicorn.access").addFilter(EndpointFilter())

# 나머지 부분 생략

위 logging.Filter 클래스를 main.py에서 적용했다.

 

이렇게 logging.Filter 클래스를 상속받은 커스텀 필터 클래스를 작성하고 filter 메소드를 오버라이팅하여 해당 필터 클래스를 추가해주면 된다.


# 적용 확인

웹서버 - Nginx

API 서버 - FastAPI

728x90
반응형