파일럿 프로젝트, Jenkins 자동화 도구 적용기

13 분 소요

해당 포스팅은 개발자 세미나 발표를 위해 작성되었습니다.
포스팅에서 사용하는 어휘나 문구가 부적절할 수 있습니다. 🙇‍♂️

로그포터와 개발자의 돌

logpotter

login();

안녕하세요. LogPotter 입니다.

이번에 회사에서 나만의 프로젝트로 자동화배포, Slack 알림봇 기능을 프로젝트에 적용하였습니다.

예전부터 불편하던 것들을 해소하고나니 참 편리하고 마법같은 기능들이었습니다.

와 자동화 배포! 지긋지긋한 수동 배포 이제 끝 ㅋㅋ
와 에러 알림!


하지만 의도한대로 적용되기까지 겪은 과정들에 난관들도 참 많았습니다.


나의 의도 : 모두를 편리하게! 익스펙토 펙트로늄!


실제 동작 : 이잉! 아바다 케다브라!

ㅋㅋ 서버 겁나 죽임


뭐 했는데?

이번 나만의 프로젝트, 파일럿 프로젝트에서 저는 아래와 같은 것들을 적용해보았습니다.

  • Jenkins 서버를 구축, 무중단 CI/CD 배포 구조를 적용
  • CI/CD 진행상황, 결과 Slack Bot 메시지 전송
  • 프로젝트 API 서버 Un Handling Exception 에러 메시지 Slack 발송
  • 프로젝트 Batch 서버 Job 실행 실패 시 실패 내용 Slack 발송

CI/CD Bot, Jengils

  • 기능
    • Github 특정 Repository의 특정 Branch에 Commit이 병합, 변경 시
      자동으로 소스 통합, 배포 파일 생성 후 무중단 배포진행 및 진행 상황 알림
  • 구조

  • 구현물

실패하면 실패 메시지랑, 실패 단계도 알랴줌, 이쁘죠


적용 과정 자체에 대한 내용은 다루지 않으므로 궁금하시면🧐 아래 링크로 고고

Jenkins, Github WebHook을 활용한 CI/CD 적용 - Gillog

Nginx, Jenkins를 활용한 CI/CD 무중단 배포 - Gillog


에러 알림 봇, Jenkills

  • 기능
    • API 서버 Handling 되지 않은 에러 알림
    • Batch Application Job 구동 실패 시 알림
    • 해당 쓰레드에 상세한 StackTrace 알림
  • 구현물


왜 저걸 했는데?

우선 이번 파일럿 프로젝트에서 작업한 내용 중,

CI/CD 적용이 핵심 주제왜 CI/CD를 선정했는지 부터 이야기 해보려 합니다.

CI/CD가 뭔지?? 무중단배포, CI/CD란 - Gillog


개발자가 CI/CD, 자동화 배포를 적용하는 이유에는 아래와 같은 것들이 있습니다.

  • 자동화된 빌드로 빠른 릴리스 사이클, 높은 품질 코드
  • 개발, 운영 서버 간의 경계 희석 피드백 주기 향상
  • 빠른 배포 속도로 출시 주기 상승

뭐 이런 이유들이 있다고 하는데,

제가 CI/CD 적용을 파일럿 프로젝트로 정한 시작점

다 필요없고 지난 1년간 배포가 드럽게 귀찮아서 였습니다.

이전 1년 넘게 진행했던 프로젝트에서 배포 가이드


또 배포 자체가 귀찮다보니, 한번 배포할 때 개발된 버전들을 한번에 모아서 배포하는 습관이 들게되더라구요.

배포하기전 관련자들에게 노티를 매번…

API 개발되고 개발서버에 적용되면 매번 노티 + 한번에 쌓아두었다가 개발 서버 배포,,,(배포가 귀찮으니까,,)

개발되고 PR 머지도 되었지만, 개발 서버 배포까지, 모아두었다가 한번에 배포


다 필요 없습니다.

배포라는 작업이 엄청난 작업은 아닌데 엄청 귀찮은 작업이어서,

이걸 자동화 해야겠다라는 생각은 항상 마음먹고 있었는데,

바쁜 일정을 핑계로, 다른 우선순위를 핑계로 뒤로 미루고 있던걸,

이번 파일럿 프로젝트에서 적용하게 되었습니다.

마음은 2년전부터 가지고 있었다,, 미안 다른게 바빠서,,, 고생했다 2년간의 Gillog


그 다음엔 이제 에러 알림봇 Jenkils인데,

해당 기능을 파일럿 프로젝트에서 실현하려고 했던 배경은 단순합니다.

Spring Batch단 작업이 Local에서 구동시에는 크게 문제가 안되는 경우가 많은데,

매번 개발계에 올라가고 나면 여러가지 이유로 실패하며,

직접 Batch 실패 원인을 분석하는 일이 잦아서 였습니다.

무수히 많은 실패,, 아직도 다 못잡고 있는 중,,


Spring Batch에서는 Batch 결과에 대해 테이블에 저장되는 형태로 데이터가 저장되는데,

현재는 잦은 주기로 Batch에서 Job들이 실패하는 경우가 많아,

최종적으로는 결국 매일 Batch 관련 테이블에 쿼리를 통해 실패한 Job들이 있는지,

실패 사유는 뭔지를 분석하게 되지만,


추후 대부분의 기능들이 안정화 되고 나서는,

매일 같이 쿼리를 날려 실패한 항목들이 있는지 검색하는 시간 자체가,

반복적으로 소요될 것을 생각하였습니다.

나중엔 몇개 실패 안할텐데 매일 쿼리날리면서 봐야되나??


API 서버에 대한 에러 알림은 이전에도 회사에서는 에러 알림 Slack 전송을 도입하고 있었고,

밥먹다가도 뛰어나가서 에러 보고 그랬는데 ㅋㅋ

현재 작업중인 프로젝트에서는 아래와 같이 의도하는 API 실패 응답 반환 상황에 대한 것들을 정의 하여,

로직 중간에 예외를 터트리는 형태로 API 응답을 반환하도록 설계되어 있는데,

API 서버에서는 우리가 의도하지 않은 Exception들이 throw 될 경우,

인지하지 못하는 서버단 내부 에러나, 서버 문제가 발생하는 것을 감지할 수 있게 되어,

API 서버에서는 Handling 하고 있지 않은 Exception에 대해 신속한 인지와 대응을 위해 적용하였습니다.

터지자마자 호다닥 확인 가능



뭘 말하려고?

진행한 파일럿 프로젝트의 핵심 문구는 자동화 였습니다.

처음 시작점은 분명 그냥 귀찮아서 였고,

이번 파일럿 프로젝트를 통해 얻고 싶었던 이점도 단순히 귀찮은걸 줄여서 편해지자 정도였습니다.

그런데 프로젝트를 진행하며 읽은,

효율적인 개발자를 위한 서적, 이펙티브 엔지니어에서 공감가던 내용들적용하고 나서 얻게 된 이점을 정리해보니,

단순히 귀찮음의 해소 보다 더 큰 가치들이 있더라구요


이번 발표에서는 파일럿 프로젝트를 진행하며 얻게되고, 알게된 가치들에 대해 이야기 해보려 합니다.


시간 절약 도구에 투자하라

성공적인 사람들은 대부분 도구를 사용한다.
문제를 발견했을 때 가장 먼저 도구부터 작성하는가는
그 사람의 성공 여부를 판가름하는 좋은 지표이다.
by Boby Johnson of FaceBook Infra Engineer

지난 최소 1년간 얼마나 많은 수동 배포를 진행했는지 모르겠습니다.

진행중인 이번 프로젝트에서 수동으로 배포하던 과정은 아래와 같았습니다.

  • 배포 파일 준비

  • 배포 서버로 파일 전송

  • 기존 프로세스 종료

  • 신규 배포 파일 구동

이런 과정을 겪으며 배포를 진행하는 것에서 뼈저르게 느낀건

반복적으로 동일한 작업을 수행한다 였습니다.


현재의 배포 프로세스는 간단히 아래와 같이 변경되었습니다.

  • Github 특정 branch에 PR Merge or Push

  • Github Webhook 발송

  • Jenkins CI/CD 진행

  • 진행상황 Slack 발송


지금까지 소모되었던, 앞으로 배포에 의해 소요될 시간을 고려하면

초기에 시간을 절약할 수 있는 자동화 도구에 대한 투자

저희에게 시간 자체가 복리로 돌아 오게 됩니다.

귀찮음 해소, 편리함은 덤으로 ㅋㅋ


관련되어 이펙티브 엔지니어에는 아래와 같은 구체적인 서술이 존재합니다.

아래부터 In. 이펙티브 엔지니어

속도가 빠르지만 개발 주기 반복의 병목 개선을 중요시 하지 않는 개발자와
속도가 느리지만 개발 주기 반복의 병목 개선을 중요시 하는 개발자가 있을 때,
장기적 관점에서 후자의 개발자가, 더 빠르게 더 많은 결과를 생산하게 된다.

이런 결과가 발생하는지는 아래와 같은 이유가 존재합니다.


더 빠른 도구가 더 많이 사용 된다

샌프란시스코에서 뉴욕으로 가는 유일한 교통편이 일주일 걸리는 기차뿐이었던, 1950년대 이전에는

사람들이 해당 경로를 자주 여행하지 않았지만,

여객 항공사의 등장으로 교통편의 종류가 늘어나고 소요 시간이 단축됨에 따라,

해당 경로를 더 자주 여행하게 되었다고 합니다.


만약 어떤 도구가 반복적으로 수행하는 특정 작업의 시간을 줄여줄 수 있다면,

해당 도구를 더 자주 사용하게 되면서, 해당 작업 수행 빈도도 높아 지게되어

최초 예상한 도구가 절약해주는 시간 보다 더 많은 시간을 절약할 수 있게 됩니다.

기존 : 매일 30분 A 작업 수행
도구 : A 작업을 20분 절약해줌

기존 개발자 : 으~ A 작업 지겹다 최대한 적게 해야지
도구 도입 후 개발자 : ㅋㅋ 도구 쓰니까 겁나 단축되네 A 작업 더 자주 해야지

예상이점 = 도구가 줄여주는 시간(20분) * 원래 작업 빈도(1/Day)
실제이점 = 도구가 줄여주는 시간(20분) * 도구 도입 후 작업 빈도(2/Day)

확장된 도구는 팀 전체의 시간을 절약시킨다

구글, 페이스북, 드롭박스, 클라우데라 같은 대규모 IT 회사들에는 사내에서 사용하는,

개발도구 만을 전담하여 개선, 개발 하는 전담팀이 존재한다고 합니다.


시간을 절약할 수 있는 도구가 개발되고 이 도구가 팀에 보급되어 확산되게 될 경우,

팀 전체적인 입장에서 얻는 이점은 N배가 됩니다.

도구 사용 개발자 : 님들 A 작업 쉽게하는 도구 만들어 봤는데 함께 써보실래요?
팀원들 : 헉, 넹

도구 도입 후 이점 = 도구 사용으로 인한 이점 * 도구 사용 개발자 수


살펴본 예시와 같이 시간 절약 도구에 대한 팀 전체적인 투자는 결국 복리로 돌아오게 됩니다.


Move Fast And Break Things

Move Fast And Break Things
망가 뜨려도 좋으니 빠르게 실행하라
In. 페이스북 본사 복도

망가지더라도 빠르게 움직여라 라는 문구

8년만에 10억 명 이상 사용자를 확보한 페이스북의 핵심 기조 문구라고 합니다.


페이스북의 개발 문화는 보수적 태도 실수 최소화 보다는,

개발 주기를 빠르게 반복하며 효과를 내는데 집중한다고 합니다.


자동화 배포 적용 전 앞서서 저는 앞서 말씀드렸듯이 local에서 작업한 결과물들

몇가지 쌓아두고 release를 생성하며 배포를 진행했었습니다.

API 개발되고 개발서버에 적용되면 매번 노티 + 한번에 쌓아두었다가 개발 서버 배포,,,(배포가 귀찮으니까,,)


개발된 여러 기능들이 한번에 서버에 적용되게 되면,

문제가 발생 했을때도 어떤 작업물에 의한 오류 사항인지 확인이 힘들어 집니다.


반면 작업한 결과물들이 단위 단위로 매번 지속적으로 통합, 배포되었을 때,

작업한 한 단위의 개발 물이 실제 개발 환경에서 안정적으로 구동되는지를,

확인하는게 더 편리했습니다.


잉? 갑자기 Handling 안되던 에러가?

마지막 배포된 작업이 이거? 너야?

바로 해당 소스본 작업자랑 대화


하나 하나의 기능이 안정적으로 구동될 수 있도록,

신중을 기하는 것은 아주 중요하지만,

지속적 배포를 통해 개발 버전 서버에 병합되는 개발주기를 빠르게 가져가고,

빠르게 원인을 파악할 수 있도록 환경을 조성하는 것이,

더 안정적인 기능 구현, 서비스 제공에 필요하다는 걸 경험하게되었습니다.



레버리지

앞선 얘기들에서는 도구 개발에 대한 장점들에 대해서 말씀드렸습니다.

이번에는 파일럿 프로젝트를 진행하며 도입해보려 했던 도구 개발을 취소했던 이유에 대해 이야기 해보려합니다.


원래 도입 계획이었던 추가적인 기능들은 아래 두가지인데요.

  • 프로젝트 데이터 별 평균 적재량 알림

하루 평균 프로젝트에 저장된 데이터 개수와 평균 추이 그래프 자정 알림 발송

프로젝트에 어떤 종류의 데이터가 얼마나 가파르게 적재되는지 감지하기 위함


  • 메모리 모니터링 구조

Spring Actuator + Grafana

Actuator로 Application 메모리 데이터 + Grafana로 데이터 시각화

EC2에서 Batch Application 메모리 이슈로 Instance가 죽은적이 많아서 모니터링을 위함


위 도구들을 도입하지 않았던 가장 큰 이유는 아래 레버리지라는 단어 개념을 접하게 되어서 입니다.

레버리지 = 생산한 효과 / 투자한 시간

레버리지 = 투입 노력에 대한 투자 자본 수익률


레버리지 라는 개념을 이펙티브 엔지니어를 통해 접하고 도구 도입을 취소했습니다.

정확히는 아래 서문때문에요.

효율적인 개발자는 더 오랜 시간 일해서 더 많은 일을 하는 사람이 아닌,
제한된 시간에 더 많은 가치를 생산할 수 있는 개발자다
In. Effective Engineer

레버리지를 높이기 위해선, 투자하는 시간은 줄이고, 생산되는 가치는 늘려야 하는데

위 도구 들은 각각 아래와 같은 이유로 레버리지가 낮다고 판단했기 때문입니다.


오 근데 이걸로 뭐함?

앞서서 하루 평균 프로젝트에 어떤 데이터가 얼마나 누적되었고,

평균적으로 지금까지는 어떤 비율로 누적되고 있었다.

라는 정보를 자정마다 발송하는 알림 시스템을 도입하려 했는데요.


도입하려고 했던 때의 생각은 이거였습니다.

흠.. 우리 시스템 Batch 때문에 데이터 엄청 쌓일텐데 어떤게 얼마나 쌓이는지 알면 좋겠는걸


그런데 막상 도입하려고 예제 가안을 작성하고 나니 이런 생각이 들더라구요.


그런데 이걸로 뭐함?


자정마다 알려주는건 알겠고, 이뻐보이고, 유용해보이는데

막상 그거 알게되서 뭐함?


뭐 로직을 뜯어 고칠거임? 데이터를 날리기를 할거임?


이거 있으면 좋겠다. 라는 생각으로 시작한 도구 도입이,

정작 도입하고 나서는 근데 이걸로 뭘 하지? 에 대한 자문에 답을 내리지 못해 멈추었습니다.


자정마다 데이터 저장 추이를 발송하는 시스템 자체는 개발하는데 시간이 많이 들지 않는 작업인데,

투자해야 하는 시간이 낮음


이를 통해 얻을 수 있는 생산 가치가 거의 없다고 판단했습니다.

생산되는 가치가 낮음


결국 아래와 같다고 판단했습니다.

데이터 적재 알림 도구 

레버리지 = 낮은 가치 / 낮은 시간


오 근데 이거 말고는 없음?

이번에 진행중인 프로젝트에서는 Batch로 외부 시스템 네트워크 I/O, DB I/O 등이 상당히 많아,

초기 구동시에 Memory 이슈로 EC2 Instance 자체가 멈추는 일이 잦았습니다.


이로인해, Application에서 누수되고 있는 메모리 사용 부분 로직들을 개선하는 이슈들을 작업했는데,

사실 메모리 모니터링을 사용해보거나 한 경험이 없어, 추정되는 로직들을 개선하는 식으로 작업했었습니다.

당시 초창기에 Memory 이슈 터졌을 때, 급하게 Intellij Profiler로 뒤적뒤적


그렇게 해서 파일럿 프로젝트에서 Batch Application에서,

메모리가 튀는 구간과 실시간 메모리 모니터링을 위해서 메모리 모니터링 시각화 관련 도구를 도입하려 했습니다.


여러 메모리 시각화 라이브러리나 툴들이 존재하는데,

Spring 에서는 국룰 같은 Actuator + Grafana 조합을 많이 사용하더라구요.

Actuator로 Application내의 메모리 관련 데이터를 API로 수급 가능

Grafana로 이를 시각화


결론적으로 도입하지 않은 이유는, 생산하는 가치가 도입 시간에 비해 높지 않아서 였습니다.


Grafana의 경우 Server 구동이 필요하고,

신규 EC2 증설, Grafana Server 설치

투자 시간이 높음

막상 얻을 수 있는 모니터링 정보들이, Java Application 구동시 GC log 파일을 통해서,

얻을 수 있는 정보와 별반 다르지 않았습니다.

실제로는 더 많을수 있는데 Actuator, Grafana 공식문서 살펴본 결과로는 그닥 차이가?


그래서 결론적으로는 Application 구동시 GC 관련 log파일을 남기는 기본 옵션을 활용하고,

모니터링이 필요할 때 다른 시각화 툴로 해당 파일을 열람하는 방식을 선택했습니다.

-Xmx128m -Xlog:gc:/app/api/logs/gc.log -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=40M


이를 레버리지 관점에서 정리하면 아래와 같은 이유 때문이었습니다.

메모리 모니터링 시각화 도구 도입

레버리지 = 높은 가치 / 높은 시간

But

GC Log 파일 저장 + 시각화 툴 사용

레버리지 = 높은 가치 / 낮은 시간

결국 동일한 가치를 나타내지만, 낮은 시간을 들여도 되는 방법이 있어,

해당 방법이 레버리지가 더 높다고 판단하여 메모리 모니터링 시각화 도구 개발을 취소하였습니다.

근데 다른 유용한 기능들도 많아서 나중에 더 찾아보고 꼭 도입해볼거임 ㅋㅋ


적용 과정 이슈

앞서서는 파일럿 프로젝트를 진행하며 생각한, 효율적인 개발자 관련된 내용에 대해 말씀드렸습니다.

이번에는 이번 파일럿 프로젝트를 진행하며 겪었던 몇 가지 고난들에 대해서 이야기 해보려 합니다.


1024 미만 포트 Root 구동

해당 이슈는 파일럿 프로젝트 초기에 굉장히 막막하게 느꼈던 이슈인데,

정작 Unix OS 관련 지식이 부족해서 발생했었습니다.

발생한 상황은 아래와 같았습니다.


어이거외않대


CI/CD 구조 개발 중 Jenkins를 설치하고나서,

Application 구동 부분을 테스트하기 위해 정상적으로 Pipeline script를 작성하고,

빌드 테스트를 진행하는데, 빌드는 성공했는데 Test로 구성한 Application 구동이 안되던 상항이었습니다.


아래와 같이 구동 테스트만을 위해 간단하게 작성한 실패할리 없는 Script 였는데 말이죠

stage('Start new version') {
        steps {
        
          sh "cd /app/test && nohup java -jar *.jar &"
           
        }
    }


이때 계속 쉐도우 복싱하고 있던 생각들은 아래와 같았는데요.

  • PipeLine script에 이상은 없다
  • test용 application을 직접 터미널 상에서 저 명령어로 구동하면 성공적으로 구동된다
  • 근데 Jenkins를 통해 실행하면 build 실패는 없고, Application이 구동되지 않는다

무한반복


한참을 쉐도우 복싱하다 원인은 테스트용으로 간단하게 작성한 Application에서 설정한 구동포트 관련 이슈였습니다.

기본 구동 포트로 80 포트 구동


어딜 감히 jenkins 따위가

원인은 아래와 같았는데, 모두 Unix 계열 OS 공식문서에서 발췌한 내용들입니다.

Well-known ports are defined by the Internet Assigned Numbers Authority (IANA).
By convention, the Internet protocol suite and the operating system recognize port numbers
that are less than 1024 as privileged,
meaning that only privileged (usually administrative) processes are allowed to bind to them.
In. Open Group, Unix Docs


Privileged ports are network ports that applications running as a non-root user are not allowed to bind to.
By convention, ports numbered less than 1024 are privileged ports.
Only root can bind to privileged ports.
In. RedHat, Linux Docs


By convention, ports below 1024 are considered “privileged” ports,
which means that processes running as regular users are not allowed to bind to them.
Only processes running with root privileges can bind to these ports.
In. Ubuntu Docs


이슈 원인은 굉장히 간단했습니다.

Unix 계열 OS에서는 1024미만 포트는 root 권한에서만 실행할 수 있다.

지금와서 생각하면 정말 별거아닌 이슈였는데, 이 OS 기초적인 지식 부재로 인해 이 당시에는 엄청난 고난을 겪었습니다.


제가 아까전 쉐도우복싱하던 아래 내용은,

test용 application을 직접 터미널 상에서 저 명령어로 구동하면 성공적으로 구동된다
근데 Jenkins를 통해 실행하면 build 실패는 없고, Application이 구동되지 않는다

사실 이거였습니다.

test용 application을 직접 터미널 상에서 root 사용자 권한에서 저 명령어로 구동하면 성공적으로 구동된다
근데 Jenkins를 통해 jenkins 사용자 권한에서 실행하면 build 실패는 없고, Application이 구동되지 않는다


직접 터미널 상에서 해당 Application 실행 명령어를 사용할 땐,

관습적으로 작성하던 sudo su, root 권한을 통해 진행했고,

Jenkins가 구동하는 Script는 jenkins 사용자 권한으로 실행되어 발생한 이슈였습니다.


여기서 배운점은 이슈 상황에 대한 추정은 더욱더 구체적, 세부적으로 가정해야하고,

권한 이슈였다는건 꿈에도 생각못함

서버 관리시 항상 관습적으로 실행하던 sudo su,

사용자 권한에 대한 귀찮음을 핑계로 root 권한을 남용하던 습관을 경계해야 한다 였습니다.

맨날 서버 접속하면 root 권한부터 얻고 봤는데, 정말 남용하면 안되겠구나 느낌



Java Application이 무겁다


앞서서 말씀드렸듯, 파일럿 프로젝트를 진행하며 서버를 굉장히 많이 멈추게 했었습니다.

흑흑 고의가 아니라고


해당 상황은 Java Application의 기본 방식과, 당시 개발 EC2내 상황과 관련이 있었는데요.


Java는 기본적으로 자원을 많이 사용한다


Java는 객체지향 언어로, 메모리 관리에 대한 걱정 없이 프로그래밍에 집중할 수 있도록
자동 가비지 컬렉션(garbage collection) 기능을 제공합니다.
그러나 이런 편의성에는 비용이 따르는데, 메모리 사용량과 CPU 시간이 그 비용입니다.
가비지 컬렉터가 메모리를 관리하고,
불필요한 객체를 회수하는 과정에서 CPU 자원을 사용하게 되며,
그로 인해 다른 언어들(특히 메모리 관리를 개발자가 직접 하는 언어들)에 비해
더 많은 메모리와 CPU 자원을 사용하게 됩니다.
In. Chat GPT


Java Application은 다른 언어에 비해 메모리, CPU 자원을 많이 사용할 수 있다.

관련내용은 Java 상식같은 내용이라,

머리로는 알고 있었지만, 한번도 체감을 해본적은 없었습니다.


Java Application이 무거운 Application이구나 느낀 상황은,

개발 EC2내에 여러 Java Application을 배포하며 체감하게 되었는데요.

당시 상황은 아래와 같았습니다.


개노답 Java Application 3형제


API용 Spring Boot Application, 실시간 데이터 정제용 Spring Batch Application,

그리고 파일럿 프로젝트를 진행하며 추가된 CI/CD용 Jenkins 서버 까지,

세 Application 모두 Java로 개발된 Server들 이었습니다.


Application이 배포된 EC2는 t3.small 아래와 같이,

vCpu 2 Core, Memory 2GB Spec에 서버였습니다.


Spec이 낮은 Instance에 세가지 Java Application을 배포하니,

아래와 같이 CPU, Network 사용량이 눈의 띠게 증가하게 되었는데요.


원인은 동시에 세 가지 서버에서, 한번에 I/O 처리를 요청하게 되니

메모리 사용량이 증가하게 되고,

제한된 EC2 메모리 내에서 제한값이 초과되어,

Swap 영역을 사용하게 되어 아래와 같이 Swap을 담당하는 Process가 CPU 사용량을 급증 시켰는데요.


Peek때 당시 kswapd Process 상황, 든든한 삼 형제들!


실제 Swap의 CPU 사용량 관련 작업을 살펴보면 아래와 같습니다.

디스크에서 메모리로 데이터를 이동시키는 스왑 인(swap in) 작업과
메모리에서 디스크로 데이터를 이동시키는 스왑 아웃(swap out) 작업은
CPU를 많이 사용하므로, 이러한 작업이 빈번하게 발생하면 CPU 사용량이 증가하게 된다.
From. Chat GPT


순차적으로, 세 가지 Application을 각기 다른 EC2로 이관하며 상황은 진정되었습니다.


대부분의 사용량은 이 Batch Application, 든든한 맏형 답다!


gradle, 너마저도

실제 저 Peek가 발생한 원인은, Jenkins에서 배포 파일 생성 작업 단계에서,

gradle을 사용배포파일, jar 파일 Build 시에 발생했습니다.


$ ./gradlew build

저 구문 한 줄이 정말 위험한 한 줄이었습니다.


gradle 역시 JVM을 사용하는 빌드 관리 도구인데요,

기본적으로 gradle의 build시 JVM Mermory 사용량은 1GB로,

저 구문이 실행되자마자 해당 EC2에서는,

Jenkins Process에 의해 1GB 메모리 사용량이 발생하게되었습니다.


후속 조치로는 build시의 최대 메모리 사용량을 제한하고,

캐시 디렉토리를 생성해 추후 build시 메모리 사용량을 낮추는 방향으로 해결했습니다.

$ ./gradlew build -g /tmp/gradle_cache -Dorg.gradle.jvmargs=-Xmx128m


앞서서 Java Application이 무겁구나 하는 내용을 말씀드렸습니다.


이게 Java Appliation은 답도없이 느리다를 말하려는 의도는 아니고,

항상 빵빵한 스펙에서 Java Application을 테스트하고 구동하다보니,

그래봤자 MacBook Local zz

실제로 제한된 서버 사양에서, 사용량 한계점에 맞딱뜨린 경험이 거의 전무하여,

앞으로 더욱 Java 메모리 관련 사용에도 관심을 기울여야 되겠구나 하는 목적으로 말씀드렸습니다.



마무리

지금까지 나만의 프로젝트를 진행하며 생각하게된

효율적인 개발자 서적 관련 내용과

겪었던 고난 몇 가지에 대해 말씀드렸습니다.


이번 발표가 다들 진행하게 될 파일럿 프로젝트에

효율적인 개발 도구 도입을 위한 도움이 되었기를 바랍니다.

감사합니다.


logout();

댓글남기기