아이스버그 AWS 통합
아이스버그 AWS 통합 (Iceberg AWS Integrations)
이 문서에서는 iceberg-aws 모듈을 통해 아이스버그를 다양한 AWS 서비스와 통합하는 방법을 알려드릴게요. AWS 통합 활성화, Glue·DynamoDB·RDS JDBC 카탈로그, DynamoDB 잠금 관리자, S3 FileIO의 다양한 기능, 그리고 AWS 클라이언트 커스터마이제이션까지 폭넓게 살펴볼게요.
출처: 문서
본문
아이스버그는 iceberg-aws 모듈을 통해 다양한 AWS 서비스와의 통합을 제공해요. 이 섹션에서는 아이스버그를 AWS와 함께 사용하는 방법을 설명해요.
AWS 통합 활성화 (Enabling AWS Integration)
iceberg-aws 모듈은 0.11.0부터 모든 버전의 스파크와 플링크 엔진 런타임에 번들돼 있어요. 하지만 AWS 클라이언트는 번들되지 않아서, 애플리케이션과 같은 클라이언트 버전을 사용할 수 있어요. 아이스버그가 의존하는 것은 AWS v2 SDK를 제공해야 해요. AWS SDK 번들을 선택하거나, 최소 의존성 풋프린트를 원한다면 개별 AWS 클라이언트 패키지(Glue, S3, DynamoDB, KMS, STS)를 선택할 수 있어요.
모든 기본 AWS 클라이언트는 HTTP 연결 관리를 위해 Apache HTTP Client를 사용해요. 이 의존성은 AWS SDK 번들의 일부가 아니므로 별도로 추가해야 해요. URL Connection HTTP Client 같은 다른 HTTP 클라이언트 라이브러리를 선택하려면 클라이언트 커스터마이제이션 섹션을 참고해주세요.
AWS 모듈의 모든 기능은 커스텀 카탈로그 속성을 통해 로드될 수 있어요. 각 엔진의 문서에서 커스텀 카탈로그를 로드하는 방법을 볼 수 있어요. 몇 가지 예시는 다음과 같아요.
스파크 (Spark)
예를 들어 Spark 3.4(scala 2.12)와 AWS 클라이언트(iceberg-aws-bundle에 패키징)로 AWS 기능을 사용하려면 다음으로 스파크 SQL 셸을 시작해요.
# start Spark SQL client shell
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.11.0,org.apache.iceberg:iceberg-aws-bundle:1.11.0 \
--conf spark.sql.defaultCatalog=my_catalog \
--conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO
보시다시피 셸 명령에서 --packages로 모든 관련 AWS 의존성을 포함하는 추가 iceberg-aws-bundle을 지정해요.
플링크 (Flink)
Flink에서 AWS 모듈을 사용하려면 필요한 의존성을 다운로드하고 Flink SQL 클라이언트를 시작할 때 지정할 수 있어요.
# download Iceberg dependency
ICEBERG_VERSION=1.11.0
MAVEN_URL=https://repo1.maven.org/maven2
ICEBERG_MAVEN_URL=$MAVEN_URL/org/apache/iceberg
wget $ICEBERG_MAVEN_URL/iceberg-flink-runtime/$ICEBERG_VERSION/iceberg-flink-runtime-$ICEBERG_VERSION.jar
wget $ICEBERG_MAVEN_URL/iceberg-aws-bundle/$ICEBERG_VERSION/iceberg-aws-bundle-$ICEBERG_VERSION.jar
# start Flink SQL client shell
/path/to/bin/sql-client.sh embedded \
-j iceberg-flink-runtime-$ICEBERG_VERSION.jar \
-j iceberg-aws-bundle-$ICEBERG_VERSION.jar \
shell
이러한 의존성으로 다음과 같은 Flink 카탈로그를 만들 수 있어요.
CREATE CATALOG my_catalog WITH (
'type'='iceberg',
'warehouse'='s3://my-bucket/my/key/prefix',
'catalog-type'='glue',
'io-impl'='org.apache.iceberg.aws.s3.S3FileIO'
);
sql-client-defaults.yaml에서 카탈로그 구성을 지정해서 미리 로드할 수도 있어요.
catalogs:
- name: my_catalog
type: iceberg
warehouse: s3://my-bucket/my/key/prefix
catalog-type: glue
io-impl: org.apache.iceberg.aws.s3.S3FileIO
하이브 (Hive)
Hive에서 AWS 모듈을 사용하려면 Flink 예시와 비슷하게 필요한 의존성을 다운로드한 뒤 Hive 클래스패스에 추가하거나 CLI에서 런타임에 jar를 추가할 수 있어요.
add jar /my/path/to/iceberg-hive-runtime.jar;
add jar /my/path/to/aws/bundle.jar;
이러한 의존성으로 CLI에서 런타임에 다음으로 Glue 카탈로그를 등록하고 Hive에서 외부 테이블을 만들 수 있어요.
SET iceberg.engine.hive.enabled=true;
SET hive.vectorized.execution.enabled=false;
SET iceberg.catalog.glue.type=glue;
SET iceberg.catalog.glue.warehouse=s3://my-bucket/my/key/prefix;
-- suppose you have an Iceberg table database_a.table_a created by GlueCatalog
CREATE EXTERNAL TABLE database_a.table_a
STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
TBLPROPERTIES ('iceberg.catalog'='glue');
hive-site.xml에서 위 구성을 설정해서 카탈로그를 미리 로드할 수도 있어요.
카탈로그 (Catalogs)
사용자가 AWS로 아이스버그 카탈로그를 구축하는 데 선택할 수 있는 여러 옵션이 있어요.
Glue 카탈로그 (Glue Catalog)
아이스버그는 AWS Glue를 카탈로그 구현으로 사용하는 것을 지원해요. 사용하면 아이스버그 네임스페이스는 Glue Database로, 아이스버그 테이블은 Glue Table로, 모든 아이스버그 테이블 버전은 Glue TableVersion으로 저장돼요. catalog-impl을 org.apache.iceberg.aws.glue.GlueCatalog로 지정하거나 catalog-type을 glue로 설정해서 Glue 카탈로그를 시작할 수 있어요. 위의 AWS 통합 활성화 섹션에서 본 것과 같아요. 카탈로그 로드에 대한 더 자세한 내용은 Spark와 Flink 같은 개별 엔진 페이지에서 찾을 수 있어요.
Glue 카탈로그 ID (Glue Catalog ID)
각 AWS 계정과 각 AWS 리전에 고유한 Glue metastore가 있어요. 기본적으로 GlueCatalog는 사용자의 기본 AWS 클라이언트 자격증명과 리전 설정을 기반으로 사용할 Glue metastore를 선택해요. glue.id 카탈로그 속성으로 Glue 카탈로그 ID를 지정해서 다른 AWS 계정의 Glue 카탈로그를 가리킬 수 있어요. Glue 카탈로그 ID는 숫자 AWS 계정 ID예요. Glue 카탈로그가 다른 리전에 있다면 AWS 클라이언트가 올바른 리전을 가리키도록 구성해야 해요. 자세한 내용은 AWS 클라이언트 커스터마이제이션을 참고해주세요.
아카이브 건너뛰기 (Skip Archive)
AWS Glue는 오래된 테이블 버전을 아카이브하는 기능이 있고, 사용자는 필요하면 테이블을 어떤 과거 버전으로든 롤백할 수 있어요. 기본적으로 Iceberg Glue 카탈로그는 오래된 테이블 버전의 아카이브를 건너뛰어요. 사용자가 오래된 테이블 버전을 아카이브하려면 glue.skip-archive를 false로 설정할 수 있어요. 아이스버그 테이블로의 스트리밍 수집의 경우, glue.skip-archive를 false로 설정하면 Glue 테이블 버전이 빠르게 많이 만들어지는 점에 유의해주세요. 자세한 내용은 Glue Quotas와 UpdateTable API를 읽어주세요.
이름 검증 건너뛰기 (Skip Name Validation)
테이블 이름과 네임스페이스에 대한 이름 검증을 건너뛰도록 허용해요. 연산이 Hive 호환되도록 Glue 모범 사례를 따르는 것이 권장돼요. 이는 비표준 문자를 사용하는 기존 규칙이 있는 사용자만을 위해 추가된 것이에요. 데이터베이스 이름과 테이블 이름 검증을 건너뛰면 다운스트림 시스템이 모두 그 이름을 지원한다는 보장이 없어요.
낙관적 잠금 (Optimistic Locking)
기본적으로 아이스버그는 테이블 동시 업데이트에 Glue의 낙관적 잠금(optimistic locking)을 사용해요. 낙관적 잠금에서 각 테이블은 버전 id가 있어요. 사용자가 테이블 메타데이터를 가져오면 아이스버그는 그 테이블의 버전 id를 기록해요. 사용자는 서버 측의 버전 ID가 변경되지 않은 동안 테이블을 업데이트할 수 있어요. 다른 누군가가 당신보다 먼저 테이블을 수정하면 버전 불일치가 발생해서 업데이트 실패를 일으켜요. 그러면 아이스버그는 메타데이터를 새로고침하고 충돌이 있는지 확인해요. 커밋 충돌이 없으면 연산이 재시도돼요. 낙관적 잠금은 Glue에서 아이스버그 테이블의 원자적 트랜잭션을 보장해요. 또한 다른 사람이 실수로 당신의 변경을 덮어쓰는 것도 방지해요.
정보 (Info)
Glue의 낙관적 잠금을 활용하려면 AWS SDK 버전 >= 2.17.131을 사용해주세요. AWS SDK 버전이 2.17.131보다 낮으면 인메모리 잠금만 사용돼요. 원자적 트랜잭션을 보장하려면 DynamoDB 잠금 관리자를 설정해야 해요.
Warehouse 위치 (Warehouse Location)
다른 모든 카탈로그 구현과 비슷하게, warehouse는 스토리지에서 데이터 웨어하우스의 루트 경로를 결정하는 필수 카탈로그 속성이에요. 기본적으로 Glue는 S3FileIO 사용 때문에 warehouse 위치를 S3에서만 허용해요. 데이터를 다른 로컬 또는 클라우드 스토어에 저장하려면 io-impl 카탈로그 속성을 설정해서 Glue 카탈로그가 HadoopFileIO 또는 어떤 커스텀 FileIO로 전환할 수 있어요. 이 기능에 대한 자세한 내용은 커스텀 FileIO 섹션에서 찾을 수 있어요.
테이블 위치 (Table Location)
기본적으로 네임스페이스 my_ns의 테이블 my_table의 루트 위치는 my-warehouse-location/my-ns.db/my-table이에요. 이 기본 루트 위치는 네임스페이스와 테이블 수준 모두에서 변경할 수 있어요.
네임스페이스 아래의 모든 테이블에 대해 다른 경로 프리픽스를 사용하려면 AWS 콘솔이나 어떤 AWS Glue 클라이언트 SDK로든 해당 Glue 데이터베이스의 locationUri 속성을 업데이트해요. 예를 들어 my_ns의 locationUri를 s3://my-ns-bucket으로 업데이트하면, 새로 만들어지는 테이블은 모두 새 프리픽스 아래에 기본 루트 위치를 가져요. 예를 들어 새 테이블 my_table_2의 루트 위치는 s3://my-ns-bucket/my_table_2가 돼요.
특정 테이블에 완전히 다른 루트 경로를 사용하려면 location 테이블 속성을 원하는 루트 경로 값으로 설정해요. 예를 들어 Spark SQL에서 다음을 할 수 있어요.
CREATE TABLE my_catalog.my_ns.my_table (
id bigint,
data string,
category string)
USING iceberg
OPTIONS ('location'='s3://my-special-table-bucket')
PARTITIONED BY (category);
LOCATION 키워드를 지원하는 Spark 같은 엔진의 경우 위 SQL 문은 다음과 동등해요.
CREATE TABLE my_catalog.my_ns.my_table (
id bigint,
data string,
category string)
USING iceberg
LOCATION 's3://my-special-table-bucket'
PARTITIONED BY (category);
DynamoDB 카탈로그 (DynamoDB Catalog)
아이스버그는 DynamoDB 테이블을 사용해서 데이터베이스와 테이블 정보를 기록하고 관리하는 것을 지원해요.
구성 (Configurations)
DynamoDB 카탈로그는 다음 구성을 지원해요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| dynamodb.table-name | iceberg | DynamoDbCatalog가 사용하는 DynamoDB 테이블 이름 |
내부 테이블 설계 (Internal Table Design)
DynamoDB 테이블은 다음 컬럼으로 설계돼요.
| 컬럼 | 키 | 타입 | 설명 |
|---|---|---|---|
| identifier | 파티션 키 | string | db1.table1 같은 테이블 식별자, 또는 네임스페이스의 문자열 NAMESPACE |
| namespace | 정렬 키 | string | 네임스페이스 이름. 네임스페이스를 파티션 키, identifier를 정렬 키로 하는 전역 보조 인덱스(GSI)가 만들어지고, 다른 프로젝션 컬럼은 없음 |
| v | string | 행 버전, 낙관적 잠금에 사용 | |
| updated_at | number | 마지막 업데이트의 타임스탬프(밀리초) | |
| created_at | number | 테이블 생성의 타임스탬프(밀리초) | |
| p.<property_key> | string | table_type, metadata_location, previous_metadata_location을 포함한 아이스버그 정의 테이블 속성 또는 네임스페이스 속성 |
이 설계는 다음과 같은 이점이 있어요.
- 파티션 키가 테이블 수준이므로 같은 네임스페이스 내 테이블에 무거운 쓰기 트래픽이 있어도 잠재적 핫 파티션 문제를 피해요.
- 네임스페이스 연산은 테이블 커밋 연산에 영향을 주지 않도록 단일 파티션에 클러스터링돼요.
- 테이블 나열 연산에는 정렬 키에서 파티션 키로의 역 GSI가 사용되고, 다른 모든 연산은 단일 행 연산 또는 단일 파티션 쿼리예요. 카탈로그의 어떤 연산도 전체 테이블 스캔이 필요하지 않아요.
- 두 프로세스가 같은 밀리초에 커밋하는 것을 피하기 위해 updated_at 대신 문자열 UUID 버전 필드 v가 사용돼요.
- catalog.renameTable의 멱등성을 보장하기 위해 다중 행 트랜잭션이 사용돼요.
- 속성이 최상위 컬럼으로 평면화되어 사용자가 어떤 속성 필드에도 커스텀 GSI를 추가해서 카탈로그를 커스터마이즈할 수 있어요. 예를 들어 사용자는 owner 정보를 테이블 속성 owner로 저장하고 p.owner 컬럼에 GSI를 추가해서 owner로 테이블을 검색할 수 있어요.
RDS JDBC 카탈로그 (RDS JDBC Catalog)
아이스버그는 관계형 데이터베이스의 테이블을 사용해서 아이스버그 테이블을 관리하는 JDBC 카탈로그도 지원해요. AWS RDS 같은 관계형 데이터베이스 서비스와 JDBC 카탈로그를 사용하도록 구성할 수 있어요. JDBC 카탈로그 사용에 대한 가이드와 예시는 JDBC 통합 페이지를 읽어주세요. IAM 인증으로 JDBC 카탈로그 구성에 대한 자세한 내용은 이 AWS 문서를 읽어주세요.
어떤 카탈로그를 선택할까요? (Which catalog to choose?)
사용할 수 있는 모든 옵션과 함께, 애플리케이션에 맞는 올바른 카탈로그를 선택할 때 다음과 같은 지침을 제공해요.
- 조직이 기존 Glue metastore를 갖고 있거나 Glue, Athena, EMR, Redshift, LakeFormation을 포함한 AWS 분석 에코시스템을 사용할 계획이라면, Glue 카탈로그가 가장 쉬운 통합을 제공해요.
- 애플리케이션이 테이블에 빈번한 업데이트 또는 높은 읽기·쓰기 처리량(예: 스트리밍 쓰기)을 요구한다면, Glue와 DynamoDB 카탈로그가 낙관적 잠금으로 최상의 성능을 제공해요.
- 카탈로그의 테이블에 대한 접근 제어를 강제하고 싶다면, Glue 테이블은 IAM 리소스로 관리될 수 있고, DynamoDB 카탈로그 테이블은 훨씬 더 복잡한 항목 수준 권한으로만 관리될 수 있어요.
- 전체 카탈로그를 스캔하지 않고 테이블 속성 정보를 기반으로 테이블을 쿼리하고 싶다면, DynamoDB 카탈로그는 어떤 임의 속성 필드에 대해서든 보조 인덱스를 만들 수 있고 효율적인 쿼리 성능을 제공해요.
- DynamoDB 카탈로그의 이점을 가지면서도 Glue에 연결하고 싶다면, Lambda 트리거와 DynamoDB 스트림을 활성화해서 DynamoDB 카탈로그의 테이블 정보로 Glue metastore를 비동기적으로 업데이트할 수 있어요.
- 조직이 RDS에서 기존 관계형 데이터베이스를 유지하거나 serverless Aurora를 사용해서 테이블을 관리한다면, JDBC 카탈로그가 가장 쉬운 통합을 제공해요.
DynamoDB 잠금 관리자 (DynamoDb Lock Manager)
Amazon DynamoDB는 HadoopCatalog 또는 HadoopTables에서 사용할 수 있어서, 모든 커밋에 대해 카탈로그가 먼저 보조 DynamoDB 테이블을 사용해 잠금을 획득하고 그다음 아이스버그 테이블을 안전하게 수정하려 시도해요. 이것은 S3처럼 파일 쓰기 상호배제를 제공하지 않는 스토리지에서 파일 시스템 기반 카탈로그가 원자적 트랜잭션을 보장하는 데 필요해요.
이 기능은 다음 잠금 관련 카탈로그 속성이 필요해요.
- lock-impl을 org.apache.iceberg.aws.dynamodb.DynamoDbLockManager로 설정.
- lock.table을 사용하고 싶은 DynamoDB 테이블 이름으로 설정. 주어진 이름의 잠금 테이블이 DynamoDB에 없으면 billing mode를 pay-per-request로 설정해 새 테이블이 만들어져요.
하트비트 간격 같은 잠금 동작을 조정하는 데에도 다른 잠금 관련 카탈로그 속성들이 사용될 수 있어요. 자세한 내용은 잠금 카탈로그 속성(Lock catalog properties)을 참고해주세요.
S3 FileIO
아이스버그는 S3FileIO를 통해 사용자가 S3에 데이터를 쓸 수 있게 해요. GlueCatalog는 기본적으로 이 FileIO를 사용하고, 다른 카탈로그는 io-impl 카탈로그 속성을 사용해 이 FileIO를 로드할 수 있어요.
점진적 멀티파트 업로드 (Progressive Multipart Upload)
S3FileIO는 데이터를 업로드하기 위해 커스터마이즈된 점진적 멀티파트 업로드 알고리즘을 구현해요. 각 파트가 준비되는 즉시 데이터 파일이 파트별로 병렬로 업로드되고, 각 파일 파트는 업로드 프로세스가 완료되는 즉시 삭제돼요. 이는 업로드 중 업로드 속도를 최대화하고 로컬 디스크 사용량을 최소화해요. 이 기능과 관련해 사용자가 조정할 수 있는 구성은 다음과 같아요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.multipart.num-threads | 시스템의 사용 가능한 프로세서 수 | 파트를 S3로 업로드하는 데 사용할 스레드 수 (모든 출력 스트림에서 공유) |
| s3.multipart.part-size-bytes | 32MB | 멀티파트 업로드 요청을 위한 단일 파트 크기 |
| s3.multipart.threshold | 1.5 | 단일 put object 요청으로 업로드하는 것에서 멀티파트 업로드로 전환하는 지점으로, 멀티파트 크기의 인자로 표현되는 임계값 |
| s3.staging-dir | java.io.tmpdir 속성 값 | 임시 파일을 보관하는 디렉터리 |
S3 서버 측 암호화 (S3 Server Side Encryption)
S3FileIO는 모든 3가지 S3 서버 측 암호화 모드를 지원해요.
- SSE-S3: Amazon S3 관리 키(SSE-S3)로 서버 측 암호화를 사용할 때 각 객체는 고유한 키로 암호화돼요. 추가 안전장치로 키 자체를 정기적으로 교체하는 마스터 키로 암호화해요. Amazon S3 서버 측 암호화는 사용할 수 있는 가장 강력한 블록 암호 중 하나인 256비트 Advanced Encryption Standard(AES-256)로 데이터를 암호화해요.
- SSE-KMS: AWS Key Management Service에 저장된 고객 마스터 키(CMK)로 서버 측 암호화(SSE-KMS)는 SSE-S3와 비슷하지만, 이 서비스를 사용하기 위한 추가 이점과 요금이 있어요. Amazon S3에서 객체를 승인되지 않은 접근으로부터 추가 보호를 제공하는 CMK 사용에 대한 별도의 권한이 있어요. 또한 SSE-KMS는 CMK가 언제, 누구에 의해 사용됐는지 보여주는 감사 추적을 제공해요. 추가로 사용자 고유의 관리형 CMK를 만들고 관리하거나 사용자, 서비스, 리전에 고유한 AWS 관리형 CMK를 사용할 수 있어요.
- DSSE-KMS: AWS Key Management Service 키가 있는 이중 레이어 서버 측 암호화(DSSE-KMS)는 SSE-KMS와 비슷하지만, Amazon S3에 업로드될 때 객체에 두 레이어의 암호화를 적용해요. DSSE-KMS는 데이터에 다층 암호화를 적용하고 암호화 키를 완전히 제어해야 하는 규정 준수 표준을 충족하는 데 사용될 수 있어요.
- SSE-C: 고객 제공 키(SSE-C)로 서버 측 암호화를 사용하면 암호화 키를 관리하고, Amazon S3가 디스크에 쓸 때 암호화하고 객체에 접근할 때 복호화하는 것을 관리해요.
서버 측 암호화를 활성화하려면 다음 구성 속성을 사용해요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.sse.type | none | none, s3, kms, dsse-kms 또는 custom |
| s3.sse.key | kms와 dsse-kms 타입은 aws/s3, 그 외는 null | kms와 dsse-kms 타입의 KMS 키 ID 또는 ARN, custom 타입의 커스텀 base-64 AES256 대칭 키 |
| s3.sse.md5 | null | SSE 타입이 custom이면 이 값은 무결성을 보장하기 위해 대칭 키의 base-64 MD5 다이제스트로 설정해야 해요. |
S3 접근 제어 목록 (S3 Access Control List)
S3FileIO는 상세한 접근 제어를 위해 S3 접근 제어 목록(ACL)을 지원해요. s3.acl 속성을 설정해 ACL 수준을 선택할 수 있어요. 자세한 내용은 S3 ACL 문서를 읽어주세요.
객체 스토어 파일 레이아웃 (Object Store File Layout)
S3와 다른 많은 클라우드 스토리지 서비스는 객체 프리픽스 기반으로 요청을 제한해요. 전통적인 Hive 스토리지 레이아웃으로 S3에 저장된 데이터는 객체가 같은 파일 경로 프리픽스 아래에 저장되면서 S3 요청 제한에 직면할 수 있어요.
아이스버그는 기본적으로 Hive 스토리지 레이아웃을 사용하지만 ObjectStoreLocationProvider로 전환할 수 있어요. ObjectStoreLocationProvider를 사용하면 저장된 각 파일에 대해 결정적 해시가 생성되고, 해시가 write.data.path 바로 뒤에 추가돼요. 이는 S3에 쓰여진 파일이 S3 버킷의 여러 프리픽스에 고르게 분산되도록 보장해서 S3 관련 IO 연산의 제한을 최소화하고 처리량을 최대화해요. ObjectStoreLocationProvider를 사용할 때 아이스버그 테이블 전체에 걸쳐 write.data.path를 공유하면 성능이 개선돼요.
S3가 API QPS를 어떻게 스케일링하는지에 대한 자세한 내용은 2018 re:Invent 세션 Amazon S3와 Amazon S3 Glacier 모범 사례를 확인해주세요. 53:39에서 S3가 어떻게 스케일링/파티셔닝되는지, 54:50에서 새 파티션이 만들어지기 전에 30-60분 대기 시간에 대해 논의합니다.
ObjectStorageLocationProvider를 사용하려면 테이블 속성에 'write.object-storage.enabled'=true를 추가해요. 아래는 ObjectStorageLocationProvider를 사용해 테이블을 만드는 예시 Spark SQL 명령이에요:
CREATE TABLE my_catalog.my_ns.my_table (
id bigint,
data string,
category string)
USING iceberg
OPTIONS (
'write.object-storage.enabled'=true,
'write.data.path'='s3://my-table-data-bucket/my_table')
PARTITIONED BY (category);
그런 다음 이 새 테이블에 단일 행을 삽입할 수 있어요.
INSERT INTO my_catalog.my_ns.my_table VALUES (1, "Pizza", "orders");
그러면 write.object-storage.path 바로 뒤에 20비트 base2 해시(01010110100110110010)가 추가되어 S3에 데이터가 쓰여요. 테이블에 대한 읽기가 S3 버킷 프리픽스에 고르게 분산되고 성능이 개선돼요. 이전에 제공된 base64 해시는 S3 General Purpose Buckets에서 더 나은 자동 스케일링 동작을 제공하기 위해 base2로 업데이트됐어요.
이 업데이트의 일부로, 디렉터리가 더 빠른 순회를 위해 워커 간 작업을 나누는 수단으로 사용되므로 아이스버그의 고아 정리 프로세스의 효율성을 개선하기 위해 엔트로피를 여러 디렉터리로 나눴어요. 아래 예시에서 볼 수 있듯이 해시를 나눠 깊이 3의 4비트 디렉터리를 만들고 해시의 마지막 부분을 끝에 붙여요.
s3://my-table-data-bucket/my_ns.db/my_table/0101/0110/1001/10110010/category=orders/00000-0-5affc076-96a4-48f2-9cd2-d5efbc9f0c94-00001.parquet
참고로 ObjectStoreLocationProvider의 경로 해석 로직은 write.data.path 다음이
하지만 0.12.0까지의 이전 버전의 경우 로직은 다음과 같아요.
- 0.12.0 이전: write.object-storage.path가 반드시 설정돼야 해요.
- 0.12.0에서: write.object-storage.path 다음이 write.folder-storage.path 다음이
/data예요. - 2.0.0에서: write.object-storage.path와 write.folder-storage.path가 제거될 예정이에요.
자세한 내용은 LocationProvider 구성(LocationProvider Configuration) 섹션을 참고해주세요.
또한 새 테이블 속성 write.object-storage.partitioned-paths를 추가했는데, false(기본값=true)로 설정하면 파일 경로에서 파티션 값을 생략해요. 아이스버그는 파일 경로에 이 값들이 필요하지 않으며 false로 설정하면 키 크기를 더 줄일 수 있어요. 이 경우 엔트로피의 마지막 8비트도 파일 이름에 직접 추가해요. 이 구성으로 삽입된 키는 다음과 같아요. category=orders가 제거됐다는 점에 유의해주세요:
s3://my-table-data-bucket/my_ns.db/my_table/1101/0100/1011/00111010-00000-0-5affc076-96a4-48f2-9cd2-d5efbc9f0c94-00001.parquet
S3 재시도 (S3 Retries)
S3 제한을 만나는 워크로드는 S3가 자동으로 스케일링하는 동안 진행하기 위해 지수 백오프로 지속적으로 재시도해야 해요. 이 목적을 위해 S3 재시도를 조정하는 아래 구성을 제공해요. 제한을 만나고 재시도 소진으로 실패하는 워크로드의 경우, S3가 자동 스케일링할 수 있도록 재시도 횟수를 32로 설정하는 것을 권장해요. S3가 아직 스케일링하지 않은 테이블에 대해 예외적으로 높은 처리량을 가진 워크로드는 재시도 횟수를 더 늘려야 할 수 있다는 점에 유의해주세요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.retry.num-retries | 5 | S3 연산을 재시도하는 횟수. 고처리량 워크로드에는 32를 권장. |
| s3.retry.min-wait-ms | 2s | S3 연산을 재시도하기 위해 기다리는 최소 시간. |
| s3.retry.max-wait-ms | 20s | S3 읽기 연산을 재시도하기 위해 기다리는 최대 시간. |
S3 강한 일관성 (S3 Strong Consistency)
2020년 11월에 S3는 모든 읽기 연산에 대해 강한 일관성을 발표했고, 아이스버그는 이 기능을 완전히 활용하도록 업데이트됐어요. IO 연산 중 성능에 부정적 영향을 줄 수 있는 중복 일관성 대기와 확인이 없어요.
Hadoop S3A FileSystem (Hadoop S3A FileSystem)
중요 (Important)
S3 사용 사례에는 S3A FileSystem(HadoopFileIO)보다 S3FileIO를 권장해요.
S3FileIO가 도입되기 전에는 많은 아이스버그 사용자가 S3A FileSystem을 통해 HadoopFileIO를 사용해 S3에 데이터를 쓰기로 선택했어요. 앞선 섹션에서 소개했듯이 S3FileIO는 최적화된 보안과 성능을 위해 최신 AWS 클라이언트와 S3 기능을 채택해요.
S3FileIO는 s3:// URI 스킴으로 데이터를 쓰지만 S3A FileSystem이 쓴 스킴과도 호환돼요. 이는 s3a:// 또는 s3n:// 파일 경로를 가진 어떤 테이블 매니페스트도 S3FileIO가 여전히 읽을 수 있다는 뜻이에요. 이 기능은 사람들이 S3A에서 S3FileIO로 쉽게 전환할 수 있게 해줘요.
어떤 이유로든 S3A를 사용해야 한다면 다음 지침이 있어요.
- S3A로 데이터를 저장하려면 warehouse 카탈로그 속성을 S3A 경로로 지정해요. 예: s3a://my-bucket/my-warehouse
- HiveCatalog의 경우 S3A로 메타데이터도 저장하려면 hadoop 구성 속성 hive.metastore.warehouse.dir을 S3A 경로로 지정해요.
- hadoop-aws를 컴퓨트 엔진의 런타임 의존성으로 추가해요.
- hadoop-aws 문서를 기반으로 AWS 설정을 구성해요 (버전을 확인하세요. S3A 구성은 사용하는 버전에 따라 크게 달라져요).
S3 쓰기 체크섬 검증 (S3 Write Checksum Verification)
업로드된 객체의 무결성을 보장하기 위해, s3.checksum-enabled 카탈로그 속성을 true로 설정해서 S3 쓰기에 대한 체크섬 검증을 켤 수 있어요. 이것은 기본적으로 꺼져 있어요.
S3 태그 (S3 Tags)
쓰기와 삭제 중에 커스텀 태그를 S3 객체에 추가할 수 있어요. 예를 들어 Spark 3.5로 S3 태그를 쓰려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.write.tags.my_key1=my_val1 \
--conf spark.sql.catalog.my_catalog.s3.write.tags.my_key2=my_val2
위 예시에서 S3의 객체는 my_key1=my_val1, my_key2=my_val2 태그로 저장돼요. 지정된 쓰기 태그는 객체 생성 중에만 저장된다는 점에 유의해주세요.
s3.delete-enabled 카탈로그 속성이 false로 설정되면 객체가 S3에서 하드 삭제되지 않아요. 이는 S3 삭제 태깅과 함께 사용하도록 의도된 것으로, 객체에 태그를 달고 S3 라이프사이클 정책을 사용해 제거돼요. 이 속성은 기본적으로 true로 설정돼요.
s3.delete.tags 구성으로 객체가 삭제되기 전에 구성된 키-값 쌍으로 태그가 지정돼요. 사용자는 버킷 수준에서 태그 기반 객체 라이프사이클 정책을 구성해서 객체를 다른 티어로 전환할 수 있어요. 예를 들어 Spark 3.5로 S3 삭제 태그를 추가하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
sh spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://iceberg-warehouse/s3-tagging \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.delete.tags.my_key3=my_val3 \
--conf spark.sql.catalog.my_catalog.s3.delete-enabled=false
위 예시에서 S3의 객체는 삭제 전에 my_key3=my_val3 태그로 저장돼요. 사용자는 s3.delete.num-threads 카탈로그 속성으로 S3 객체에 삭제 태그를 추가하는 데 사용할 스레드 수를 명시할 수도 있어요.
s3.write.table-tag-enabled와 s3.write.namespace-tag-enabled 카탈로그 속성을 true로 설정하면 S3의 객체가 iceberg.table=
sh spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://iceberg-warehouse/s3-tagging \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.write.table-tag-enabled=true \
--conf spark.sql.catalog.my_catalog.s3.write.namespace-tag-enabled=true
태그 제한에 대한 자세한 내용은 사용자 정의 태그 제한(User-Defined Tag Restrictions)을 참고해주세요.
S3 접근 포인트 (S3 Access Points)
접근 포인트를 사용해 버킷에서 접근 포인트로의 매핑을 지정해서 S3 연산을 수행할 수 있어요. 이는 다중 리전 접근, 교차 리전 접근, 재해 복구 등에 유용해요.
교차 리전 접근 포인트를 사용하려면 S3FileIO가 교차 리전 호출을 할 수 있도록 use-arn-region-enabled 카탈로그 속성을 추가로 true로 설정해야 해요. 같은/다중 리전 접근 포인트에는 필요하지 않아요.
예를 들어 Spark 3.5로 S3 접근 포인트를 사용하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.use-arn-region-enabled=false \
--conf spark.sql.catalog.my_catalog.s3.access-points.my-bucket1=arn:aws:s3::<ACCOUNT_ID>:accesspoint/<MRAP_ALIAS> \
--conf spark.sql.catalog.my_catalog.s3.access-points.my-bucket2=arn:aws:s3::<ACCOUNT_ID>:accesspoint/<MRAP_ALIAS>
위 예시에서 my-bucket1과 my-bucket2 버킷의 S3 객체는 모든 S3 연산에 arn:aws:s3::<ACCOUNT_ID>:accesspoint/<MRAP_ALIAS> 접근 포인트를 사용해요.
접근 포인트 사용에 대한 자세한 내용은 호환되는 Amazon S3 연산에서 접근 포인트 사용과 샘플 노트북을 참고해주세요.
S3 접근 허가 (S3 Access Grants)
S3 접근 허가는 IAM 보안 주체를 사용해 S3 데이터에 접근을 부여하는 데 사용할 수 있어요. Iceberg에서 S3 접근 허가가 동작하도록 하려면 S3 Access Grants Plugin jar를 클래스패스에 추가한 후 s3.access-grants.enabled 카탈로그 속성을 true로 설정할 수 있어요. 이 플러그인의 Maven 목록 링크는 여기에서 찾을 수 있어요.
또한 fallback-to-IAM 구성을 허용하는데, 이는 S3 접근 허가가 S3 호출을 승인할 수 없는 경우 S3 데이터에 접근하기 위해 IAM 역할(및 그 권한 집합을 직접) 사용하도록 폴백할 수 있게 해요. 이는 s3.access-grants.fallback-to-iam boolean 카탈로그 속성으로 수행할 수 있어요. 기본적으로 이 속성은 false로 설정돼요.
예를 들어 Spark 3.5로 S3 접근 허가 통합을 추가하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.access-grants.enabled=true \
--conf spark.sql.catalog.my_catalog.s3.access-grants.fallback-to-iam=true
S3 접근 허가 사용에 대한 자세한 내용은 S3 접근 허가로 접근 관리(Managing access with S3 Access Grants)를 참고해주세요.
S3 교차 리전 접근 (S3 Cross-Region Access)
S3 교차 리전 버킷 접근은 s3.cross-region-access-enabled 카탈로그 속성을 true로 설정해서 켤 수 있어요. 이는 첫 S3 API 호출 지연이 증가하는 것을 피하기 위해 기본적으로 꺼져 있어요.
예를 들어 Spark 3.5로 S3 교차 리전 버킷 접근을 활성화하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.cross-region-access-enabled=true
자세한 내용은 Amazon S3 교차 리전 접근(Cross-Region access for Amazon S3)을 참고해주세요.
S3 가속 (S3 Acceleration)
S3 가속은 Amazon S3로/로부터의 전송을 큰 객체의 장거리 전송에서 최대 50-500%까지 빠르게 하는 데 사용할 수 있어요.
S3 가속을 사용하려면 S3FileIO가 가속된 S3 호출을 할 수 있도록 s3.acceleration-enabled 카탈로그 속성을 true로 설정해야 해요.
예를 들어 Spark 3.5로 S3 가속을 사용하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.acceleration-enabled=true
S3 가속 사용에 대한 자세한 내용은 Amazon S3 전송 가속으로 빠르고 안전한 파일 전송 구성(Configuring fast, secure file transfers using Amazon S3 Transfer Acceleration)을 참고해주세요.
S3 분석 가속기 (S3 Analytics Accelerator)
Amazon S3용 Analytics Accelerator Library는 애플리케이션에서 Amazon S3 데이터로의 접근을 가속화하는 데 도움을 줘요. 이 오픈소스 솔루션은 데이터 분석 워크로드의 처리 시간과 컴퓨트 비용을 줄여요.
Iceberg에서 S3 Analytics Accelerator Library가 동작하도록 하려면 s3.analytics-accelerator.enabled 카탈로그 속성을 true로 설정할 수 있어요. 기본적으로 이 속성은 false로 설정돼요.
예를 들어 Spark에서 S3 Analytics Accelerator를 사용하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.analytics-accelerator.enabled=true
Analytics Accelerator Library는 S3 CRT 클라이언트 또는 S3AsyncClient와 함께 동작할 수 있어요. 이 라이브러리는 향상된 연결 풀 관리와 더 높은 다운로드 처리량 때문에 S3 CRT 클라이언트 사용을 권장해요.
클라이언트 구성 (Client Configuration)
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.crt.enabled | true | S3 Async 클라이언트를 CRT로 만들어야 하는지 제어 |
| s3.crt.max-concurrency | 500 | S3 CRT 클라이언트의 최대 동시성 |
라이브러리 전용 추가 구성은 다음 섹션으로 구성돼요.
논리 IO 구성 (Logical IO Configuration)
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.analytics-accelerator.logicalio.prefetch.footer.enabled | true | 풋터 프리페칭이 활성화되는지 제어 |
| s3.analytics-accelerator.logicalio.prefetch.page.index.enabled | true | 페이지 인덱스 프리페칭이 활성화되는지 제어 |
| s3.analytics-accelerator.logicalio.prefetch.file.metadata.size | 32KB | 일반 파일에 대해 프리페치할 메타데이터 크기 |
| s3.analytics-accelerator.logicalio.prefetch.large.file.metadata.size | 1MB | 큰 파일에 대해 프리페치할 메타데이터 크기 |
| s3.analytics-accelerator.logicalio.prefetch.file.page.index.size | 1MB | 일반 파일에 대해 프리페치할 페이지 인덱스 크기 |
| s3.analytics-accelerator.logicalio.prefetch.large.file.page.index.size | 8MB | 큰 파일에 대해 프리페치할 페이지 인덱스 크기 |
| s3.analytics-accelerator.logicalio.large.file.size | 1GB | 파일을 큰 것으로 간주하는 임계값 |
| s3.analytics-accelerator.logicalio.small.objects.prefetching.enabled | true | 작은 객체의 프리페칭 제어 |
| s3.analytics-accelerator.logicalio.small.object.size.threshold | 3MB | 작은 객체 프리페칭의 크기 임계값 |
| s3.analytics-accelerator.logicalio.parquet.metadata.store.size | 45 | parquet 메타데이터 저장소 크기 |
| s3.analytics-accelerator.logicalio.max.column.access.store.size | 15 | 컬럼 접근 저장소의 최대 크기 |
| s3.analytics-accelerator.logicalio.parquet.format.selector.regex | ^.*.(parquet|par)$ | parquet 파일을 식별하는 정규식 패턴 |
| s3.analytics-accelerator.logicalio.prefetching.mode | ROW_GROUP | 프리페칭 모드 (유효 값: OFF, ALL, ROW_GROUP, COLUMN_BOUND) |
물리 IO 구성 (Physical IO Configuration)
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.analytics-accelerator.physicalio.metadatastore.capacity | 50 | 메타데이터 저장소의 용량 |
| s3.analytics-accelerator.physicalio.blocksizebytes | 8MB | 데이터 전송을 위한 블록 크기 |
| s3.analytics-accelerator.physicalio.readaheadbytes | 64KB | 미리 읽을 바이트 수 |
| s3.analytics-accelerator.physicalio.maxrangesizebytes | 8MB | 범위 요청의 최대 크기 |
| s3.analytics-accelerator.physicalio.partsizebytes | 8MB | 전송을 위한 개별 파트 크기 |
| s3.analytics-accelerator.physicalio.sequentialprefetch.base | 2.0 | 순차 프리페치 크기 조정의 기본 요소 |
| s3.analytics-accelerator.physicalio.sequentialprefetch.speed | 1.0 | 순차 프리페치 성장의 속도 요소 |
텔레메트리 구성 (Telemetry Configuration)
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.analytics-accelerator.telemetry.level | STANDARD | 텔레메트리 세부 수준 (유효 값: CRITICAL, STANDARD, VERBOSE) |
| s3.analytics-accelerator.telemetry.std.out.enabled | false | stdout 텔레메트리 출력 활성화 |
| s3.analytics-accelerator.telemetry.logging.enabled | true | 로깅 텔레메트리 출력 활성화 |
| s3.analytics-accelerator.telemetry.aggregations.enabled | false | 텔레메트리 집계 활성화 |
| s3.analytics-accelerator.telemetry.aggregations.flush.interval.seconds | -1 | 집계 텔레메트리를 플러시하는 간격 |
| s3.analytics-accelerator.telemetry.logging.level | INFO | 텔레메트리의 로그 수준 |
| s3.analytics-accelerator.telemetry.logging.name | com.amazon.connector.s3.telemetry | 텔레메트리의 로거 이름 |
| s3.analytics-accelerator.telemetry.format | default | 텔레메트리 출력 형식 (유효 값: json, default) |
객체 클라이언트 구성 (Object Client Configuration)
| 속성 | 기본값 | 설명 |
|---|---|---|
| s3.analytics-accelerator.useragentprefix | null | S3 요청의 User-Agent 문자열에 추가할 커스텀 프리픽스 |
S3 이중 스택 (S3 Dual-stack)
S3 이중 스택은 클라이언트가 이중 스택 엔드포인트로 S3 버킷에 접근할 수 있게 해줘요. 클라이언트가 이중 스택 엔드포인트를 요청하면 버킷 URL이 가능하면 IPv6 주소로 해석되고, 그렇지 않으면 IPv4로 폴백해요.
S3 이중 스택을 사용하려면 S3FileIO가 이중 스택 S3 호출을 할 수 있도록 s3.dualstack-enabled 카탈로그 속성을 true로 설정해야 해요.
예를 들어 Spark 3.5로 S3 이중 스택을 사용하려면 다음과 같이 Spark SQL 셸을 시작할 수 있어요.
spark-sql --conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket2/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.my_catalog.s3.dualstack-enabled=true
S3 이중 스택 사용에 대한 자세한 내용은 AWS CLI와 AWS SDK에서 이중 스택 엔드포인트 사용(Using dual-stack endpoints from the AWS CLI and the AWS SDKs)을 참고해주세요.
AWS 클라이언트 커스터마이제이션 (AWS Client Customization)
많은 조직이 자체 자격증명 제공자, 접근 프록시, 재시도 전략 등으로 AWS 클라이언트를 구성하는 방식을 커스터마이즈했어요. 아이스버그는 client.factory 카탈로그 속성을 설정해서 org.apache.iceberg.aws.AwsClientFactory의 자체 구현을 플러그인할 수 있게 해줘요.
교차 계정 및 교차 리전 접근 (Cross-Account and Cross-Region Access)
조직이 Glue metastore와 S3 버킷을 위한 중앙 집중 AWS 계정을 갖고, 다른 팀이 그 리소스에 접근하기 위해 다른 AWS 계정과 리전을 사용하는 것이 일반적인 사용 사례예요. 이 경우 중앙 집중 리소스에 접근하기 위해 교차 계정 IAM 역할이 필요해요. 아이스버그는 이 일반적인 사용 사례를 지원하기 위해 AWS 클라이언트 팩토리 AssumeRoleAwsClientFactory를 제공해요. 이는 자체 AWS 클라이언트 팩토리를 구현하고 싶은 사용자에게 예시로도 사용돼요.
이 클라이언트 팩토리는 다음 구성 가능한 카탈로그 속성을 가져요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| client.assume-role.arn | null, 사용자 입력 필요 | 맡을(assume) 역할의 ARN, 예: arn:aws:iam::123456789:role/myRoleToAssume |
| client.assume-role.region | null, 사용자 입력 필요 | STS 클라이언트를 제외한 모든 AWS 클라이언트가 기본 리전 체인 대신 주어진 리전을 사용 |
| client.assume-role.external-id | null | 선택적 외부 ID |
| client.assume-role.timeout-sec | 1 hour | 각 assume role 세션의 타임아웃. 타임아웃이 끝나면 STS 클라이언트를 통해 새 역할 세션 자격증명 집합이 가져와짐 |
이 클라이언트 팩토리를 사용하면 지정된 역할을 맡기 위해 STS 클라이언트가 기본 자격증명과 리전으로 초기화돼요. 그런 다음 Glue, S3, DynamoDB 클라이언트가 assume-role 자격증명과 리전으로 초기화되어 리소스에 접근해요. 이 클라이언트 팩토리로 스파크 셸을 시작하는 예시는 다음과 같아요.
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.11.0,org.apache.iceberg:iceberg-aws-bundle:1.11.0 \
--conf spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.my_catalog.warehouse=s3://my-bucket/my/key/prefix \
--conf spark.sql.catalog.my_catalog.type=glue \
--conf spark.sql.catalog.my_catalog.client.factory=org.apache.iceberg.aws.AssumeRoleAwsClientFactory \
--conf spark.sql.catalog.my_catalog.client.assume-role.arn=arn:aws:iam::123456789:role/myRoleToAssume \
--conf spark.sql.catalog.my_catalog.client.assume-role.region=ap-northeast-1
HTTP 클라이언트 구성 (HTTP Client Configurations)
AWS 클라이언트는 URL Connection HTTP Client와 Apache HTTP Client 두 가지 타입의 HTTP 클라이언트를 지원해요. 기본적으로 AWS 클라이언트는 Apache HTTP Client를 사용해 서비스와 통신해요. 이 HTTP 클라이언트는 expect-continue 핸드셰이크와 TCP KeepAlive 같은 다양한 기능과 커스터마이즈된 설정을 지원하지만, 추가 의존성과 추가 시작 지연을 대가로 해요. 반대로 URL Connection HTTP Client는 최소 의존성과 시작 지연을 위해 최적화되지만 다른 구현보다 적은 기능을 지원해요.
구성에 대한 자세한 내용은 URL Connection HTTP Client 구성과 Apache HTTP Client 구성 섹션을 참고해주세요.
HTTP 클라이언트 구성은 카탈로그 속성으로 설정할 수 있어요. 아래는 사용 가능한 구성의 개요예요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| http-client.type | apache | HTTP 클라이언트 타입. urlconnection: URL Connection HTTP Client, apache: Apache HTTP Client |
| http-client.proxy-endpoint | null | HTTP 클라이언트에 사용할 선택적 프록시 엔드포인트 |
| http-client.proxy-use-system-property-values | null, 기본적으로 활성화 | 프록시 구성을 Java 시스템 속성(http.proxyHost, http.proxyPort, http.nonProxyHosts 등)에서 읽는지 제어하는 선택적 true/false 설정 |
| http-client.proxy-use-environment-variable-values | null, 기본적으로 활성화 | 프록시 구성을 환경 변수(HTTP_PROXY, HTTPS_PROXY, NO_PROXY 등)에서 읽는지 제어하는 선택적 true/false 설정 |
URL Connection HTTP Client 구성 (URL Connection HTTP Client Configurations)
URL Connection HTTP Client는 다음 구성 가능한 속성을 가져요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| http-client.urlconnection.socket-timeout-ms | null | 선택적 소켓 타임아웃(밀리초) |
| http-client.urlconnection.connection-timeout-ms | null | 선택적 연결 타임아웃(밀리초) |
사용자는 카탈로그 속성으로 기본값을 재정의할 수 있어요. 예를 들어 스파크 셸을 시작할 때 URL Connection HTTP Client의 소켓 타임아웃을 구성하려면 다음을 추가할 수 있어요:
--conf spark.sql.catalog.my_catalog.http-client.urlconnection.socket-timeout-ms=80
Apache HTTP Client 구성 (Apache HTTP Client Configurations)
Apache HTTP Client는 다음 구성 가능한 속성을 가져요.
| 속성 | 기본값 | 설명 |
|---|---|---|
| http-client.apache.socket-timeout-ms | null | 선택적 소켓 타임아웃(밀리초) |
| http-client.apache.connection-timeout-ms | null | 선택적 연결 타임아웃(밀리초) |
| http-client.apache.connection-acquisition-timeout-ms | null | 선택적 연결 획득 타임아웃(밀리초) |
| http-client.apache.connection-max-idle-time-ms | null | 선택적 연결 최대 유휴 타임아웃(밀리초) |
| http-client.apache.connection-time-to-live-ms | null | 선택적 연결 유지 시간(밀리초) |
| http-client.apache.expect-continue-enabled | null, 기본적으로 비활성화 | expect continue 활성화 여부를 제어하는 선택적 true/false 설정 |
| http-client.apache.max-connections | null | 선택적 최대 연결 수(정수) |
| http-client.apache.tcp-keep-alive-enabled | null, 기본적으로 비활성화 | tcp keep alive 활성화 여부를 제어하는 선택적 true/false 설정 |
| http-client.apache.use-idle-connection-reaper-enabled | null, 기본적으로 활성화 | 유휴 연결 리퍼(reaper) 사용 여부를 제어하는 선택적 true/false 설정 |
사용자는 카탈로그 속성으로 기본값을 재정의할 수 있어요. 예를 들어 스파크 셸을 시작할 때 Apache HTTP Client의 최대 연결 수를 구성하려면 다음을 추가할 수 있어요:
--conf spark.sql.catalog.my_catalog.http-client.apache.max-connections=5
AWS에서 아이스버그 실행 (Run Iceberg on AWS)
Amazon Athena
Amazon Athena는 아이스버그 테이블에 대해 읽기, 쓰기, 업데이트, 최적화 작업을 수행하는 데 사용할 수 있는 서버리스 쿼리 엔진을 제공해요. 자세한 내용은 여기에서 찾을 수 있어요.
Amazon EMR
Amazon EMR은 Iceberg를 실행할 수 있는 Spark(EMR 6은 Spark 3, EMR 5는 Spark 2), Hive, Flink, Trino로 클러스터를 프로비저닝할 수 있어요.
EMR 버전 6.5.0부터 EMR 클러스터는 부트스트랩 액션 없이 필요한 Apache Iceberg 의존성을 설치하도록 구성할 수 있어요. Iceberg가 설치된 클러스터를 만드는 방법에 대한 공식 문서를 참고해주세요.
6.5.0 이전 버전의 경우 다음 비슷한 부트스트랩 액션을 사용해 필요한 모든 의존성을 미리 설치할 수 있어요:
#!/bin/bash
ICEBERG_VERSION=1.11.0
MAVEN_URL=https://repo1.maven.org/maven2
ICEBERG_MAVEN_URL=$MAVEN_URL/org/apache/iceberg
# NOTE: this is just an example shared class path between Spark and Flink,
# please choose a proper class path for production.
LIB_PATH=/usr/share/aws/aws-java-sdk/
ICEBERG_PACKAGES=(
"iceberg-spark-runtime-3.5_2.12"
"iceberg-flink-runtime"
"iceberg-aws-bundle"
)
install_dependencies () {
install_path=$1
download_url=$2
version=$3
shift
pkgs=("$@")
for pkg in "${pkgs[@]}"; do
sudo wget -P $install_path $download_url/$pkg/$version/$pkg-$version.jar
done
}
install_dependencies $LIB_PATH $ICEBERG_MAVEN_URL $ICEBERG_VERSION "${ICEBERG_PACKAGES[@]}"
AWS Glue
AWS Glue는 아이스버그 테이블에 대해 읽기, 쓰기, 업데이트 작업을 수행하는 데 사용할 수 있는 서버리스 데이터 통합 서비스를 제공해요. 자세한 내용은 여기에서 찾을 수 있어요.
AWS EKS
AWS Elastic Kubernetes Service(EKS)는 Iceberg를 작업하기 위해 어떤 Spark, Flink, Hive, Presto 또는 Trino 클러스터든 시작하는 데 사용할 수 있어요.
Amazon Kinesis
Amazon Kinesis Data Analytics는 완전 관리형 Apache Flink 애플리케이션을 실행하는 플랫폼을 제공해요. 애플리케이션 Jar에 Iceberg를 포함하고 플랫폼에서 실행할 수 있어요.
AWS Redshift
AWS Redshift Spectrum 또는 Redshift Serverless는 AWS Glue Data Catalog에 카탈로그된 Apache Iceberg 테이블 쿼리를 지원해요.
Amazon Data Firehose
Firehose를 사용해 스트리밍 데이터를 Amazon S3의 Apache Iceberg 테이블로 직접 전달할 수 있어요. 이 기능으로 단일 스트림의 레코드를 서로 다른 Apache Iceberg 테이블로 라우팅하고, Apache Iceberg 테이블의 레코드에 삽입, 업데이트, 삭제 연산을 자동으로 적용할 수 있어요. 이 기능은 AWS Glue Data Catalog 사용을 필요로 해요.