스냅샷(snapshot). 특정 시간대를 기준으로 읽기만 가능한 복제파일을 만들 수 있다. 나중에 문제가 생겨면, 스냅샷 파일이 만들어진 시점으로 복구 할 수 있다. 뒤에 자세히 살펴보자.
압축. 실행 중에 읽기와 쓰기에 대해서 압축이 된다.
NFS, SMB, iSCSI등의 볼륨 및 파일 시스템 공유 프로토콜 제공. 이들 프로토콜에 대한 툴들은 이미 나와 있는 것 아니냐라고 할 수 있겠다. 중요한 점은 이들 기능이 zfs 와 통합되 있다는 점이다. 전문 엔지니어가 아니더라도 간단하게 관리 할 수 있다.
ZFS의 라이센스와 리눅스 커널 지원
ZFS는 오라클에서 개발한 파일 시스템으로 2006년 솔라리스 10에 처음 적용됐다. CDDL이라는 오픈소스 라이센스 정책을 따르고 있어서 리눅스에 적용하는게 별 문제가 없는 것 같지만 GPL과 충돌하는 요소가 있어서, 리눅스 커널에 직접 포함되진 못하고 있다. 대신 커널 모듈 형식으로 개발하고 있다. 2015년 현재 ZFS 리눅스 커널 모듈의 버전은 0.6.4다. 1.0이 아니지만 관련 커뮤니티에서는 사실상 안정화 버전으로 보고 있는 상태다. 코드자체가 오픈소스로 풀린 마당이니, 충분한 안정성을 보장하고 있다고 볼 수 있겠다. 실제 우분투 리눅스의 경우 ZFS Stable Release for Ubuntu 라면서 패키지를 배포하고 있다. 또한 ZFS 파일 시스템을 우분투의 표준 파일 시스템으로 사용 할 계획을 가지고 있음을 밝힌 기사도 있다. 리눅스 ZFS의 역사를 살펴보자.
2008 : 사용가능성을 확인하기 위한 프로토 타이핑
2009 : 기본적인 ZVOL과 Lustre 지원
2010 : Github로 옮김
2011 : POSIX 레이어 추가
2012 : production usage ZFS
2013 : 안정된 GA
릴리즈
(2015년)현재 우분투와 젠투 리눅스는 ZFS를 잘 지원하고 있다. 루트 파일 시스템을 지원하고 있으며 곧 정식으로 지원하게 될 것으로 예상된다. 레퍼런스가 충분하지 않은 것 같지만, 사용하기엔 문제 없다 대충 이런 평가를 내리면 될 것 같다.
ZFS 관련 용어들
zpool
논리적 볼륨이다. ZFS는 물리적인 디스크를 논리적으로 재 구성한 vdev를 만든다. 이 vdev를 다시 묶은 것이 zpool이다. 물리적인 디스크들을 논리적으로 묶을 수 있기 때문에 소프트웨어만으로 RAID 시스템을 만들 수 있다. 리눅스에서 VLM으로 논리적인 디스크를 만들고 mdadm으로 소프트웨어 RAID를 구축하는 것과 매우 비슷하다.
vdev
zpool을 구성하는 요소다. Virtual Device(가상 장치)의 줄임말로 물리적인 디스크와 zpool 사이에 존재하는 추상화된 계층이다. 즉 ZFS는 물리적인 디스크 < vdev < zpool의 구성을 가지는데, LVM의 PV < VG < LV 의 관계와 비슷하다고 보면 되겠다. vdev 들은 몇 가지 구성 타입을 가지고 있다.
RAID 타입 vdev
Stripe : RAID0에 대응
Mirror : RAID1에 대응
Raidz1/z2/z3 : 패리티를 몇 개 두느냐에 따라 달라진다. raidz1은 RAID5, raidz2는 RAID6에 대응된다.
cache : L2ARC로 쓰이는 vdev다. RAM에 있는 ARC 캐시의 보조(2차)캐시다.
Log 타입 vdev
Seperate intent LOG다. 동기쓰기를 비동기 쓰기처럼 동적하게 할 수 있다. 데이터쓰기에는 동기 쓰기 와 비동기 쓰기가 있다.
데이터 쓰기를 요청하면, 운영체제는 데이터를 RAM의 캐시에 기록한다. 이 캐시에 기록된 내용이 실제 디스크까지 저장되는 것이 확인돼야 쓰기 요청이 완료된다. 완료까지 프로그램은 대기를 해야 하기 때문에 프로그램의 수행 속도가 느려지게 된다. 물론 "데이터가 안전하게 저장된다"는 동기화의 장점을 누릴 수 있다.
비동기는 RAM 캐시에 기록된걸 확인하면 쓰기 요청이 완료된다. 상대적으로 느린 디스크 쓰기 작업을 기다릴 필요가 없기 때문에, 소프트웨어가 빠르게 작동하는 장점이 있다. 반면 쓰기 명령 수행과 실제로 디스크에 데이터를 쓰는 시간이 일치하지 않기 때문에, 예상치 못한 상황에서 데이터가 유실될 수 있는 문제가 있다.
SLOG를 이용하면 비동기적인 방식으로 작동하면서, 데이터의 안정성까지 확보할 수 있다. 기본 개념은 단순하다.
소프트웨어가 요청한 쓰게 데이터는 메모리와 SLOG에 모두 저장된다.
SLOG에 쓰기가 끝나면, ZFS는 애플리케이션에 쓰기 완료 메시지를 보낸다.
디스크에 데이터가 저장된다.
동기쓰기이지만 마치 비동기처럼 작동한다. 당연한 이야기지만 SLOG vdev가 디스크보다 충분히 빨라야 지만 성능 효과를 볼 수 있다. 달리 말해서 이미 SSD를 데이터 저장 매체로 사용하고 있다면 SLOG를 운용해봐야 별 효과를 누릴 수 없다는 이야기. 이미 SSD를 데이터 저장 매체로 사용하고 있다면, zpool에 그냥 붙여도 상관 없다.
Dataset
일반적인 파일시스템에 해당하는 부분이다. 애플리케이션이 실제 사용하는 공간이다. 논리적인 디스크위에 구축되기 때문에, 물리적인 특성과 상관없이 관리 할 수 있다. 데이터셋 안에 새로운 데이터셋을 만들 수 있고(예컨데, 파티션 안에 다른 파티션을 만드는게 가능하다.), 용량도 마음대로 조절 할 수 있다.
scrub
Silent corruption을 방지 한다. 100% 안전한 매체는 없다. 디스크는 그냥 가만히 둬도 여러가지 이유로 비트가 변경될 수 있다. 이렇게 변질된 데이터는 바로 검출 할 수 없기 때문에 위험할 수 있다. ZFS의 scrub 명령을 이용하면, 디스크의 메타데이터와 체크섬을 검사해서 변질된 데이터를 찾아서 정정한다. 모든 파일 시스템을 검사하기 때문에 많은 시간이 걸린다.
Data corruption에 대한 내용은 wikipedia 문서를 참고하자.
native zfs 모듈 설치
설치 환경
설치 환경은 다음과 같다.
Host 운영체제 : Ubuntu 15.04
virtualbox로 VM을 만들어서 테스트 했다. Guest 운영체제는 우분투 리눅스 15.04다.
# cat /etc/apt/sources.list
.....
deb http://ppa.launchpad.net/zfs-native/stable/ubuntu vivid main
저장소 정보를 업데이트 하자.
# apt-get update
.....
Get:87 http://us.archive.ubuntu.com vivid-backports/restricted Translation-en [14 B]
Get:88 http://us.archive.ubuntu.com vivid-backports/universe Translation-en [3,760 B]
Fetched 31.6 MB in 3min 7s (169 kB/s)
Reading package lists... Done
W: Size of file /var/lib/apt/lists/partial/apt.dockerproject.org_repo_dists_ubuntu-vivid_Release.gpg is not what the server reported 819 442
W: GPG error: http://ppa.launchpad.net vivid InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 1196BA81F6B0FC61
에러가 떨어진다. PPA를 인증하기 위한 퍼블릭키가 없단다. 설치하고 다시 업데이트 하자.
sbd, sdc, sdd, sde 4개의 디스크가 보인다.
이제 zpool을 만들자. zpool을 만들 때, zpool의 raid 타입을 선택해야 한다.
Striped Vdev : RAID0과 같다. 패리티 없이 stripe만 한다. 이 방식은 공간을 효율적으로 사용할 수 있으며, (패리티 연산이 없으니)빠르다는 장점이 있지만 디스크에 문제가 생겼을 경우 데이터를 복구할 방법이 없다는 단점이 있다. 데이터는 zpool을 구성하는 디스크에 분산 저장되기 때문에, 디스크 하나에 생긴 문제가 전체 데이터에 치명적인 영향을 미칠 수 있다.
Striped Mirror : RAID10과 비슷하다. 미러링된 디스크에 데이터를 스트리핑 한다.
RAIDZ : RAID5와 비슷하다. 비용과 안정성 사이에 적절한 균현을 맞춘 타입이라고 볼 수 있다. 가장 널리 사용하는 타입이기도 하다.
RAIDZ2 : RAID6와 비슷하다. 더블 패리티를 사용해서 안정성을 높이고 있다. 퍼블릭 클라우드 정도에서 필요로 하는 안정성을 갖추길 원한다면 선택을 고려해봄 직하다. zpool은 최소 4개의 디스크로 구성이 되며, 동시에 3개의 디스크에 문제가 생기지 않는 한은 복구가 가능하다.
RAIDZ3 : 트리플 패리티를 사용한다. 디스크 3개에 문제가 생겨도 복구 할 수 있다.
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
volumes 135K 23.0G 25.4K /volumes
volumes/red3018 25.4K 23.0G 25.4K /volumes/red3018
volumes/yundream 25.4K 23.0G 25.4K /volumes/yundream
압축
압축을 설정해보자. 테스트를 위해서 lz4와 gzip 방식을 선택했다.
# zfs set compression=lz4 volumes
# zfs get compression=gzip2 volumes/yundream
NAME PROPERTY VALUE SOURCE
volumes compression lz4 local
volumes/red3018 compression lz4 inherited from volumes
volumes/yundream compression gzip inherited from volumes
압축 테스트를 위해서 linux-3.18.22.tar를 복사해 보기로 했다. 파일의 크기는 약 600메가다.
# ls -al linux-3.18.22.tar
-rw-r--r-- 1 root root 580802560 Oct 3 21:02 linux-3.18.22.tar
volumes/yundream과 volumes/red3018로 복사했다.
# time cp linux-3.18.22.tar /volumes/red3018/
real 0m3.209s
user 0m0.000s
sys 0m0.232s
# time cp linux-3.18.22.tar /volumes/yundream
real 0m15.922s
user 0m0.000s
sys 0m0.272s
거의 5배의 시간 차이가 난다. lz4가 고속이긴 고속인가 보다. 압축률은 어떨까.
# zfs get compressratio
NAME PROPERTY VALUE SOURCE
volumes compressratio 3.42x -
volumes/red3018 compressratio 2.76x -
volumes/yundream compressratio 4.51x -
확실히 gzip이 60% 정도 압축륙이 더 높긴 하지만, 걸리는 시간을 생각한다면 일반적인 상황에서는 lz4가 나은 선택이다. 읽기/쓰기 속도 보다 압축률이 더 중요한 서비스라면 gzip을 사용해 볼만 하다.
쿼터 설정
파일시스템 별로 사용용량을 제한 할 수 있다.
# zfs create volumes/red3018
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
volumes 414K 23.0G 25.4K /volumes
volumes/red3018 25.4K 23.0G 25.4K /volumes/red3018
volumes/yundream01 26.9K 10.0G 26.9K /volumes/yundream01
red3018이라는 파일 시스템을 만들었다. 쿼터제한 없이 전체 디스크를 소비할 수 있게 돼있다. 쿼터를 5G로 제한했다.
# zfs set quota=5G volumes/red3018
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
volumes 419K 23.0G 25.4K /volumes
volumes/red3018 25.4K 5.00G 25.4K /volumes/red3018
volumes/yundream01 26.9K 10.0G 26.9K /volumes/yundream01
이렇게 파일 시스템 가동중에 간단히 쿼터를 변경 할 수 있다. 리눅스의 LVM을 이용해서 삽질해 본 경험이 있다면, 이게 얼마나 편한지 느낌이 올 거다.
파일 시스템을 만들 때 쿼터를 설정할 수도 있다.
유저와 그룹에 대한 쿼터 설정도 가능하다. yundream 유저에 대해서 /volumes/yundream01에 2G의 쿼터를 설정했다.
# zfs set userquota@yundream=2G volumes/yundream01
# zfs get userquota@yundream volumes -r
NAME PROPERTY VALUE SOURCE
volumes userquota@yundream none local
volumes/red3018 userquota@yundream none local
volumes/test02 userquota@yundream none local
volumes/yundream01 userquota@yundream 2G local
developer 그룹에 5G의 쿼터를 설정했다.
# zfs set groupquota@developer=5G volumes/test02
# zfs get groupquota@developer volumes/test02
NAME PROPERTY VALUE SOURCE
volumes/test02 groupquota@developer 5G local
파일 시스템별로 그룹과 유저에 할당된 쿼터와 사용량을 확인 할 수 있다.
# zfs groupspace volumes/test02
TYPE NAME USED QUOTA
POSIX Group developer 0 5G
POSIX Group root 512 none
# zfs userspace volumes/yundream01
TYPE NAME USED QUOTA
POSIX User root 6.00K none
POSIX User yundream 0 2G
spare
spare 지원도 테스트 해봤다. 3개의 디스크를 raidz로 묶고, 디스크 하나를 spare로 묶었다.
# zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd spare /dev/sde
# zpool status
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
spares
sde AVAIL
이제 raidz1 pool의 디스크 중 하나가 FAILURE 되면 spares의 디스크가 FAILURE 디스크를 대신해서 작동할 거다. 역시 물리적 환경을 구성해야 제대로 테스트할 수 있을 것 같다.
Share
파일 시스템에 대한 공유 기능도 포함돼 있다. 관리자는 파일 시스템에 대한 SMB, iSCSI, NFS 공유를 관리 할 수 있다.
NFS
NFS를 지원하기 위해서 커널 모듈을 설치해야 한다.
volumes/test02를 NFS 공유 설정 했다.
192.168.56.1 호스트에서 읽기/쓰기로 volumes/test02 파일 시스템을 마운트 하도록 허용 했다. 192.168.56.0/24 와 같은 CID 형식으로 표기 할 수도 있다.
# zfs get sharenfs
zfs get sharenfs
NAME PROPERTY VALUE SOURCE
volumes sharenfs off local
volumes/red3018 sharenfs off inherited from volumes
volumes/test02 sharenfs rw=@192.168.56.1,insecure local
하나 이상의 호스트에 대한 접근 설정도 가능하다.
# zfs set sharenfs=rw=@192.168.56.1:@192.168.56.2:ro=@172.12.0.0/8,insecure volumes/test02
192.168.56.1, 192.168.56.2 호스트에 대해서는 읽기/쓰기 권한으로 공유한다.
172.12.0.0/8 호스트들에 대해서는 읽기전용으로 공유했다.
192.168.56.1에서 nfs 파일 시스템을 마운트 해보자. mount가 nfs를 지원하도록 하기 위해서 nfs-common 패키지를 설치한 후 마운트 했다.
# apt-get install nfs-common
# moun 192.168.56.50:/volumes/test02 /mnt/myvolume
iSCSI
iSCSI는 블럭 스토리지를 공유하기 위한 도구다. 원격에 있는 하드디스크를 로컬 PC에 붙이는 거라고 보면 된다.
()현재 Linux ZFS는 iscsi를 지원하지 않는 것 으로 보인다. 메뉴얼 상에는 shareiscsi가 보이는데, 공유하려고 하면 잘못된 property라는 에러가 뜬다. 그래서 tgtadm을 이용해서 iscsi를 구성하기로 했다. iSCSI에 대한 자세한 내용은 iSCSI를 참고하자.
먼저 테스트를 위한 볼륨을 만들었다. iSCSI는 파일 시스템이 아닌 디스크를 공유하는 툴이므로 Disk 타입의 볼륨을 만들어야 한다.
# zfs create -V 5G volumes/docker
zfs list를 해보자.
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
volumes 5.16G 17.9G 25.4K /volumes
volumes/docker 5.16G 23.0G 12.0K -
volumes/red3018 25.4K 5.00G 25.4K /volumes/red3018
volumes/test02 25.4K 5.00G 25.4K /volumes/test02
디스크 타입이기 때문에 마운트 포인트가 없다. 대신 zvol 디바이스가 만들어지는데 /dev/zvol 밑에서 찾을 수 있다.
# ls -al /dev/zvol/volumes/docker
lrwxrwxrwx 1 root root 9 Oct 17 12:35 /dev/zvol/volumes/docker -> ../../zd0
# file /dev/zd0
/dev/zd0: block special (230/0)
iSCSI 타겟을 만들고 확인했다.
# tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.joinc.com.example:storage.disk1
# tgtadm --lld iscsi --op show --mode target
Target 1: iqn.joinc.com.example:storage.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
Account information:
ACL information:
LUN에 zvol을 맵핑한다.
# tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun 1 -b /dev/zvol/volumes/docker
# tgtadm --lld iscsi --op show --mode target
Target 1: iqn.joinc.com.example:storage.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 5369 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: rdwr
Backing store path: /dev/zvol/volumes/docker
Backing store flags:
Account information:
ACL information:
LUN 1에 연결된 디스크 정보를 확인 할 수 있다.
이제 클라이언트에서 iSCSI를 마운트해서 사용하면 된다. 타겟을 찾아서 붙이면 된다.
스냅샷은 파일 시스템과 볼륨에 대한 읽기 전용의 복사본이다. 일정한 공간을 확보해서, 스냅샷 정보를 저장한다. 스냅샷에는 실제 파일(혹은 블록) 정보가 저장되는 대신에 위치 정보만 링크형식으로 저장하기 때문에 적은 공간으로 백업 시스템을 구축 할 수 있다. 이게 가능한 이유는 zfs가 cow를 사용하고 있기 때문이다. 스냅샷을 이해하려면 먼저 cow(copy on write)의 원리를 알고 있어야 한다.
현재 파일 시스템에 4개의 데이터가 있다고 가정해 보자. 스냅샷을 뜨게 될경우 파일을 복사하는 대신에 파일의 위치와 시간 정보만을 스냅샷 공간에 저장하고 이들에 대한 링크만 관리한다. 작업이 계속 진행되서 2 개의 데이터가 추가됐다.
앗.. 그런데 실수로 데이터를 잘못 추가 했다. 이 경우 스냅샷에 있는 정보를 재구성하면, 스냅샷을 떳던 시간으로 데이터를 복구 할 수 있다. 이렇게 주기적으로 스냅샷을 만들어 두면, 원하는 시간대로 데이터를 복구 할 수 있다.
하지만 헛점이 보인다. 위의 시나리오는 데이터 수정이 없이 추가만 있을 때를 가정하고 있다. 현실적으로 데이터에 대한 수정은 반드시 발생을 한다. 이 경우 기존 스냅샷의 "수정된"데이터를 가리키게 되므로 스냅샷이 깨지게 된다. "이미 만들어진 스냅샷이 가리키는 정보는 변경이 되면 안된다." COW는 기존 데이터를 다른 위치로 복사해서 원본을 안전하게 유지하고, 새로운 데이터를 다른 블럭에 쓰는 방식으로 문제를 해결하고 있다.
유저가 데이터 작업을 하고 있다.
그런데, 스냅샷 2가 가리키는 위치의 데이터를 수정하게 됐다.
스냅샷이 가리키는 데이터가 수정되면 안되므로, 다른 블럭에 데이터를 저장(copy)하고 스냅샷 2가 가리키는 정보를 수정한다.
수정된 데이터는 새로운 블럭에 쓴다(write).
스냅샷 데이터를 수정하는 문제는 깔끔하게 해결 했다. 굉장히 좋은 솔류션 같지만 문제가 없는 건 아니다. 마법의 은탄환 같은 건 없다.
하지만 스냅샷 데이터에 대한 수정이 있을 때 마다, 추가적인 복사가 발생한다. 데이터베이스처럼 많은 수의 작은 파일을 수정하는 작업에는 좋지 않다.
스냅샷은 저장되는 데이터와 동일한 볼륨에 있어야 한다. 디스크 자체에 생기는 문제에는 대응 할 수 없다. 디스크 실패에 대한 레이드등의 구성은 어차피 해야 한다.
스냅샷 관리
아래와 같이 만들 수 있다.
# zfs snapshot volumes/test02@snapshotName
테스트를 해보자. 1-1.txt 1-2.txt 파일 두개를 만든다음 스냅샷을 떴다. 스냅샷 이름은 현재 시간으로 정했다.
# zfs list -t snapshot -r volumes/test02
NAME USED AVAIL REFER MOUNTPOINT
volumes/test02@201510171423 13.5K - 25.4K -
volumes/test02@201510171430 0 - 25.4K -
rollback을 이용해서 특정 스냅샷 시점으로 복원 할 수 있다. test02@201510171423 시점으로 복원해 보자.
# zfs rollback -r volumes/test02@201510171423
복원 됐는지 확인해 보자.
# ls
1-1.txt 1-2.txt
'-r 옵션을 이용 할 경우 롤백한 시점 이후에 만들어지는 모든 스냅샷들은 삭제되기 때문에 사용에 주의해야 한다.
Storage Node 복구
나는 AWS 상에서 운영하려 한다. 어떤 이유로 zfs 인스턴스의 운영체제에 문제가 생기면, 다른 인스턴스를 재 빨리 띄워서 volume을 붙여야 한다. 대략 아래의 과정을 따를 것이다.
AWS API를 이용해서 문제가 생긴 인스턴스로 부터 EBS 볼륨을 Detach 한다.
새로운 인스턴스를 띄운다. EBS 볼륨을 Attach 한다.
테스트는 Virtualbox로 진행했다. 4개의 볼륨을 원래 인스턴스에서 detach 한 다음, 동일한 버전의 리눅스와 zfs 모듈을 설치한 다음 볼륨을 attach해서 실행했다. zfs 모듈이 올라가는 즉시 zpool을 구성하는 걸 확인 할 수 있었다.
이상 테스트 결과로 볼 때 AWS 상에서 Atcive & Standby 방식의 고가용성 구성도 쉽게 가능 할 것 같다. 문제라면 인스턴스로 부터 EBS 볼륨을 detach / attach 하는데 시간이 꽤 걸린다는 점이다. 대략 10초 정도는 걸리는 느낌이다.
Volume Attach
운영 중에 디스크 용량이 찰 것 같으면, 디스크 공간을 늘려줘야 한다. RaidZ로 구성했다면, 새로운 Raidz pool을 만들어서 추가해줘야 한다. 역시 virtualbox로 테스트를 하기로 했다. 4개의 디스크를 추가 해서 테스트를 진행. 현재의 디스크 상태는 아래와 같다.
# fdisk -l
Disk /dev/sda: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x0232a3fd
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 499711 497664 243M 83 Linux
/dev/sda2 501758 16775167 16273410 7.8G 5 Extended
/dev/sda5 501760 16775167 16273408 7.8G 8e Linux LVM
Disk /dev/sdb: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: A6914B49-3A77-A542-A7A7-913498D3ABA1
Device Start End Sectors Size Type
/dev/sdb1 2048 16758783 16756736 8G Solaris /usr & Apple ZFS
/dev/sdb9 16758784 16775167 16384 8M Solaris reserved 1
Disk /dev/sdc: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 41AF10F3-BE03-C140-AB2E-DE8EA8DD9453
Device Start End Sectors Size Type
/dev/sdc1 2048 16758783 16756736 8G Solaris /usr & Apple ZFS
/dev/sdc9 16758784 16775167 16384 8M Solaris reserved 1
Disk /dev/sdd: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 22A76EA8-D4CC-564E-931D-C11C5D306FF1
Device Start End Sectors Size Type
/dev/sdd1 2048 16758783 16756736 8G Solaris /usr & Apple ZFS
/dev/sdd9 16758784 16775167 16384 8M Solaris reserved 1
Disk /dev/sde: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 3B6323BA-B087-E844-AB3F-C1221899539A
Device Start End Sectors Size Type
/dev/sde1 2048 16758783 16756736 8G Solaris /usr & Apple ZFS
/dev/sde9 16758784 16775167 16384 8M Solaris reserved 1
Disk /dev/sdf: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdg: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdh: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdi: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/mapper/ubuntu--vg-root: 6.7 GiB, 7226785792 bytes, 14114816 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/mapper/ubuntu--vg-swap_1: 1020 MiB, 1069547520 bytes, 2088960 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/zd0: 3 GiB, 3221225472 bytes, 6291456 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 8192 bytes
I/O size (minimum/optimal): 8192 bytes / 8192 bytes
/dev/sdf ~ /dev/sdi 4개의 디스크가 보인다. zfs add 명령을 이용해서 볼륨을 추가했다.
운영체제의 업데이트, 복구 등의 이유로 스토리지 풀을 마이그레이션 해야 하는 경우가 있다. 우선 마이그레이션 할 볼륨의 정보를 확인해 보자.
# zpool status
pool: volumes
state: ONLINE
scan: resilvered 512 in 0h0m with 0 errors on Sun Nov 8 06:11:58 2015
config:
NAME STATE READ WRITE CKSUM
volumes ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
ata-VBOX_HARDDISK_VBff36b243-479041f1 ONLINE 0 0 0
ata-VBOX_HARDDISK_VB4ab3827f-4c5044ad ONLINE 0 0 0
ata-VBOX_HARDDISK_VBb6246c2c-0b7a4919 ONLINE 0 0 0
ata-VBOX_HARDDISK_VB42a0c1e1-145956f4 ONLINE 0 0 0
4개의 디바이스로 이루어진 volumes를 확인 할 수 있다. 먼저 export 명령을 이용해서 운영체제로 부터, 모든 디바이스를 disconnect 한다.
# zfs export volumes
리눅스에서 export를 하면 디바이스를 umount 하는 작업을 한다. 따라서 export 전에 디스크의 모든 작업을 완료해야 한다. 그렇지 않으면 아래와 같은 (umount하면서 많이 봤음직한)에러 메시지를 볼 수 있다.
# zpool export volumes
umount: /volumes: target is busy
(In some cases useful info about processes that
use the device is found by lsof(8) or fuser(1).)
cannot unmount '/volumes': umount failed
export를 성공하고 나면 더 이상 디바이스 풀을 볼 수 없다.
# zpool export volumes
# zpool status
no pools available
이제 목적지 운영체제에 디바이스를 붙이고 import를 해보자.
# zpool import
pool: volumes
id: 18357592395927659775
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
volumes ONLINE
raidz1-0 ONLINE
ata-VBOX_HARDDISK_VBff36b243-479041f1 ONLINE
ata-VBOX_HARDDISK_VB4ab3827f-4c5044ad ONLINE
ata-VBOX_HARDDISK_VBb6246c2c-0b7a4919 ONLINE
ata-VBOX_HARDDISK_VB42a0c1e1-145956f4 ONLINE
import 명령을 내리면 물리적인 디스크를 검사해서 스토리지 풀의 정보를 읽어온다. id가 18357592395927659775 인 스토리지 풀을 사용 할 수 있음을 알 수 있다. 이제 id 혹은 풀 이름으로 import 할 수 있다.
# zpool import volumes
마이그레이션 목적지 운영체제에 동일한 이름의 볼륨이 있을 경우 충돌이 나서 실패한다. 이 경우 다른 이름으로 import 할 수 있다.
# zpool import volumes volumes02
# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
volumes02 63.5G 45.4M 63.5G - 0% 0% 1.00x ONLINE -
zpool 백업 및 복구
기본적으로 스냅샷은 로컬디스크 기반으로 작동한다. 만약 파일시스템이나 물리적 디스크 자체에 문제가 생길 경우에는 스냅샷만으로는 복구 할 수 없다. 스냅샷은 빠른 롤백이나 복구를 위해서 사용하는 툴이지, 그 자체로 완전한 백업/복구 솔류션은 아니다. 완전한 백업을 위해서는 아래의 요구사항이 지켜져야 한다.
파일 시스템의 스냅샷과 스냅샷을 이용한 복구
스냅샷의 저장
원격 복제(replication)
tar, cpio, pax와 같은 서드파티 툴들의 지원
이중 스냅샷을 이용한 원격복제에 대해서 살펴보려한다.
ZFS send를 이용한 snapshot 전송
zfs send 명령을 이용하면 스냅샷의 스트림을 로컬 시스템의 다른 pool이나 혹은 원격에 있는 다른 시스템으로 복사 할 수 있다. 아래는 로컬의 다른 풀로 복사하는 예제다.
먼저 스냅샷을 만든다. 최초의 스냅샷이라고 가정한다. 즉 지금시간 까지의 모든 내용을 가지고 있다.
원격으로 복사하는 방법은 크게 두 가지다. 하나는 나중에 복구하기 위해서 스냅샷만 복사해두는 방법이고, 또 다른 하나는 아예 복제를 만드는 방법이다. 스냅샷 복사는 간단하다. send snapshot 내용을 로컬에 복사하고 scp등을 이용해서 원격에 복사하기만 하면 된다.
매번 스냅샷 전체를 뜨는 것은 공간 낭비다. ZFS는 증분 스냅샷을 지원한다. 이전 스냅샷에서 변경된 부분만 저장되므로 공간을 아낄 수 있다. 아래와 같이 3개의 스냅샷을 가진 파일 시스템이 있다고 가정해보자.
기타 이야기
loop 디바이스를 이용한 zfs 테스트 환경 구축
zfs기반의 애플리케이션을 개발한다면, virtualbox에 구축하는 것보다는 로컬에 구축하는게 더 나을 수 있다. 어쨋든 virtualbox로 관리하는 건 여러모로 괴롭다. losetup을 이용하면 간단하게 블럭디바이스를 만들 수 있다.
5G까지 image 파일 4개를 만들었다. 하나 만들고 나머지 세개는 그냥 복사했다.
Contents
리눅스 native zfs 모듈
ZFS의 라이센스와 리눅스 커널 지원
ZFS 관련 용어들
zpool
vdev
RAID 타입 vdev
Spare 타입 vdev
Cache 타입 vdev
Log 타입 vdev
Dataset
scrub
native zfs 모듈 설치
설치 환경
native zfs 설치
리눅스 ZFS 관리
zpool 생성
파일 시스템 생성
압축
쿼터 설정
spare
Share
NFS
iSCSI
SnapShot 관리
COW
스냅샷 관리
Storage Node 복구
Volume Attach
zpool migration
zpool 백업 및 복구
ZFS send를 이용한 snapshot 전송
증분 스냅샷 저장
기타 이야기
loop 디바이스를 이용한 zfs 테스트 환경 구축
참고 문헌
결론
Recent Posts
Archive Posts
Tags