1 전제 조건
온프레미스 GPU 서버에 SSH 접속이 가능한 상태를 전제한다. SSH 접속 원리와 설정은 SSH 개요와 작동 원리를 참고한다.
접속 후 가장 먼저 해야 할 일은 서버 환경을 파악하는 것이다.
2 서버 환경 파악
2.1 GPU 확인
출력에서 확인할 항목:
| 항목 | 확인 내용 |
|---|---|
| GPU 모델 | 어떤 GPU가 몇 장 있는지 |
| VRAM | GPU당 메모리 용량 |
| Memory-Usage | 현재 사용 중인 메모리 |
| GPU-Util | GPU 사용률 |
| Processes | 어떤 프로세스가 GPU를 점유 중인지 |
2.2 GPU 점유 프로세스 확인
nvidia-smi의 Processes 섹션에 PID가 보이면, 해당 프로세스의 소유자를 확인한다.
예를 들어 root가 FastAPI 서빙 중이고 GPU 4장을 각 6GB씩 점유하고 있더라도, GPU당 VRAM이 48GB라면 나머지 42GB는 사용 가능하다.
2.3 특정 GPU 지정하여 사용
다른 사용자의 프로세스와 충돌을 피하려면 특정 GPU를 지정한다.
# 0번 GPU만 사용
CUDA_VISIBLE_DEVICES=0 python train.py
# 0, 1번 GPU 사용
CUDA_VISIBLE_DEVICES=0,1 python train.pyGPU를 사용하기 전에 담당자에게 사용 가능한 GPU 번호를 확인하는 것이 좋다. 서빙 중인 서비스가 갑자기 메모리를 더 사용할 수 있기 때문이다.
2.4 기타 환경 확인
3 pyenv로 Python 설치
온프레미스 서버에서는 보통 sudo 권한이 없다. 시스템 Python(예: 3.8)은 오래된 버전일 수 있고, 직접 업그레이드할 수도 없다. pyenv는 사용자 홈 디렉토리(~/.pyenv/)에 Python을 설치하므로 sudo가 필요 없다.
3.1 설치 및 Python 빌드
3.2 시스템 Python과 pyenv Python의 관계
pyenv는 시스템 Python을 건드리지 않는다. PATH 앞에 shim을 끼워넣어 명령을 가로채는 방식이다.
python3 입력
|
v
PATH 순서대로 탐색
|
v
~/.pyenv/shims/python3 발견 (pyenv가 가로챔)
|
v
pyenv가 현재 설정된 버전(3.11.9) 실행
--> ~/.pyenv/versions/3.11.9/bin/python3
pyenv가 없다면 /usr/bin/python3(시스템 Python)이 실행된다. pyenv는 시스템 바이너리를 수정하지 않고, 앞에서 가로채서 사용자 버전을 대신 실행해주는 구조이다.
3.3 shim이란
~/.pyenv/shims/ 안의 python3, pip, poetry 등은 실제 바이너리가 아니라 중간 스크립트(shim)이다. 이 스크립트가 pyenv에 “현재 어떤 버전을 쓸지” 물어보고, 해당 버전의 실제 바이너리를 실행한다.
# shim 내용 확인
cat ~/.pyenv/shims/python3
# → pyenv exec "$program" "$@" 형태의 bash 스크립트
# 실제 실행되는 Python 경로 확인
pyenv which python3
# → /home/user/.pyenv/versions/3.11.9/bin/python3이 구조 덕분에 pip install도 시스템이 아닌 ~/.pyenv/versions/3.11.9/lib/에 패키지를 설치한다.
pip install poetry
|
v
~/.pyenv/shims/pip → pyenv가 가로챔
|
v
~/.pyenv/versions/3.11.9/bin/pip 실행
|
v
~/.pyenv/versions/3.11.9/lib/ 에 설치됨 (시스템 아님)
4 시스템 라이브러리 누락 트러블슈팅
pyenv는 Python을 소스에서 컴파일한다. 이때 시스템에 특정 라이브러리가 없으면 해당 모듈이 빠진 채로 빌드된다. 대표적으로 libsqlite3-dev가 없으면 sqlite3 모듈이 누락된다.
4.1 증상
4.2 원인
pyenv가 Python을 컴파일할 때 시스템의 libsqlite3-dev를 찾지 못해 _sqlite3 확장 모듈을 빌드하지 않은 것이다.
4.3 해결
시스템 라이브러리는 sudo 권한이 필요하므로 인프라 담당자에게 요청한다.
# 담당자가 실행 (sudo 필요)
sudo apt install libsqlite3-dev libffi-dev libbz2-dev libreadline-dev libssl-dev라이브러리 설치 후 Python을 재빌드해야 한다. 이미 설치된 pyenv Python에는 반영되지 않는다.
# 기존 버전 삭제 후 재설치
pyenv uninstall 3.11.9
pyenv install 3.11.9
# 모듈 정상 포함 확인
~/.pyenv/versions/3.11.9/bin/python -c "import sqlite3; print('OK')"OK가 출력되면 정상이다. 이후 Poetry 가상환경도 재생성해야 한다.
5 Poetry로 프로젝트 의존성 관리
Python이 준비되면 Poetry로 프로젝트 의존성을 설치한다. Poetry 자체의 상세한 사용법은 Poetry 시리즈를 참고한다.
# Poetry 설치 (pyenv Python에 설치됨)
pip install poetry
# 프로젝트 디렉토리로 이동
cd ~/my_project
# 의존성 설치
poetry install5.1 가상환경 활성화
Poetry 2.x에서는 poetry shell이 deprecated되었다. 대신 poetry env activate를 사용한다.
# 가상환경 활성화 명령 출력 후 실행
eval $(poetry env activate)
# 또는 매번 poetry run을 붙여 실행
poetry run python train.py
poetry run jupyter notebook --no-browser --port 8888poetry run은 가상환경 안에서 명령을 실행한다. 활성화 없이도 사용 가능하지만, 매번 붙여야 하는 번거로움이 있다.
6 SSH 터널로 Jupyter 원격 접속
서버에서 Jupyter를 실행하면 브라우저가 없어 직접 접근할 수 없다. SSH 포트 포워딩으로 로컬 PC의 브라우저에서 접속한다. 포트 포워딩의 원리는 SSH 포트 포워딩과 터널링을 참고한다.
6.1 서버에서 Jupyter 실행
출력에서 토큰이 포함된 URL을 확인한다.
http://localhost:8888/tree?token=0d92c500833fd9...
6.2 로컬 PC에서 SSH 터널 열기
새 터미널을 열고 다음을 실행한다.
-L 8888:localhost:8888의 의미:
- 로컬 PC의 8888 포트로 들어오는 요청을
- SSH 암호화 통로를 통해
- 서버의 8888 포트로 전달한다
[로컬 PC] [GPU 서버]
브라우저 Jupyter (포트 8888)
| ^
| http://localhost:8888 |
v |
로컬 포트 8888 <---- SSH 터널 ----> 서버 포트 8888
6.3 브라우저에서 접속
로컬 브라우저에서 http://localhost:8888에 접속하면 로그인 화면이 나타난다. 서버 터미널 출력의 토큰을 붙여넣는다.
매번 토큰을 복사하기 번거로우면 비밀번호를 설정한다.
이후에는 설정한 비밀번호로 로그인할 수 있다.
6.4 포트 충돌 시
8888 포트를 다른 사용자가 이미 쓰고 있다면 다른 번호를 사용한다. 포트는 논리적인 번호(0~65535)이므로 서버와 터널이 같은 번호만 사용하면 된다.
# 서버
poetry run jupyter notebook --no-browser --port 9999
# 로컬 터널
ssh -L 9999:localhost:9999 kmkim@10.10.101.61 -p 30307 전체 워크플로 요약
[1] SSH 접속
ssh user@server -p 3030
[2] 환경 파악
nvidia-smi # GPU 확인
ps -p <PID> -o user,pid,cmd # 점유 프로세스 확인
[3] Python 설치 (최초 1회)
pyenv install 3.11.9
pyenv global 3.11.9
pip install poetry
[4] 프로젝트 세팅
cd ~/my_project
poetry install
[5] Jupyter 실행
poetry run jupyter notebook --no-browser --port 8888
[6] 로컬에서 SSH 터널 열기
ssh -L 8888:localhost:8888 user@server -p 3030
[7] 브라우저 접속
http://localhost:8888
[8] GPU 지정하여 학습
CUDA_VISIBLE_DEVICES=0 poetry run python train.py