[GCP] SSH authentication has failed 디스크 용량 부족으로 인한 SSH 접속 실패 해결
2024-01-29 작성됨
Ubuntu 20.04 LTS
Google Cloud Platform Service
얼마 전 연재했던 GCP 마인크래프트 24시간 서버 열기의 연장선이라고 할 수 있겠다
지금껏 서버에서 발생한 여러 가지 사소한 오류들을 해결해봤는데 이번 오류는 나에게 너무 힘들었다
밥 먹는 시간 빼고 5시간 내내 고군분투하다가 결국 해결해냈다
아는 사람이랑 밖에서 잠깐 만나는 중이었는데 같이 서버 운영하는 친구한테 카톡이 왔다
지난번에 마인크래프트 서버 콘솔을 연결해놓은 디스코드 채널이 랄나고 있었다..
급하게 집에 들어가서 디스코드로 마인크래프트 서버 콘솔 로그를 보니 오후 2시부터 끊임없이 오류 메세지가 출력되고 있었다
어제 오후 10시까지는 정상적으로 서버가 잘 작동하다가 오늘 오후 2시 23분부터 문제가 생겼다
[오전 2:23:29 WARN] org.sqlite.SQLiteException: [SQLITE_IOERR_SHMSIZE] I/O error within xShmMap while trying to resize an existing shared memory segment (disk I/O error)
[오전 2:23:29 WARN] at org.sqlite.core.DB.newSQLException(DB.java:1179)
[오전 2:23:29 WARN] at org.sqlite.core.DB.newSQLException(DB.java:1190)
[오전 2:23:29 WARN] at org.sqlite.core.DB.throwex(DB.java:1150)
[오전 2:23:29 WARN] at org.sqlite.core.NativeDB._exec_utf8(Native Method)
[오전 2:23:29 WARN] at org.sqlite.core.NativeDB._exec(NativeDB.java:93)
[오전 2:23:29 WARN] at org.sqlite.jdbc3.JDBC3Statement.lambda$executeLargeUpdate$2(JDBC3Statement.java:128)
[오전 2:23:29 WARN] at org.sqlite.jdbc3.JDBC3Statement.withConnectionTimeout(JDBC3Statement.java:454)
[오전 2:23:29 WARN] at org.sqlite.jdbc3.JDBC3Statement.executeLargeUpdate(JDBC3Statement.java:115)
[오전 2:23:29 WARN] at org.sqlite.jdbc3.JDBC3Statement.executeUpdate(JDBC3Statement.java:102)
[오전 2:23:29 WARN] at net.coreprotect.database.Database.performCheckpoint(Database.java:94)
[오전 2:23:29 WARN] at net.coreprotect.consumer.process.Process.processConsumer(Process.java:77)
[오전 2:23:29 WARN] at net.coreprotect.consumer.Consumer.run(Consumer.java:133)
[오전 2:23:29 WARN] at java.base/java.lang.Thread.run(Thread.java:840)(JDBC3Statement.java:115)
[오전 2:23:33 WARN] at org.sqlite.jdbc3.JDBC3Statement.executeUpdate(JDBC3Statement.java:102)
[오전 2:23:33 WARN] at net.coreprotect.database.Database.performCheckpoint(Database.java:94)
[오전 2:23:33 WARN] at net.coreprotect.consumer.process.Process.processConsumer(Process.java:77)
[오전 2:23:33 WARN] at net.coreprotect.consumer.Consumer.run(Consumer.java:133)
[오전 2:23:33 WARN] at java.base/java.lang.Thread.run(Thread.java:840)
이런 메세지가 반복적으로 출력되고 있었다
다만, 마인크래프트 서버에는 별 문제가 없었는지 경고들이 출력되는 와중에도 마인크래프트 서버에는 잘만 접속됐다
디스코드 console 채널 같은 경우 콘솔 특성상 알림이 꽤 많이 오기 때문에 알림을 비활성화해놓아서 이런 난장판이 벌어지고 있는지 몰랐다
사실 이 문제의 해결법만 알아냈고 오류 발생 원인은 잘 모르지만 내 추측이 맞긴 한 것 같으니 좀 읊어보자
해결하면서 추측해보기로는 일단 위 오류 메세지에 I/O Error가 있는 것을 알 수 있다
디스크 손상이라는데 처음에는 GCP에서 내 서버 컴퓨터를 잘못 관리해 작살낸 줄 알았다
일단 마인크래프트 서버부터 닫기 위해 GCP 인스턴스 서버에 SSH로 접근해보았다
잉?? 평소에 잘만 접속되던 SSH가 접속되지 않는다
'SSH authentication has failed'
일단 오류 메세지가 마인크래프트 서버 콘솔에 너무 많이 떠서 디스코드에 연동해두었던 console 채널을 사용해 마인크래프트 서버를 stop하고 GCP에서 인스턴스를 아예 종료했다
마냥 GCP 문제라고 볼 수만은 없는 것이 FileZilla로도 접속이 되지 않았다
참고로 FileZilla의 접속 실패 메세지는 키 파일 거부였다
조금 찾아보니까 SSH 버튼 아래의 직렬 포트 콘솔을 살펴보래서 한번 살펴봤다
mkdir: cannot create directory ‘start’: No space left on device
"No space left on device"
서버 컴퓨터에 용량이 꽉 차서 스타트 파일을 생성할 수 없어서 그런 것이었다
용량이 부족하면 SSH 키 파일을 거부한다고 한다
얼마 전에 마인크래프트 서버 인스턴스 이전을 했다
50Gb 디스크를 사용했었는데 서버 파일 용량이 5Gb도 안 되서 20Gb 디스크를 사용해도 될 것이라 판단해 20Gb로 인스턴스를 만들어 서버 이전을 한 상태였다
하지만, 내가 간과한 것이 있었다
예전에 하던 갤러리 서버에서 사용하던 Dynmap 이라는 플러그인을 사용해보고 싶어서 서버 이전을 하면서 그 플러그인을 같이 도입했다
2~3일간 fullrender를 돌렸는데 용량이 그렇게 부풀어오를지 몰랐다
마인크래프트 서버 사람들이 겉날개를 얻기 위해 엔더월드를 활발히 개척하니 엔더월드 청크가 매우 넓어져 렌더링 파일이 너무 커져서 그런가보다..
나중에 보니 Dynmap 플러그인 폴더의 Web 폴더 크기만 15Gb였다..
이전하기 전 서버 파일 용량이 3.5Gb 정도였는데 Dynmap의 영향 때문인지는 몰라도 나중에 보니 11Gb였다
엔더 월드 용량만 9Gb..
SSH로 접속할 수 없을 정도로 용량을 100.0000% 꽉꽉 야무지게 포화 상태로 먹고 있던 것이었다..
아쉽게도 Dynmap 플러그인은 포기해야했다.. ㅠㅠ
정말 신기하고 좋은 플러그인인데 서버의 안정을 위해 포기해야 하다니..
사실 해결법은 그리 어렵지 않다
용량이 꽉 찬 디스크 용량을 확장시키거나 디스크를 좀 정리해주면 된다
GCP 공식 문서에서 몇 가지 해결법들이 나왔다
1. 부팅 디스크 수정
인스턴스를 중지하면 부팅 디스크를 마운트하고 다른 디스크를 사용할 수 있다
이때 부팅 디스크로 스냅샷을 만들어 백업해놓고 새로운 디스크에 스냅샷을 넣어서 데이터를 옮길 수 있다
2. GCP Console 사용
찾다 보니까 이런 것도 있더라 GCP Console로 명령어 좀 쳐서 디스크 용량을 확장시킬 수도 있다
gcloud compute instances stop (VM_NAME)
gcloud compute disks resize (BOOT_DISK_NAME) --size=(DISK_SIZE)
gcloud compute instances start (VM_NAME)
3. GCP Shell 사용
GCP Shell로 인스턴스에 접속해 용량을 잡아먹는 파일을 삭제할 수 있는 것 같다
이렇게 간단한 해결책인데 왜 5시간씩 걸렸냐면 보통 VM은 저렇게 디스크 확장을 하면 알아서 자동으로 파일 시스템 크기가 조절된다
나도 잘 모르지만 쉽게 설명해보자면 대부분의 VM은 연결된 디스크가 50Gb에서 100Gb로 확장되면
'아 100Gb 디스크로 확장되었네, SSH를 통해 접속할 수 있는 공간이 생겼어!!'
라고 생각한다
이는 우리의 보편적인 생각에도 부합하는 것 같다
하지만 내가 사용하는 VM은 멍청한 놈인지 디스크를 100Gb로 확장해도
'아 50Gb가 꽉 차서 SSH를 실행할 수 없네ㅠㅠ'
이라고 생각한다.. 띨띨한 년
그래서 VM에게 디스크가 확장되었다고 알려주고 그에 맞는 파일 시스템을 구축하도록 해야 하는데 내가 검색했을 때는 죄다 SSH를 이용해야 하는 방법 밖에 나오지 않았다..
난 SSH조차 접속이 안 되는데..
이것저것 검색하고 이것저것 다 해보다가 삽질만 엄청 했다
만약 디스크 확장을 했을 때 자동으로 파일 시스템 크기가 조절되는 VM이라면 아래 과정을 모두 생략하고 인스턴스만 재시작해도 정상적으로 사용이 가능하다
일단 내가 접속하지 못하는 인스턴스는 20Gb 디스크를 사용 중이다
프로그램 하나가 20Gb 디스크에 파일들을 꽉꽉 야무지게 채워넣어서 VM이 SSH로 안 열린다
여기서 VM에 SSH로 접속하기 위한 최소한의 용량은 남도록 디스크를 정리해주어야 하는데 어떻게 하는지 알아보자
1. 스냅샷 생성
백업용이다
굳이 필요하지는 않지만 혹시 실수하거나 잘못될 수 있으니 스냅샷을 만들어 백업해두도록 하자
2. 디스크 생성
용량이 꽉 찬 디스크 속 데이터를 전부 유지하고 싶다면 새 디스크를 생성한다
만약, 파일 좀 지워서 원래 쓰던 디스크를 확장하지 않고 그대로 쓰려면 굳이 생성할 필요는 없다
Compute Engine의 디스크 탭에서 새 디스크를 추가할 수 있다
용량은 기존 디스크 용량 이상으로 확장해서 추가한다
기존 용량이 꽉 찬 디스크로 스냅샷을 만들어 디스크를 백업해둘 수 있다
용량 확장을 하려면 그 스냅샷을 활용해 새 디스크를 추가한다
2. 디스크 마운트
용량이 꽉 차서 사용하지 못하는 디스크를 인스턴스에서 분리한다
인스턴스를 중지해야 부팅 디스크를 분리할 수 있다
(인스턴스 >> 수정 >> 부팅 디스크 분리)
3. 새 인스턴스 생성
실제로 서비스하지는 않고 SSH만 사용해서 몇 가지 명령어만 사용하고 지울 거니까 간단하게 인스턴스를 하나 생성한다
4. 새 인스턴스 디스크 설정
인스턴스 생성 시 부팅 디스크는 뭘로 하든 상관없으나 난 Ubuntu 20.04 LTS로 진행하겠다
이때 비부팅 디스크에 기존 디스크 추가를 눌러 아까 새로 생성한 디스크를 추가한다
아까 새 디스크를 생성하지 않았다면 용량이 꽉 찬 디스크를 추가한다
5. SSH
새로 만든 깡통 인스턴스에 SSH로 접속한다
sudo lsblk
디스크 파티션 정보를 볼 수 있다
sda가 우리의 부팅 디스크이다
sdb는 아까 추가한 디스크 (용량이 꽉 찬 디스크)인데 몇 개의 디스크를 추가했느냐에 따라 디스크 이름이 다르다
(2개를 추가한 경우 sdb, sdc 등의 이름을 가짐)
여기서 정리가 필요한 파티션은 sdb1이다
sudo mkdir -p /oldD
sudo mount -o discard,defaults /dev/sdb1 /oldD
sudo chmod a+w /oldD
cd /oldD
위 명령어를 순서대로 입력한다
그러면 oldD라는 디렉토리에서 우리의 용량이 꽉 찬 드라이브에 접근할 수 있게 된다
만약 디스크 용량 확장 없이 사용할 예정이라면 rm 등의 명령어로 디스크를 정리해주자
아까 용량 확장을 한 디스크를 추가했다면 아래 더보기를 눌러보자
확장된 디스크 용량이 충분하다면 아래 단계를 진행하자
sudo df -Th
sudo lsblk
파일 시스템 크기를 나열하고 디스크 이름을 볼 수 있다
sudo parted /dev/sdb
(parted) resizepart
Partition number? 1
Warning: Partition /dev/sdb1 is being used. Are you sure you want to continue? Yes
End? 100%
(parted) quit
sudo partprobe /dev/sdb
sudo resize2fs /dev/sdb1
위 명령어들을 입력하면 파일 시스템 설정을 마칠 수 있다
umount /dev/sdb1
위 명령어를 통해 마운트 해제를 하면 SSH를 나가도 좋다
6. 디스크 분리
이제 깡통 인스턴스를 중지하고 디스크를 모두 분리하자
디스크 분리 후에는 이 인스턴스를 더 이상 쓸 일이 없으니 삭제해도 좋다
7. 기존 인스턴스 디스크 마운트
기존 인스턴스에 파일 시스템 크기 조절까지 마친 확장된 디스크를 마운트하면 성공적으로 인스턴스에 SSH로 접속할 수 있게 된다
5시간 만에 이 SSH를 보았을 때의 기분은 째진다
앞으로 검색 능력과 정보 활용 능력을 향상시켜야겠다고 생각한 하루다