REST 카탈로그 통합
REST 카탈로그 통합 (REST Catalog Integration)
Hive가 Iceberg REST 카탈로그를 사용하도록 설정하는 방법을 소개하는 문서예요. OAuth2 인증을 거친 Iceberg REST 서버로는 Gravitino(+Keycloak)와 Polaris 두 가지 구성을 다룹니다.
출처: 문서
본문
이 문서는 다음 두 구성을 다룹니다.
- Hive + Gravitino + Keycloak
- Hive + Polaris
Hive + Gravitino + Keycloak
이 설정의 코드는 Hive 저장소의 packaging/src/docker/thirdparties/gravitino 폴더에 있어요. Apache Hive, Gravitino Iceberg REST 서버, OAuth2 인증용 Keycloak을 통합한 docker-compose 기반 설정을 담고 있으며, Hive가 Keycloak으로 보호된 Iceberg REST 카탈로그를 사용할 수 있게 합니다.
아키텍처 개요 (Architecture Overview)
oAuth2 (REST API)
+-------------------------------------------------------------------+
| |
| v
+--------+----------+ +-------------------+ +-----------------+
| | RESTCatalog | | oauth2 | |
| Hive | (REST API) | Gravitino | (REST API) | Keycloak |
| (HiveServer2) +-------------->| Iceberg REST +----------->| OAuth2 Auth |
| | | Server | | Server |
+--------+----------+ +---------+---------+ +-----------------+
| |
data | metadata files |
files +------------------------------------+
|
v
+-------------------+ +-------------------+
| | creates dir | |
| /warehouse |<--------------+ init |
| (Docker volume) | sets | container |
| | permissions | |
+-------------------+ +-------------------+
- Hive: HiveServer2를 실행하고 Iceberg REST 카탈로그를 통해 Gravitino에 연결해요. Iceberg 데이터 파일을 공유 웨어하우스 볼륨에 씁니다.
- Gravitino: Iceberg 카탈로그용 REST API를 노출해요. Iceberg 메타데이터 파일을 공유 웨어하우스 볼륨(.metadata.json)에 씁니다. OAuth2 제공자 역할을 하지 않으므로, 이 예시는 외부 OAuth2 제공자(Keycloak)를 사용합니다.
- Keycloak: Hive/Gravitino용 인증과 토큰 발급을 제공하는 OAuth2 서버.
- /warehouse: Iceberg 테이블 데이터와 메타데이터용 공유 Docker 볼륨.
- Init container: 공유 /warehouse 폴더를 만들고 파일시스템 권한을 일회성 초기화 단계로 설정.
전제 조건 (Prerequisites)
- Hive 버전 4.2.0+
- Docker & Docker Compose
- Java (로컬 Hive beeline 클라이언트용)
- Beeline 연결용
$HIVE_HOME환경 변수 (Hive 설치를 가리키는)
빠른 시작 (Quickstart)
STEP 1: Hive 버전 export
export HIVE_VERSION=4.2.0
STEP 2: 서비스 시작
docker-compose up -d
STEP 3: beeline에 연결
"${HIVE_HOME}/bin/beeline" -u "jdbc:hive2://localhost:10001/default" -n hive -p hive
STEP 4: 서비스 중지:
docker-compose down -v
구성 (Configuration)
Keycloak
- Realm:
hive - Client:
iceberg-client - Secret:
iceberg-client-secret - Protocol: OpenID Connect
- Audience:
hive-iceberg - Keycloak 컨테이너의
realm-export.json으로 import됨. - Port: 8080
Gravitino
- HTTP port: 9001
- Catalog backend: JDBC H2 (
/tmp/gravitino_h2_db) - Warehouse:
/warehouse(Hive와 공유) - Iceberg REST Catalog 백엔드 구성:
# Backend type for the catalog. Here we use JDBC (H2 database) as the metadata store.
gravitino.iceberg-rest.catalog-backend = jdbc
# JDBC connection URI for the H2 database storing catalog metadata.
gravitino.iceberg-rest.uri = jdbc:h2:file:/tmp/gravitino_h2_db;AUTO_SERVER=TRUE
# JDBC driver class used to connect to the metadata database.
gravitino.iceberg-rest.jdbc-driver = org.h2.Driver
# Database username for connecting to the metadata store.
gravitino.iceberg-rest.jdbc-user = sa
# Database password for connecting to the metadata store (empty here).
gravitino.iceberg-rest.jdbc-password = ""
# Whether to initialize the catalog schema on startup.
gravitino.iceberg-rest.jdbc-initialize = true
# --- Warehouse Location (shared folder) ---
# Path to the Iceberg warehouse directory shared with Hive.
gravitino.iceberg-rest.warehouse = file:///warehouse
Keycloak을 가리키는 OAuth2 구성:
# Enables OAuth2 as the authentication mechanism for Gravitino.
gravitino.authenticators = oauth
# URL of the Keycloak realm to request tokens from.
gravitino.authenticator.oauth.serverUri = http://keycloak:8080/realms/hive
# Path to the OAuth2 token endpoint on Keycloak.
gravitino.authenticator.oauth.tokenPath = /protocol/openid-connect/token
# OAuth2 scopes requested when obtaining a token. Includes "openid" and the custom "catalog" scope.
gravitino.authenticator.oauth.scope = openid catalog
# OAuth2 client ID registered in Keycloak.
gravitino.authenticator.oauth.clientId = iceberg-client
# OAuth2 client secret associated with the client ID.
gravitino.authenticator.oauth.clientSecret = iceberg-client-secret
# Java class used to validate incoming JWT tokens using the JWKS endpoint.
gravitino.authenticator.oauth.tokenValidatorClass = org.apache.gravitino.server.authentication.JwksTokenValidator
# URL to fetch JSON Web Key Set (JWKS) for verifying token signatures.
gravitino.authenticator.oauth.jwksUri = http://keycloak:8080/realms/hive/protocol/openid-connect/certs
# Identifier for the OAuth2 provider configuration in Gravitino.
gravitino.authenticator.oauth.provider = default
# JWT claim field(s) to extract as the principal/username (here, 'sub' claim).
gravitino.authenticator.oauth.principalFields = sub
# Acceptable clock skew (in seconds) when validating token expiration times.
gravitino.authenticator.oauth.allowSkewSecs = 60
# Expected audience claim in the token to ensure it is intended for this service.
gravitino.authenticator.oauth.serviceAudience = hive-iceberg
Hive
Iceberg REST 카탈로그(Gravitino) 연결에 HiveRESTCatalogClient를 사용해요. hive-site.xml의 카탈로그 구성:
<property>
<name>metastore.catalog.default</name>
<value>ice01</value>
<description>Sets the default Iceberg catalog for Hive. Here, "ice01" is used.</description>
</property>
<property>
<name>metastore.client.impl</name>
<value>org.apache.iceberg.hive.client.HiveRESTCatalogClient</value>
<description>Specifies the client implementation to use for accessing Iceberg via REST.</description>
</property>
<property>
<name>iceberg.catalog.ice01.uri</name>
<value>http://gravitino:9001/iceberg</value>
<description>URI of the Iceberg REST server (Gravitino). Hive will send catalog requests here.</description>
</property>
<property>
<name>iceberg.catalog.ice01.type</name>
<value>rest</value>
<description>Defines the catalog type as "rest", indicating it uses a REST API backend.</description>
</property>
<!-- Iceberg REST Catalog: OAuth2 authentication -->
<property>
<name>iceberg.catalog.ice01.rest.auth.type</name>
<value>oauth2</value>
<description>Configures Hive to use OAuth2 for authenticating requests to the REST catalog.</description>
</property>
<property>
<name>iceberg.catalog.ice01.oauth2-server-uri</name>
<value>http://keycloak:8080/realms/hive/protocol/openid-connect/token</value>
<description>URL of the Keycloak OAuth2 token endpoint used to request access tokens.</description>
</property>
<property>
<name>iceberg.catalog.ice01.credential</name>
<value>iceberg-client:iceberg-client-secret</value>
<description>Client credentials (ID and secret) used to authenticate with Keycloak.</description>
</property>
- HiveServer2 port: 10000 (Docker Compose에서 10001로 매핑)
네트워킹 메모 (Networking Notes)
- 모든 컨테이너는 커스텀 브리지 네트워크
hive-net을 공유해요. - 서비스는 컨테이너 이름(
hive,gravitino,keycloak)으로 통신합니다. - 호스트 접근용 매핑 포트: Keycloak → 8080, Gravitino → 9001, HiveServer2 → 10001
Hive + Polaris
이 설정의 코드는 Hive 저장소의 packaging/src/docker/thirdparties/polaris 폴더에 있어요. Apache Hive와 Polaris를 통합하는 docker-compose 기반 설정이며, Hive가 Polaris가 제공하는 oAuth2로 보호된 Iceberg REST 카탈로그를 사용할 수 있게 합니다.
아키텍처 개요 (Architecture Overview)
+-------------------+ +-------------------+
| | RESTCatalog | |
| Hive | (REST API) | Polaris |<-------+
| (HiveServer2) +-------------->| Server | |
| | oAuth2 | | |
+--------+----------+ (REST API) +---------+---------+ | creates:
| | | catalog,
data | metadata files | | principal,
files +------------------------------------+ | roles,
| | grants (REST API)
v |
+-------------------+ +-------------------+ |
| | creates dir | | |
| /warehouse |<--------------+ Polaris-init +--------+
| (Docker volume) | syncs | container |
| | permissions | |
+-------------------+ +-------------------+
- Hive: HiveServer2를 실행하고 Iceberg REST 카탈로그를 통해 Polaris에 연결해요. Iceberg 데이터 파일을 공유 웨어하우스 볼륨에 씁니다.
- Polaris: Iceberg 카탈로그용 REST API를 노출하고 인증용 oauth2를 제공해요. OAuth2 제공자 역할도 하므로 이 예시는 외부 OAuth2 컴포넌트가 필요 없습니다. Iceberg 메타데이터 파일을 공유 웨어하우스 볼륨(.metadata.json)에 씁니다.
- /warehouse: Iceberg 테이블 데이터와 메타데이터용 공유 Docker 볼륨.
- Polaris-init: Hive-Iceberg용 Polaris를 부트스트랩해요. REST API로 Polaris 리소스를 만들고 구성하며, 공유
/warehouse/*폴더의 파일시스템 권한을 지속적으로 동기화합니다. Polaris와 Hive가 각각의 컨테이너에서 다른 사용자로 실행되기 때문에 필요해요.
전제 조건 (Prerequisites)
- Hive 버전 4.2.0+
- Docker & Docker Compose
- Java (로컬 Hive beeline 클라이언트용)
$HIVE_HOME환경 변수
빠른 시작 (Quickstart)
STEP 1: Hive 버전 export
export HIVE_VERSION=4.2.0
STEP 2: 서비스 시작
docker-compose up -d
STEP 3: beeline에 연결
"${HIVE_HOME}/bin/beeline" -u "jdbc:hive2://localhost:10001/default" -n hive -p hive
STEP 4: 서비스 중지:
docker-compose down -v
구성 (Configuration)
Polaris
- HTTP port: 8181
- Warehouse:
/warehouse(Hive와 공유) - 핵심 Polaris 구성(docker-compose.yml의 env 변수로 정의):
# A realm provides logical isolation for different Polaris environments.
polaris.realm-context.realms: POLARIS
# Initial bootstrap credentials for the Polaris server.
# The format is: <realm-name>,<client-id>,<client-secret>
POLARIS_BOOTSTRAP_CREDENTIALS: POLARIS,iceberg-client,iceberg-client-secret
Hive
Iceberg REST 카탈로그(Polaris) 연결에 HiveRESTCatalogClient를 사용해요. hive-site.xml의 카탈로그 구성:
<property>
<name>metastore.catalog.default</name>
<value>ice01</value>
<description>Sets the default Iceberg catalog for Hive. Here, "ice01" is used.</description>
</property>
<property>
<name>metastore.client.impl</name>
<value>org.apache.iceberg.hive.client.HiveRESTCatalogClient</value>
<description>Specifies the client implementation to use for accessing Iceberg via REST.</description>
</property>
<property>
<name>iceberg.catalog.ice01.uri</name>
<value>http://polaris:8181/api/catalog</value>
<description>URI of the Iceberg REST server (Polaris). Hive will send catalog requests here.</description>
</property>
<property>
<name>iceberg.catalog.ice01.type</name>
<value>rest</value>
<description>Defines the catalog type as "rest", indicating it uses a REST API backend.</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>file:///warehouse</value>
<description>Defines the warehouse location, required for Polaris</description>
</property>
<!-- Iceberg REST Catalog: OAuth2 authentication -->
<property>
<name>iceberg.catalog.ice01.rest.auth.type</name>
<value>oauth2</value>
<description>Configures Hive to use OAuth2 for authenticating requests to the REST catalog.</description>
</property>
<property>
<name>iceberg.catalog.ice01.oauth2-server-uri</name>
<value>http://polaris:8181/api/catalog/v1/oauth/tokens</value>
<description>URL of the Polaris OAuth2 token endpoint used to request access tokens.</description>
</property>
<property>
<name>iceberg.catalog.ice01.credential</name>
<value>iceberg-client:iceberg-client-secret</value>
<description>Client credentials (ID and secret) used to authenticate with Keycloak.</description>
</property>
<property>
<name>iceberg.catalog.ice01.scope</name>
<value>PRINCIPAL_ROLE:ALL</value>
<description>oAuth2 scope tied to the principal role defined in Polaris</description>
</property>
- HiveServer2 port: 10000 (Docker Compose에서 10001로 매핑)
네트워킹 메모 (Networking Notes)
- 모든 컨테이너는 커스텀 브리지 네트워크
hive-net을 공유해요. - 서비스는 컨테이너 이름(
hive,polaris)으로 통신합니다. - 호스트 접근용 매핑 포트: Polaris → 8181, HiveServer2 → 10001
더 알아보기 (Learn more)
REST 카탈로그는 Hive가 Iceberg 같은 오픈 테이블 포맷의 메타데이터를 원격 서버로부터 가져오는 방식이에요. 구성요소를 컨테이너 이름으로 연결하는 docker-compose 구조를 이해하면, 운영 환경에서도 같은 원리로 OAuth2 보호 REST 카탈로그를 붙일 수 있습니다.