2 minute read

Intro.

현재 진행중인 사이드 프로젝트에서 백엔드와 인프라를 같이 담당하고 있습니다. 아무래도 인프라는 익숙하지 않다보니 트러블 슈팅도 많이 발생하고 배워가는 점이 많습니다 😂 

사이드 프로젝트의 배포 자동화는 Github Actions 를 사용하고 있습니다

사이드 프로젝트 배포 자동화 관련 포스트

프로젝트 진행중인 어느 날 마스터 브랜치에 푸쉬하면서 자동화된 배포 과정을 즐기는 와중…. EC2 인스턴스 접속이 무한로딩과 함께 먹통이 되었습니다❗️

Trouble Shooting.

EC2 모니터링 결과 CPU 사용률이 급격히 터지는 구간을 확인했습니다.

cpu-monitoring.png

용의선상

  • MySQL : 트러블 슈팅 발생 전날 비용 절감 문제로 RDS 에서 EC2에 직접 MySQL을 설치해서 사용
    • MySQL 설치시 additional space를 약 250MB 가량 필요하다는 로그를 확인했었고 이는 크게 문제가 되지 않았을 것이라고 판단
  • Docker Container : 혹시 서버 백그라운드에 도커 컨테이너가 여러 개 구동되고 있는것이 아닌가?
    • docker ps -a : 모든 도커 컨테이너 확인
    • docker images : 모든 도커 이미지 확인

유력한 용의자

  • 도커 컨테이너가 여러개 올라가 있었다.
    • docker run 명령어 인해 배포시마다 새 컨테이너가 구동되어서!
  • 도커 이미지 또한 여러개 pull된 상태였다.

스크린샷 2023-05-09 오전 10 57 35

  • 어떤 부분이 가장 큰 원인인지는 불확실 하지만, 컨테이너가 가상 머신같은 역할이라고 추측 (도커 공부를 해야하는 부분) 되어 큰 원인이라고 생각했습니다.
    • 서버 백그라운드에 컨테이너 여러개가 구동되고 있는 부분

Solution.

일단 빠르게 문제를 해결하기 위해 EC2 서버의 모든 컨테이너를 삭제했습니다.

  • docker system prune (모두 정리)

또한 pull 한 이미지 또한 모두 삭제했습니다.

  • docker images 로 확인후 docker rmi {image id}

위 두 스텝을 실행한 후 재배포를 하니 서버와 데이터베이스 모두 정상작동함을 확인할 수 있었고, 깔끔하게 컨테이너 1개, 이미지 1개가 서버에 구동되도록 했습니다.

하지만, 기존 방식의 배포 자동화 스크립트는 해당 문제를 지속해서 발생시킬 것으로 예상합니다.

재발 방지 솔루션

  • 배포시 인스턴스 서버에 접속해서 도커 컨테이너와 이미지를 체크해서 필요시 삭제해준다.
    • 확실하지만, 귀찮다. 자동화하고 싶은 부분입니다.
  • Github Actions 배포 자동화 스크립트를 수정한다.

생각되는 스크립트 수정 시나리오는 2개가 있습니다.

  1. 도커 컨테이너는 1개만 올려놓고 해당 컨테이너에서만 도커 이미지를 pull해 온다.
  2. 배포할 때마다 기존 컨테이너를 삭제하는 스크립트를 추가한다.
    • 공통부분은 배포시 서버에 있는 기존 도커 이미지를 삭제하는 스크립트가 필요할 것으로 생각

Script

1번 방법 docker exec 명령어 사용해서 도커 컨테이너 내부에서 실행

2번 방법으로 배포시 기존 컨테이너 중지 후 삭제

  • docker rm -f $(sudo docker ps -qa)

그리고 이미지를 삭제하는 방법으로 스크립트를 만들었습니다.

  • docker rmi $/blahblah
# 서버에서 Docker 이미지 실행
- name: EC2 Docker Run
  uses: appleboy/ssh-action@master
  with:
    host: $
    username: ubuntu
    key: $
    script: |
      sudo docker rm -f $(sudo docker ps -qa)
      sudo docker rmi $/san-monkey
      sudo docker pull $/san-monkey
      sudo docker run -d -p 8080:8080 $/san-monkey
      sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

추후 해당 관련 오류 및 개선점이 생기면 추가 포스팅 하겠습니다.

Cleanup Script 추가

  • docker run 스크립트로 이미지 실행시 새 컨테이너가 구동되고 기존 컨테이너는 exited 상태로 변경됩니다.
  • exited 컨테이너는 리소스를 차지하지 않지만, 컨테이너에서 사용하던 데이터베이스나 파일 시스템 리소스 등을 정리하지 않고 그대로 남겨두면 서버 리소스를 점유하게 됩니다.
  • 컨테이너를 종료하기 전에 컨테이너가 사용하던 리소스를 정리하고 반납하는 것이 좋습니다.
- name: EC2 Docker Cleanup
  uses: appleboy/ssh-action@master
  with:
    host: $
    username: ubuntu
    key: $
    script: |
      # Stop and remove all stopped containers
      sudo docker stop $(sudo docker ps -q --filter "status=exited")
      sudo docker rm $(sudo docker ps -q --filter "status=exited")
      
      # Remove all unused images
      sudo docker image prune -a -f

Leave a comment