오프라인 매칭 플랫폼 밥풀
의 모니터링 서버는 구글 클라우드 VM 위에 구성되어 있습니다.
그러던 어느날, 그동안 잘 접속되던 Grafana 대시보드에 로그인을 시도하니, 500 Internal Server Error
가 응답되었습니다.
당시 화면 캡쳐가 없어서 유사한 이미지를 가져왔습니다. 위 Unknown 메시지 대신 Internal Server Error
메시지와 함께 500 응답이 내려왔습니다.
원인 분석을 위해 GCP를 통한 SSH 접속을 시도했습니다. 그런데! 아래와 같이 SSH 인증 실패 SSH authentication has failed
가 발생하면서 연결되지 않는 문제가 발생했습니다.
문제해결 버튼을 클릭하면, VM은 정상 상태라는 응답 뿐 이었습니다. 원인을 파악하기 위해 VM 인스턴스 → 로깅
페이지에 진입했고, 아래와 같이 ssh 키가 만료되었다는 오류 메시지를 확인했습니다.
최초에 SSH 키를 생성할 때, 만료기한을 따로 생성해둔 적이 없었던 것으로 기억하지만, expired 되었다고 하니 새로 생성을 시도했습니다. 키 생성, 설정, 접속 방법은 다음과 같습니다.
1. SSH 키 생성
ssh-keygen -t rsa -f ~/.ssh/[KEY_FILENAME] -C [USERNAME]
KEY_FILENAME
: 생성할 키 파일의 이름 (예: gcp_key)USERNAME
: 사용자 이름 (예: hyun)2. GCP에 SSH 키 등록
3. 서버 인스턴스에 접속
ssh -i ~/.ssh/[KEY_FILENAME] [USERNAME]@[외부IP]
KEY_FILENAME
: 앞서 생성한 비공개 키 파일의 경로USERNAME
: SSH 키 생성 시 사용한 사용자 이름외부IP
: GCP 인스턴스의 외부 IP 주소하지만, 위 방법은 저에게는 해결되지 않은 시도였습니다. 동일하게 SSH 접속 시도에 실패했습니다.
이번에는 직렬포트
출력 페이지에 진입했고, 이 곳에서 해당 문제의 원인을 찾을 수 있었습니다. (직렬포트는 해당하는 VM 인스턴스 후 로그 부분에서 클릭을 통해 확인할 수 있습니다.)
이전에 gcp authentication has failed
또는 gcp ssh Permission denied (publickey)
와 같은 키워드로 검색하는 과정에서 드물게 디스크 용량이 꽉 차서 SSH 접속이 불가했다는 내용을 보았으나, 한 번도 용량이 찼던 경험이 없었고, expired 라는 로그 메시지에 꽂혀, 디스크 용량에 대해서는 차순위로 미뤄뒀었습니다. 그런데 직렬포트 출력 페이지를 확인해보니 아래와 같이 No space left on device
메시지를 확인할 수 있었습니다.
GCP 는 SSH 접속 외에도 gcloud CLI 라는 shell 을 지원합니다. 브라우저 기반의 명령줄 인터페이스로, 구글 클라우드에서 돌아가는 컴퓨팅 리소스에 접근할 수 있습니다. gcloud를 통해서도 접속을 시도하면, 아래 캡쳐와 같이 디스크에 공간이 없어 Login Service 가 정상적으로 동작하지 못한다
는 것을 확인 할 수 있었습니다.
이로써, 약 2시간의 삽질 끝에 드디어 디스크의 용량이 꽉 찼기 때문
이라는 원인을 파악했습니다.
그저 간단하게 Snapshot을 생성 → 해당 스냅샷으로 새로운 디스크를 생성 → 생성과정에서 기존 디스크보다 큰 용량을 가진 디스크를 생성 → VM에 새로 생성한 디스크를 연결
과정을 통해 VM에 정상 접속되는 행복회로를 머릿속에서 그렸으나.. 쉽게 해결되지 않았습니다.
블로그를 참고해 제가 수행한 과정은 다음과 같습니다. 참고한 링크는 이곳(GCP 부팅 디스크 용량 늘리기 : 스냅샷 활용) 입니다.
스냅샷 생성
새로운 부팅 디스크 생성
VM 인스턴스에 새 부팅 디스크 연결
VM 인스턴스 재시작 및 확인
인스턴스 수정에서 디스크 사이즈를 기존 30G 에서 40G 으로 업데이트 하고 VM을 재시작했으나, 동일하게 SSH 접속이 불가했습니다.
원인은, 자동 파티션 확장을 위한 여유 디스크 공간이 없었기 때문입니다. 즉, 디스크의 크기를 늘려준 후, VM을 재시작할 경우 자동 파티션 확장을 위해 서비스가 동작해야 합니다. 그런데, 해당 서비스가 동작하는 과정에서 필요한 로그파일을 생성하거나 파일 쓰기 작업이 수행되기 위한 여유 공간이 조금도 없었기에 자동확장이 되지 않았음을 추정할 수 있었습니다.
그러니, 여유 공간이 조금이라도 있었다면 파티션 자동확장이 되어 위 과정을 끝으로 문제가 해결되었을 것입니다.
전체 해결 과정을 크게 4단계로 요약하자면 다음과 같습니다.
1. 용량 늘린 부팅디스크 만들기
2. 임시 VM 만들어, 추가 디스크로 붙이기
3. Mount 하여 대용량 파일 줄이기
4. 원래 VM에 재연결 하기
위 단계들을
문제가 있는 VM 중지
원래VM에서 부팅 디스크를 분리
디스크 크기 증가시키기
임시 VM 생성
디스크 확인
du -sh /mnt/disk/*
/mnt/disk/var
폴더의 크기가 가장 컸다.sudo du -h /mnt/disk/var | sort -rh | head -n 20
명령어로 /mnt/disk/var
디렉토리와 그 하위 디렉토리의 크기를 계산하고, 크기 순으로 정렬한 후 상위 20개를 보여줍니다.
sudo truncate -s 0 /mnt/disk/var/lib/docker/containers/9d18351b34b0ba2a9fa8c56e3be6e3defb08a7c891dd6c4f550f721c57fb24de/*-json.log
umount /mnt/newdisk
마운트 해제
도커 로그 파일의 용량이 끝없이 늘어났던 이번 이슈를 재발방지 하기 위해 Docker 데몬 설정을 적용했습니다. 모든 컨테이너에 대해 기본 설정을 적용하려면, etc/docker/daemon.json
파일을 수정해야 합니다. 이 json-file 도커 로깅 드라이버가 기본적으로 최대 용량이 정해져있지 않기 때문에 만약 이번 모니터링 서버와 같이 로그가 많이 남는 서비스라면 저장 공간이 부족해지는 일이 발생할 수도 있습니다. 다음 명령어를 통해 daemon.json
파일 수정을 위한 vi 에디터를 실행합니다.
sudo vi /etc/docker/daemon.json
아래와 같은 설정을 적용해주었습니다. max-size
를 통해 로그 파일 크기가 5 기가에 도달하였을 때, 로그는 종료되지 않고 lotation 됩니다. 즉, 새로운 로그는 기존 파일을 덮어쓰지 않고 새 파일에 기록됩니다. 또한 max-file
을 통해 파일의 개수가 이미 3개인 경우 가장 오래된 로그파일이 삭제되고 새 파일이 생성됩니다.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "5G",
"max-file": "3"
}
}
설정이 완료되면 Docker 데몬 재시작을 해야 합니다.
이 방식으로 로그는 계속 기록되며, 지정된 크기와 파일 수를 유지합니다. 따라서 애플리케이션은 중단 없이 계속 실행되고 로그도 계속 생성됩니다. 단, 오래된 로그는 자동으로 삭제되므로 중요한 로그는 별도로 백업하는 것이 좋을 것 같다고 판단했습니다.
이 과정을 통해 디스크 공간 부족 문제를 해결하고 VM의 정상적인 작동을 복구할 수 있었습니다.
향후 유사한 문제를 방지하기 위해 정기적인 로그 관리와 디스크 사용량 모니터링의 중요성을 인식하게 되었습니다.
참고한 링크