NFS(Network File System)는 파일시스템을 컴퓨터끼리 공유할 수 있게 해주는 서비스이다. 즉, 여러 대의 컴퓨터(NFS 클라이언트)가 큰 용량의 하드디스크를 가진 컴퓨터(NFS 서버)로부터 서버의 하드웨어나 운영체제에 관계없이 파일시스템을 가져다 마치 자신의 파일 시스템인 것처럼 사용할 수 있게 해주는 것이 NFS의 기본 개념이다. 네트웨어나 NT, 윈도우 95에서의 파일 공유를 접해본 일이 있는 사람은 쉽게 이해할 것이다.
이러한 NFS의 개념은 적은 용량의 디스크를 가진, 또는 아예 그것조차도 없는 클라이언트를 나타나게 하였다. 그리고 이들이 NFS 서버의 대용량 파일 시스템을 공유할 수 있게 됨으로써 아무런 불편 없이 저렴하게 시스템을 사용할 수 있도록 하는 파급 효과를 낳기도 하였다.
NFS는 1985년 썬(Sun Microsystems)사가 도입했다. 원래는 하드디스크가 없는 클라이언트를 구현하기 위해 도입했었지만, 지금은 리눅스를 포함한 대부분의 유닉스가 어떤 형태로든지 NFS를 구현하고 있을 정도로 유닉스에서의 대표적인 파일 공유 방법이 되었다. 그리고, 이런 NFS의 유명함 때문에 유닉스만이 아니라 도스를 비롯한 거의 모든 OS에서도 NFS를 쓸 수 있다.
이 글은 물론 리눅스를 중심으로 설명하지만, 다른 유닉스의 시스템의 NFS도 간략하게나마
다루고자 한다. 현실적으로 NFS를 필요로 하는 네트워크가 리눅스만으로 이루어져 있는 경우는 극히 드물기 때문이다. 덧붙여 말하자면, 리눅스를 공부할 때 좋은 자세는 기본 뼈대나 개념을 충분히 파악하고 난 후, 다른 유닉스 시스템에서는 이를 어떻게 구현하고 있는 가도 살펴보는 것이다. 유닉스 시스템이 다양하긴 하지만 기본 철학과 개념은 동일하고 다만 몇몇 세부 사항에서만 약간 틀린 정도이기 때문에, 리눅스만을 공부할 때보다 약간의 신경만 더 쓰면 유닉스 시스템이 가진 다양한 맛과 향(?)을 음미할 정도의 유닉스 전문가가 될 수 있을 것이다.
1장에서는 NFS 서버에 대해서 다룬다. 서버에서 NFS를 설치하는 방법, 그리고 NFS 서버가
실행하는 중요한 데몬을 살펴보고, 서버의 환경 설정 파일인 exports 파일의 자세한 설정방법을 다룬다.
이어서, 2장에서는 NFS 클라이언트에 대해서 다룬다. NFS클라이언트를 설치하는 방법, 그리고 클라이언트의 환경 설정 방법인 fstab 파일의 자세한 설정 방법을 다룬다. 3장에서는 fstab 파일의 단점을 보완하기 위해 나온 자동 마운터 중에서 가장 유명한 amd의 사용법을 다루고, 마지막 4장에서는 유닉스 관리자 입장에서 NFS를 다룰 때 알아두어야 할 UID와 GID의 통일, 표준적인 디렉토리 명명규칙의 필요성, 외부 네트워크와 NFS를 할 때의 문제점, 전용 NFS 파일서버, 보안, 모니터링과 튜닝 등의 문제를 다룬다.
1. NFS 서버
1.1 NFS 서버 프로그램 설치
모든 유닉스 시스템은 처음 설치할 때 NFS에 필요한 파일을 설치한다. 따라서 별도의 NFS 설치 과정은 필요 없다. 리눅스도 초기 설치 과정에서 NFS가 기본으로 선택되어 있으므로 대부분의 시스템에 설치되어있을 것이다. 그러나, NFS가 설치되지 않았더라도 크게 걱정할 필요는 없다. 쉽게 새로 설치할 수 있으니 말이다.
국내에서 많이 쓰이는 레드헷 리눅스의 경우 nfs-server-???-?.rpm과 nfs-server-clients-???-?.rpm이 설치되어 있는지 살펴보면 NFS의 설치 여부를 알 수 있다.
라고 입력해보자.
Name : nfs-server
…
Name : nfs-server-clients
… |
라는 메시지가 뜨는 경우엔 NFS가 이미 설치되어 있는 것이다.
rpm -aqi |grep nfs 명령에 "no match"메시지가 뜨는 경우엔 새로 설치해주면 된다. 이미 잘 알고 있겠지만 다시 한번 반복한다면,
rpm -ivh nfs-server-???-?.rpm
rpm -ivh nfs-server-???-?.rpm |
1.2 NFS 서버 데몬
당연한 얘기지만 NFS 서버를 만들기 위해서는 관련되는 데몬 프로그램이 제대로 설정되어 실행되어야 한다. 이들 데몬 프로그램은 시스템의 rc 스크립트에 의해서 부팅할 때 자동으로 실행된다.
BSD 계열의 rc 스크립트를 쓰는 시스템에서는 대개 /etc/rc.local 파일에서 mountd나 nfsd와 같은 프로그램이 실행되고 있을 것이다. 혹시 이 부분이 주석 처리되어 있으면 주석을 제거해야 한다.
AT&T 계열의 rc 스크립트를 쓰는 시스템에서는 /etc, 혹은 /etc/rc.d 디렉토리의 하위디렉토리인 rc2.d나 rc3.d 디렉토리 밑에 S??nfs과 같은 스크립트에 의해서 실행된다. 혹시 이런 스크립트가 없다면, S??nfs라는 이름의 심볼릭 링크를 /etc/init.d/ 혹은 /etc/rc.d/init.d 디렉토리 안에 있는 NFS 실행 스크립트에 시키면 된다.
레드헷 리눅스의 경우 /etc/rc.d/rc3.d/S??nfs에 의해 부팅할 때 자동으로 실행된다.
이들 스크립트에 의해서 실행되는 데몬은 다음과 같다.
1.2.1. portmap: RPC 서비스를 TCP/UDP 포트에 연결
NFS는 썬의 XDR(아키텍쳐와 무관하게 데이터를 표현하는 방법)과 RPC(remote procedure call) 인터페이스를 기반으로 설계되었다. RPC를 이용하는 프로그램이 시작되면 그 프로그램은 자신이 제공하는 서비스와 자신이 사용하는 포트를 portmap에 등록한다. 그리고, 클라이언트는 portmap에 문의해 원하는 서버에 접근할 수 있는 방법을 알아내게 된다. 유닉스 시스템에 따라서는 portmap 대신에 rpc.portmap, 또는 rpcbind라고도 부른다.
1.2.2. rpc.mountd: 마운트 요청이 들어오면 응답
NFS 클라이언트가 서버의 파일시스템을 이용하기 위해서는 먼저 서버가 자신의 파일시스템을 NFS를 이용해 다른 호스트가 공유할 수 있도록 설정해야 한다. 이와 같은 작업을 BSD 계열 유닉스에서는 export라는 용어를, AT&T 계열 유닉스에서는 share라는 용어를 쓴다. 리눅스는 export라는 용어를 쓴다.
NFS 클라이언트가 공유된 NFS 서버의 파일시스템을 이용하기 위해서는 반드시 서버의 파일시스템을 마운트해야 한다. NFS 클라이언트가 마운트를 요청해오면, rpc.mountd 데몬이 /etc/exports 파일의 설정에 따라 마운트 요청을 처리한다.
클라이언트가 서버 파일시스템을 마운트할 수 있는 권한을 획득한 이후에도 서버와 클라이언트간에 접속이 계속 유지되는 것은 아니라는 점은 알아둘 필요가 있다. 즉, http처럼 요청이 들어오는 경우에만 접속이 이루어졌다가 더 이상 필요가 없으면 접속이 해제되는 (stateless) 방식을 취하게 된다.
유닉스 시스템에 따라서는 rpc.mountd 대신에 mountd라는 용어를 쓰기도 한다.
1.2.3. rpc.nfsd: 파일을 클라이언트에 제공
rpc.mountd가 클라이언트의 마운트 요청을 받아들이면, 클라이언트는 마운트된 파일시스템에 대해 다양한 작업을 할 수 있다. 클라이언트가 작업을 수행하면서 서버 쪽 파일시스템에 무언가를 요구하게 되면 rpc.mountd와 마찬가지로 자기 자신이 NFS 서버로서의 역할도 동시에 수행하고 있지 않다면 NFS 클라이언트가 rpc.nfsd를 실행시킬 필요는 없다.
rpc.nfsd는 포크(fork)를 통해 만들어내는 자기 복사본의 수를 몇 개로 할 것인가를 지정하는 하나의 매개변수만 받아들인다. 리눅스를 제외한 대부분의 시스템에서 적절한 수의 rpc.nfsd를 설정하는 것은 매우 중요하다. 하지만, 안타깝게도 어떤 수가 적절한 숫자인지 알 수 있는 명확한 척도는 없고, 대부분의 경우 시행착오를 통해서 알아낼 수 밖에 없다. 이 숫자가 너무 많거나 적으면 NFS의 성능은 크게 영향을 받는다.
적어도 4개의 rpc.nfsd는 실행시키는 게 일반적이다. NFS를 자주 이용하지 않는다면 4개 정도면 충분하다. 이론적으론 수백, 수천 개의 rpc.nfsd를 실행하는 것도 가능하다. 그러나, 너무 많은 rpc.nfsd를 실행하는 것도 각각의 프로세스가 CPU를 두고 서로 경쟁하기 때문에 시스템 성능을 저하시킨다.
서버의 load average(uptime audfufd으로 알 수 있다)가 급격히 많아지는 시점까지 rpc.nfsd의 숫자를 늘려보면, 시스템이 감당할 수 있는 rpc.nfsd의 최대 값은 알 수 있다. 이 최대 값에서 몇 개를 줄이면 안전한 값이 되긴 하겠지만, 이 값이 최선의 값이라는 보장은 없다. 단지 최대 값을 기준으로 한 것이기 때문이다.
또 하나의 방법은 UDP 오버플로우의 개수를 파악하는 방법이다. 부하가 많이 걸리는 NFS 서버의 경우, 모든 rpc.nfsd가 사용중일 때 또다른 요청이 들어오면 UDP 소켓이 오버플로우를 일으킬 수 있다. 오버플로우의 개수는 netstat -s 명령으로 알아볼 수 있는데, 이를 통해 UDP 소켓 오버플로우가 0으로 떨어지려면 대략 얼마나 많은 rpc.nfsd가 있어야 하는지 알아내는 것이다. 이렇게 알아낸 rpc.nfsd의 최적 값을 시스템의 rc 스크립트에 적용하면 된다.
그러나, 리눅스의 경우 rpc.nfsd를 여러 개 띄우는 것이 불가능하진 않지만, 아직 완전하게 테스트가 끝난 사항이 아니므로 권장하고 싶진 않다.
유닉스 시스템에 따라서는 rpc.nfsd 대신에 nfsd라고도 한다.
1.2.5. rpc.statd
파일 잠금의 해제와 복구를 담당한다. 리눅스에서는 실행되지 않는다.
이들 데몬이 제대로 실행되었는지를 확인하고 싶다면, 우선 rpcinfo -p 명령을 통해서 rpc.mountd와 rpc.nfsd가 portmap에 제대로 등록되었는지를 확인해본다. 등록된 이름은 실제 데몬 이름과 약간 다를 수는 있다. 이를테면 rpc.mountd가 mountd로, rpc.nfsd가 nfs로 등록될 수 있다. Ps -aux(AT&T 계열에선 ps -ef) 명령을 통해서 해당 데몬이 실행되고 있는지 확인해보는 것도 유용하다. 때로는 해당 프로세스가 제대로 작동하지 않아도 portmap에 등록되어있을 수 있기 때문이다.
1.3 파일시스템 공유 설정
대부분의 유닉스에서는 /etc/exports 파일에 어느 디렉토리(또는 파일 시스템)를 어떤 제약을 두어 공유할 것인가 하는 내용을 담는다. 아무에게나 자신의 파일 시스템을 마구 사용할 수 있게 하는 것은 마치 대문을 활짝 열어두고 사는 것과 같은 일이기 때문이다.
exports 파일의 형식은 공유하는 디렉토리를 왼쪽에 적고 그 디렉토리와 관련된 옵션이나 속성을 오른쪽에 적어 준다. 백문이 불여일견 이므로 리눅스의 exports 파일을 예로 들어보도록 하자.
/lily/users daisy(rw,no_root_squash) rose(ro)
/usr/share/man freesia(ro) clover(ro) daisy(ro) |
이 export 파일은 /lily/users 디렉토리를 daisy라는 호스트가 읽고 쓸 수 있고 루트의 권한으로 접근하는 것도 허가한 것이며, rose라는 호스트는 읽기 전용으로 마운트할 수 있게 설정한 것이다. 그리고 /usr/share/man 디렉토리에 대해서는 freesia, clover, disy가 읽기 전용으로 마운트할 수 있게끔 설정한 것이다. 중요한 옵션은 표1과 같다.
표 1)exports 옵션(리눅스)
옵션 |
설명 |
ro |
읽기만 가능하도록 마운트 |
rw |
읽고 쓰기가 가능하도록 마운트 |
no-root-squash |
루트의 자격으로 파일시스템에 접근할 수 있도록 마운트 |
root-squash |
루트의 자격으로 파일시스템에 접근하면 anonymous uid/gid로 바꿔서 허가 |
noaccess |
디렉토리를 접근하지 못하게 한다. 공유된 디렉토리의 특정 하위 디렉토리만을 접근하지 못하도록 제한하고 싶을 때 유용하다. |
리눅스의 /etc/exports 파일 형식은 다른 유닉스 시스템에 비해 특이한 편이다. 일반적인 유닉스 시스템의 exports 파일은 옵션사이엔 쉽표(,)를 쓰고, 호스트를 나열할 때는 콜론(:)을 써서 다음과 같이 나타낸다.
/lily/users -access=rose,rw=daisy,root=daisy
/usr/share/man -access
=freesia:clover:daisy,ro=freesia:clover:daisy |
exports 파일의 옵션도 유닉스마다 약간 다른데, 자주 쓰이는 옵션을 정리하면 다음 표 2,3과 같다.
옵션 |
설명 |
-access = 호스트 이름 |
파일시스템을 마운트할 수 있는 호스트(":"여러 개 나열 가능) |
-ro |
읽기 전용으로 공유 |
-rw = 호스트 이름 |
읽고 쓸 수 있는 호스트
(":"여러 개 나열 가능) |
-root = 호스트 이름 |
루트의 자격으로 파일시스템에 접근할 수 있는 호스트 (":"여러 개 나열 가능) |
-anon = 숫자 |
익명 사용자의 요청이 있을 때 부여하는 UID. 디폴트는 nobody |
표 2) exports 옵션(IRIX, HP-UX, SunOs)
옵션 |
설명 |
호스트 이름 |
지정된 호스트가 파일시스템을
마운트할 수 있다. |
-ro |
읽기 전용으로 공유 |
-root = 숫자 |
루트의 자격으로 파일시스템에 접근할 때
부여하는 UID. 지정 하지 않으면 nobody |
표 3) exports 옵션(BSDI, OSF/1)
이처럼 유닉스마다 export 옵션이 약간씩 다르므로 자세한 exports 파일 형식은 man exports 명령을 이용해 확인하는 것이 좋다.
NFS는 물리적 파일시스템을 대상으로 하는 것이 아니라 논리적 파일시스템을 대상으로 한다. 바꿔 말하면, 물리적인 파일 시스템에 구애받지 않고 어떤 디렉토리도 공유할 수 있다. 하위 디렉토리에 다른 파티션이 존재하더라도, 이를 전혀 신경 쓰지 않아도 된다.
exports 파일에 아무런 호스트도 지정하지 안고 단순히 공유할 디렉토리만 적어주게 되면 그 디렉토리는 "모든" 호스트가 마운트할 수 있게 된다. 이 경우 보안상의 문제를 불러일으킬 수 있으므로 주의해야한다. Solaris의 경우 /etc/exports 대신 /etc/dfs/dfstab 파일을 쓴다. 이 파일은 환경설정파일이라기보다는 share 명령을 실행하는 쉘스크립트다. Share 명령에 쓰이는 옵션은 SunOs의 export 옵션과 유사하다. 예를 들자면,
share -F nfs -o rw=lily:rose,root=lily /lily/users
share -F nfs -o ro=lily:rose:daisy /usr/share/man |
/etc/exports 파일을 바꿔도 당장 그 변경이 효력을 발생하진 않는다. exports 파일을 바꾼 이후에는 rpc.mountd가 설정파일을 다시 읽도록 해줘야 한다. /etc/exports 파일을 수정한 다음 이를 반영하는 절차는 유닉스 시스템에 따라 다르다. 리눅스는 exportfs 명령이 없기 때문에 kill 명령으로 rpc.mountd와 rpc.nfsd에 SIGHUP 시그널을 보내야 한다. 다음과 같은 스크립트를 /usr/sbin/exportfs라는 이름으로 저장하는 것도 한가지 방법이다.
#!/bin/sh
killall -HUP /usr/sbin/rpc.mountd
killall -HUP /usr/sbin/rpc.nfsd
echo re-exportted file system |
HP-UX, IRIX, SunOs 같은 경우는 /usr/etc/exportfs -a 명령을 실행시키면 된다. Exportfs 명령이 없는 OSF/1이나 BSDI는 kill 명령으로 mountd에 SIGHUP 시그널을 보내주어야 한다. Solaris의 경우는 특이한데, share 명령을 수행하면 mountd에게 변경된 내용을 알려주게 되므로, 수정한 /etc/dfs/dfstab 파일을 실행시켜주면 변경된 내용이 반영된게 된다.
2. NFS 클라이언트
2.2 커널 컴파일
NFS 클라이언트를 설정하기 위해서는 먼저 커널이 NFS를 지원하도록 컴파일되어 있어야 한다. 리눅스 커널은 디폴트로 NFS를 지원하도록 컴파일되어 있으므로 신경쓰지 않아도 된다. 만약 새로 커널을 컴파일할 경우에는 make config 명령을 내린 다음에,
…
*
* Filesystems
*
…
NFS filesystem support (CONFIG_NFS_FS)
[M/n/y/?] |
이와 같은 부분이 나왔을 때 M 또는 Y를 선택해주면 된다. M을 선택한 경우는 모듈로 컴파일하게 된다. 별로 그럴 일은 없겠지만, 만약 하드디스크가 없는 클라이언트를 구성하고 싶다면 반드시 Y를 선택해야 한다. 다른 유닉스 시스템의 커널도 디폴트로 NFS를 지원하도록 컴파일되어 있다.
2.2 NFS 클라이언트 프로그램 설치
모든 유닉스 시스템은 설치 과정에서 NFS에 필요한 파일을 설치한다. 따라서 별도의 NFS 클라이언트 프로그램 설치는 필요 없다. 리눅스도 NFS 클라이언트로 동작하기 위해서 특별히 설치해줘야 하는 프로그램은 없다. 레드헷 리눅스의 경우, nfs-server-clients-???-?.rpm를 설치하면 한두가지 유틸리티가 설치되지만, 반드시 필요한 것은 아니다.
2.3 NFS 클라이언트 데몬
NFS 클라이언트가 실행시키는 데몬은 nfsiod 하나정도밖에 없다. 엄격히 말해 필수적인 데몬은 아니지만, 반드시 이 데몬을 실행하길 바란다. 하지만, 리눅스의 경우는 커널 차원에서 nfsiod를 지원하므로 이 데몬에 신경 쓰지 않아도 된다.
2.3.1 nfsiod: 클라이언트 쪽의 캐쉬를 담당
NFS의 성능을 전반적으로 향상시키기 위해서 대부분의 시스템은 자동으로 nfsiod를 실행하게끔 하고 있다. nfsiod 데몬은 기본적인 캐쉬 기능(read-ahead, write-behind)을 제공한다.
리눅스를 제외한 보통의 시스템에서는 rpc.nfsd처럼 nfsiod도 그 매개변수로 자기 복사본의 수를 몇 개로 할 것인가를 지정한다. Rpc.nfsd에 적용한 규칙을 그래도 nfsiod에 적용할 수 있다. 만약, NFS 서버와 클라이언트의 역할을 동시에 한다면 프로세스의 최적값을 rpc.nfsd와 nfsiod 사이에 적절하게 나누는 것이 좋다. 물론 적절한 값은 시스템에 따라, 그리고 어느 정도로 사용하느냐에 따라 다를 수 있다.
리눅스, BSDI, OSF/1을 제외한 다른 유닉스에서는 nfsiod라는 이름 대신에 biod(block I/O 데몬)라는 이름을 쓰는 것이 일반적이다.
2.4 파일시스템 마운트 설정
커널이 지원해주고 nfsiod 데몬이 실행된다면, 남은 일은 NFS 파일시스템을 마운트해서 쓰는 일 뿐이다. NFS 서버의 파일시스템을 마운트하기 위해서는 mount 명령의 장치(device) 이름을 적는 자리에 다음과 같은 방법으로 NFS서버의 파일시스템을 지정하면 된다.
이 의미는 lily라는 호스트의 /usr/share/man 디렉토리를 의미한다. 따라서, lily라는 호스트의 /usr/share/man 디렉토리를 /usr/share/man 디렉토리에 마운트하려면,
mount -t nfs -o soft,intr lily:/usr/share/man
/usr/share/man |
과 같은 명령을 주면 된다. 여기에서 soft,intr 등은 NFS 파일시스템을 마운트할 때 쓰이는 옵션이다.
유닉스 시스템간에 공통된 옵션은 표 4와 같다.
옵션 |
설명 |
rw |
읽고 쓰기가 가능하게 파일시스템을 마운트(서버에서 rw로 공유해야) |
ro |
읽기 전용으로 마운트 |
bg |
만약 첫 번째 NFS 마운트 시도가 타임아웃에 걸리면 파일 시스템을 백그라운드로 마운트시킬 것을 알려주는 옵션. 이것은 NFS로 파일시스템을 공유하는 여러 호스트를 동시에 부팅할 때 편리한 옵션이다. 호스트 A와 B가 동시에 부팅 한다고 생각해보자. 호스트 A는 호스트 B의 파일시스템을 마운트하려 들지만, 이 때 호스트 B도 부팅 중이어서 호스트 B의 파일시스템이 아직 공유되지 않았을 수 있다. 이때 호스트 A는 마운트가 바로 되지 않으면 일단 mount 명령을 백그라운드로 수행하게 되는 것이다. 불행하게도 리눅스에서 아직까지는 이 옵션을 받아들이긴 하지만 그냥 무시해버린다. |
hard |
NFS 서버가 다운되었을 때 서버가 응답이 있을 때까지 끝없이 마운트 시도를 한다. 이때 클라이언트 쪽에서 이를 해제할 수도 없다. 이 같은 hard 마운트는 하드디스크 없는 컴퓨터가 부트 서버(boot server)의 파일 시스템중 루트 파티션이나 스왑 파티션을 마운트할 때 유용하다. 즉 hard 마운트는 핵심적인 파일시스템에 대해서 행하는 것이 좋다. 디폴트값은 hard다. |
soft |
NFS 서버가 다운되었을 때, hard 마운트와 달리 에러를 내고 마운트 시도를 중단한다. 이 옵션은 중요하지 않은 파일시스템에 대한 마운트 시도 때문에 시스템의 프로세스가 더 이상 수행되지 않는 최악의 상황을 피하는데 유용하다. |
retrans=숫자 |
soft마운트의 경우, 마운트가 되지 않아 에러를 출력하기 전에 몇 번 재 시도할지를 지정한다. 리눅스의 rudd 기본 값은 3이다. |
timeo=숫자 |
타임아웃이 생기고 나서 첫 번째 재전송요구를 보낼 때 사용되는 시간이다. 네트웍 속도가 느리거나 서버 자체가 느리다든지 여러 개의 라우터와 게이트웨이를 거칠 때는 타임 아웃 시간을 늘려주는 것이 좋다. |
intr |
사용자가 마운트 시도를 중단시킬 수 있도록 한다. |
raize=숫자 |
NFS 서버로부터 읽어 들이는 바이트 수를 지정한다. 기본 값은 커널에 따라 다른데 리눅스의 겨우 현재로서는 1024바이트이다. |
wsize=숫자 |
NFS 서버에 쓰기를 할 때 사용하는 바이트 수를 정한다. 기본값은 커널에 따라 다른데 리눅스의 경우 현재로서는 1024바이트이다. |
nosuid |
마운트된 파일시스템에서 setuid 비트가 붙은 파일을 실행시킬 때 setuid의 효과가 일어나지 못하도록 OS 차원에서 막아 주는 역할을 한다. 따라서 security 문제를 좀더 신경 쓰고 싶은 경우 nosuid로 마운트 시켜야 한다. |
표 4) NFS와 관련된 마운트 옵션
2.4.1 /etc/fstab을 이용한 설정
mount 명령을 통해 NFS 파일시스템을 마운트 시켰을 경우, 시스템이 재부팅 되면 다시 원래 상태대로 돌아가므로 임시로 마운트 할 때밖에는 쓰이지 않는다. 그러나 보통의 경우 시스템의 영구적인 설정으로 마운트를 하려면 /etc/fstab 파일에 이를 정의하거나 아니면 자동으로 마운트를 관리해주는 자동마운터를 쓰는 게 일반적이다.
모든 시스템에서 /etc/fstab 파일을 쓰는 것은 아니다. Solaris의 경우 /etc/fstab 파일이 아니라 /etc/vfstab 파일을 사용한다. 마찬가지로 Sco Unix에서는 /etc/default/filesys 파일에, AIX는 /etc/filesystems 파일을 사용한다. 이 파일들은 /etc/fstab 파일에 비해 형식이 약간씩 틀리지만, NFS에 대한 옵션은 동일하다.
다음 /etc/fstab 파일은 lily 호스트의 /lily/users 디렉토리와 daisy 호스트의 /usr/share/man 디렉토리를 마운트하는 예를 보여주는 것이다.
lily:/lily/users /lily/users nfs rw,bg,intr,hard 0 0
daisy:/usr/share/man /usr/share/man nfs ro,bg,intr,soft 0 0 |
위의 예에서 /etc/fstab 파일의 왼쪽 4번째 항목은 NFS 마운트를 위한 옵션을 지정하는 곳이다. 여기에 쓰이는 옵션은 mount 명령에 쓰였던 옵션(위의 표 ?)과 같다.
hard 옵션으로 파일시스템을 마운트한 컴퓨터는 서버가 다운되었을 때 시스템의 프로세스를 더 이상 진행하지 못하고 정지해버린다. 즉, 서버가 다운되었을 때, 클라이언트 마저 멈춰버리는 것이다. 따라서, 일반적으로 soft 옵션과 intr 옵션을 쓰는 것이 NFS와 관련한 여러 골치 아픈 문제를 줄이는 방법이다. 그러나 이 옵션은 약간의 바람직하지 못한 측면도 있다. 이를테면 20시간이 걸리는 시뮬레이션을 돌리고 있는데 사소한 네트워크 장애 때문에 18시간이나 돌린 시뮬레이션이 종료되어버리는 일도 발생할 수 있다.
/etc/fstab 파일이 바뀐 것을 즉각 반영해주기 위해서는 mount -a -t nfs 명령을 실행해주면 된다. 그리고, etc/fstab에 항목을 추가할 때는 마운트가 될 디렉토리(mount point)를 미리 만들어줘야 한다.
3. 자동마운터
대규모 네트워크에서는 많은 파일시스템을 마운트해야 하므로 /etc/fstab 파일의 내용이 상당히 복잡해진다. 이로 인해 한꺼번에 많은 파일시스템을 /etc/fstab 파일을 통해 마운트하는 것은 골치 아픈 문제를 불러일으킨다.
첫째, /etc/fstab 파일을 유지 보수하는데 상당한 시간과 노력이 들어간다. 수십 개의 NFS 클라이언트가 있고, 그 각각의 /etc/fstab 파일에 수십 개의 NFS 서버를 나열한다고 생각해보자. 각각의 컴퓨터마다 /etc/fstab 내용이 조금씩 달라야 하기 때문에 하나하나의 /etc/fstab 파일마다 주의를 기울여야 한다.
둘째, 클라이언트가 수십 개 혹은 그 이상의 NFS 파티션을 마운트했을 때, 이 중 하나의 서버만 다운되어도 클라이언트의 프로세스가 완전히 멈춰버릴 수 있다.
셋째, 중요한 서버가 다운되면, 설령 클라이언트까지 다운되지 않더라도, 사용자들이 중요한 파일시스템, 이를테면 /usr/share/man 등을 사용할 수 없게 된다. 이 경우 백업 서버로부터 임시로 파일시스템의 복사 본을 마운트할 수 있어야 하는데, /etc/fstab 파일을 가지고는 이런 경우 대처할 방안이 없다.
자동마운터는 파일시스템이 필요할 때 마운트하고 필요없을 때 마운트를 해제한다. 사용자는 /etc/fstab 파일을 이용한 방법과 아무런 차이를 느끼지 못하지만, 이 방법을 통해 실제 마운트된 파일 시스템의 수를 최소화되고 따라서 문제 발생 가능성 자체를 줄어든다. 대부분의 자동마운터는 중요한 파일서버가 다운되었을 때에도 자동으로 백업서버를 마운트해 계속 작업을 수행할 수 있도록 하는게 가능하다.
자동마운터는 가상 파일시스템을 만들고, 네트워크상의 실제 파일시스템을 거기에 대응시킨다. 사용자가 가상 파일시스템을 이용하려 하면 자동마운터는 그 시도를 인식해서 실제 파일시스템을 마운트한다. 그리고 마운트한 파일시스템을 가상 디렉토리에 심볼릭 링크해 마치 가상 파일시스템을 실제 파일시스템인 것처럼 보이게 하는 환상을 만들어낸다.
자동마운터에 대한 아이디어는 원래 썬에서 나왔다. 썬의 자동마운터인 automount는 대부분의 썬 호환 NFS 시스템에 탑재되어왔다. 그러나 불행하게도 automount는 버그와 디자인 오류 등으로 인해 amd에 비해 기술적으로 많이 떨어진다.
런던 임페리얼 칼리지의 Jan-Simon Pendry에 의해 만들어진 amd는 썬의 아이디어를 확장한 박사학위 논문의 결과이다. amd는 automount의 심각한 결점을 많이 고쳤고 공개이므로 많은 유닉스 버전에 포팅 되었다. 따라서 가능하다면 amd를 쓰는 것을 권장한다.
3.1. amd
amd는 automount에 비해 다음과 같은 이점을 가진다.
-> amd를 사용하는 클라이언트는 NFS 서버가 다운되는 경우에도 같이 다운되지 않는다.
-> amd는 일정한 간격으로 NFS 서버가 살아있는지를 확인하는 메시지를 보내고,
접속 가능한 서버 목록을 보관한다. amd는 이 정보에 기초해 파일시스템을 마운트하거나
혹은 마운트를 해제한다. 만약 서버가 다운된다 해도, 클라이언트마저 다운되지 않도록
이 서버에 대한 마운트 시도를 중지하고 에러 메시지를 사용자에게 보여준다.
-> amd는 소스코드가 공개되어 있어 20개 이상의 유닉스버전에 포팅 되어 있다.
그리고, 리눅스는 무론이고 BSDI와 OSF/1에는 OS 설치할 때 기본으로 포함된다.
-> amd는 텍스트 파일은 물론이고 NIS, Hesiod, ndbm같은 여러 가지 유형의 데이터베이스
파일, 심지어 홈디렉토리를 마운트할 경우에는 /etc/passwd 파일도 설정 파일로 선택할
수 있다.
-> amd는 amd에 의한 마운트 상황을 알려주고 여러 가지 유용한 명령 (예를 들면 강제
마운트 해제)을 실행할 수 있는 도구인 amq 프로그램을 제공한다.
-> amd 설정파일의 구조는 automount 설정파일의 구조보다 더 일반적이다.
그러므로, 똑 같은 설정파일 파일이라도 다른 호스트에 쓰이면 그 호스트에 맞게 동작
하도록 설정할 수 있다. 따라서 수백 개의 NFS 클라이언트가 있더라도 모든 호스트에
동일한 amd 설정파일을 쓸 수 있다.
-> amd는 개념적으로 일관성 있는 파일시스템 개념을 사용하므로 automount보다
하위 디렉토리등을 간단하게 다룰 수 있다.
3.2. amd의 설치
amd가 설치되어있지 않은 유닉스 시스템은 인터넷에서 소스코드를 받아와서 컴파일해 설치할 수 있다. Amd를 받을 수 있는 ftp 서버는 ftp://ftp.cs.umn.edu/pub/AMD/나 ftp://ftp.eunet.fr/.01/network/amd/ 등 여러 군데가 있다.
영문 레드햇 배포판 사용자는 amd-???-?.rpm 파일을 설치해주면 된다. 국내에서 만들어진 알짜 레드햇 배포판에는 amd가 어쩐 일인지 빠져있으나 당황할 필요는 없다. 패치맨 CD의 excluded 디렉토리에 rpm 파일이 보관되어 있으므로 이것을 이용해 설치하면 된다. 설치방법은 rpm -ivh amd-???-?.rpm 명령을 실행시켜주면 된다.
3.3 amd의 실행 및 종료
amd의 명령행 옵션은 다양하지만, 주로 다음과 같은 옵션을 써서 실행시킨다.
amd -a /.automount -l syslog / net/ etc/amd.conf |
여기서 -a는 실제 마운트되는 디렉토리를 지정하는 옵션이고 디폴트값은 /a이다. 그리고 -l 다음에는 로그 파일 이름이나 syslog를 써주는데, 에러 메시지를 기록하기 위한 옵션이다. 그 다음 아무런 옵션없이 적어주는 디렉토리는 가상으로 마운트되는 디렉토리를 뜻하고, 마지막에 적어주는 파일 이름은 amd의 설정 파일 이름이 된다. 따라서, 위 명령은 실제 마운트되는 디렉토리가 /.automount이고, syslog에 의해서 로그를 기록하며, 가상으로 마운트되는 디렉토리는 /net, 그리고 amd 설정파일은 /etc/amd.conf로 한다는 뜻이다.
amd를 강제로 종료하면 amd의 가상 파일시스템을 안전하게 제거할 수 없다. 따라서 amd를 종료하기 위해서는 amd에 kill 명령으로 SIGTERM 시그널을 주는 방식을 택해야 한다.
부팅될 때마다 자동으로 수행되게 하기 위해서는 BSD계열 유닉스의 경우 /etc/rc.local 파일에 위의 내용을 추가 하면 된다. AT&T 계열 유닉스에서는 위의 내용으로 /etc/init.d/amd 또는 /etc/rc.d/init.d/amd라는 스크립트를 만들고, 이 스크립트에 /etc, 혹은 /etc/rc.d 디렉토리의 하위디렉토리인 rc2.d나 rc3.d 디렉토리 밑에 S??amd라는 심볼릭 링크를 만들면 된다.
레드햇 리눅스의 경우 amd를 설치하면 자동으로 실행 스크립트까지 만들어준다. amd를 실행시키기 위해서는 /etc/rc.d/init.d/amd start 명령을 실행시키기 위해서는 /etc/rc.d/init.d/amd start 명령을 실행시키거나 시스템을 재부팅 시키면 된다. 그리고 amd를 종료하기 위해서는 /etc/rc.d/init.d/amd stop 명령을 실행시키면 된다.
사용자가 amd 설정파일에 정의된 가상 마운트 디렉토리 밑의 파일시스템을 이용하려 하면, amd는 파일시스템을 마운트하고, 사용 상황을 계속적으로 모니터 한다. 마운트한 파일시스템을 일정한 시간이 지나도록 아무도 사용하지 않으면 amd는 마운트를 해제하고 다시 사용될 때를 기다린다.
마운트 상태를 보기 위해서는 amq 명령을 이용하면 된다.
3.4. amd의 설정
amd 설정파일의 구조는 매우 유연하여 하나의 설정을 가지고 여러 컴퓨터에 사용될 수 있다. amd 설정파일에 나열된 각 파일 시스템은 연관된 마운트 형식을 가지고 있어야 한다. 가장 흔한 마운트 형식이 표 5에 나열되어 있다.
옵션 |
설명 |
nfs |
NFS서버의 공유 디렉토리를 일반적인 방식으로 마운트 |
ufs |
로컬 파일시스템을 일반적인 방식으로 마운트 |
host |
NFS 서버의 공유 디렉토리를 전체 경로 명까지 포함해 마운트 |
nfsx |
/usr/man이나 /usr/local/man과 같은 설정파일의 한 항목에 열거된 NFS 서버에 있는 여러 공유디렉토리를 동시에 마운트 |
program |
특수한 파일시스템의 경우 마운트 또는 마운트를 해제하기 위한 용도의 프로그램이 따로 있다. 이런 파일시스템을 다룰 때 사용. |
link |
amd를 통해 어떤 디렉토리든지 접근할 수 있도록 실제 마운트 디렉토리를 가리키는 심볼릭 링크 생성 |
auto |
이미 존재하는 마운트 디렉토리 아래에 새로운 자동마운트 디렉토리를 생성. 주로 중요한 서버가 다운되었을 때 백업 서버를 마운트하는 용도로 사용된다. |
direct |
가상 디렉토리 밑이 아니라 다른 디렉토리로 마운트 |
union |
여러 개의 디렉토리를 합쳐서 하나의 디렉토리로 마운트 (예를 들어 /tmp와 /var/tmp를 합치기) |
표 5) 흔히 사용되는 amd 마운트 형식
특정한 조건, 이를테면 특정한 호스트나 하드웨어 형태에서만 실행되도록 설정파일을 구성할 수도 있다. 이런 조건은 변수를 사용해서 '{변수명}' 형식으로 표시한다. 이용 가능한 변수는 표 6에 나열되어 있다.
변수 |
설명 |
arch |
호스트의 하드웨어 구조(architecture) |
autodir |
파일 시스템이 마운트되는 디폴트 디렉토리 |
byte |
시스템의 byte ordering("little" 아니면 "big") |
cluster |
호스트의 집합체 이름, 디폴트는 domain |
domain |
NIS 도메인 이름 |
host |
호스트 이름 |
hostd |
호스트 이름 + 도메인 이름 |
karch |
커널 구조(디폴트값은 arch 변수의 값과 같다) |
key |
해석된 볼륨 이름 |
map |
사용된 마운트 설정파일의 이름 |
os |
OS 종류 |
wire |
랜카드가 연결되어 있는 네트워크 이름 |
표 6) amd 설정파일에서 사용 가능한 변수
"rw,soft,timeo=10,retrans=5"로 지정한 것이다. '이름=값' '이름=값' 같은 형식은 조건문을 나타낸다. 조건문의 오른쪽에 적힌 내용은 조건문이 참일 경우에만 쓰인다. ${autodir}이나 ${key} 자리에는 해당 변수값이 들어가게 된다.
이 amd 설정파일은 /usr/man, /cs/tools 두 가지 파일 시스템들에 대해 정의한 것이다. /default 항목은 명시적으로 옵션을 지정하지 않았을 경우 모든 항목에 적용되는 디폴트값을 지정한다. Mad 설정파일에서 쓰이는 옵션은 다음 표 7에 나와 있다.
옵션 |
설명 |
rhost |
특정 볼륨이 존재하는 NFS 서버 |
rfs
type |
NFS 파일시스템 이름
마운트 형태 |
fs |
마운트 포인트 |
표 7) amd 설정파일 옵션
3.5. 백업서버 지정
automount처럼 amd도 특정 파일시스템에 대해 복수의 서버를 지정하는 것이 가능하다. 그러나 amd는 대부분의 경우에 주서버가 사용중에 다운되더라도 파일시스템의 마운트를 해제하고 곧바로 백업 서버를 마운트할 수 있는 부가적인 능력이 있다.
다음 예제는 /usr/man 디렉토리를 lily와 daisy 두 개의 서버에서 마운트하도록 설정한 것이다.
/default opts:=rw,soft,timeo=10,retrans=5
usr/man host==lily;type:=ufs;dev:=/dev/sdlf ||
host==daisy;type:=ufs;dev:=/dev/sd3c ||
rhost:=lily rhost:=daisy;rfs:=/${key};
type:=nfs;fs:=${autodir}/${key} |
3.6. 간단한 사용 예
아주 복잡한 마운트도 amd 설정파일을 정의하기에 따라 간단하게 할 수 있다. 한번 다양하게 마운트를 시도해보기 바란다.
그러나, amd의 이런 설정방식이 어렵게 트껴진다면, 다음과 같은 설정 파일을 /etc/amd.conf라는 이름으로 저장하고, 가상 마운트 디렉토리를 /net으로 해서 mad를 실행해보자.
ls /net 명령을 내리면 /net 디렉토리에는 아무런 파일도
/defaultstype:=host;fs:
=${autodir}/${rhost}/root;rhost:=${key}
* opts=rw,nosuid,grpi |
|