Search

Docker: Storage Driver

Created
2021/05/27
Tags
Docker
Storage Driver
AUFS
Devicemapper
OverlayFS
Btrfs
ZFS

Subject

β€’

1. Storage Driver

이전 κΈ€μ—μ„œ Container에 λŒ€ν•΄ μ½μ–΄λ³ΈλŒ€λ‘œ, Container의 Storageλ₯Ό μ œν•œν•˜κΈ° μœ„ν•΄μ„  Docker Engine 자체 κΈ°λŠ₯을 μ΄μš©ν•˜μ§€ μ•Šκ³  Storage Driver의 도움이 ν•„μš”ν•˜λ‹€κ³  ν–ˆλ‹€. μ΄λŠ” Containerκ°€ Storage Driver의 파일 μ‹œμŠ€ν…œμ„ 기반으둜 λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. κ·Έλ ‡λ‹€λ©΄ AλΌλŠ” Storage Driverλ₯Ό 기반으둜 μƒμ„±ν•œ Containerκ°€ μžˆμ„ λ•Œ, Docker 데λͺ¬μ˜ κΈ°λ³Έ λ™μž‘μ„ BλΌλŠ” Storage Driver둜 λ°”κΎΈκ²Œ 되면 κΈ°μ‘΄ Aλ₯Ό μ΄μš©ν•˜λ˜ Container듀이 λ™μž‘ν•  수 μžˆμ„κΉŒ? 각 ContainerλŠ” μ„œλ‘œ λ‹€λ₯Έ 파일 μ‹œμŠ€ν…œμ„ 기반으둜 ν•˜λ―€λ‘œ 각 Container듀이 μ‚¬μš©ν•˜λŠ” 파일 μ‹œμŠ€ν…œκ³Ό λ‹€λ₯Έ ν™˜κ²½μ΄λΌλ©΄ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λŠ” 곧 Docker 데λͺ¬μ— 적용된 Storage Driver에 λ”°λΌμ„œ Container와 Imageκ°€ λ³„λ„λ‘œ 생성됨을 μ˜λ―Έν•˜λŠ”λ°, μ‹€μ œλ‘œ Container와 Imageλ₯Ό μƒμ„±ν•˜κ²Œ 되면 각 Storage Driver에 λ§žλŠ” 디렉토리에 Container와 Imageκ°€ μœ„μΉ˜ν•˜κ²Œ λœλ‹€.
예λ₯Ό λ“€μ–΄ AUFSλ₯Ό μ΄μš©ν•˜λŠ” Container와 Devicemapperλ₯Ό μ΄μš©ν•˜λŠ” Containerκ°€ μžˆλ‹€κ³  해보면, AUFS의 κ²½μš°μ—” Containerκ°€ /var/lib/docker/aufs에 μ‘΄μž¬ν•˜κ³  Devicemapper의 κ²½μš°μ—” Containerκ°€ /var/lib/docker/devicemapper에 μ‘΄μž¬ν•œλ‹€.
μœ„ κ·Έλ¦Όκ³Ό 같이 container_storage_driverλ₯Ό λ§Œλ“€μ—ˆμ„ λ•Œ, Storage DriverλŠ” OverlayFS 쀑 overlay2λ₯Ό μ΄μš©ν•˜κ³  μžˆλŠ” 것을 λ³Ό 수 μžˆλ‹€.
docker run -i -t --rm --privileged --pid=host justincormack/nsenter1
μœ„ λͺ…λ Ήμ–΄λ₯Ό μ΄μš©ν•˜μ—¬ container_storage_driverκ°€ Linuxkit λ‚΄λΆ€ 어디에 μœ„μΉ˜ν•˜κ³  μžˆλŠ”μ§€ ν™•μΈν•΄λ³΄μž. ν˜„μž¬ overlay2λΌλŠ” Storage Driverλ₯Ό μ΄μš©ν•˜κ³  있기 λ•Œλ¬Έμ—, μ•„λž˜ κ·Έλ¦Όμ—μ„œ λ³΄μ΄λŠ” κ²ƒμ²˜λŸΌ /var/lib/docker/overlay2κ°€ μ‘΄μž¬ν•˜λŠ” 것을 확인할 수 μžˆλ‹€. ν•˜μ§€λ§Œ λ‚΄λΆ€ μ–΄λ””λ₯Ό λ‘˜λŸ¬λ΄λ„ container_storage_driver에 ν•΄λ‹Ήν•˜λŠ” Digest 값을 찾을 수 μ—†λ‹€. μžμ„Ένžˆ λ‘˜λŸ¬λ³΄λ©΄ lμ΄λΌλŠ” 디렉토리엔 심볼릭 링크가 κ±Έλ¦° νŒŒμΌλ“€λ§Œ λ‹€μˆ˜ μ‘΄μž¬ν•˜κ³ , κ·Έ μ™Έμ˜ 디렉토리듀은 무엇인지 μ •ν™•νžˆ μ•Œ 수 μ—†λ‹€.
μœ„ κ·Έλ¦Όμ—μ„œ -init이 뢙은 디렉토리가 방금 μƒμ„±λœ Containerλ₯Ό μ˜λ―Έν•˜λ©°, -init이 뢙지 μ•Šμ€ 디렉토리가 μ‹€μ œ Container의 파일 μ‹œμŠ€ν…œμ„ λ‹΄κ³  μžˆλŠ” 디렉토리이닀.
이와 같은 상황을 μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„  μœ„ κ·Έλ¦Όκ³Ό 같이 μ΄ν•΄ν–ˆλ˜ Container와 Image에 λŒ€ν•΄ 쑰금 더 μžμ„Ένžˆ μ•Œμ•„λ³Ό ν•„μš”κ°€ μžˆλ‹€.
μ‹€μ œλ‘œ Container λ‚΄λΆ€μ—μ„œ Read, μƒˆλ‘œμš΄ νŒŒμΌμ— λŒ€ν•œ Write, κΈ°μ‘΄ νŒŒμΌμ— λŒ€ν•œ Write와 같은 μž‘μ—…μ΄ μΌμ–΄λ‚˜λ©΄ Storage Driver에 λ”°λΌμ„œ Copy-on-Write (CoW) ν˜Ήμ€ Redirect-on-Write (RoW)둜 λ™μž‘ν•œλ‹€. 그리고 CoW와 RoWμ—μ„œ μ‚¬μš©λ˜λŠ” κ°œλ…μ΄ Snapshotκ³Ό Snapshot Pool이닀.
기본적으둜 Snapshot은 Immutableν•œ μ†μ„±μœΌλ‘œ Read-Only이닀. 그리고 Snapshot Pool은 Snapshot이 Read / Write μ‹œμ— μ΄μš©ν•˜λŠ” 곡간인데, CoW와 RoW에 λ”°λΌμ„œ μ‚¬μš© 방법이 λ‹€λ₯΄λ‹€. μ‚¬μš© 쀑인 Storageλ₯Ό Snapshot으둜 λ§Œλ“€κ²Œ 되면 λ‚΄λΆ€μ˜ 파일이 μ–΄λŠ μœ„μΉ˜μ— 무엇듀이 μžˆλŠ”μ§€ λͺ©λ‘μœΌλ‘œ μœ μ§€λ˜λŠ”λ°, 이λ₯Ό 톡해 νŒŒμΌμ— λŒ€ν•œ Tracing이 κ°€λŠ₯해진닀. 이에 λŒ€ν•œ κ΅¬μ‘°λŠ” μ•„λž˜ κ·Έλ¦Όκ³Ό κ°™λ‹€.
μœ„μ™€ 같은 ꡬ쑰λ₯Ό CoW와 RoW λͺ¨λ‘ μœ μ§€ν•˜κ³  μžˆλŠ”λ° 이듀은 Read μž‘μ—…μ— λŒ€ν•΄μ„œλŠ” 파일 μ‹œμŠ€ν…œ μƒμ˜ νŒŒμΌμ— μ ‘κ·Όν•˜μ—¬ λ‚΄μš©λ§Œ 읽으면 λ˜λ‹ˆ λ¬Έμ œκ°€ μ—†λ‹€. ν•˜μ§€λ§Œ 각각의 μ΄λ¦„μ²˜λŸΌ Write μž‘μ—…μ— λŒ€ν•΄μ„œλŠ” Snapshot Pool을 μ΄μš©ν•˜λŠ” 방식이 각각 λ‹€λ₯΄λ‹€. Storage Driverκ°€ Write μž‘μ—…μ— λŒ€ν•΄ CoWλ₯Ό μ‚¬μš©ν•˜λ“  RoWλ₯Ό μ‚¬μš©ν•˜λ“  원본 νŒŒμΌμ€ κ·ΈλŒ€λ‘œ μœ μ§€λ₯Ό ν•˜λ˜, λ³€κ²½ 사항에 λŒ€ν•΄μ„œ 기둝할 수 μžˆμ–΄μ•Ό ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

1) CoW (Copy-on-Write)

CoWλŠ” Snapshot으둜 μœ μ§€ν•˜κ³  μžˆλŠ” νŒŒμΌμ— λŒ€ν•΄ Write μš”μ²­μ„ λ°›κ²Œ λ˜μ—ˆμ„ λ•Œ, μ›λ³ΈμœΌλ‘œ μœ μ§€ 쀑인 νŒŒμΌμ„ λ³΅μ‚¬ν•˜μ—¬ ν•΄λ‹Ή νŒŒμΌμ— λŒ€ν•œ Snapshot을 Snapshot Pool에 λ‘κ²Œ λœλ‹€. μ—¬κΈ°κΉŒμ§€κ°€ 1번과 2λ²ˆκ³Όμ •μ΄κ³ , 3번 과정이 곧 Write μš”μ²­μ„ 받은 Snapshot에 λŒ€ν•΄μ„œ λ³€κ²½ 사항을 λ°˜μ˜ν•œ 것이닀.
이와 같은 과정은 이름 κ·ΈλŒ€λ‘œ Copyλ₯Ό 기반으둜 ν•˜κΈ° λ•Œλ¬Έμ— 원본 νŒŒμΌμ— λŒ€ν•œ 볡사λ₯Ό μˆ˜ν–‰ν•  λ•Œ Read / Write 각 1νšŒκ°€ μΌμ–΄λ‚˜κ³ , Write μš”μ²­μ— λŒ€ν•œ λ³€κ²½ 사항 반영 μ‹œ Write 1νšŒκ°€ λ°œμƒν•œλ‹€. 총 2회의 Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— 이에 λŒ€ν•œ Overheadκ°€ μžˆλŠ” νŽΈμ΄λ‹€. λ˜ν•œ νŒŒμΌμ— λŒ€ν•œ 변경은 μ™„λ£Œκ°€ 된 μƒνƒœλ‘œ μœ μ§€λ˜κ³  λ³€κ²½ 사항 μ μš©μ„ μœ„ν•œ 좔가적인 μž‘μ—…μ΄ ν•„μš” μ—†μœΌλ―€λ‘œ, μž‘μ—…μ— λŒ€ν•œ μˆ˜ν–‰μ€ λΉ λ₯΄λ‹€κ³  λ³Ό 수 μžˆλ‹€. 즉, CoWλŠ” μ„±λŠ₯μ—μ„œ 손해λ₯Ό λ³΄μ§€λ§Œ Container의 생성과 μ‚­μ œ 같은 μž‘μ—…μ€ λΉ λ₯΄λ‹€κ³  λ³Ό 수 μžˆλ‹€.

2) RoW (Redirect-on_Write)

RoWλŠ” Snapshot으둜 μœ μ§€ν•˜κ³  μžˆλŠ” νŒŒμΌμ— λŒ€ν•΄ Write μš”μ²­μ„ λ°›κ²Œ λ˜μ—ˆμ„ λ•Œ, μ›λ³ΈμœΌλ‘œ μœ μ§€ 쀑인 νŒŒμΌμ„ λ³€κ²½ν•  수 없도둝 Freezeν•˜κ³  Snapshot Pool에 μƒˆλ‘œμš΄ 블둝을 ν• λ‹Ή λ°›μ•„ λ³€κ²½ 사항을 κΈ°λ‘ν•˜κ²Œ λœλ‹€. Snapshot Pool에 μœ μ§€ν•˜κ³  μžˆλŠ” λΈ”λ‘μ—λŠ” λ³€κ²½λœ λ‚΄μ—­λ§Œ diff 파일둜써 μœ μ§€ν•œλ‹€. RoWλŠ” 1회의 Write μž‘μ—…λ§Œ 이뀄지고 CoW처럼 전체 νŒŒμΌμ„ 볡사λ₯Ό ν•˜λŠ” 것이 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ—, μ„±λŠ₯λ©΄μ—μ„œλŠ” 이득을 μ±™κΈΈ 수 μžˆλ‹€. ν•˜μ§€λ§Œ λ³€κ²½ 사항에 λŒ€ν•œ λ°˜μ˜μ„ μœ„ν•΄ ν•΄λ‹Ή νŒŒμΌμ„ μ°ΎλŠ”λ°μ„œ 좔가적인 μ‹œκ°„μ΄ μš”κ΅¬λ˜λ―€λ‘œ Container의 생성과 μ‚­μ œ 같은 μž‘μ—…μ΄ λŠλ¦¬λ‹€κ³  λ³Ό 수 μžˆλ‹€.

3) κ²°λ‘ 

CoWλ“  RoWλ“  Write에 λŒ€ν•΄ λ³€κ²½ 사항을 κΈ°λ‘ν•˜λŠ” 방식이 μ–΄λ–€ 것이 더 μ’‹κ³  λ‚˜μ˜λ‹€λŠ” 것이 μ—†λ‹€. λ§Œμ•½ 두 방법에 더 μ’‹κ³  λ‚˜μœ 것이 μ‘΄μž¬ν•˜λ©΄, Storage DriverλŠ” νšμΌν™” λ˜μ–΄ μžˆμ„ 것인데 μ‹€μ œλ‘œλŠ” 그렇지 μ•Šλ‹€. κ·Έμ € 상황에 λ”°λΌμ„œ μ–΄λ–€ λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜λŠ” Storage Driverλ₯Ό μ΄μš©ν• μ§€κ°€ μ€‘μš”ν•˜λ‹€.
그리고 Snapshot이 Immutableμ΄λΌλŠ” 점을 염두에 두고 μœ„μ—μ„œ CoW와 RoW에 λŒ€ν•΄μ„œ λ³΄μ•˜λ“―, 원본 νŒŒμΌμ— λŒ€ν•œ Snapshotκ³Ό λ³€κ²½ 사항에 λŒ€ν•œ Snapshot이 각각 Image와 Container에 λŒ€μ‘λœλ‹€λŠ” 것을 눈치 μ±˜μ„ 것이닀. Storage Driver λ³„λ‘œ 각 Snapshot듀을 μ§€μΉ­ν•˜λŠ” μš©μ–΄κ°€ 쑰금 λ‹€λ₯Ό μˆ˜λŠ” μžˆμ§€λ§Œ, Image의 Layer듀이 원본 νŒŒμΌμ— λŒ€ν•œ Snapshot듀이 λ˜λŠ” 것이고, Container의 LayerλŠ” λ³€κ²½ 사항에 λŒ€ν•œ Snapshot듀이 λ˜λŠ” 것이닀. λ”°λΌμ„œ μ‹€ν–‰ 쀑인 Containerλ₯Ό Image둜 λ§Œλ“€λ©΄ 기쑴에 μœ μ§€ 쀑인 λͺ¨λ“  Snapshot듀이 λͺ¨μ—¬ ν•˜λ‚˜μ˜ Imageκ°€ μƒμ„±λ˜λŠ” 것이고, 이 λ•Œμ˜ Snapshot듀은 λΉ„λ‘œμ†Œ 원본 νŒŒμΌμ— λŒ€ν•œ Snapshot이 λ˜λŠ” 것이닀.
Image와 Containerκ°€ μ–΄λ–€ μ‹μœΌλ‘œ λ§Œλ“€μ–΄μ§€λŠ”μ§€ μ•Œμ•„λ΄€λ‹€. Storage Driver λ§ˆλ‹€ 차이가 μžˆκ² μ§€λ§Œ 이듀이 λ™μž‘ν•˜λŠ” 방식은 μ „λ°˜μ μœΌλ‘œ Image에 ν•΄λ‹Ήν•˜λŠ” Layerλ“€μ˜ Snapshotκ³Ό Container에 ν•΄λ‹Ήν•˜λŠ” Layerλ“€μ˜ Snapshot을 합쳐 Containerκ°€ μ‹€ν–‰λ˜λŠ” 지점에 mountν•˜λŠ” 것이닀. 각 Storage Driver λ³„λ‘œ μ–΄λ–€ νŠΉμ„±μ΄ 있고 μ–΄λ–€ ν˜•νƒœλ‘œ Layer듀을 μœ μ§€ν•˜κ³  μžˆλŠ”μ§€ μ•Œμ•„λ³΄μž.
μ–΄λ–€ Storage Driverλ₯Ό μ΄μš©ν•  μ§€λŠ” Docker 데λͺ¬μ˜ μ„€μ • 값을 μ‘°μž‘ν•˜μ—¬ λ³€κ²½ν•  수 μžˆλŠ”λ°, 이 κΈ€μ—μ„œλŠ” Storage Driverλ₯Ό λ³€κ²½ν•˜λŠ” 방법은 닀루지 μ•ŠλŠ”λ‹€. Docker 데λͺ¬ μ„€μ • 값을 μ‘°μž‘ν•˜λŠ” 방법은 Docker κΈ€λ“€ 쀑에 κ°€μž₯ 첫 번째 글에 μ†Œκ°œ λ˜μ–΄ μžˆμœΌλ‹ˆ 이λ₯Ό μ°Έκ³ ν•˜μž.

2. AUFS

1) νŠΉμ§•

1.
ubuntuμ—μ„œ 주둜 μ΄μš©ν–ˆμœΌλ©°, Kernel에 ν¬ν•¨λ˜μ–΄ μžˆμ§€ μ•Šμ•„ 일뢀 ν™˜κ²½μ—μ„œλŠ” μ‚¬μš©ν•  수 μ—†λ‹€.
2.
Dockerμ—μ„œ 였랜 κΈ°κ°„ μ‚¬μš©λ˜μ—ˆκ³  μ•ˆμ •μ„± μΈ‘λ©΄μ—μ„œ 쒋은 평가λ₯Ό λ°›λŠ” Storage Driver이닀.
3.
CoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— Container의 생성과 μ‚­μ œμ— λŒ€ν•œ μž‘μ—…μ΄ 빨라 PaaS (Platform as a Service)에 μ ν•©ν•œ Storage Driver이닀.
4.
Host의 μ €μž₯ 곡간 크기λ₯Ό κ³΅μœ ν•˜μ—¬ Container λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” μ €μž₯ 곡간은 Host와 λ™μΌν•˜λ‹€.
5.
κ³„μΈ΅ν™”λœ Image의 Layerλ“€λ‘œ κ΅¬μ„±λœλ‹€.

2) ꡬ쑰

AUFSλŠ” 기쑴에 μ„€λͺ…ν–ˆλ˜ Image와 Container의 ꡬ쑰와 ꡉμž₯히 μœ μ‚¬ν•˜λ‹€. Image둜 μ‘΄μž¬ν•˜λŠ” μ—¬λŸ¬ Layer듀은 /var/lib/docker/aufs/mnt에 μ‘΄μž¬ν•˜λ©°, Container둜 μ΄μš©λ˜λŠ” LayerλŠ” /var/lib/docker/aufs/diff에 μ‘΄μž¬ν•œλ‹€. 이 λ•Œ, Imageκ°€ μ‘΄μž¬ν•˜λŠ” /var/lib/docker/aufs/mntλΌλŠ” λ””λ ‰ν† λ¦¬λŠ” Union Mount Point둜 μ΄μš©λ˜μ–΄ Container의 /var/lib/docker/aufs/diffκ°€ mountλ˜μ–΄ μ΄μš©λœλ‹€. mount된 ContainerλŠ” Union Mount Point에 μ‘΄μž¬ν•˜λŠ” Image듀을 Read-Only둜 μ‚¬μš©ν•˜κ²Œ λœλ‹€.
Containerλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ Read-Only둜만 μˆ˜ν–‰λ˜λŠ” νŒŒμΌμ— λŒ€ν•΄μ„œ 변경을 ν•΄μ•Όν•  λ•Œ AUFSλŠ” CoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ—, ν•΄λ‹Ή 파일 전체λ₯Ό Container의 Layer둜 λ³΅μ‚¬ν•˜κ³  λ³΅μ‚¬λœ νŒŒμΌμ„ λ³€κ²½ν•˜λŠ” μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•œλ‹€. νŒŒμΌμ— λŒ€ν•΄μ„œ λ³€κ²½ν•  λ•Œ 원본 파일 전체λ₯Ό Container의 Layer둜 볡사해야 ν•˜λ―€λ‘œ, 볡사할 νŒŒμΌμ„ μ°Ύμ•„λ‚΄λŠ” 과정이 ν•„μš”ν•˜λ‹€. 이 λ•Œ AUFSλŠ” νŒŒμΌμ„ Image의 κ°€μž₯ μœ„ μͺ½μ— μ‘΄μž¬ν•˜λŠ” LayerλΆ€ν„° μ•„λž˜ μͺ½μœΌλ‘œ νŒŒμΌμ„ μ°Ύμ•„λ‚Έλ‹€. λ”°λΌμ„œ μ°ΎμœΌλ €λŠ” 파일이 κ°€μž₯ μ•„λž˜ μͺ½ Layer에 μ‘΄μž¬ν•œλ‹€λ©΄ Write에 κ±Έλ¦¬λŠ” μ‹œκ°„μ΄ 였래 걸릴 수 있으며, λ”κ΅°λ‹€λ‚˜ Writeλ₯Ό μˆ˜ν–‰ν•˜λ €λŠ” 파일의 크기가 크닀면 그만큼 λ³΅μ‚¬ν•˜λŠ”λ° μ‹œκ°„μ΄ 더 걸릴 수 μžˆλ‹€. 이에 λŒ€ν•΄μ„  νŒŒμΌμ„ λ³€κ²½ν•˜λ €κ³  ν•  λ•Œ 졜초 1νšŒμ— λŒ€ν•΄μ„œλ§Œ νŒŒμΌμ„ λ³΅μ‚¬ν•˜κΈ° λ•Œλ¬Έμ—, ν•΄λ‹Ή νŒŒμΌμ„ μ—¬λŸ¬ μ°¨λ‘€ λ³€κ²½ν•˜μ—¬ Writeν•  λ•ŒλŠ” 기쑴에 λ³΅μ‚¬λœ νŒŒμΌμ„ μ΄μš©ν•œλ‹€.

3. Devicemapper

1) νŠΉμ§•

1.
λ ˆλ“œν–‡ κ³„μ—΄μ˜ Linuxμ—μ„œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ§„ Storage Driver이닀.
2.
CentOS와 같은 μš΄μ˜μ²΄μ œμ—μ„œ 주둜 μ‚¬μš©ν–ˆμ§€λ§Œ, μ„±λŠ₯이 쒋지 μ•Šμ•„ Deprecated된 Storage Driver이닀. λ”°λΌμ„œ Docker Engine 버전 1.13.0 μ΄μ „μœΌλ‘œλŠ” Devicemapperλ₯Ό, μ΄ν›„λ‘œλŠ” OverlayFSλ₯Ό κΈ°λ³Έ Storage Driver둜 μ΄μš©ν•œλ‹€.
3.
RoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯으둜 이득을 λ³Ό 수 μžˆμ§€λ§Œ, Container의 생성과 μ‚­μ œμ— λŒ€ν•œ μž‘μ—…μ΄ 느린 νŽΈμ΄λ‹€.
4.
Docker 데λͺ¬μ—μ„œ Container의 Storage μ œν•œμ— λŒ€ν•œ 섀정이 κ°€λŠ₯ν•˜λ‹€. 이 λ•Œ κΈ°μ‘΄ Storage μ œν•œ μ„€μ • 값을 μ΄μš©ν•˜κ³  μžˆλŠ” Containerκ°€ μžˆλ‹€λ©΄ 섀정이 λ˜μ§€ μ•ŠμœΌλ‹ˆ Containerλ₯Ό μ‚­μ œ ν›„ μ„€μ •ν•΄μ€˜μ•Ό ν•œλ‹€. μ œν•œ 값을 Container μ „μ²΄μ μœΌλ‘œ μ μš©ν•˜μ§€ μ•Šκ³  κ°œλ³„μ μœΌλ‘œ μ μš©ν•˜λŠ” 것도 κ°€λŠ₯ν•œλ°, 이 λ•ŒλŠ” Docker 데λͺ¬ μ„€μ • 값보닀 μ˜΅μ…˜μœΌλ‘œ κΈ°μž¬ν•˜λŠ” 값이 더 컀야 Containerκ°€ μƒμ„±λœλ‹€.
5.
κ³„μΈ΅ν™”λœ Image의 Layerλ“€λ‘œ κ΅¬μ„±λœλ‹€.

2) ꡬ쑰

Devicemapperλ₯Ό μ΄μš©ν•˜κ²Œ 되면 Host의 일정 곡간을 ν• λ‹Ή λ°›μ•„ Storage Pool둜 μ΄μš©ν•œλ‹€. dataλΌλŠ” 디렉토리가 Storage Pool둜 μ΄μš©λ˜λŠ” 곡간이닀. μ΄λ ‡κ²Œ ν• λ‹Ή 받은 곡간을 ν•œ λ²ˆμ— λ‹€ μ“°λŠ” 것은 μ•„λ‹ˆκ³ , Image와 Containerλ₯Ό μ΄μš©ν•  λ•Œ Storage Pool둜 λΆ€ν„° νŠΉμ • 크기의 곡간을 블둝 λ‹¨μœ„λ‘œ ν• λ‹Ή λ°›μ•„ Layerλ₯Ό μ €μž₯ν•˜κ²Œ λœλ‹€. λ‹€λ₯Έ Storage Driverλ“€κ³ΌλŠ” 달리 Image의 Layer와 Container의 Layerλ₯Ό λΆ„λ¦¬ν•˜μ—¬ μ΄μš©ν•˜λŠ” DriverλŠ” μ•„λ‹ˆλ‹€. 블둝 λ‹¨μœ„λ‘œ 할당받은 Image와 Container의 Layer듀은 Storage Poolλ‘œλΆ€ν„° ν• λ‹Ή 받은 μ •λ³΄λ“€λ§Œ 기둝되며, μ΄λŠ” metadataλΌλŠ” 디렉토리에 μ €μž₯λœλ‹€.
Devicemapperκ°€ μ΄μš©ν•˜λŠ” Storage Pool μœ„μ—λŠ” Devicemapper의 ν”„λ ˆμž„μ›Œν¬κ°€ μ‘΄μž¬ν•˜κ³  이λ₯Ό Snapshot으둜써 μ΄μš©ν•œλ‹€. μ΄ˆκΈ°μ— μƒμ„±λœ ν•΄λ‹Ή Snapshot은 Image와 Container의 Layerλ“€μ—κ²Œ 곡간을 할당해쀄 수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ£Όκ³ , 이λ₯Ό μ΄μš©ν•˜μ—¬ 일정 곡간을 ν• λ‹Ή λ°›κ²Œ 되면 Image의 μ—¬λŸ¬ Layer듀이 κ³„μΈ΅μ μœΌλ‘œ μƒμ„±λœλ‹€. Image의 Layerλ“€κΉŒμ§€ ν¬ν•¨ν•˜μ—¬ λ‹€μ‹œ Snapshot으둜 λ§Œλ“  λ’€μ—λŠ” Image의 Layer에 λŒ€ν•œ λ³€κ²½ 사항을 λ§Œλ“€μ–΄ λ‚Ό 수 μžˆλ„λ‘ Container의 Layerλ₯Ό λ‘κ²Œ 되고, μ΄λŠ” Image의 Layer듀이 μžˆλŠ” 곳에 mount λœλ‹€.
Writeλ₯Ό μ΄μš©ν•˜μ—¬ λ³€κ²½ 사항이 λ°œμƒ ν–ˆμ„ λ•ŒλŠ” RoW λ°©μ‹μœΌλ‘œ κΈ°λ‘ν•˜κΈ° λ•Œλ¬Έμ— Storage Poolλ‘œλΆ€ν„° ν•„μš”ν•œ 만큼의 블둝듀을 ν• λ‹Ή λ°›μ•„ λ³€κ²½ 사항을 κΈ°λ‘ν•˜κ²Œ λœλ‹€. 이 λ•Œ λ³€κ²½ν•˜λ €λŠ” 원본 파일 전체λ₯Ό λ³΅μ‚¬ν•˜λŠ” 것이 μ•„λ‹ˆλΌ μˆ˜μ •ν•˜λ €λŠ” 뢀뢄에 λŒ€ν•΄μ„œλ§Œ 볡사λ₯Ό μˆ˜ν–‰ν•˜λ―€λ‘œ AUFS 보닀 μ„±λŠ₯μ—μ„œ 이점을 κ°–κΈ°λŠ” ν•˜μ§€λ§Œ 전체적인 λ™μž‘ 흐름을 λ³΄μ•˜λ“―μ΄ Container 생성과 μ‚­μ œκ°€ λΉ λ₯Έ νŽΈμ€ μ•„λ‹ˆλ‹€.

4. OverlayFS

1) νŠΉμ§•

1.
λ ˆλ“œν–‡ κ³„μ—΄μ˜ Linuxμ—μ„œ 주둜 μ‚¬μš©λ˜λŠ” Storage Driver이닀.
2.
CoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— Container의 생성과 μ‚­μ œμ— λŒ€ν•œ μž‘μ—…μ΄ 빨라 PaaS (Platform as a Service)에 μ ν•©ν•œ Storage Driver이닀.
3.
CoW 방식을 μ΄μš©ν•œλ‹€λŠ” μ μ—μ„œ AUFS와 λΉ„μŠ·ν•œ μ›λ¦¬λ‘œ μž‘λ™ν•˜μ§€λ§Œ OverlayFSλŠ” 쑰금 더 κ°„λ‹¨ν•œ ꡬ쑰둜 μ‚¬μš©λ˜μ–΄ AUFS보닀 μ„±λŠ₯이 더 μ’‹λ‹€. (AUFSλ₯Ό λŒ€μ²΄ν•  수 μžˆλŠ” μ°¨μ„ΈλŒ€ 파일 μ‹œμŠ€ν…œμœΌλ‘œ μΈμ‹λœλ‹€.)
4.
OverlayFSμ—λŠ” overlay와 overlay2둜 λ‚˜λ‰˜λŠ”λ°, overlay2κ°€ 더 μš°μˆ˜ν•œ μ„±λŠ₯을 보여쀀닀.
5.
Host의 μ €μž₯ 곡간 크기λ₯Ό κ³΅μœ ν•˜μ—¬ Container λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” μ €μž₯ 곡간은 Host와 λ™μΌν•˜λ‹€.
6.
Container의 Storage μ œν•œμ— λŒ€ν•œ 섀정이 κ°€λŠ₯ν•˜λ‹€. λ‹€λ§Œ 방법이 κΉŒλ‹€λ‘œμš΄λ° κ°„λ‹¨νžˆ μš”μ•½ν•˜λ©΄, Storage Driverλ₯Ό OverlayFS둜 μ΄μš©ν•˜λ©΄μ„œ Docker에 λŒ€ν•œ 데이터가 xfs에 μ €μž₯λ˜μ–΄ μžˆλŠ” κ²½μš°μ— xfs의 project quotaλΌλŠ” κΈ°λŠ₯을 톡해 Container의 Storage μ œν•œμ΄ κ°€λŠ₯ν•˜λ‹€.
7.
λ‹€λ₯Έ Storage Driverλ“€κ³Ό 달리 λ‹¨μΌν™”λœ Image의 Layer둜 κ΅¬μ„±λœλ‹€. 이 λ•Œλ¬Έμ— AUFS 보닀 쑰금 더 λ‚˜μ€ μ„±λŠ₯을 보인닀.

2) ꡬ쑰

/var/lib/docker/overlay ν˜Ήμ€ /var/lib/docker/overlay2λΌλŠ” 디렉토리λ₯Ό μ‚΄νŽ΄λ³΄λ©΄ -init이 뢙은 디렉토리가 있고 그렇지 μ•Šμ€ 디렉토리가 μžˆλŠ” 것을 확인할 수 μžˆλ‹€. μƒμ„±λœ ContainerλŠ” -init이 뢙은 디렉토리에 ν•΄λ‹Ήλ˜λ©°, -init이 뢙지 μ•Šμ€ λ””λ ‰ν† λ¦¬λŠ” Container의 파일 μ‹œμŠ€ν…œμ„ λ‹΄κ³  μžˆλŠ” 디렉토리이닀.
파일 μ‹œμŠ€ν…œμ„ λ‹΄κ³  μžˆλŠ” λ””λ ‰ν† λ¦¬μ˜ λ‚΄λΆ€ κ΅¬μ‘°λŠ” lowerdir, upperdir, merged둜 λ‚˜λ‰˜μ–΄ μžˆλ‹€. lowerdir이 Image에 λŒ€ν•œ Layerλ₯Ό μ˜λ―Έν•˜κ³ , upperdir이 Container의 Layerλ₯Ό μ˜λ―Έν•œλ‹€. 이에 λŒ€ν•΄μ„œ λ‹€λ₯Έ Storage Driverμ™€λŠ” 달리 Image와 Container의 Layerκ°€ 각각 단일 κ³„μΈ΅μœΌλ‘œ μ‘΄μž¬ν•˜λ©°, merged λ””λ ‰ν† λ¦¬λŠ” 두 Layer에 ν•΄λ‹Ήν•˜λŠ” λ””λ ‰ν† λ¦¬μ˜ mount 지점이 λœλ‹€.
OverlayFSλŠ” CoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— lowerdir의 νŒŒμΌμ— λŒ€ν•΄μ„œ λ³€κ²½ 사항이 λ°œμƒν•˜κ²Œ 되면 ν•΄λ‹Ή νŒŒμΌμ„ Container의 Layer에 ν•΄λ‹Ήν•˜λŠ” upperdir둜 λ³΅μ‚¬ν•˜κ²Œ λœλ‹€. 이 λ•Œ 크기가 큰 νŒŒμΌμ„ λ³΅μ‚¬ν•œλ‹€λ©΄ 그만큼 μ‹œκ°„μ΄ 더 μ†Œμš”λ˜κ² μ§€λ§Œ, λ‹€λ₯Έ 파일 μ‹œμŠ€ν…œκ³Ό 달리 단일 κ³„μΈ΅μœΌλ‘œ Layerλ₯Ό μœ μ§€ν•˜κ³  μžˆμœΌλ―€λ‘œ 볡사할 νŒŒμΌμ„ μ°ΎλŠ”λ° μ‹œκ°„ μ†Œμš”κ°€ λœν•œ νŽΈμ΄λ‹€. upperdirμ—μ„œλŠ” λ³΅μ‚¬λœ νŒŒμΌμ— λ³€κ²½ 사항을 κΈ°λ‘ν•˜κ²Œ 되고, upperdir의 λ³€κ²½λœ νŒŒμΌλ“€κ³Ό λ³€κ²½ 사항이 λ°œμƒν•˜μ§€ μ•Šμ€ lowerdir의 νŒŒμΌλ“€μ΄ 각각 merged 디렉토리에 mountλ˜μ–΄ λ™μž‘ν•˜κ²Œ λœλ‹€.

5. Btrfs

1) νŠΉμ§•

1.
Linuxμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” Storage Driver둜 SSD μ΅œμ ν™”, 데이터 μ••μΆ• λ“± λ‹€μ–‘ν•œ κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.
2.
Dockerμ—μ„œ 기본적으둜 μ§€μ›ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λ³„λ„λ‘œ 파일 μ‹œμŠ€ν…œμ„ κ΅¬μ„±ν•΄μ€˜μ•Ό μ΄μš©ν•  수 μžˆλ‹€.
3.
파일 μ‹œμŠ€ν…œμ΄ κ΅¬μ„±λ˜μ–΄ μžˆλ”λΌλ„, /var/lib/docker 디렉토리가 Btrfsλ₯Ό μ΄μš©ν•˜λŠ” 곡간에 mount λ˜μ–΄μ•Ό Storage Driver둜 μΈμ‹λœλ‹€.
4.
RoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯으둜 이득을 λ³Ό 수 μžˆμ§€λ§Œ, Container의 생성과 μ‚­μ œμ— λŒ€ν•œ μž‘μ—…μ΄ 느린 νŽΈμ΄λ‹€.
5.
RoW 방식과 λ”λΆˆμ–΄, SSD에 μ΅œμ ν™”λœ Storage Driverμ΄λ―€λ‘œ μš°μˆ˜ν•œ μ„±λŠ₯을 보인닀.
6.
κ³„μΈ΅ν™”λœ Image의 Layerλ“€λ‘œ κ΅¬μ„±λœλ‹€.

2) ꡬ쑰

BtrfsλΌλŠ” 파일 μ‹œμŠ€ν…œμ„ κ΅¬μ„±ν•œ λ’€ 이λ₯Ό /var/lib/docker에 mountν•˜λŠ” 과정이 λ¨Όμ € ν•„μš”ν•˜λ‹€. /var/lib/docker에 Btrfsκ°€ mount되면, Storage Driver둜 Btrfsλ₯Ό μ΄μš©ν•  수 있게 λœλ‹€. BtrfsλŠ” Image와 Container의 Layer듀을 Subvolumeκ³Ό Snapshot λ‹¨μœ„λ‘œ κ΄€λ¦¬ν•œλ‹€.
Image의 Base Layerκ°€ 곧 Btrfs의 파일 μ‹œμŠ€ν…œμ΄λ©°, μ΄λŠ” Subvolume으둜 μœ μ§€λœλ‹€. Image의 Layer듀은 ν•˜μœ„ Layer듀을 μ΄μš©ν•˜μ—¬ Snapshot의 ν˜•νƒœλ‘œ μœ μ§€λœλ‹€. Container의 Layer μ—­μ‹œ ν•˜μœ„ Image의 Layer듀을 μ΄μš©ν•˜μ—¬ Snapshot ν˜•νƒœλ‘œ μœ μ§€λœλ‹€. 즉, Container의 LayerλŠ” Image의 κ°€μž₯ μƒμœ„μ— μžˆλŠ” Layer에 λŒ€ν•œ Snapshot으둜 μœ μ§€λœλ‹€.
Btrfs μ—­μ‹œ RoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜λ―€λ‘œ λ³€κ²½ 사항을 기둝할 λ•ŒλŠ” Snapshot 내뢀에 μƒˆλ‘œμš΄ 곡간을 ν• λ‹Ή λ°›μ•„ μˆ˜ν–‰λœλ‹€. RoW 방식이기 λ•Œλ¬Έμ— 전체 파일이 λ³΅μ‚¬λ˜μ–΄ κΈ°λ‘λ˜λŠ” 것이 μ•„λ‹ˆλΌ, λ³€κ²½ 사항이 λ°œμƒν•œ 뢀뢄에 λŒ€ν•œ λ³΅μ‚¬λ§Œ μ΄λ€„μ§€κ²Œ λœλ‹€.

6. ZFS

1) νŠΉμ§•

1.
Sun Microsystemsμ—μ„œ κ°œλ°œν•˜μ˜€μœΌλ©°, Btrfs처럼 λ‹€μ–‘ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” Storage Driver이닀.
2.
λΌμ΄μ„ΌμŠ€ 문제 λ•Œλ¬Έμ— Linux에 기본적으둜 ν¬ν•¨λ˜μ–΄ μžˆμ§€ μ•Šμ•„ λ³„λ„λ‘œ κ΅¬μ„±ν•΄μ€˜μ•Ό ν•œλ‹€. (ZFS on Linux (ZoL)μ΄λΌλŠ” ν”„λ‘œμ νŠΈλ₯Ό μ΄μš©ν•˜μ—¬ ZFS μ„€μΉ˜ν•  λ•Œ 도움을 받을 수 μžˆλ‹€.)
3.
RoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— μ„±λŠ₯으둜 이득을 λ³Ό 수 μžˆμ§€λ§Œ, Container의 생성과 μ‚­μ œμ— λŒ€ν•œ μž‘μ—…μ΄ 느린 νŽΈμ΄λ‹€.
4.
비둝 RoW λ°©μ‹μ΄λΌμ„œ Container의 생성과 μ‚­μ œμ— λŒ€ν•΄ 느릴 수 μžˆμ§€λ§Œ, μ„±λŠ₯ 및 μ•ˆμ •μ„±μ— μ΄ˆμ μ„ λ‘μ—ˆλ‹€λŠ” 점과 Adaptive Replacement CacheλΌλŠ” ꡬ쑰둜 Disk의 블둝을 Caching ν•œλ‹€λŠ” 점 덕뢄에 PaaSμ—μ„œλ„ λ‚˜μ˜μ§€ μ•Šμ€ Storage Driver이닀. ν•˜μ§€λ§Œ 그만큼 κ°€λ²Όμš΄ Storage Driverκ°€ μ•„λ‹ˆλ―€λ‘œ ZFSλ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μˆ˜μ˜ Containerλ₯Ό μœ μ§€ν•  λ•ŒλŠ” Containerκ°€ μ‚¬μš©ν•˜λŠ” Host μžμ› 관리에 ꡉμž₯히 μœ μ˜ν•΄μ•Ό ν•œλ‹€.
5.
κ³„μΈ΅ν™”λœ Image의 Layerλ“€λ‘œ κ΅¬μ„±λœλ‹€.

2) ꡬ쑰

ZFSλΌλŠ” 파일 μ‹œμŠ€ν…œμ„ κ΅¬μ„±ν•œ λ’€ 이λ₯Ό /var/lib/docker에 mountν•˜λŠ” 과정이 λ¨Όμ € ν•„μš”ν•˜λ‹€. /var/lib/docker에 ZFSκ°€ mount되면, zpool이라고 ν•˜λŠ” ZFS의 Storage Pool을 μ΄μš©ν•  수 있게 λœλ‹€. Image의 Base Layerκ°€ ZFS의 파일 μ‹œμŠ€ν…œμ΄ 되고, 이λ₯Ό 동일 Layerμ—λŠ” ZFS Snapshotμ΄λΌλŠ” Snapshot을 μƒμ„±ν•˜κ²Œ λœλ‹€. μƒμœ„ Layerλ₯Ό 기둝할 λ•ŒλŠ” ν•˜μœ„ Layer의 Snapshot을 λ³΅μ œν•˜μ—¬ ZFS Clone을 μƒμ„±ν•˜κ²Œ 되고, 이에 λŒ€ν•œ 기둝을 마치면 λ‹€μ‹œ ZFS Snapshot을 λ§Œλ“œλŠ” μ‹μœΌλ‘œ λ°˜λ³΅λœλ‹€.
ZFS μ—­μ‹œ RoW λ°©μ‹μœΌλ‘œ Writeλ₯Ό μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— zpoolμ΄λΌλŠ” Storage Poolλ‘œλΆ€ν„° λ³€κ²½ 사항 기둝을 μœ„ν•œ νŠΉμ • 크기의 곡간을 블둝 λ‹¨μœ„λ‘œ ν• λ‹Ήλ°›κ²Œ λœλ‹€. 블둝 λ‹¨μœ„μ˜ κ³΅κ°„μ—λŠ” 전체 파일 λ³΅μ‚¬λ˜μ–΄ κΈ°λ‘λ˜λŠ” 것이 μ•„λ‹ˆλΌ λ³€κ²½ 사항이 λ°œμƒν•œ 뢀뢄에 λŒ€ν•œ λ³΅μ‚¬λ§Œ μ΄λ€„μ§€λ―€λ‘œ 비ꡐ적 μ„±λŠ₯이 쒋은 νŽΈμ΄λ‹€.

7. Reference

μ‹œμž‘ν•˜μ„Έμš”! 도컀/μΏ λ²„λ„€ν‹°μŠ€: μΉœμ ˆν•œ μ„€λͺ…μœΌλ‘œ μ‰½κ²Œ μ΄ν•΄ν•˜λŠ” μ»¨ν…Œμ΄λ„ˆ 관리
μΏ λ²„λ„€ν‹°μŠ€μ™€ λ„μ»€μ˜ κΈ°λ³Έ μ‚¬μš© 방법을 μ •ν™•νžˆ μ΄ν•΄ν•˜λŠ” 것을 λͺ©ν‘œλ‘œ ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€! 도컀 μ»¨ν…Œμ΄λ„ˆλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ°°ν¬ν•˜κΈ° μœ„ν•œ μƒˆλ‘œμš΄ νŒ¨λŸ¬λ‹€μž„μ„ μ œμ‹œν•˜λŠ” 가상화 νŒ¨λŸ¬λ‹€μž„μž…λ‹ˆλ‹€. μ»¨ν…Œμ΄λ„ˆ μžμ²΄λŠ” μ‚¬μš©ν•˜κΈ° 맀우 μ‰½μ§€λ§Œ 이λ₯Ό ν™œμš©ν•˜κ³  κ΄€λ¦¬ν•˜κΈ°λŠ” κ²°μ½” 쉽지 μ•ŠμŠ΅λ‹ˆλ‹€. 이 책은 도컀λ₯Ό 처음 μ ‘ν•˜λŠ” 개발자λ₯Ό μœ„ν•œ 도컀 μ»¨ν…Œμ΄λ„ˆμ™€ μ΄λ―Έμ§€μ˜ 기본적인 κ°œλ…μ„ λ¨Όμ € μ„€λͺ…ν•œ λ’€, 도컀 μ»΄ν¬μ¦ˆμ™€ μŠ€μ›œ λͺ¨λ“œλ₯Ό 톡해 μ»¨ν…Œμ΄λ„ˆ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ YAML 파일둜 μž‘μ„±ν•˜κ³  ν΄λŸ¬μŠ€ν„°μ—μ„œ λ°°ν¬ν•˜λŠ” 방법을 μ†Œκ°œν•©λ‹ˆλ‹€.