MLOps 플랫폼을 구축하는 도중, 학습에 사용될 대용량 데이터, 모델 등을 저장해야 할 필요성을 느끼게 되었습니다.
여러 네트워크 스토리지 시스템 중, Network File System을 사용하기 위한 테스트를 진행하였습니다.
Network File System은 NFS Server와 NFS Client로 나뉨
두가지 모두 서로 다른 머신에서 Container 형태로 사용하는 테스트 진행
- NFS Server : Container를 띄울 시 volume mount한 경로(home/nfs-server/mount)에 모든 FIle을 저장
- NFS Server Container 이미지: erichough/nfs-server
- NFS Client : NFS Server와 mount한 host machine의 경로(home/nfs-client/mount) == container를 띄울 시 volume mount한 host 경로
1. Requirement
- host kernel에 nfs, nfsd, rpcsec_gss_krb5 module 활성화 필요
2. NFS Server Container
- nfs config 역할을 하는 export.txt 작성
- /nfsshared : nfs server container 내 nfsshare 라는 폴더를 공유
- * : 모든 client가 접근 가능
- rw : 읽기 및 쓰기 권한 가짐 (ro : read only)
- fsid = 0 : root 파일 시스템으로 지정
- async : server가 client의 요청에 비동기적으로 응답
- no_subtree_check : client가 요청하는 파일이 정확한 디렉토리의 하위에 있는지를 확인하지 않도록 설정
- no_auth_nlm : 네트워크 잠금 관리자 사용 시 인증 요구하지 않음
- insecure : client가 1024 이상의 높은 포트를 사용해도 접근 허용
- no_root_squash : cilent가 nfs server에서 root 권한 유지
/nfsshared *(rw,fsid=0,no_root_squash,async,insecure)
- container run
- `-privileged` : 컨테이너가 호스트의 커널 모듈을 접근할 수 있는 권한 부여, 보안상 취약 가능성 있음
- `-network host` : host와 동일한 네트워크 환경 사용, nfs server 접속 시 host ip로 접속할 수 있음
- `-v home/nfs-server/mount:/nfsshared` : nfs container 내 /nfsshare 경로와
- `-v home/nfs-server/exports.txt:/etc/exports` : 앞에서 정의한 nfs server config file 'exports.txt' 볼륨 매핑
docker run -d --name nfs-server --privileged \
--network host \
-v /home/nfs-server/mount:/nfsshared \
-v /home/nfs-server/exports.txt:/etc/exports \
erichough/nfs-server
- `docker logs nfs-server` 확인
==================================================================
SETTING UP ...
==================================================================
----> setup complete
==================================================================
STARTING SERVICES ...
==================================================================
----> starting rpcbind
----> starting exportfs
exportfs: /etc/exports [1]: Neither 'subtree_check' or 'no_subtree_check' specified for export "*:/shared".
Assuming default behaviour ('no_subtree_check').
NOTE: this default has changed since nfs-utils version 1.0.x
----> starting rpc.mountd on port 32767
----> starting rpc.statd on port 32765 (outgoing from port 32766)
----> starting rpc.nfsd on port 2049 with 64 server thread(s)
----> all services started normally
==================================================================
SERVER STARTUP COMPLETE
==================================================================
----> list of enabled NFS protocol versions: 3
----> list of container exports:
----> /shared *(rw,sync,insecure)
----> list of container ports that should be exposed:
----> 111 (TCP and UDP)
----> 2049 (TCP and UDP)
----> 32765 (TCP and UDP)
----> 32767 (TCP and UDP)
==================================================================
READY AND WAITING FOR NFS CLIENT CONNECTIONS
2. NFS Client Container
- host machine 2에 nfs 경로를 mount 한 후, job 실행을 위한 컨테이너(e.g. 모델 학습 컨테이너)를 띄울 때 해당 directory를 volume mount 진행
- nfs-utils 설치 필요
yum install nfs-utils
- NFS mount 요청
- sudo 권한 필요
- o nolock : NFS 파일 잠금 비활성화, 여러 클라이언트가 동시에 같은 파일에 접근할 수 있음
- `/home/nfs-client/mount` : host machine2에서 mount할 경로
sudo mount -t nfs -o nolock {nfs server host ip}:/ /home/nfs-client/mount
- mount 확인
[user@binni ~]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
... (생략)
172.12.144.10:/ 47808 92096 5712 86% home/nfs-client/mount
- container 생성
- `Mounted on`의 경로를 volume mount 진행
docker run --it --network host -v /home/nfs-client/mount:/mnt ubuntu /bin/bash
- host machine2 container(nfs-client)에서 파일을 write 후 해당 파일이 host machine 1(nfs-server) mount 경로에 저장되었는지 확인
root@1af15010:/mnt# echo "hello" > volume_test.txt
root@1af15010:/mnt# ls -al
drwxrwxrwx 2 500 500 91 Sep 7 02:10 .
drwxr-xr-x 1 root root 40 Sep 7 02:10 ..
-rw-r--r-- 1 nobody nogroup 6 Sep 7 02:10 volume_test.txt
- host machine 1의 /home/nfs-server/mount에 들어가서 파일이 생겼는지 확인 → 성공
[user@binni]$ ls
volume_test.txt
- nfs mount 옵션 확인
root@1af15010:/mnt# mount | grep nfs
172.12.144.10:/ on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr={ip},local_lock=none,addr={ip})
테스트 결과
- /etc/exports 파일에서 권한 설정 후, nfs client container에서 기본적인 read, write가 가능
- 다만, 매번 network를 통해서 파일을 r/w시 latency가 발생할 수 있기 때문에 한번 읽은 파일에 대해서 nfs client에 저장해두는 local cache 기능 추가 조사 필요
'MLOps' 카테고리의 다른 글
[Docker] Docker Network / Container와 외부의 통신은 어떻게 할까 (2) | 2024.11.02 |
---|---|
[CI/CD] Github Actions, AWS CodeDeploy, EC2와 Docker를 활용한 CI/CD 구축 | EC2에 FastAPI 배포 (1) | 2024.07.01 |
[MLOps] AWS SageMaker를 사용한 ML 모델 서빙 도전기(2) - Serverless Inference (1) | 2024.06.12 |
[MLOps] AWS SageMaker를 사용한 ML 모델 서빙 도전기! (0) | 2024.04.08 |