Published on

EC2 디스크 용량 부족 문제 발생

Authors
  • avatar
    Name
    ywj9811
    Twitter

문제의 시작

어느날, 모니터링 서버의 그라파나에 접속이 안되기 시작했다.

처음에는 너무 많은 리다이렉트가 시도되었다고 해서 크롬 브라우저 캐시가 너무 많이 쌓여서 그런건가 싶어서 캐시를 삭제했었다.

이때는 순간적으로 해결이 되었으나, 다시 다음날 접속이 안되었다.

그래서 이번에는 도커 컨테이너를 내리고, 다시 올려보았다.

그랬더니 또 접속이 다시 됐다. 그렇게 해결된 줄 알았으나, 다음날 또 접속이 안되기 시작했다.

원인 찾기

그냥 단순하게 순간적인 오류가 아닌 것 같아, 본격적으로 원인을 알아보기 시작했다.

우선, docker ps 를 통해 필요한 컨테이너가 모두 동작중인지 확인했더니, 모두 동작중이었다.

모두 정상 동작중인데, 제대로 운영이 안되기 때문에 또 다시 컨테이너를 내리고 다시 올려보려고 했다.

이때, 문제가 발생한 원인을 찾게 되었다.

ERROR: for prometheus Cannot create container for service 이런 경고가 뜨면서, no space left on device 라는 경고를 주었다.

그렇게 모니터링 서버가 현재 디스크 용량이 꽉찾다는 사실을 알게 되었다.

물론 이런 문제가 발생할 수 있다고 생각했기 때문에 cron으로 도커의 사용하지 않는 이미지와 볼륨 등등을 삭제시키도록 자정에 docker system prune -f 를 동작시키고 있었다.

하지만, 그럼에도 불구하고 디스크의 용량은 꽉차게 되었다.

이제 천천히 어느 디렉토리가 용량을 많이 차지고 있는 것인지 찾아보기로 했다.

sudo du -h --max-depth=1 이렇게 용량의 차지 공간을 확인해 보았더니 26G /var 이런 부분을 찾을 수 있었다.

프리티어 서버를 사용하는 상황에서 30G의 디스크중 26G 를 사용하고 있는 /var 는 문제가 될 수 있다.

이제 sudo du -h --max-depth=1 /var 를 통해서 /var 디렉토리의 어느 부분이 문제가 되고 있는지 확인을 해봐야 한다.

그랬더니 /var/lib/docker 에 26G 가 발견되었다…!

알고보니, 간과했던 부분이 문제가 된 것이었다.

도커 컨테이너에서 생성되는 로그 파일이 쌓여가고 있던 것이다.

그렇게 도커 컨테이너에서 로그가 쌓였고 이 로그가 관리되지 않아 26G 가까이 쌓이게 된 것이다.

문제 해결

로그 파일을 관리하며 해결하기 위해서 몇가지 방법을 찾아보았다.

  1. 로그 파일 크기 제한하기

    도커의 로깅 드라이버 설정을 통해 로그 파일의 크기를 제한할 수 있다고 한다.

    예를 들어 json-file 로깅 드라이버를 사용하는 경우 최대 크기와 로그 파일의 개수를 설정할 수 있다고 한다.

  2. 주기적으로 로그 정리하기

    이는 단순하고 직관적인 방법으로, 로그 파일을 주기적으로 정리 혹은 삭제하는 스크립트를 작성하여 cron 작업으로 설정하는 것이다.

  3. 외부 로깅 시스템 사용하기

    ELK 스택과 같은 외부 로깅 시스템을 사용해 로그를 중앙에서 관리하고 분석하는 방법 또한 있다고 한다.

  4. 로그 드라이버 변경

    다른 로그 드라이버를 사용하여, 로그를 외부 서버로 전송하는 방법 또한 가능하다고 한다.

이렇게 다양한 방법이 있다는 것을 알게 되었지만, 현재 상황에서는 1번 혹은 2번의 방법이 적절하다고 판단되었다.

아무래도, 현재 운영중인 프로젝트의 크기가 작은 점과 많은 자원을 사용할 수 없고, 백엔드를 혼자 도맡아 하는 상황에서 추가적으로 서버를 개설하거나, 외부 시스템을 추가하는 것 보다는 내부적으로 해결할 수 있는 1번 혹은 2번 방법이 적절하다고 생각했다.

그중 1번 보다는 2번의 방법을 사용하기로 하였다.

서버 시스템 관련해서 경험이 적고, 모니터링 서버 뿐만 아닌 운영 서버와 개발 서버 또한 마찬가지로 준비를 해야하기 때문에 하나의 스크립트를 작성하고 간편하게 등록할 수 있는 cron 을 사용하는 것이 효율적이라고 생각이 되었기 때문이다.

#!/bin/bash
find /var/lib/docker/containers/ -type f -name "*.log" -exec truncate -s 0 {} \;

위와 같은 스크립트 파일을 생성하고,

cron 으로 등록시켜준다.

위의 스크립트의 내용이 root 권한을 필요로 하는 것으로 확인되어 root의 cron 을 사용하여 등록하였다.

[root config]# crontab -l
0 0 * * * /usr/bin/docker system prune -f
0 1 * * * /home/ec2-user/config/clear_docker_logs.sh

이제, 위의 작업들을 나머지 서버에서도 동일하게 작업하고, 모니터링 서버에서 자신의 용량 상태 또한 모니터링 할 수 있도록 설정을 추가해주도록 했다.

모니터링 서버에 node_exporter 를 설치하고, 프로메테우스에 설정을 추가해 우선은 위험을 감지할 수 있도록 변경해주었다.