✍ Posted by Immersive Builder Seong
1. 시작하며
얼마 전에, MSP 기술 지원 업무를 수행하면서 클라우드 버킷 내 보관되어 있는 TB 단위의 대용량 파일 데이터(텍스트, 이미지, 영상, 문서 등 첨부파일)를 외장하드로 이관해달라는 요청사항이 있었다. 이 때, 사용한 Rclone 명령어와 전송 최적화를 고려하여 작성한 스크립트, 그리고 마이그레이션 단계에서 직면한 이슈 상황과 해당 이슈를 해결해나간 사례를 소개하고자 한다.
우선 네트워크를 통해 원격으로 데이터를 이관하는 유틸리티로는 Rclone과 Rsync가 있으며, 2가지 방법 모두 데이터를 이관함에 있어 사용하기에는 무리가 없다. 차이라고 한다면 소스/타겟 저장소의 유형이 무엇이냐와 압축 지원 여부 정도가 아닐까 한다. 경험상 소스든 타겟이든 저장소가 버킷인 경우에는 Rclone이 적합하고, 저장소가 서버에 연결된 스토리지인 경우에는 Rsync가 적합한 듯하다. 또한, Rclone은 압축을 지원하지 않는 반면, Rsync는 옵션으로 압축을 지원하는 차이가 있다. Rclone과 Rsync를 조합하여 사용하는 방법도 있으니, 상황에 따라 적절한 방법을 선택하여 진행하는 것을 권장한다.
구분 | Rclone | Rsync |
소스/타겟 저장소 | 버킷 ↔ 버킷 버킷 ↔ 물리 저장 장치 버킷 ↔ 서버 |
로컬 ↔ 서버 서버 ↔ 서버 |
압축 지원 여부 | X | O |
이전에 대용량 데이터 마이그레이션을 주제로 Rsync를 활용한 사례를 포스팅한 바 있는데, 한 번 비교해서 읽어보기 바란다.
▶ Rsync를 이용한 대용량 데이터 마이그레이션
[Migration] Rsync를 이용한 대용량 데이터 마이그레이션
✍ Posted by Immersive Builder Seong 1. 시작하며 고객사 클라우드 전환 사업을 수행하면서 정보시스템별로 최소 GB 단위에서 시작하여 최대 TB 단위에 이르는 대용량 파일 데이터(텍스트, 이미지, 영상,
okms1017.tistory.com
2. Rclone 소개
1) Rclone 이란?
Rclone은 클라우드 스토리지 서비스 간 데이터 전송, 동기화, 백업 등을 명령어 기반으로 수행할 수 있는 유틸리티이다.
Linux/Windows OS는 일반적으로 Rclone 기능을 제공하지 않으므로 사전에 OS에 맞는 유틸리티를 설치해주어야 한다.
※ 설치 및 기본 설정 방법(rclone config)은 인터넷을 검색하면 관련 자료가 많이 나오니 찾아보기 바란다.
2) 명령어 형식 및 옵션
2-1) 명령어 형식
Rclone은 copy와 sync 2개의 전송 명령어를 제공한다. copy와 sync 모두 소스에서 타겟으로 파일 복사를 수행하지만 삭제 동작에서 차이가 있다. copy는 소스에 없는 파일이 타겟에 있으면 그대로 보존하지만, sync는 소스에 없는 파일이 타겟에 있으면 삭제를 진행한다. 따라서 sync 사용 시, 타겟에 중요한 파일이 있다면 데이터 손실이 발생할 수 있으므로 유의해야 한다. 정리하면 소스와 완전히 동일하게 이관하는 것이 목적이라면 sync가 적절하고, 단순히 백업이 목적이라면 copy가 안전하다.
# 원격 저장소의 파일을 로컬 저장소로 복사 or 동기화
rclone copy [REMOTE_PATH] [LOCAL_PATH] --progress
rclone sync [REMOTE_PATH] [LOCAL_PATH] --progress
# 로컬 저장소의 파일을 원격 저장소로 복사 or 동기화
rclone copy [LOCAL_PATH] [REMOTE_PATH] --progress
rclone sync [LOCAL_PATH] [REMOTE_PATH] --progress
# 원격 저장소 디렉토리/파일 목록 확인
rclone lsd [REMOTE_PATH]
rclone lsf [REMOTE_PATH]
# 로컬 저장소 디렉토리/파일 목록 확인
rclone lsd [LOCAL_PATH]
rclone lsf [LOCAL_PATH]
2-2) 명령어 옵션
Rclone은 다양한 옵션을 제공한다. 전송 성능을 최적화하기 위해 데이터 이관을 진행하는 환경의 네트워크 대역폭, PC 사양, 디스크 I/O 등을 고려하여 적절한 옵션 값을 설정할 수 있다. 특히, 데이터 이관 프로세스를 병렬로 실행하기 위해서 --transfers, --buffer-size, --checkers, --multi-thread-streams 등 4가지 옵션을 활용하는 것이 가장 중요하다. 하나씩 살펴보면 --transfers는 동시에 전송할 수 있는 파일의 수를 의미하며, --checkers는 파일이 전송 대상인지 여부를 확인하는 옵션이다. 즉, --checkers를 통해 전송 대상을 먼저 식별한 후에 파일을 병렬로 전송하는 것이다. 따라서 --checkers 값을 --transfers 값과 동일하게 또는 크게 설정해주는 것이 좋다. 그리고 --buffer-size는 파일 하나당 버퍼 크기를 의미하는데, 이 값을 크게 설정할수록 메모리 사용량이 증가한다. 예를 들어, Rclone 프로세스의 --transfers 값을 16, --buffer-size 값을 64M으로 설정한다면 두 개의 값을 곱하여 약 1GB RAM을 할당하게 되는 것이다. 만일 PC의 RAM이 넉넉하다면 --transfers와 --buffer-size 값을 크게 설정하여 메모리를 최대로 활용할 수 있다. 마지막으로 --multi-thread-streams는 다중 스트림을 활성화하는 옵션으로 .zip, .tar와 같은 압축 파일을 포함하여 GB 단위의 대형 파일을 전송함에 있어 시간을 단축시킬 수 있다. 하지만 100MB 미만의 소용량 파일을 전송하는데 효과는 아주 미미하다.
Option | Description |
--transfers | 동시 전송 파일 개수 |
--buffer-size | 파일 버퍼 크기 |
--checkers | 파일이 전송 대상인지 여부 확인 |
--multi-thread-streams | 대형 파일 전송 시, 다중 스트림 활성화 |
--progress | 실시간 전송 속도 표시 |
--retries | 전송 실패 시, 전체 작업 최대 재시도 횟수 |
--low-level-retries | 전송 실패 시, 개별 파일 재시도 횟수 |
--log-level | 로그 레벨 |
--log-file | 전송 파일 로그 |
--local-encoding | 인코딩 형식 정의 |
--timeout | 서버에 연결된 상태에서 요청에 대한 응답시간 제한 |
--contimeout | 서버에 연결할 때 최대 대기 시간 |
--size-only | 파일 변경 여부 판단 시, 파일 크기만 비교 |
--dry-run | 실제 수행하지 않고 이관 속도만 측정 |
2-3) 사용 예시
# 원격 저장소에서 파일 복사 or 동기화
rclone copy remote_bucket:remote_bucket/remote_dir D:\local_dir --progress
rclone sync remote_bucket:remote_bucket/remote_dir D:\local_dir --progress
# 로컬 저장소에서 파일 복사 or 동기화
rclone copy D:\local_dir remote_bucket:remote_bucket/remote_dir --progress
rclone sync D:\local_dir remote_bucket:remote_bucket/remote_dir --progress
3. 이슈 상황 및 해결 과정
CT 데이터를 외장하드로 옮겨달라고?
앞서 언급하였다시피, 고객의 요청사항은 클라우드 버킷에 보관되어 있는 대용량의 파일 데이터를 외장하드로 내려받아 제출해야 하는 건이었다. 정확히는 의료기관에서 촬영한 대용량의 CT 영상과 이미지를 외장하드에 모두 담아 NIA에 전달하는 것이 목표였다. 우선적으로 해야 할 일은 버킷에 보관되어 있는 데이터의 총 용량이 얼마나 되는지 파악하는 것이다. 버킷에 접근할 수 있는 권한(access key/secret key)이 있으니, S3 브라우저를 이용해 소스 디렉토리의 총 용량이 약 1.5TB임을 확인하였다. 외장하드의 여유 공간이 약 1.81TB이니 이관하기에 공간은 충분하다.
그리고 아웃바운드 트래픽 비용이 얼마나 발생하는지 확인해야 한다. 네이버클라우드는 아웃바운드 트래픽 비용이 1TB~5TB 구간에서 GB당 100원이 발생하므로 1.5TB의 데이터를 모두 이관하는데 약 15만원 정도의 비용이 발생할 것이다. 비용 관련한 부분은 고객으로부터 문제 없다는 답변을 받았다. 예전에 7TB의 파일 데이터를 100% 이관해본 경험이 있기에, 1.5TB라면 무난히 이관할 것으로 예상했다. 앞으로 중요한 것은 전송 속도일 것이다.
버킷에서 외장하드로 내려받는 케이스였으므로 전용선이나 VPN 따위가 있을 리 없었다. 그럼 결국 회사 인터넷망을 탄다는 이야기인데, 회사 인터넷망의 대역폭과 다운로드 속도가 전송 속도에 가장 큰 영향을 미칠 것이다. 회사 인터넷망은 KT 와이파이 5G를 사용하고 있었고, 다운로드 속도를 측정해보니 약 200Mbps가 나왔다. 사내 직원들이 공유하는 네트워크 환경임에도 불구하고 이 정도 속도라면 꽤나 준수한 편이다.
소스 버킷의 총 용량과 아웃바운드 트래픽 비용 그리고 회사 네트워크 환경을 파악하였으니, 이제 결정해야 하는 건 어떤 전송 도구를 사용할 것이냐이다. 대용량 파일을 이관하기 위한 원격 유틸리티로는 Rsync와 Rclone이 대표적이고, 두 가지 도구 중에 버킷 연결에 적합한 Rclone을 사용하기로 결정을 내렸다. 먼저 윈도우용 Rclone을 설치하고 소스 버킷에 연결하여 파일 업/다운로드가 정상적으로 되는지부터 테스트를 완료했다.
자, 터미널에 Rclone 명령어를 입력하여 이관을 진행해도 아무 문제 없다.
그러나 엔지니어로서 갖추어야 할 소양이 무엇인가? 바로 자동화 아니던가.
이관을 진행하기 전에 윈도우 환경에서 실행할 수 있는 재사용이 가능한 배치 파일을 작성하기 시작했다. 소스 및 타겟 경로, 로그 파일 경로 등은 변수화하여 재사용성을 높이고, 로그 파일을 남기도록 하여 배치 프로세스의 시작 및 종료 시간과 이관 결과를 확인할 수 있도록 작성했다. 물론 Rclone의 여러 옵션들을 활용하여 이관 프로세스를 병렬로 실행하여 전송 속도를 향상시켰을 뿐만 아니라 네트워크 이슈로 프로세스 중단 시, 파일 크기를 기준으로 빠르게 재개할 수 있도록 --size-only 옵션도 적용하였다. PC의 사양이 16GB RAM 이었기에 OS나 기타 프로그램에서 점유하는 메모리를 제외하고 나머지 6GB를 전부 할당하도록 --transfers=48, --buffer-size=128M 으로 최적화 작업을 진행했다.
또한, 퇴근 이후에 PC 꺼짐 현상으로 인해 이관 프로세스가 중단되지 않도록 추가 조치를 하였다. PC가 절전 모드에 빠지지 않도록 PC의 절전 모드를 해제하고, PCI Express 해제 및 하드 디스크를 끄기로 설정했다. 그리고 나서 Rclone 배치 파일을 백그라운드로 실행시켰다. 최적화 이후 외장하드는 보란듯이 강한 모터 소리를 내며 열을 뿜어내기 시작했다.
아뿔싸. 외장하드의 여유 공간이 부족하다.
이게 웬걸. 이관 시작 이틀째 예상치 못한 난관에 봉착했다.
이관 프로세스가 멈춘 것이다.
확인해보니 총 1.5TB 중에 1.13TB를 이관하였는데 외장하드의 여유 공간이 없단다.
외장하드는 1.81TB인데 여유 공간이 없다니 이게 말이 되는가?
말이 된다. 파일 크기와 파일을 저장하기 위한 디스크 할당 크기가 다르다는 점을 간과했던 것이다.
실제로 317KB 크기의 파일 하나를 저장하는데 384KB 클러스터 크기를 할당하고 있었다. 단순히 파일 하나만 놓고 보면 고작 67KB 크기 차이지만, 이러한 소용량의 파일이 지속적으로 쌓이다보니 전체로 놓고 보았을 때 약 40%가량의 공간 낭비가 발생한 것이다. 버킷의 파일 대부분은 DCM과 JSON 형식의 소파일이 주를 이루고 있었다. 이제서야 외장하드의 파일 시스템과 클러스터 크기를 확인해보았다. exFAT 타입의 128KB로 설정되어 있었다. 즉, DCM 파일 하나를 저장하기 위해 3개의 클러스터를 할당하고 있는 것이다.
얼마나 이삿짐을 빠르게 이사할 것인지만 고려하였지, 이사할 방의 크기와 개수는 고려하지 않은 것이다.
즉, 넓은 방 안에 이사박스를 한 두개씩만 넣으니 결국에 방이 부족하고 이사박스가 남는 상황이 발생한 것이다.
이사박스의 크기에 맞게 방의 크기를 적절히 줄이고 방의 개수를 늘린다면 이사박스를 더 넣을 수 있을 것이다.
클라우드 엔지니어는 클라우드 관점에서 바라보는 시각에 익숙해져 있다.
버킷 역시 객체를 업로드할 때마다 크기가 자동으로 증가하기 때문에 여유 공간을 걱정할 필요가 없으니까 말이다.
그러나 반대의 경우라면 다른 관점이 필요하다.
버킷에서 물리 저장 장치로 다운로드할 때는 디스크의 여유 공간과 클러스터 크기를 가장 먼저 고려해야 하는 것이다.
포맷하여 재이관을 진행하다.
이를 해결하기 위한 방법은 두 가지가 있었다.
첫 번째는 외장하드를 32KB로 포맷하여 재이관을 진행하는 방법이다. 이 방법은 포맷 이후 바로 재이관 작업이 가능하나, 전송 속도가 느려지고 아웃바운드 비용이 중복으로 발생하는 부담이 있었다.
두 번째는 3TB 이상의 외장하드를 새로 구매하여 지금까지 내려받은 1.13TB 데이터를 새 외장하드로 이관한 후, 나머지 약 400GB 데이터를 버킷에서 이어서 내려받는 방법이다. 이 방법은 새 외장하드를 구매하기까지 작업을 진행할 수 없으나, 아웃바운드 비용이 추가로 발생하지 않는 특징이 있다. (그러나 새 외장하드 구매 비용이 더 나온다면 ?)
내부 협의 결과, 외장하드를 32KB로 포맷하여 재이관하는 방법으로 결정했다.
왜냐하면 아웃바운드 비용은 청구하지 않아도 된다는 답변을 받았고, 새 외장하드 구매 비용이 더 비싸다고 판단하였기 때문이다.
그래서 32KB로 포맷하여 재이관을 진행했다. 진행 상황을 모니터링하다가 약 200GB 정도 이관하였을 때 무언가 이상한 점을 발견했다. 내려받은 데이터 용량에 비해 디스크 할당 크기가 개선되지 않은 것이다. 317KB 크기의 파일 하나를 저장할 때 320KB 클러스터 크기를 할당할 것으로 예상하였으나, 여전히 384KB 클러스터 크기를 할당하고 있었다. 이유를 알 수 없었는데 알고보니 파일의 메타데이터를 저장하기 위한 공간으로 여유있게 1~2개의 클러스터를 추가로 할당한다고 하더라. 이렇게 두 번째 실패를 경험하게 된다.
이번에는 공간을 컴팩트하게 활용하기 위해 4KB로 포맷하여 재이관을 진행했다. 아웃바운드 비용은 청구하지 않으니 더 이상 비용은 고려하지 않았다. 아예 외장하드를 집으로 가져와서 5월 연휴 내내 이관 프로세스를 돌려놓았다. 허허.. 데이터는 컴팩트하게 들어가는데 전송 속도가 굼벵이다. 연휴가 끝나는 시점에 약 200GB 내려받았으니 하루에 40GB도 못 내려받은 꼴이다. 이 속도라면 1.5TB를 전부 이관하는데 적어도 한 달은 걸릴 것이다. 진행 상황을 내부적으로 공유하고 새 외장하드를 구매하는 방법 밖에 없다. 이렇게 또 한 번의 실패를 맛보았다.
대용량 데이터를 100% 이관 완료하다.
소스 버킷의 총 용량에서 1.5~2배를 감안하여 4TB 외장하드를 새로 구매하였다. 이제는 여유 공간을 계산할 필요 없이 exFAT 타입의 128KB로 포맷하여 이관을 진행하면 된다. 새 외장하드를 구매하기 전 1.13TB를 이관하는데 이틀이 소요되었으니, 1.5TB를 전부 이관하는데 3일 정도 소요될 것이다. 실제로 한 시간에 30GB씩 전송하여 데이터를 100% 이관하는데 2일 2시간 46분이 소요되었음을 로그를 통해 확인할 수 있었다. 아래 스크린샷에서 보다시피 1.49TB를 이관하기 위해 2.42TB 디스크 크기를 할당하였으며, 여유 공간으로 1.20TB가 남아 있는 것을 확인할 수 있다.
4. 이관 및 검증 스크립트 (Batch File)
1) 이관 스크립트
원격 저장소 버킷으로부터 로컬 저장소인 외장하드로 데이터를 이관하는 스크립트이다. 소스 및 타겟 경로는 환경 변수로 설정하여 필요에 따라 언제든지 변경이 가능하므로 버킷이든 물리 저장소이든 상관없이 모두 이관이 가능하다. 이관 프로세스는 설정한 옵션 값에 따라 병렬로 실행되며, 특정 이슈로 중단될 시 중단 시점부터 전송을 재개한다. 또한, 로그 파일을 생성하여 진행 상황을 주기적으로 모니터링할 수 있도록 하였다.
@echo off
chcp 65001
setlocal enabledelayedexpansion
:: Env
set RCLONE_PATH=C:\rclone\rclone.exe
set REMOTE_PATH=remote_bucket:remote_bucket/remote_dir/
set LOCAL_PATH=D:\local_dir
set LOG_FILE=C:\rclone\rclone_download.log
:retry
echo.
echo [Start Time] - %DATE% %TIME%
"%RCLONE_PATH%" sync "%REMOTE_PATH%" "%LOCAL_PATH%" ^
--size-only ^
--transfers=48 ^
--checkers=64 ^
--buffer-size=128M ^
--local-encoding="Slash,BackSlash,Del,Ctl,RightSpace,Dot,InvalidUtf8" ^
--log-file="%LOG_FILE%" ^
--log-level=INFO ^
--progress ^
--retries=10 ^
--low-level-retries=20 ^
--timeout=5m ^
--contimeout=10s
IF %ERRORLEVEL% EQU 0 (
echo.
echo All File is downloaded - %DATE% %TIME%
goto end
) ELSE (
echo.
echo [Error!] (Code %ERRORLEVEL%) - After 5 Minutes, RETRY - %DATE% %TIME%
timeout /t 300
goto retry
)
:end
echo.
echo [End Time] - %DATE% %TIME%
exit /b
2) 검증 스크립트
데이터 이관을 완료한 이후 정상적으로 이관되었는지 여부를 검증하는 스크립트이다. 파일 크기를 기준으로 빠르게 비교하기 때문에 이관 스크립트보다 시간이 덜 소요된다. 이 스크립트는 파일 크기, 총 이관 용량을 기준으로 확인하고자 할 때 유용하다. 다만, 검증이라 하면 총 데이터 용량, 디렉토리 구조, 디렉토리별 용량, 파일 크기 및 개수, 파일 권한, 체크섬 등 모든 요소를 검증해야 정확한 검증이므로 해당 스크립트는 파일 크기만 반영하고 있다는 점 참고하기 바란다.
@echo off
chcp 65001
setlocal enabledelayedexpansion
:: Env
set RCLONE_PATH=C:\rclone\rclone.exe
set REMOTE_PATH=remote_bucket:remote_bucket/remote_dir/
set LOCAL_PATH=D:\local_dir
set LOG_FILE=C:\rclone\rclone_check.log
echo.
echo [Start Integrity Check] - %DATE% %TIME%
"%RCLONE_PATH%" check "%REMOTE_PATH%" "%LOCAL_PATH%" ^
--size-only ^
--checkers=64 ^
--log-file="%LOG_FILE%" ^
--log-level=INFO ^
--stats=30s ^
--progress
IF %ERRORLEVEL% EQU 0 (
echo.
echo [Check Success] All files match! - %DATE% %TIME%
) ELSE (
echo.
echo [Check Failed] Some files are missing or mismatched. - %DATE% %TIME%
)
echo.
echo [End Integrity Check] - %DATE% %TIME%
exit /b
5. 마치며
오랜만에 대용량 데이터 마이그레이션을 진행했다.
사실 내가 이 작업을 또 하게 될 줄 전혀 몰랐다.
어찌보면 데이터 이관 작업은 다소 시간이 걸리고 주기적으로 진행 상황을 모니터링해야 하기 때문에 꽤나 지루한 작업이기도 하다. 이관 용량이 클수록 작업 시간은 그에 비례하기 때문에 굉장한 인내심을 필요로 한다.
더군다나 데이터 마이그레이션은 이관하고 끝나는 것이 아니라 검증까지 완료되어야 한다.
검증을 통해 정상 이관 여부를 체크하고, 누락되거나 에러가 발생한 파일이 있으면 재이관 또는 일부 동기화 작업을 추가로 진행해야 하는 것이다. 그러기에 할 수 있음에도 웬만하면 기피하는 업무이기도 하다.
어떻든 간에 주어진 과제이고 개인 역량으로 마무리지었다. S3 버킷에서 외장하드로 내려받는 케이스는 또 다른 경험이어서 중간에 발생한 이슈 상황과 해결 과정을 글로 풀어보고 싶었다.
요즘에는 클라우드 비용 이슈로 인해 클라우드에서 다시 온프레미스로 전환하는 사례가 많이 발생하고 있다. 이 과정에서 데이터 마이그레이션 역시 필수로 진행되어야 한다. 마찬가지로 이 글에서 공유한 스크립트를 활용해 볼 수 있을 것이다.
그럼 마치면서.
이 글이 버킷에서 대용량 데이터 이관을 고려하고 있는 엔지니어들에게 도움이 되기를 바란다.
[출처] 나의 경험
'SA > Migration' 카테고리의 다른 글
[Migration] Rsync를 이용한 대용량 데이터 마이그레이션 (8) | 2023.11.07 |
---|