저번달에 새벽1시였나 서버가 갑자기 죽었다 깜짝놀라서 기존 서버를 내리고 새로운 서버를 배포 했다 그러니 잘 돌아갔다...
하지만 이유를 알 수 없었다... 기존 서버를 없에버려서... 그때 실제 유저들이 돈을 내고 사용하고 있던 서비스라서 너무 놀라서 일단 서버를 복구해야겠다는 생각으로 한 행동인데 복구가 되자마자 왜 서버가 꺼졌을까 너무 궁금해졌다 나중에 생각해보면 그냥 기존 ec2를 냅두고 새로운 서버를 배포하고 기존 서버에서 이슈 트래킹을 했으면 어땠을까 라는 생각이 들었다 몇가지 예상되는 원인(OOM 등)들이 있었지만 이건 예상이지 확실한건 아니다
그리고 또한 가끔 시스템이 느린 경우도 있었다 이것에 대한 이유를 해결하고 싶었지만 하루에 몇번의 요구사항이 변경되던 시기라서 너무 바빴고, 가끔 느린경우도 어느순간 돌아오기도하고 아주 가끔이라서 백로그에 두고 해결은 안했다

어플리케이션의 성능 문제를 실시간으로 감지하고, 장애의 근본 원인을 빠르게 찾을 수 있도록 도와주는 APM(어플리케이션의 성능을 모니터링하고 관리하는 도구)을 도입하기로 했다
핀포인트, 스카우터, 다이나트레이스, 뉴 레릭, 인스타나, 와탭 등등 여러 도구가 있었지만 돈이 없기 때문에 오픈소스인 핀포인트, 스카우터중 골라야 했고 그중에 스카우터는 문서도 잘 되어있고 사람들이 많이 사용해서 참고 자료도 많았다 그래서 스카우터로 도입하기로 했다

1. 인프라 현황

우리는 Elastic beanstalk(이하 빈스톡) + github acions를 활용해서 CICD배포를 진행하고 있다

scouter를 도입하는 방법자체는 ec2에 들어가서 scouter wget하고 설정파일 설정하고 실행하는 간단한 작업이지만 cicd를 하고 있는 서비스에서 배포할때마다 ec2에 접근해서 저 일련과정을 하는것 자체가 비효율적이라고 생각했고 .ebextensions라고 웹 어플리케이션 소스 코드에 빈스톡 구성 파일을 추가해서 사용하기로 했다 (벌써부터 느껴지는 삽질의 기운...)

스카우터의 개념과 작동방식, 용어와 스카우터를 설치하고 설정하고 실행하는 방법은 너무 잘 나와있어서 여기에 굳이 쓰진 않겠다

2. 도입 시작

스카우터의 개념과 작동방식, 용어와 스카우터를 설치하고 설정하고 실행하는 방법은 너무 잘 나와있어서 여기에 굳이 쓰진 않겠다

1. 계획

스카우터 서버(collector), 스카우터 호스트 에이전트, 스카우터 자바 에이전트를 전부 어플리케이션이 돌아가는 서버(이하 상용 서버)에 넣는거 자체가 좀 성능에 누를 끼치지 않을까 고려해서 스카우터 서버는(collector) 새로운 ec2를 파기로 했다 (이것도 돈 아까우니까 새로운 계정 파서 일단 1년 프리티어) 왜 와이? 제대로 도입하기전에 실제로 한번 ec2에 접속해서 서버, 에이전트, 스프링 3개를 돌리니까 cpu 메모리가 고갈되는 현상을 확인했기 때문
스카우터 서버 ec2는 고정 ip를 설정해줬다 참고로 고정 ip 할당하면 프리티어까진 돈이 안든다

2. 스카우터 클라이언트 도입

그냥 로컬에 설치하고 실행하면 된다

실행 안되는 이슈

스카우터 클라이언트를 내 로컬 컴퓨터에 설치하는중에 실행이 안되는것을 보았다 권한이 없었다 했나 맥북에서 발생하는 이슈였다

실행 안되는 이슈 해결

맥용 클라이언트는 자바 11이상인데 나는 17이라서 괜찮고
xattr -cr scouter.client.app 이 명령어를 입력하니까 잘 됬다
scouter.client.app 디렉토리와 그 안의 모든 파일 및 디렉토리의 확장 속성을 제거하는 명령어인데 인터넷에서 다운로드한 애플리케이션이나 파일이 실행되지 않을 때, "확장 속성"을 제거하여 실행할 수 있게 한다고 한다
해결!

3. 스카우터 서버(collector) 도입

설정파일에 6100포트와 db_dir, log_dir 설정해주고 실행했다 물론 스카우터 서버 ec2에 인바운드 규칙에 6100 포트 대상은 상용 서버 ip로 해서 tcp, udp다 열어주었고, 아웃바운드 규칙에 6100포트 대상은 내 로컬 컴퓨터 ip 로 tcp, udp 다 열어주었다 스카우터 서버는 도입할때 딱히 이슈는 없었다

4. 스카우터 호스트 에이전트 도입

상용 서버의 아웃바운드 규칙에 6100 포트 대상은 스카우터 서버(collector) 고정ip로 tcp, udp다 열어주자

여기서부터 삽질 시작이였다
ebextensions에
03-install-scouter-host-agent.config

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/03-install-scouter-host-agent.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash

      SCOUTER_VERSION="2.20.0"
      SCOUTER_DIR="/opt/scouter"
      SCOUTER_URL="https://github.com/scouter-project/scouter/releases/download/v$SCOUTER_VERSION/scouter-all-$SCOUTER_VERSION.tar.gz"
      SCOUTER_HOST_AGENT_DIR="$SCOUTER_DIR/agent.host"
      SCOUTER_HOST_AGENT_CONF="$SCOUTER_HOST_AGENT_DIR/conf/scouter.conf"

      mkdir -p $SCOUTER_DIR
      wget $SCOUTER_URL -O /tmp/scouter-all.tar.gz
      tar -xzf /tmp/scouter-all.tar.gz -C $SCOUTER_DIR --strip-components=1

      cat <<EOF > $SCOUTER_HOST_AGENT_CONF
      net_collector_ip= {스카우터 서버(collector) 의 고정 ip}
      net_collector_udp_port=6100
      net_collector_tcp_port=6100
      EOF

      # Ensure the script has execution permissions
      chmod +x $SCOUTER_HOST_AGENT_DIR/host.sh

      cd $SCOUTER_HOST_AGENT_DIR
      ./host.sh start

commands:
  01_run_scouter_install_script:
    command: sudo /opt/elasticbeanstalk/hooks/appdeploy/pre/03-install-scouter-host-agent.sh

스카우터 호스트 에이전트 메모리 이슈

이렇게 해줬는데 배포가 안됬다... github actions에 로그는

Error: Deployment failed: Error: Environment still has health Yellow 30 seconds after update finished!

이렇다

  1. 03-install-scouter-host-agent.config의 코드 문제일까?
    1) 03-install-scouter-host-agent.config에서 command 삭제하고 배포, 그다음에 ec2 직접 접속해서 수동 실행 해보기

1-1 번 방법으로 해보니

cpu 그래프에 파란 선이 보인다 잘 되는 것이다 ec2 상태 모니터링을 확인했는데 스토리지가 갑자기 치솟으더니 cpu도 치솟고 서버가 죽었다 일단 메모리 문제라고 생각이 들었다

스카우터 호스트 에이전트 메모리 이슈 해결

  1. 샘플링 단위가 1초라서 너무 많은 메모리를 사용하고 있는건 아닐까?
    1) 일단 scouter.host 의 conf에 설정할때 샘플링 단위를 널널하게 10초로 둬보자
    net_collector_ip=3.36.225.29
    net_collector_udp_port=6100
    net_collector_tcp_port=6100
    hook_profile_fullstack_method_sampling_interval_ms=10000
    hook_args_sampling_interval_ms=10000

1-1) 해도 같은 이슈 발생

  1. 스카우터가 실행되는 Java 애플리케이션에 할당할 최대 힙 메모리 크기를 제한해보자
    1) 메모리 설정 값인 -Xmx256m 사용

2-1) 해도 같은 이슈 발생

  1. t3.micro의 메모리가 1G라서 그런가?
    1) t3.small로 변경

3-1 실행 하니 이젠 다른 에러가 터짐

스카우터 호스트 에이전트 timeout 이슈

16:29:46 WARN: The following instances have not responded in the allowed command timeout time (they might still finish eventually on their own): [{인스턴스id}].
16:29:46 INFO: Command execution completed on all instances. Summary: [Successful: 0, TimedOut: 1].
16:29:46 ERROR: Unsuccessful command execution on instance id(s) 'i-{인스턴스id}'. Aborting the operation.
16:29:46 ERROR: Failed to deploy application.
16:29:52 ERROR: Deployment failed! Current State: Version: ***-2024-06-03T19-24-02, Health: Green, Health Status: Ok
Error: Deployment failed: Error: Deployment failed! Current State: Version: ***-2024-06-03T19-24-02, Health: Green, Health Status: Ok

그러면 아까랑 똑같이 03-install-scouter-host-agent.config에서 command 삭제하고 배포, 그다음에 ec2 직접 접속해서 수동 실행 해보기를 해보자 -> 이렇게 하니 계속 잘 된다.... 메모리 이슈는 해결된 것 같다 메모리 1기가로는 scouter와 스프링을 같이 돌리기 힘든 것 같다 성능 최적화는 나중에 해보고 일단 timeout이슈를 해결해보자

거의 하루종일 구글링을 해본 결과 https://theholyjava.wordpress.com/2015/07/29/fixing-a-mysterious-ebextensions-command-time-out-aws-elastic-beanstalk/ 해당 블로그 글을 참고할 수 있었다

나랑 같은 이슈가 생겼고 &를 이용하여 백그라운드로 시작하는 명령어의 stdin stderr의 출력을 /dev/null로 redirection하라는 소리였다

스카우터 호스트 에이전트 timeout 이슈 해결

  1. &를 이용하여 백그라운드로 시작하는 명령어의 stdin stderr의 출력을 /dev/null로 redirection
    1) &를 이용하여 백그라운드로 시작하는 명령어의 stdin stderr의 출력을 /dev/null로 redirection

1-1) 그래도 계속 timeout이슈 발생

  1. commands가 인스턴스를 시작할때 실행되니까 인스턴스가 힘든거 아닐까?
    1) container_command를 이용해서 어플리케이션 코드가 배포된 후 실행해보자

2-1) 이렇게 하니까 해결됬다!

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/03-install-scouter-host-agent.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash

      SCOUTER_VERSION="2.20.0"
      SCOUTER_DIR="/opt/scouter"
      SCOUTER_URL="https://github.com/scouter-project/scouter/releases/download/v$SCOUTER_VERSION/scouter-all-$SCOUTER_VERSION.tar.gz"
      SCOUTER_HOST_AGENT_DIR="$SCOUTER_DIR/agent.host"
      SCOUTER_HOST_AGENT_CONF="$SCOUTER_HOST_AGENT_DIR/conf/scouter.conf"

      mkdir -p $SCOUTER_DIR
      wget $SCOUTER_URL -O /tmp/scouter-all.tar.gz
      tar -xzf /tmp/scouter-all.tar.gz -C $SCOUTER_DIR --strip-components=1

      cat <<EOF > $SCOUTER_HOST_AGENT_CONF
      net_collector_ip={스카우터 서버(collector) 의 고정 ip}
      net_collector_udp_port=6100
      net_collector_tcp_port=6100
      hook_profile_fullstack_method_sampling_interval_ms=10000
      hook_args_sampling_interval_ms=10000
      hook_dbsql_enabled=true
      hook_http_enabled=true
      hook_thread_enabled=true
      hook_profile_fullstack_method_sampling_enabled=true
      hook_args_enabled=true
      EOF

      # Ensure the script has execution permissions
      chmod +x $SCOUTER_HOST_AGENT_DIR/host.sh

      cd $SCOUTER_HOST_AGENT_DIR
      sed -i 's/^JAVA_OPTS=.*$/JAVA_OPTS="-Xmx256m"/' ./host.sh
      nohup ./host.sh start > /dev/null 2>&1 &

container_commands:
  01_run_scouter_install_script:
    command: sudo /opt/elasticbeanstalk/hooks/appdeploy/pre/03-install-scouter-host-agent.sh

최종 코드

잘 된다....... 해결!

5. 스카우터 자바 에이전트 도입

04-install-scouter-java-agent.config

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/04-install-scouter-java-agent.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash

      # Variables
      SCOUTER_VERSION="2.20.0"
      SCOUTER_AGENT_DIR="/opt/scouter"
      SCOUTER_JAVA_AGENT_URL="https://github.com/scouter-project/scouter/releases/download/v$SCOUTER_VERSION/scouter-agent-java-$SCOUTER_VERSION.tar.gz"
      SCOUTER_JAVA_AGENT_CONF="/opt/scouter/agent.java/conf/scouter.conf"

      # Download and extract Scouter agent
      # Configure Scouter agent
      cat <<EOF > $SCOUTER_JAVA_AGENT_CONF
      obj_name=java
      net_collector_ip=3.36.225.29
      net_collector_udp_port=6100
      net_collector_tcp_port=6100
      EOF

container_commands:
  01_run_scouter_install_script:
    command: sudo /opt/elasticbeanstalk/hooks/appdeploy/pre/04-install-scouter-java-agent.sh

스카우터 자바 에이전트는 호스트 에이전트와 다르게 독립적인 실행이 아니라 java 어플리케이션이 실행될 때 attach되서 실행된다 한다

실행 방법은
1. 톰캣의 시작 스크립트에 스카우터 정보 넣기
2. 어플리케이션 시작할때 scouter 명령행 옵션을 포함하여 jar 파일을 실행

2번으로 실행해보자
00-makeFiles.config

files:
    "/sbin/appstart":
        mode: "000755"
        owner: webapp
        group: webapp
        content: |
            #!/usr/bin/env bash
            JAR_PATH=/var/app/current/application.jar
            SCOUTER_AGENT_PATH=/opt/scouter/agent.java/scouter.agent.jar
            SCOUTER_CONF_PATH=/opt/scouter/agent.java/conf/scouter.conf

            # run app
            java -javaagent:$SCOUTER_AGENT_PATH \
             -Dscouter.config=$SCOUTER_CONF_PATH \
             -jar \
             -Dspring.profiles.active=prod -Dfile.encoding=UTF-8 -jar $JAR_PATH

스카우터 자바 에이전트의 obj_name을 넣어줄 수 있지만 안해도 돌아가긴한다 그냥 패스!

참고자료
https://gunsdevlog.blogspot.com/2017/07/scouter-apm-1.html
https://theholyjava.wordpress.com/2015/07/29/fixing-a-mysterious-ebextensions-command-time-out-aws-elastic-beanstalk/
https://github.com/scouter-project/scouter/blob/master/README_kr.md

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN