jam2in / arcus-test-container

Apache License 2.0
0 stars 1 forks source link

isHealthy()가 제대로 동작하지 않음 #2

Closed brido4125 closed 3 months ago

brido4125 commented 3 months ago

⛔ What happened?

ArcusContainer 인스턴스를 생성 후, isHealthy()를 호출하면 아래와 같은 예외가 발생한다.

java.lang.RuntimeException: This container's image does not have a healthcheck declared, so health cannot be determined. Either amend the image or use another approach to determine whether containers are healthy.

    at org.testcontainers.containers.ContainerState.isHealthy(ContainerState.java:111)
    at com.jam2in.arcus.testcontainers.ArcusContainerTest.createArcusContainerSingle(ArcusContainerTest.java:42)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at java.util.ArrayList.forEach(ArrayList.java:1259)

💡 Expected Behavior / Solution

찾아보니 컨테이너를 생성하는 도커 이미지가 내부적으로 Healthtch Check 명령어가 적용되어있어야 한다고 한다. 도커 파일에 아래의 명령어를 추가하면 된다고 한다.

HEALTHCHECK [OPTIONS] CMD <command>

https://lumigo.io/container-monitoring/docker-health-check-a-practical-guide/ https://docs.docker.com/reference/dockerfile/#healthcheck

캐시 서버에 존재하는 명령어 중, 헬스 체크를 위한 명령어가 있는지 확인하고 도커 파일에 이를 적용시켜야한다. 예를 들어 redis의 ping과 같은 연산을 고려하면 된다.

brido4125 commented 3 months ago

@namsic @ing-eoking

현재 arcus-memcached 도커 이미지를 만드는 파일은 아래와 같은 것으로 보입니다. 아래 파일에 HEALTHCHECK와 관련된 명령어는 없는 것 같습니다. https://github.com/naver/arcus-memcached/blob/develop/Dockerfile

위 기능을 추가하려고 하는데 위와 같은 요구사항을 만족할만한 캐시 서버 명령어가 존재할까요?

brido4125 commented 3 months ago

@namsic

@ing-eoking 님과 얘기해보니 ready 명령어를 사용하면 될 것 같네요. 다만, 궁금한 점 코멘트로 몇개 남겨봅니다.

  1. ready 명령어의 경우 해당 캐시 서버 프로세스가 정상적으로 동작하는 동안 계속해서 READY라는 응답을 주는 명령어가 맞을까요?

  2. memached Dockerfile을 빌드하는 별도의 명령어가 있으면 공유해주실 수 있을까요? build 명령어의 다양한 옵션이 존재하기 때문입니다.

namsic commented 3 months ago

ready 명령어의 경우 해당 캐시 서버 프로세스가 정상적으로 동작하는 동안 계속해서 READY라는 응답을 주는 명령어가 맞을까요?

  • ready 참고 바랍니다.
  • 다만 ready 명령은 operator에서 사용할 목적으로 추가했다가 더 이상 사용되지 않을 것으로 판단하여 내부 명령으로만 남겨둔 상태인데, 나중에 ready 명령을 제거하기로 결정하면 healthcheck 명령도 함께 변경해야 할 수 있습니다.
  • 그 외에 운영자는 서버 상태 확인 목적으로 version, stats, set 등의 명령을 수행할 수 있습니다.

memached Dockerfile을 빌드하는 별도의 명령어가 있으면 공유해주실 수 있을까요? build 명령어의 다양한 옵션이 존재하기 때문입니다.

jhpark816 commented 3 months ago

이 용도로 version 명령이 적합해 보입니다

brido4125 commented 3 months ago

@jhpark816

version 명령어를 사용할 경우 아래와 같은 의문이 듭니다.

version의 경우, 서버 엔진이 정상적인 상태인지 보장할 수 있는 명령어 인가요? 듣기로는 version이란 명령어가 일종의 자료구조로부터 version 정보만 get 해서 응답해주는것으로 이해하고 있습니다.

jhpark816 commented 3 months ago

@brido4125 작업 스레드가 정상 동작 중임을 알 수 있습니다. 이는 아래를 의미합니다.

데이터 타입 별 연산을 처리할 수 있는 지를 확인할 필요는 없습니다. 참고로, ping 이라고 하는 것도 version 정도의 요청을 처리하는 것입니다.

brido4125 commented 3 months ago

@namsic

아래와 같이 명령어 추가하고 build 한 후, 컨테이너 실행 시켜 보면 (-p 11211:11211) 정상적으로 healty가 작동합니다.

# ...
# for arcus-test-container
HEALTHCHECK CMD [echo "version" | nc 127.0.0.1 11211]
# ...

image

문제가 되는 부분은 docker run 또는 Docker-compose를 통해 컨테이너를 실행 시킬 때, 건네지는 -p 옵션의 포트 정보를 Dockerfile 단에서 알아야 합니다.

여쭤볼 사항은 두가지입니다.

  1. 위와 같이 nc를 사용하는 방법말고 다른 방법으로 version을 실행시키고 응답을 받는 법
  2. 만약 nc를 사용한다면 해당 포트 번호를 가져올 수 있는 방법

위 질문들에 대해 제가 알아본 부분은 아래와 같습니다. 1번은 expect라는 도구를 통해 telnet의 대화형 인터페이스를 자동화하는 방안을 사용하는 경우가 있습니다. 이는 expect를 도커 컨테이너 내부에 설치해야해서 우선 보류했습니다. (의존성을 함부로 설치하면 안될 것 같아서)

2번의 경우 저는 ps -ef | grep memcached | grep -v grep | awk '{print $2}'로 PID를 추출하고 netstat으로 포트를 가져오려 했는데 도커 컨테이너 내부 환경에서 netstat이 설치되지 않아서 마찬가지로 우선 중단시켰습니다.

의견 부탁드립니다.

namsic commented 3 months ago

redis 및 다른 서비스들도 같은 문제가 있을 것 같은데, netstat이나 expect를 사용하나요?

brido4125 commented 3 months ago

@namsic

우선 officail-image가 붙은 도커 이미지에서는 health-check를 다음과 같은 이유로 사용하지 않습니다. https://github.com/docker-library/faq?tab=readme-ov-file#healthcheck

redis test container는 사용해보니 본 이슈와 같은 예외를 발생시켜줍니다.

저희가 취할 수 있는 방안은 두가지인것 같습니다.

  1. 도커 허브에 test-container용 이미지를 별도로 관리
  2. isHealthy 호출 시 예외발생

다만 1번을 선택한다고해도 사용자가 직접 도커 이미지를 설정할 수 있기에, 모든 경우에 대해서 처리해주진 못합니다.

namsic commented 3 months ago

TestContainer 사용을 위해 isHealthy()를 꼭 지원해야 하는 줄 알았는데, 다른 major 서비스에서 그냥 예외 처리하고 있다면 HEALTHCHECK 추가할 이유가 없어 보입니다.

  1. 언급한 endpoint 문제로 구현이 생각보다 단순하지 않고
  2. HEALTHCHECK가 추가된 이미지를 별도로 관리하는 비용에 비해 얻는 이점이 미미해 보입니다.
  3. 실 서비스가 아닌 테스트 도중에 isHealthy() 호출할 일이 사실상 없을 것입니다.
brido4125 commented 3 months ago

@jhpark816

저도 @namsic 님 의견에 동의하는데, 이렇게 마무리 지을까요?

jhpark816 commented 3 months ago

@brido4125 health check 추가하지 않는 걸로 마무리 지읍시다.