Hadoop-S3 (S3A) 정리
1. 정의
**Hadoop-S3(S3A)**는 Hadoop이 Amazon S3 또는 MinIO 같은 S3 호환 오브젝트 스토리지에 접근할 수 있게 해주는 파일 시스템 커넥터
2. 주요 구성 요소
hadoop-aws.jar Hadoop이 S3A를 인식하도록 하는 커넥터
aws-java-sdk-bundle.jar AWS S3 API를 사용하기 위한 Java SDK
core-site.xml S3A 설정을 명시하는 Hadoop 설정 파일 (endpoint, 키 등)
3. 작동 방식
- 내부적으로 s3a:// 스킴을 사용해 오브젝트 스토리지(S3/MinIO)에 접근
- HDFS처럼 다룰 수 있도록 추상화
- 예: hadoop fs -ls s3a://my-bucket/
4. MinIO와 Hadoop-S3의 관계
기본 관계 MinIO는 S3A의 backend로 동작 가능
역할 Hadoop-S3 커넥터가 MinIO에 s3a://를 통해 접근
설정 방법 core-site.xml 또는 Spark 설정에 MinIO endpoint, access key, secret key를 넣으면 연동
사용 예 Iceberg, Spark, Presto 등이 s3a://my-bucket/... 경로를 통해 MinIO의 데이터를 읽고 쓰기
[Iceberg or Spark or Presto]
|
| (fs.s3a.impl)
v
[Hadoop S3A 커넥터 (hadoop-aws + aws-sdk)]
|
v
[MinIO 서버 (S3 호환 스토리지)]
5. Hadoop-s3 만으로 충분 한 경우
- Spark, Iceberg 등에서 단순히 MinIO를 스토리지로만 쓸 경우
- hadoop fs 명령이나 HDFS 클러스터가 필요 없는 경우
- 이럴 때는 Hadoop을 설치할 필요 없이 필요한 JAR만 넣고 설정만 적용하면 충분
6. core-site.xml 확인
- MinIO 설정은 /home/본인계정/hadoop-conf/core-site.xml
<configuration>
<property>
<name>fs.s3a.access.key</name>
<value>minioadmin</value>
</property>
<property>
<name>fs.s3a.secret.key</name>
<value>minioadmin</value>
</property>
<property>
<name>fs.s3a.endpoint</name>
<value>http://localhost:9000</value>
</property>
<property>
<name>fs.s3a.path.style.access</name>
<value>true</value>
</property>
<property>
<name>fs.s3a.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
</configuration>
7. 프로젝트 구조 생성
~/hadoop/
├── minio-s3a-maven/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ └── minio/
│ └── MinioTest.java
$ mkdir -p ~/hadoop/minio-s3a-maven/src/main/java/com/example/minio
$ cd ~/hadoop/minio-s3a-maven
8. pom.xml 생성
$ cat <<EOF > pom.xml
<dependencies>
<!-- Hadoop AWS -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-aws</artifactId>
<version>3.3.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Hadoop Common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.3.6</version>
<exclusions>
<!-- 여기서도 log4j 관련 바인딩 제거 -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- AWS SDK -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bundle</artifactId>
<version>1.12.367</version>
</dependency>
<!-- SLF4J API -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<!-- SLF4J 바인딩: simple만 유지 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
EOF
9. Java 코드 생성
$ cat <<EOF > src/main/java/com/example/minio/MinioTest.java
package com.example.minio;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.LocatedFileStatus;
import java.net.URI;
public class MinioTest {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
conf.addResource(new Path("/home/본인계정/hadoop-conf/core-site.xml"));
FileSystem fs = FileSystem.get(new URI("s3a://my-bucket"), conf);
RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path("s3a://my-bucket/"), false);
while (files.hasNext()) {
LocatedFileStatus fileStatus = files.next();
System.out.println(fileStatus.getPath());
}
}
}
EOF
10. 빌드
$ cd ~/hadoop/minio-s3a-maven
$ mvn clean package
11. 실행( 파일 목록 화면에 뿌리기 )
$ java -cp "target/minio-s3a-test-1.0-SNAPSHOT.jar:$(cat cp.txt)" com.example.minio.MinioTest
12. 업로드 셈플 파일 만들기
$ echo "Hello hadoop-s3 to minIo!!" > ~/hadoopToMinioTest.txt
13. MinioUpload.java
$ nano src/main/java/com/example/minio/MinioUpload.java
package com.example.minio;
// Hadoop 설정 및 파일 시스템 관련 클래스 임포트
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;
public class MinioUpload {
public static void main(String[] args) throws Exception {
// 로컬에서 업로드할 파일 경로 (절대경로 사용)
String localFile = "/home/ubuntu/sample.txt";
// MinIO의 업로드 대상 경로 (s3a 프로토콜 사용)
String s3aPath = "s3a://my-bucket/uploaded-sample.txt";
// core-site.xml 로딩하여 Hadoop 설정 객체 생성
Configuration conf = new Configuration();
conf.addResource(new Path("/home/ubuntu/hadoop-conf/core-site.xml"));
// Hadoop FileSystem 객체 생성 (s3a 프로토콜에 맞는 구현체로 초기화)
FileSystem fs = FileSystem.get(new URI(s3aPath), conf);
// Hadoop 대상 경로 객체 생성
Path destPath = new Path(s3aPath);
// try-with-resources 문법으로 파일 스트림 열기
try (
// 로컬 파일을 읽기 위한 InputStream
InputStream in = new FileInputStream(localFile);
// MinIO(S3A)에 쓸 Hadoop OutputStream 생성 (덮어쓰기 허용)
FSDataOutputStream out = fs.create(destPath, true)
) {
// 버퍼를 사용하여 데이터를 읽고 씀 (4KB 단위)
byte[] buffer = new byte[4096];
int bytesRead;
// in.read(): 버퍼 크기만큼 로컬 파일에서 읽고, out.write()로 S3A에 씀
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
}
}
// 업로드 완료 메시지 출력
System.out.println("업로드 완료 → " + s3aPath);
}
}
13. 빌드/실행
$ mvn clean package
$ mvn dependency:build-classpath -Dmdep.outputFile=cp.txt
$ java -cp "target/minio-s3a-test-1.0-SNAPSHOT.jar:$(cat cp.txt)" com.example.minio.MinioUploadTest
14. 파일 삭제
14.1. FileSystem.delete(Path, recursive)
fs.delete(new Path("s3a://my-bucket/삭제할파일이름"), false);
- 첫 번째 인자: 삭제할 S3A 경로
- 두 번째 인자: 디렉토리일 경우 true로 주면 하위 파일까지 재귀 삭제
→ 지금은 단일 파일이므로 false
14.2. MinioDelete.java
$ nano src/main/java/com/example/minio/MinioDelete.java
package com.example.minio;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.net.URI;
public class MinioDelete {
public static void main(String[] args) throws Exception {
// 삭제할 파일의 S3A 경로
String s3aPath = "s3a://my-bucket/uploaded-sample.txt";
// core-site.xml 기반 설정 로딩
Configuration conf = new Configuration();
conf.addResource(new Path("/home/본인계정/hadoop-conf/core-site.xml"));
// S3A용 FileSystem 객체 생성
FileSystem fs = FileSystem.get(new URI(s3aPath), conf);
Path target = new Path(s3aPath);
// 파일 삭제 시도
boolean success = fs.delete(target, false);
if (success) {
System.out.println("삭제 완료 ::: " + s3aPath);
} else {
System.out.println("삭제 실패 또는 파일 없음 ::: " + s3aPath);
}
}
}
14.3. 빌드/실행
$ mvn clean package
$ mvn dependency:build-classpath -Dmdep.outputFile=cp.txt
$ java -cp "target/minio-s3a-test-1.0-SNAPSHOT.jar:$(cat cp.txt)" com.example.minio.MinioDelete
'kill' 카테고리의 다른 글
apache/hive:3.1.3 기반 Docker 환경 구성 (11) | 2025.05.26 |
---|---|
minio, hadoop-s3, iceberg, stremPark, hive (29) | 2025.05.20 |
minio, hadoop (6) | 2025.05.15 |
Kafka (Helm 기반) 제거 스크립트 (2) | 2025.05.14 |
Kafka 설치 - Bitnami Helm Chart (20) | 2025.05.14 |