MinIO Study 1주차 MinIO 소개
가시다님이 운영하시는 MinIO Study 1주차 내용을 정리한 게시글 입니다.
1. MinIO 소개
MinIO를 알기 위해서는 데이터를 저장하기 위한 스토리지들의 종류들에 대한 내용을 먼저 알아보겠습니다.
✅ Block Storage
Block Stoage는 데이터를 고정된 크기의 블록(Block) 단위로 저장하는 스토리지 방식입니다. 각 블록은 고유한 주소(Address)를 가지며, 운영체제는 이 주소를 통해 특정 블록에 직접 접근하여 데이터를 읽거나 쓸 수 있습니다. 이러한 특성 덕분에 데이터베이스, 가상머신 디스크 파일(VMDK, VHD), 트랜잭션이 많은 애플리케이션 등 빠른 I/O와 낮은 지연 시간이 필수적인 워크로드에서 많이 사용합니다.
Block Stoage 자체는 파일명, 경로, 권한과 같은 파일 시스템 레벨의 메타데이터를 관리하지 않고 메타데이터 관리는 블록 스토리지 위에 설치되는 운영체제의 파일 시스템이 관리합니다. 이처럼 역할이 분리되어 있어 블록 스토리지는 순수한 데이터 I/O에만 집중하여 높은 성능을 제공할 수 있습니다. ISCSI나 Fibre Channel과 같은 프로토콜을 통해 서버에 블록 디바이스 형태로 제공되는 것이 일반적인 사용 방식입니다.
✅ File Storage
File Storage는 데이터를 파일(File)과 디렉터리(Directory)로 구성된 계층적 구조로 관리하는 스토리지 방식입니다. 사용자와 애플리케이션은 같은 경로와 파일명을 통해 데이터에 접근하며, 파일 단위의 읽기, 쓰기, 수정이 가능합니다.
File Storage지의 핵심은 파일명, 크기, 소유자, 권한, 타임스탬프 등 풍부하고 구조화된 메타데이터를 직접 관리하는 파일 시스템(예: NTFS, ext4, APFS)에 있습니다. 이러한 메타데이터 관리를 통해 복잡한 디렉터리 구조와 파일 접근 제어를 구현합니다.
네트워크 환경에서는 주로 NAS(Network Attached Storage) 형태로 제공되며, NFS(Linux/Unix)나 SMB/CIFS(Windows)와 같은 표준 파일 공유 프로토콜을 통해 여러 클라이언트가 동시에 접속하여 파일을 공유하고 협업할 수 있습니다. 이때 파일 잠금(File Locking) 메커니즘을 통해 데이터의 일관성을 보장합니다.
근본적으로 파일 스토리지는 블록 스토리지 디바이스 위에 파일 시스템을 포맷하여 구축됩니다.
✅ Object Storage
Object Storage는 데이터를 파일이나 블록이 아닌, 독립된 단위인 '오브젝트(Object)'로 저장하는 스토리지 방식입니다. 각 오브젝트는 데이터 본체(blob), 전역적으로 고유한 식별자(ID), 그리고 사용자가 자유롭게 정의할 수 있는 풍부한 메타데이터(Key-Value)로 구성됩니다.
이러한 오브젝트들은 디렉터리 구조 없이 평면적인 주소 공간(Flat Namespace)에 저장되므로, 시스템 확장이 거의 무제한에 가깝습니다. 이는 수십억 개 이상의 객체를 저장하고 관리해야 하는 대규모 비정형 데이터 저장에 최적화된 이유입니다.
오브젝트 스토리지와의 모든 상호작용은 일반적으로 HTTP/HTTPS 프로토콜 기반의 REST API를 통해 이루어집니다. 파일 잠금 기능이 없는 대신, 강력한 데이터 일관성 모델(Strong Consistency)과 객체 버저닝(Versioning)을 지원하여 데이터의 안정성과 복구를 보장합니다. 이러한 특성 덕분에 클라우드 환경의 백업 및 아카이브, 빅데이터 분석, 웹사이트의 정적 콘텐츠(이미지, 동영상) 호스팅 등에 널리 사용됩니다.
✅ MinIO
MinIO는 고성능 오픈소스 Object Storage 서버이며, MinIO가 Object Storage를 선택한 이유는 다음과 같습니다.
Block Storage는 일반적으로 특정 파일시스템(ZFS.NTFS,ext4)를 적용하는 Row 저장소 위에 파일 시스템을 적용해야하며,File Storage는 파일 저장 시스템의 오버헤드(NFS, SMB)의 영향을 받으며, 메타데이터 부족으로 인해 대량의 비정형 Data 검색 시 검색이 매우 느리다는 단점과 달리 Object Storage는 메타데이터를 활용하여 큰 비정형 Data Set으로 확장 및 검색이 가능하고, Rest API로 접근 시에는 오버헤드가 낮아 빠르게 접근이 가능합니다. 성능은 네트워크와 기본 디스크속도에만 의존하기 때문에 MinIO는 Object Storage를 선택하게 됐습니다.
MinIO 객체 저장소는 Bucket을 이용해서 객체를 구성하고, 버킷은 파일 시스템의 폴더와 디렉토리와 유사한 개념입니다. MinIO 버킷은 AWS S3와 동일한 기능을 제공합니다.
MinIO 배포 방식 및 아키텍처
Single-Node Sing-Drive
한개의 Node와 한개의 Disk로 배포하는 방식을 말하며, 가장 리소스를 적게 사용하는 배포 방식입니다.
Node 장애나, Disk 장애가 발생하는 경우 사용할 수 없기 떄문에 운영 환경에서는 사용을 추천하지 않습니다.
Single-Node Multi-Drive
한개의 Node와 여러개의 Disk로 배포하는 방식을 말하며, Disk 장애에 대해서는 예방할 수 있지만, Node 장애에 대해서는 예방할 수 없는 배포 방식입니다.
Multi-Node Multi-Drive
여러개의 Node와 여러개의 Disk로 배포하는 방식을 말하며, Disk와 Node 장애에 대해서 예방할 수 있는 가장 안전한 배포 방식이며 운영환경에서 사용합니다.
MinIO가 Multi-Node Multi-Drive 방식으로 배포 되었을때 관리되는 과정을 예시를 통해 알아보겠습니다.
각 노드당 4개의 Disk를 사용하며, 4개의 Node로 배포된 단일 서버풀을 사용하는 MinIO Cluster 경우 다음과 같이 관리 됩니다.
MinIO server https://MinIO{1...4}.example.net/mnt/disk{1...4}
각 노드당 4개의 Disk를 사용하며, 4개의 Node로 배포된 2개의 서버풀을 사용하는 MinIO Cluster 경우 다음과 같이 관리 됩니다.
MinIO server https://MinIO{1...4}.example.net/mnt/disk{1...4}
https://MinIO{5...8}.example.net/mnt/disk{1...4}
Best Practice는 한개의 서버 풀에 최소 4개의 Node로 Cluster를 구성하는 것을 공식문서에서 강력하게 권장하고 있습니다.
MinIO로 Cluster 구성 시 PCI-E 컨트롤러 보드에 연결된 NVMe 또는 SSD 드라이브와 같은 로컬 연결 스토리지를 사용할 때 최상의 성능을 제공 합니다.
스토리지 컨트롤러는 RADI나 복원력 계층 없이 "Just a Bunch of Drives"(JBOD) 구성으로 XFS 포맷 드라이브를 제공해야 합니다.
MinIO에서는 드라이브, 컨트롤러 계층에서 캐싱을 사용하지 않는 것을 권장하는데, 캐시가 채워지고 지워지는 과정에서 I/O 스파크가 발생하여 성능 저하를 발생 시킬 수 있습니다.
각 MinIO 서버는 분산 토폴로지에 대한 완전한 그림을 가지고 있어, Application은 배포 내의 어떤 노드에든 연결하여 작업을 지시할 수 있습니다.

Figure 1.1 분산 토폴로지에 대한 완전한 그림 예시
2. MinIO의 가용성 및 복원력
MinIO의 가용성 및 복원력에 대해서 알아보기 전에 공식 문서에서 사용하는 용어들에 대해서 먼저 정리를 해보겠습니다.
용어 정리
✅ Bit Rot
Bit Rot란 모스토리지 매체(HDD, SSD 등)에 저장된 데이터가 시간이 지남에 따라 점차적으로 손상되어, 1비트 또는 그 이상의 데이터가 의도치 않게 변경되는 현상을 말합니다.
✅ Eraser Coding
Eraser Coding은 원본 데이터를 여러 개의 데이터 조각(Data Shard)으로 나누고, 이 데이터 조각들을 기반으로 수학적 계산을 통해 추가적인 패리티 조각(Parity Shard)을 생성하는 기술입니다. 이렇게 생성된 전체 조각(데이터 + 패리티)들을 여러 Disk에 나누어 저장하는 기술을 말합니다.
✅ Eraser set
Eraser set이란 Erasure Coding을 적용하는 물리적 드라이브의 그룹을 의미합니다. 즉, 하나의 객체를 여러 조각(데이터 + 패리티)으로 나누어 저장할 때, 그 조각들이 분산되어 저장되는 드라이브들의 집합을 말합니다.
✅ Read Quorum
Read Quorum은 객체 읽기(GET) 요청에 응답하기 위해, 성공적으로 읽어야 하는 최소 조각의 개수를 말합니다.
✅ Write Quorum
Write Quorum은 객체 쓰기(PUT) 작업을 '성공'으로 최종 판정하기 위해, 성공적으로 저장되어야 하는 최소 조각(데이터+패리티)의 개수를 말합니다.
✅ Parity
원본 데이터를 기반으로 수학적 계산을 통해 생성된 추가적인 복구용 데이터 조각이며, Erasure Set중 일부에 장애가 발생하여 저장된 데이터 조각을 잃어버렸을 때, 남아있는 다른 조각들과 이 패리티 조각을 조합하여 원본 데이터를 복원하는 데 사용합니다.
MinIO의 가용성 및 복원력 원리
MinIO는 가용성 및 복원력을 제공하기 위해 Eraser Coding과 데이터 분산을 이용하여 가용성 및 복원력을 제공합니다.
Eraser Coding을 사용하게되면, MinIO Cluster의 여러 Node나 Disk에 장애가 발생한 경우 객체를 즉시 자동으로 재구성을 할 수 있습니다.
MinIO는 객체를 Shard라는 Chunk로 나누고 이를 Eraser set의 각 Disk에 균등하게 분배합니다. 이로 인해 Disk에 장애가 발생해도 읽기 및 쓰기 작업을 수행 할 수 있습니다.
Parity를 사용하여 객체 수준에서 데이터를 보호합니다. 운영 환경에서 MinIO는 Data Disk와 Parity Disk로 나누며, MinIO Eraser Coding을 을 수행 할 때 해싱 정보를 Parity Disk 에 추가를 하고 MinIO는 Parity 정보를 사용해서 객체 무결성과 손실 및 손상된 객체 Shard를 복원합니다.
또한 해싱 알고리즘을을 아용해서 객체의 무결성을 확인 합니다. 객체에 대한 모든 작업을 수행 할 때마다 무결성을 확인하며, Bit Rot로 인해 객체가 손상된 것을 확인하게 되며 해당 객체의 Parity Shard 가용성에 따라 자동으로 복구할 수 있습니다.
파일 검색 및 업로드 과정
MinIO에 PUT Method를 사용해서 파일을 업로드 하는 과정은 다음과 같습니다.
sequenceDiagram
participant Client as 클라이언트
participant LB as 로드 밸런서
participant MinIO_Node1 as MinIO 노드 1<br>(Coordinator)
participant MinIO_Node2 as MinIO 노드 2
participant MinIO_NodeN as MinIO 노드 N
%% 1. 클라이언트 요청 %%
Client->>+LB: PUT /my-bucket/my-object.jpg (객체 데이터 포함)
%% 2. 로드 밸런서가 코디네이터 노드로 요청 전달 %%
LB->>+MinIO_Node1: PUT /my-bucket/my-object.jpg
%% 3. 코디네이터 노드 내부 처리 %%
Note over MinIO_Node1: 1. 파일명으로 Hash 값 생성 & Modulus 함수 수행
Note over MinIO_Node1: 2. 저장되는 Drive Set 확인 & <br> Eraser Coding으로 객체를 데이터와 패리티블록으로 분리
Note over MinIO_Node1: 3. Drive Set과 데이터와 패리티블록끼리 Mapping
Note over MinIO_Node1: 4. Mapping된 정보로 Node 및 Disk에 데이터 저장
%% 4. 데이터 조각 분산 저장 %%
par
MinIO_Node1->>+MinIO_Node1: 조각 1 저장
MinIO_Node1->>+MinIO_Node2: 조각 2 저장
MinIO_Node1->>+MinIO_NodeN: 조각 N 저장
and
MinIO_Node1-->>-MinIO_Node1: 저장 성공
MinIO_Node2-->>-MinIO_Node1: 저장 성공
MinIO_NodeN-->>-MinIO_Node1: 저장 성공
end
%% 5. 최종 응답 반환 %%
Note over MinIO_Node1: 모든 조각 저장 완료 확인
MinIO_Node1-->>-LB: HTTP/1.1 200 OK
LB-->>-Client: HTTP/1.1 200 OK
Figure 2.1 MinIO 객체 삽입 프로세스
sequenceDiagram
participant Client as 클라이언트
participant LB as 로드 밸런서
participant MinIO_Node1 as MinIO 노드 1<br>(Coordinator)
participant MinIO_Node2 as MinIO 노드 2
participant MinIO_NodeN as MinIO 노드 N
Title: MinIO 객체 조회 (GET Method)
%% 1. 클라이언트 요청 %%
Client->>+LB: GET /my-bucket/my-object.jpg
%% 2. 로드 밸런서가 코디네이터 노드로 요청 전달 %%
LB->>+MinIO_Node1: GET /my-bucket/my-object.jpg
%% 3. 코디네이터 노드 내부 처리 %%
Note over MinIO_Node1: 1. 파일명으로 Hash 값 생성 & Modulus 함수 수행
Note over MinIO_Node1: 2. 수행된 결과로 객체조회
%% 4. 데이터 조각 요청 및 재조립 %%
par
MinIO_Node1->>+MinIO_Node1: 조각 1 요청
MinIO_Node1->>+MinIO_Node2: 조각 2 요청
MinIO_Node1->>+MinIO_NodeN: 조각 N 요청
and
MinIO_Node1-->>-MinIO_Node1: 조각 1 전송
MinIO_Node2-->>-MinIO_Node1: 조각 2 전송
MinIO_NodeN-->>-MinIO_Node1: 조각 N 전송
end
Note over MinIO_Node1: Parity Block으로 데이터 재조립
%% 5. 최종 응답 반환 %%
MinIO_Node1-->>-LB: HTTP/1.1 200 OK + 최종 객체 데이터
LB-->>-Client: HTTP/1.1 200 OK + 최종 객체 데이터
Figure 2.2 MinIO에 객체 조회 프로세스
Quorum을 통한 가용성 및 복원력
MinIO는 객체 이름과 경로를 기반하는 결정적 Hashing 알고리즘을 사용하여 객체에 대한 Eraser Set을 선택합니다.
객체에 읽기/쓰기 작업을 수행할 때, 항상 동일한 Eraser Set을 사용하기 떄문에 읽기 및 쓰기 Quorum이 필요합니다.
읽기 Quorum은 Parity에 따라 갯수가 달라지며, Parity 보다 적은 Disk에서 장애가 발생해도 정상 Disk에 있는 Eraser Set을 통해 읽기 작업을 수행할 수 있습니다.

Figure 2.3 읽기 Querm 장애 발생 시 복원
쓰기 Quorum은 Parity가 Eraser Set Disk의 수의 절반보다 작으면 쓰기 Quorum은 Parity와 같아집니다.
쓰기 Quorum으로 지정된 Disk에 장애가 발생해서 Eraser Set에 장애가 발생한 경우, MinIO는 복구를 위한 Parity의 수를 자동으로 늘려서 가용성과 복원력을 보장합니다.
해당 방식은 임시적인 조치라, 장기적으로 안정성을 보장하기 위해서는 장애 Disk를 수리 및 교체를 해야합니다.

Figure 2.3 쓰기 Querm 장애 발생 시 복원
Parity가 Eraser set Disk의 절반인 경우 쓰기 Quorum은 Parity + 1이 되어 Distribue Brain 시나리오로 인한 데이터 불일치를 방지할 수 있습니다.

Figure 2.4 Querm 장애 예시
구성된 Parity보다 많은 Disk에 장애가 발생한 경우 MinIO에서는 데이터 손실 문제가 발생합니다.
예를들어, 최대 Eraser Set이 16이고, 최대 Parity가 8일때 9개의 Disk에서 장애가 발생한 경우 데이터 손실이 발생합니다.

Figure 2.5 MinIO 데이터 손실 사례
3. Docker을 이용한 간단 실습
Single-Node Sing-Drive 환경 실습
mkdir /tmp/data
docker run -itd -p 9000:9000 -p 9090:9090 --name MinIO -v /tmp/data:/data \
-e "MinIO_ROOT_USER=admin" -e "MinIO_ROOT_PASSWORD=MinIO123" \
quay.io/MinIO/MinIO server /data --console-address ":9090"

Figure 3.1 Test Bucket 생성 후 파일 업로드
tree -h /tmp/data
# [4.0K] /tmp/data
# └── [4.0K] test
# └── [4.0K] temp.txt
# └── [ 427] xl.meta
# 3 directories, 1 file
cat /tmp/data/test/temp.txt/xl.meta
# ▒MTime▒d▒{e▒▒▒MetaSys▒▒x-MinIO-internal-inline-data▒true▒MetaUsr▒▒etag▒ 06a6c5fd18eca1898d5f4c905083610b▒content-type▒text/plain▒v▒h▒▒▒x?K▒▒▒null▒,▒▒K▒*▒▒e▒▒f▒[▒▒▒▒▒IAOp▒▒▒▒_▒▒임시파일
MinIO Client 사용 실습
MinIO Client(MC)는 MinIO에 저장되어있는 객체들에 대해 cat, cp, mirror, diff와 같은 Unix Command를 사용할 수 있게 해줍니다.
# MinIO Client Install
curl --progress-bar -L https://dl.min.io/aistor/mc/release/linux-amd64/mc \
--create-dirs \
-o $HOME/aistor-binaries/mc
chmod +x ~/aistor-binaries/mc
sudo mv ~/aistor-binaries/mc /usr/local/bin/
mc alias set 'myMinIO' 'http://127.0.0.1:9000' 'admin' 'MinIO123'
mc admin info myMinIO
# ● 127.0.0.1:9000
# Uptime: 1 hour
# Version: 2025-09-07T16:13:09Z
# Network: 1/1 OK
# Drives: 1/1 OK
# Pool: 1
# ┌──────┬───────────────────────┬─────────────────────┬──────────────┐
# │ Pool │ Drives Usage │ Erasure stripe size │ Erasure sets │
# │ 1st │ 0.6% (total: 956 GiB) │ 1 │ 1 │
# └──────┴───────────────────────┴─────────────────────┴──────────────┘
# 12 B Used, 1 Bucket, 1 Object
mc ls myMinIO/test
# [2025-09-13 13:53:11 KST] 12B STANDARD temp.txt
### 실습 리소스 삭제
docker rm -f MinIO && rm -rf /tmp/data
Single-Node Multi-Disk 실습
mkdir -p /tmp/disk1 /tmp/disk2 /tmp/disk3 /tmp/disk4
# 최대 한개의 장애 디스크 허용 설정 적용
docker run -itd -p 9000:9000 -p 9090:9090 --name MinIO \
-v /tmp/disk1:/data1 \
-v /tmp/disk2:/data2 \
-v /tmp/disk3:/data3 \
-v /tmp/disk4:/data4 \
-e "MinIO_ROOT_USER=admin" -e "MinIO_ROOT_PASSWORD=MinIO123" -e "MinIO_STORAGE_CLASS_STANDARD=EC:1" \
quay.io/MinIO/MinIO server /data{1...4} --console-address ":9090"
docker logs MinIO
# INFO: Formatting 1st pool, 1 set(s), 4 drives per set.
# INFO: WARNING: Host local has more than 1 drives of set. A host failure will result in data becoming unavailable.
이전 실습과 다르게 저는 GPT로 생성한 임의의 영어문장 200개를 생성을 하고 UI에 파일을 업로드 하겠습니다.

Figure 3.2 Test Bucket 생성 후 파일 업로드
tree -h /tmp
# [4.0K] /tmp
# ├── [4.0K] disk1
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
# │ └── [3.6K] xl.meta
# ├── [4.0K] disk2
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
# │ └── [3.6K] xl.meta
# ├── [4.0K] disk3
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
# │ └── [3.6K] xl.meta
# ├── [4.0K] disk4
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
# │ └── [3.6K] xl.meta
cat /tmp/disk1/test/temp.txt/xl.meta
# XL2 ▒m▒&▒▒▒d▒Ӡ[n▒▒▒▒▒▒?▒▒Type▒V2Obj▒▒ID▒▒DDir▒▒▒k▒KɁ▒:%▒▒%▒EcAlgo▒EcM▒EcN▒EcBSize▒▒EcIndex▒EcDist▒▒CSumAlgo▒PartNums▒▒PartETags▒PartSizes▒▒%▒PartASizes▒▒%▒Size▒%▒MTime▒d▒Ӡ[n▒▒MetaSys▒▒x-MinIO-internal-inline-data▒true▒MetaUsr▒▒content-type▒text/plain▒etag▒ 03125ee79c66f31f9a6403805965af29▒v▒h▒▒▒j▒;▒▒▒null▒
# ȁ=j.▒ی.▒▒▒__▒a4▒/[}+▒-k▒▒▒d 1 The sun rises in the east.
# 2 She reads a book every night.
# 3 Cats are known for their independence.
# 4 He plays the guitar in a band.
cat /tmp/disk2/test/temp.txt/xl.meta
# XL2 ▒m▒&▒▒▒d▒Ӡ[n▒▒▒▒▒▒?▒▒Type▒V2Obj▒▒ID▒▒DDir▒▒▒k▒KɁ▒:%▒▒%▒EcAlgo▒EcM▒EcN▒EcBSize▒▒EcIndex▒EcDist▒▒CSumAlgo▒PartNums▒▒PartETags▒PartSizes▒▒%▒PartASizes▒▒%▒Size▒%▒MTime▒d▒Ӡ[n▒▒MetaSys▒▒x-MinIO-internal-inline-data▒true▒MetaUsr▒▒content-type▒text/plain▒etag▒ 03125ee79c66f31f9a6403805965af29▒v▒h▒▒▒▒Zg▒▒null▒
# ▒`6M{Q▒.▒xB-'v&▒=Q▒▒3▒▒n▒
# c▒▒L(▒ 78 The forest is home to many animals.
# 79 She is giving a presentation.
cat /tmp/disk4/test/temp.txt/xl.meta
# $"=&p^oH5r;5e3~.,k{$kgvyr4&baas `ug 7!:Z^.d
3개의 Disk에 분산저장이 되었고, 한개의 Disk에 Parity가 지정된 것을 실습을 통해 확인할 수 있습니다.
유실 재현 및 복구하는 방법에 대해서 실습해보겠습니다.
mc admin info myMinIO
# ┌──────┬───────────────────────┬─────────────────────┬──────────────┐
# │ Pool │ Drives Usage │ Erasure stripe size │ Erasure sets │
# │ 1st │ 0.6% (total: 2.8 TiB) │ 4 │ 1 │
# └──────┴───────────────────────┴─────────────────────┴──────────────┘
# 강제로 (패리티 아닌)디렉터리 1개 제거
sudo rm -rf /tmp/disk1/test
# Bucket 복구
mc admin heal myMinIO/test
# ◐ test
# 0/0 objects; 0 B in 0s
# ┌────────┬───┬─────────────────────┐
# │ Green │ 1 │ 100.0% ████████████ │
# │ Yellow │ 0 │ 0.0% │
# │ Red │ 0 │ 0.0% │
# │ Grey │ 0 │ 0.0% │
# └────────┴───┴─────────────────────┘
cat /tmp/disk1/test/temp.txt/xl.meta
# XL2 ▒m▒&▒▒▒d▒Ӡ[n▒▒▒▒▒▒?▒▒Type▒V2Obj▒▒ID▒▒DDir▒▒▒k▒KɁ▒:%▒▒%▒EcAlgo▒EcM▒EcN▒EcBSize▒▒EcIndex▒EcDist▒▒CSumAlgo▒PartNums▒▒PartETags▒PartSizes▒▒%▒PartASizes▒▒%▒Size▒%▒MTime▒d▒Ӡ[n▒▒MetaSys▒▒x-MinIO-internal-inline-data▒true▒MetaUsr▒▒etag▒ 03125ee79c66f31f9a6403805965af29▒content-type▒text/plain▒v▒h▒▒▒3▒▒▒▒null▒
# ȁ=j.▒ی.▒▒▒__▒a4▒/[}+▒-k▒▒▒d 1 The sun rises in the east.
# 2 She reads a book every night.
# 3 Cats are known for their independence.
# 4 He plays the guitar in a band.
# 강제로 디렉터리 2개 제거
sudo rm -rf /tmp/disk1/test
sudo rm -rf /tmp/disk2/test
tree -h /tmp
# [4.0K] /tmp
# ├── [4.0K] disk1
# ├── [4.0K] disk2
# ├── [4.0K] disk3
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
# │ └── [3.6K] xl.meta
# ├── [4.0K] disk4
# │ └── [4.0K] test
# │ └── [4.0K] temp.txt
mc stat myMinIO/test/temp.txt
# mc: <ERROR> Unable to list folder. The specified bucket does not exist
# mc: <ERROR> Unable to stat `myMinIO/test/temp.txt`. Object does not exist.
mc admin heal myMinIO/test
# ◐ test
# 0/0 objects; 0 B in 0s
# ┌────────┬───┬─────────────────────┐
# │ Green │ 1 │ 100.0% ████████████ │
# │ Yellow │ 0 │ 0.0% │
# │ Red │ 0 │ 0.0% │
# │ Grey │ 0 │ 0.0% │
# └────────┴───┴─────────────────────┘
tree -h /tmp
# [4.0K] /tmp
# ├── [4.0K] disk1
# │ └── [4.0K] test
# ├── [4.0K] disk2
# │ └── [4.0K] test
# ├── [4.0K] disk3
# │ └── [4.0K] test
# ├── [4.0K] disk4
docker rm -f MinIO && sudo rm -rf /tmp/disk{1..4}
Parity 갯수가 넘어가는 Disk에서 장애가 발생하는 경우 복구시도를 하면서 Disk3, Disk4(Parity)의 파일도 전부 삭제되는 것으로 확인했습니다.
EC를 2로 지정했을때는 PUT/GET이 정상적으로 작동하는지 확인해 보겠습니다.
mkdir -p /tmp/disk1 /tmp/disk2 /tmp/disk3 /tmp/disk4
docker run -itd -p 9000:9000 -p 9090:9090 --name MinIO \
-v /tmp/disk1:/data1 \
-v /tmp/disk2:/data2 \
-v /tmp/disk3:/data3 \
-v /tmp/disk4:/data4 \
-e "MinIO_ROOT_USER=admin" -e "MinIO_ROOT_PASSWORD=MinIO123" -e "MinIO_STORAGE_CLASS_STANDARD=EC:2" \
quay.io/MinIO/MinIO server /data{1...4} --console-address ":9090"
# cat 명령어를 이용하여 Parity Disk 확인(3,4 Parity Disk)
cat /tmp/disk1/test/temp.txt/xl.meta
# 강제로 디렉터리 2개 제거
sudo rm -rf /tmp/disk1/test
sudo rm -rf /tmp/disk2/test
간단한 Python Code를 이용하여 PUT/GET을 테스트해보겠습니다.
import os
from MinIO import MinIO
from MinIO.error import S3Error
# 사용자의 MinIO 서버 정보로 수정하세요.
MinIO_ENDPOINT = "localhost:9000"
MinIO_ACCESS_KEY = "admin"
MinIO_SECRET_KEY = "MinIO123"
# 로컬 개발 환경이 아니라면 secure=True로 설정하는 것이 안전합니다.
USE_SECURE = False
# 테스트에 사용할 버킷 및 객체 정보
BUCKET_NAME = "test"
OBJECT_NAME = "temp.txt"
SOURCE_FILE_PATH = "upload_source.txt"
DEST_FILE_PATH = "download_destination.txt"
def main():
"""
MinIO 클라이언트를 초기화하고, PUT/GET 테스트를 수행하는 메인 함수
"""
try:
# 1. MinIO 클라이언트 초기화
client = MinIO(
MinIO_ENDPOINT,
access_key=MinIO_ACCESS_KEY,
secret_key=MinIO_SECRET_KEY,
secure=USE_SECURE
)
print("✅ MinIO 클라이언트 초기화 성공")
# 2. 버킷 존재 여부 확인 및 생성
found = client.bucket_exists(BUCKET_NAME)
if not found:
client.make_bucket(BUCKET_NAME)
print(f"📦 버킷 '{BUCKET_NAME}' 생성 완료")
else:
print(f"📦 버킷 '{BUCKET_NAME}'가 이미 존재합니다.")
# 3. PUT 테스트: 객체 업로드
print("\n--- PUT 테스트 시작 ---")
# 업로드할 테스트 파일 생성
test_content = "Hello, MinIO! This is a test file for Python PUT operation."
with open(SOURCE_FILE_PATH, "w") as f:
f.write(test_content)
print(f"📝 로컬 테스트 파일 '{SOURCE_FILE_PATH}' 생성 완료")
# fput_object를 사용하여 파일 업로드
result = client.fput_object(
BUCKET_NAME, OBJECT_NAME, SOURCE_FILE_PATH,
)
print(
f"⬆️ 객체 '{result.object_name}' (버전: {result.version_id}) 업로드 성공"
)
# 4. GET 테스트: 객체 다운로드
print("\n--- GET 테스트 시작 ---")
# fget_object를 사용하여 파일 다운로드
client.fget_object(
BUCKET_NAME, OBJECT_NAME, DEST_FILE_PATH
)
print(f"⬇️ 객체 '{OBJECT_NAME}'를 '{DEST_FILE_PATH}'로 다운로드 성공")
# 5. 검증: 원본 파일과 다운로드된 파일 내용 비교
print("\n--- 검증 시작 ---")
with open(SOURCE_FILE_PATH, 'r') as f1, open(DEST_FILE_PATH, 'r') as f2:
source_content = f1.read()
dest_content = f2.read()
if source_content == dest_content:
print("👍 검증 성공: 업로드된 파일과 다운로드된 파일의 내용이 일치합니다.")
else:
print("❌ 검증 실패: 파일 내용이 일치하지 않습니다.")
print(f"원본 내용: {source_content}")
print(f"대상 내용: {dest_content}")
except S3Error as exc:
print("❌ MinIO 에러 발생:", exc)
finally:
# 6. 정리: 테스트에 사용된 로컬 파일 삭제
print("\n--- 정리 시작 ---")
if os.path.exists(SOURCE_FILE_PATH):
os.remove(SOURCE_FILE_PATH)
print(f"🗑️ 로컬 파일 '{SOURCE_FILE_PATH}' 삭제 완료")
if os.path.exists(DEST_FILE_PATH):
os.remove(DEST_FILE_PATH)
print(f"🗑️ 로컬 파일 '{DEST_FILE_PATH}' 삭제 완료")
if __name__ == "__main__":
main()
# ✅ MinIO 클라이언트 초기화 성공
# 📦 버킷 'test'가 이미 존재합니다.
# --- PUT 테스트 시작 ---
# 📝 로컬 테스트 파일 'upload_source.txt' 생성 완료
# ...
PUT을 하기 위해서는 쓰기 Quorum이 3개가 있어야하는데, 2개밖에 충족시키지 못하여 PUT작업은 에러가 발생합니다. 하지만 읽기 Quorum에는 해당하지 않아 파일을 정상적으로 읽어올 수 는 있습니다.
'DevOps > Study' 카테고리의 다른 글
| MinIO Study 2주차 DirectPV (0) | 2025.09.20 |
|---|---|
| MinIO Study 1주차 MinIO On k8s (0) | 2025.09.13 |
| Cilium Study [1기] 8주차 K8S Security & Tetragon (0) | 2025.09.06 |
| Cilium Study [1기] 7주차 Cilium Performance & Tunning (1) | 2025.08.31 |
| Cilium Study [1기] 7주차 K8S Performance & Tunning (1) | 2025.08.31 |