기존에 계획하셨던 무거운 이벤트 기반 아키텍처(Kafka + Redis + 대규모 Meta DB) 대신, "기존 API Server 기능을 일부 확장하고 MinIO AIStor의 순정 API 및 엔터프라이즈 기능을 최대한 활용하는 방향(Thin API + Fat Storage)"으로의 선회는 매우 현명한 결정입니다. 500~1,000개 노드 규모의 에어갭 환경에서 운영 오버헤드를 극적으로 줄일 수 있는 현실적인 접근입니다.
제시해주신 26가지 요구사항을 분석하여 [AIStor 순정 기능으로 즉시 진행 가능한 부분]과 [순정 기능만으로는 안 되어 최소한의 가벼운 로직/DB 보완이 필요한 부분]으로 명확히 분류하고, 이에 따른 한계와 구체적인 대안을 가이드해 드립니다.
스토리지 고유의 기능이거나 표준 S3 API 규격 내에서 해결되는 요건들입니다. 복잡한 비동기 이벤트 파이프라인 없이 기존 API Server가 MinIO SDK를 호출하는 것만으로 구현 가능합니다.
| 분류 | ID | 요구사항명 | AIStor 순정 기능 대응 및 가이드 |
|---|---|---|---|
| Prefix 라이프사이클 | REQ-01-01 REQ-01-02 | Prefix 동적 생성 플레이스홀더 자동 생성 | S3 규격상 폴더는 실존하지 않으므로, API Server가 새 프리픽스 경로 끝에 .placeholder (또는 .keep) 이름의 빈 객체를 PutObject로 생성해 주면 가상 디렉터리가 즉시 유지됩니다. |
| REQ-01-05 | 하위 객체 리스트 조회 | 표준 S3 ListObjectsV2 API의 Prefix, Delimiter, ContinuationToken을 사용하면 AIStor 자체 엔진이 페이징 처리를 수행하므로 API Server는 단순 전달만 하면 됩니다. | |
| REQ-01-08 | 하위 객체 일괄 삭제 | S3 표준 DeleteObjects (Multi-Object Delete) API를 호출하거나, MinIO 내장 Batch Jobs (Batch Delete) 기능을 트리거하여 스토리지 백엔드에 삭제 연산을 위임합니다. | |
| REQ-01-09 | 소프트 삭제 및 보존 정책 | AIStor의 Bucket Versioning을 활성화하고 ILM (Lifecycle) Policy 규칙을 설정합니다. 삭제 시 DeleteMarker가 생성되며, 설정한 기간(예: 30일) 후 NoncurrentVersionExpiration에 의해 백그라운드에서 자동 영구 삭제됩니다. | |
| 인증 및 인가 | REQ-02-01 REQ-02-02 REQ-02-03 REQ-02-04 | 테넌트별 인증/인가 및 권한 분리 | AIStor IAM 엔진 고유 기능입니다. 사내 AD/LDAP을 연동하고, 정책 변수(${aws:username})가 포함된 단 하나의 글로벌 Policy만 등록해 두면, STS AssumeRole을 통해 발급된 임시 토큰으로 AIStor가 알아서 타인 경로 접근을 차단(Access Denied)하고 Read/Write 권한을 격리합니다. |
| 모니터링 | REQ-04-01 | 전체 Bucket 메트릭 수집 | AIStor가 자체 노출하는 Prometheus v3 메트릭 프리미티브(minio_cluster_usage_buckets_...)를 연동하여 즉시 수집 가능합니다. |
| 안정성 및 로그 | REQ-06-02 | 행위 추적을 위한 Logging | AIStor의 Audit Log 기능이 내부 API 호출 내역(사번 계정, 출발지 IP, 수행 API 종류)을 자체 수집하므로, 이를 기존 웹훅/카프카 타겟으로 지정하여 사내 로그 솔루션(Opensearch 등)으로 쏘아주기만 하면 됩니다. |
| REQ-06-03 | 정기 동기화 보정 배치 | AIStor의 Inventory API를 활성화하면 매일 새벽 전체 객체 상태를 Parquet 파일로 덤프해 줍니다. 이 파일을 배치 프로세스가 읽어 정합성을 검증하면 됩니다. |
S3 아키텍처 특성상 'Prefix(가상 경로)' 단위로는 지원하지 않는 영역입니다. 가장 치명적인 부분은 Prefix 단위의 저장 용량(Byte) 규제 기능이 없다는 점입니다.
| 분류 | ID | 요구사항명 | 미지원 사유 및 한계 |
|---|---|---|---|
| Prefix 라이프사이클 | REQ-01-03 REQ-01-04 | Prefix 목록 및 상태 조회 | S3 규격상 Prefix 자체에는 생성일, 소유자, 상태 등의 메타데이터(Timestamp)가 존재하지 않아 조회가 불가능합니다. |
| REQ-01-06 REQ-01-07 | Prefix 메타데이터(별칭) 수정 | AIStor에는 Prefix에 별칭(Alias을 부여하는 기능이 없습니다. | |
| 용량 쿼터 관리 | REQ-03-01 REQ-03-02 REQ-03-03 | Prefix 단위 쿼터 설정 및 쓰기 제한 | AIStor의 최대 제약 사항. AIStor는 버킷 단위 쿼터(mc quota set)와 Prefix 단위 요청 속도/동시성 제한(mc qos)은 지원하지만, Prefix 단위의 누적 저장 용량(Byte) 하드 제한 기능은 존재하지 않습니다. |
| 모니터링 & 알람 | REQ-04-02 REQ-05-01~04 | Prefix별 시계열 가공 및 쿼터 임계치 알람 | AIStor 내장 메트릭은 버킷 중심이므로 Prefix 단위의 일일 용량 증가율이나 쿼터 임계치(80%, 100%) 도달 여부를 AIStor 스스로 판단하여 알람을 보낼 수 없습니다. |
원래 계획했던 'Kafka + Redis + 복잡한 Consumer 파이프라인'을 전면 전개하지 않고, 기존 API Server에 아주 가벼운 RDB(예: 단일 PostgreSQL 또는 MariaDB) 테이블 1~2개만 추가하여 위 한계들을 우아하게 해결하는 아키텍처 슬리밍(Slimming) 대안입니다.
REQ-01-03, 04, 06, 07 해결)테이블 스키마 필드 예시:
id,prefix_path,owner_sabun,alias_name,created_at,hard_quota_bytes,current_usage_bytes
REQ-03-01~03, REQ-05-01~04 해결)mc qos는 RPS/동시성만 제어 가능).SUM(size)을 계산할 수 있습니다. 계산된 값을 위 마스터 테이블의 current_usage_bytes 컬럼에 하루에 한 번 업데이트합니다.hard_quota_bytes를 초과하는지 체크합니다. 초과 시 URL 발급을 거부(403 Deny)합니다.current_usage_bytes가 설정된 soft_limit(80%)이나 hard_limit을 넘은 테넌트들을 골라내어 사내 알람 시스템(큐브)으로 웹훅을 한 번에 쏘아줍니다.이 방식을 채택하면 시스템 구조가 아래와 같이 극적으로 단순해집니다.
[유저 요청] ──> [ 기존 API Server ] ─── (Pre-signed URL 발급) ───> [ 유저 ]
│ │
(1. DB에서 어제 자 용량 (2. AIStor로
기반 쿼터 고속 체크) 직접 업로드)
│ │
▼ ▼
[ 초경량 Prefix 마스터 DB ] [ MinIO AIStor ]
▲ │
│ (새벽마다 전체 스캔 자동 덤프)
(3. 일일 용량 갱신) │
│ ▼
[ 야간 Inventory 분석 Batch ] <── (Parquet 읽기) ── [ Inventory 버킷 ]
현재 인프라를 이용할 현업 부서나 유저들의 업로드 패턴을 고려했을 때, '실시간 바이트 차단'을 양보하고 위와 같은 '야간 배치 정합성 기반의 하루 주기 쿼터 규제 및 차단 방식'으로 현업 요구사항 유관 부서와 타협할 수 있는 여지가 있으신가요?
===
정확하고 아주 날카로운 지적입니다. 인프라와 스토리지의 보안 메커니즘을 깊게 이해하고 계셔야만 잡을 수 있는 핵심 허점입니다.
사용자가 API Server를 우회하여 MinIO Console(Object Browser) UI나 mc CLI 툴을 통해 S3 엔드포인트로 직접 PutObject API를 호출하면, 앞서 말씀드린 Pre-signed URL 기반의 진입점 차단 방식은 무력화됩니다.
하지만 MinIO AIStor의 강력한 IAM 정책 엔진과 Admin API를 ‘스위치’처럼 활용하면, Kafka나 Redis 같은 무거운 대량 트래픽 처리 인프라 없이도 이 직통 경로를 아주 효과적으로 틀어막을 수 있습니다. 크게 3가지 현실적인 대응 전략을 제시해 드립니다.
"첫 발은 허용하되, 연사(Continuous Upload)는 수초 내에 즉시 차단하는 방식"
Kafka 클러스터를 구축하지 않더라도, MinIO 내부의 이벤트 서브시스템은 API Server의 특정 HTTP Endpoint로 직접 이벤트를 던지는 순정 Webhook 드라이버를 제공합니다.
mc나 웹 UI로 파일 업로드를 시작합니다./api/v1/event-webhook)로 파일 크기 정보를 던집니다.mc admin policy attach)를 호출하여 해당 유저나 AD 그룹에 명시적 쓰기 금지(Deny PutObject) 정책을 실시간으로 강제 바인딩해 버립니다.mc mirror나 대용량 폴더 업로드를 걸어두었더라도, 몇 개 파일이 올라간 직후(수초 내)에 전체 권한이 Access Denied로 동결되므로 스토리지 폭발을 막을 수 있습니다."직접 접속(Console/mc)은 Read-Only만 허용하고, Write는 오직 API Server만 가능하게 분리"
엔터프라이즈 데이터 레이크하우스에서 거버넌스를 유지하기 위해 가장 흔히 쓰는 패러다임입니다. 유저의 접속 경로에 따라 권한을 다르게 부여하는 방식입니다.
s3:ListBucket 및 s3:GetObject (읽기 전용) 권한만 가진 STS 토큰이 발급되도록 MinIO IAM Policy를 고정합니다.PutObject가 가능하게 제한합니다.mc나 웹 UI를 아무리 조작해도 파일 업로드 버튼 자체가 비활성화되거나 권한 에러가 나므로, 우회 업로드 가능성이 원천 봉쇄됩니다."한 번의 우회 업로드로 수 TB를 밀어 넣어 시스템을 마비시키는 상황 방지"
배치나 가벼운 웹훅이 돌기 전, 단 한 번의 직접 호출(mc cp)로 수백 GB나 수 TB짜리 대형 압축 파일을 밀어 넣어 쿼터를 대규모로 초과하는 엣지 케이스를 방지하는 안전장치입니다.
s3:object-size-less-than 조건을 추가하여, 직접 권한으로 올릴 수 있는 단일 파일의 최대 크기를 엄격하게 제한합니다 (예: 단일 파일은 최대 5GB까지만 허용)."Condition": {
"NumericLessThan": {
"s3:object-size-less-than": [5368709120]
}
}
가장 현실적이고 완벽한 조합은 [전략 1 (가벼운 웹훅 기반 동적 Deny 정책 부여)] + [전략 3 (단일 파일 크기 제한)]의 결합입니다.
이렇게 구성하시면 Kafka/Redis 클러스터라는 거대한 인프라 부채를 전혀 지지 않고도, 기존 API Server에 '이벤트 수신 엔드포인트 1개'와 'MinIO Admin SDK를 통한 Policy Attach 로직 1개'만 추가하여 mc와 Object Browser 우회 경로까지 완벽하게 통제권 안에 넣을 수 있습니다.
혹시 사내 유저들이 mc나 Console UI를 통해 데이터를 '직접 업로드(Write)' 해야만 하는 필수적인 비즈니스 요구사항이나 워크플로우가 존재하나요?
==