0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【第3編】Apache OzoneのローカルS3からAWS S3へrawログとIcebergを移行してみる

0
Last updated at Posted at 2026-09-19

はじめに

前回は、HDFS上のrawログとApache Icebergを、Apache OzoneのS3 Gatewayを使ったローカルS3へ移行した。

今回はその続きとして、Ozone上のrawログとIcebergをAWSへ移行する。ただし、これまでの記事で作成済みのS3 Raw backupとS3 Icebergがあるため、本seriesの標準手順では再コピーせず、その既存データを引き継ぐ。

既存バックアップを引き継ぐ(標準手順)

source /etc/rawlog-s3-backup/common.env
export AWS_RAW_BUCKET="${S3_BUCKET_NAME}"
export AWS_RAW_PROFILE=home-rawlog-backup

source /etc/iceberg/aws.env
export AWS_ICEBERG_BUCKET="${ICEBERG_BUCKET}"
export AWS_ICEBERG_PROFILE=home-aws

aws sts get-caller-identity --profile "${AWS_RAW_PROFILE}"
aws s3api head-bucket --bucket "${AWS_RAW_BUCKET}" --profile "${AWS_RAW_PROFILE}"
aws s3 ls "s3://${AWS_RAW_BUCKET}/raw/" --profile "${AWS_RAW_PROFILE}"

aws sts get-caller-identity --profile "${AWS_ICEBERG_PROFILE}"
aws s3api head-bucket --bucket "${AWS_ICEBERG_BUCKET}" --profile "${AWS_ICEBERG_PROFILE}"
aws glue get-tables --database-name "${GLUE_DATABASE}" \
  --region "${AWS_REGION}" --profile "${AWS_ICEBERG_PROFILE}"

この経路では、後述のbucket作成、rcloneによるRaw再コピー、AWS側Iceberg tableの再作成、過去データのINSERT INTO ... SELECTを省略する。既存Rawのobject数・sizeと、既存Icebergの件数・時刻範囲をOzone側と比較し、差がないことだけを確認する。

以降のコピー手順は、既存AWS backupを利用できず、Ozoneから別の検証用AWS環境へ移す場合だけ実施する代替手順である。

  • raw JSON TextはOzoneからAmazon S3へobject単位でコピーする
  • IcebergはAWS Glue Data CatalogとAmazon S3上に新規テーブルを作り、Spark SQLで論理コピーする
  • Ozoneをすぐに削除せず、AWS側との比較とrollbackができる状態で切り替える

前提

以下は構築済みとする。

項目 値
Ozone S3 Gateway http://ozone1:9878
Ozone raw bucket log-raw
Ozone Iceberg bucket lakehouse
Ozone Spark catalog ozone_s3
Ozone namespace logs_s3
Spark 3.5.8
Apache Iceberg 1.10.1
移行対象 syslog_iceberg、authlog_iceberg
AWS region ap-northeast-1
操作ホスト ope1

Ozone側の既存テーブルは次の通りである。

ozone_s3.logs_s3.syslog_iceberg
ozone_s3.logs_s3.authlog_iceberg

AWS側には次の構成を作る。

Amazon S3 raw bucket
Amazon S3 Iceberg warehouse
AWS Glue Data Catalog
Amazon Athena

移行方針

Apache Ozoneへの移行が完了したログ基盤を、AWS S3とAWS Glue Data Catalogへ移行する。rawとIcebergでは内部構造が異なるため、移行方法を分ける。

rawはobject単位でコピーできる。一方、Ozone上のIceberg warehouseをAWS S3へそのままコピーすると、metadata内にs3a://lakehouse/...が残る可能性がある。このため、AWS側に新しいIcebergテーブルを作成し、Sparkで論理コピーする。

代替手順: 別の検証用AWS環境へ移行する

ここから「AWSへ切り替える」までの節は、既存バックアップを使う標準経路では実施しない。

AWS側の変数を設定する

bucket名はAWS全体で一意になる値へ変更する。

export AWS_REGION='ap-northeast-1'
export AWS_PROFILE='home-aws-admin'
export AWS_RAW_BUCKET='<YOUR_UNIQUE_RAW_BUCKET>'
export AWS_ICEBERG_BUCKET='<YOUR_UNIQUE_ICEBERG_BUCKET>'
export GLUE_DATABASE='logs'

AWS CLIの認証を確認する。

aws sts get-caller-identity \
  --profile "${AWS_PROFILE}" \
  --region "${AWS_REGION}"

Spark実行ユーザーには、少なくとも対象S3 prefixへの読み書き、Glue Database/Tableの作成・取得・更新権限が必要である。長期access keyをshellへ直接記載せず、可能であればIAM Roleまたは短期credentialを使用する。

AWS S3 bucketを作成する

東京regionに2つのbucketを作成する。

aws s3api create-bucket \
  --bucket "${AWS_RAW_BUCKET}" \
  --region "${AWS_REGION}" \
  --create-bucket-configuration LocationConstraint="${AWS_REGION}" \
  --object-ownership BucketOwnerEnforced \
  --profile "${AWS_PROFILE}"

aws s3api create-bucket \
  --bucket "${AWS_ICEBERG_BUCKET}" \
  --region "${AWS_REGION}" \
  --create-bucket-configuration LocationConstraint="${AWS_REGION}" \
  --object-ownership BucketOwnerEnforced \
  --profile "${AWS_PROFILE}"

public accessをblockし、default encryptionとversioningを有効にする。

for bucket in "${AWS_RAW_BUCKET}" "${AWS_ICEBERG_BUCKET}"; do
  aws s3api put-public-access-block \
    --bucket "${bucket}" \
    --public-access-block-configuration \
      BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true \
    --profile "${AWS_PROFILE}"

  aws s3api put-bucket-encryption \
    --bucket "${bucket}" \
    --server-side-encryption-configuration \
      '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}' \
    --profile "${AWS_PROFILE}"

  aws s3api put-bucket-versioning \
    --bucket "${bucket}" \
    --versioning-configuration Status=Enabled \
    --profile "${AWS_PROFILE}"
done

KMS customer managed keyを使う場合は、bucket encryptionだけでなくSpark実行RoleへKMS権限も付与する。

rcloneへ2つのS3 remoteを登録する

AWS CLIの--endpoint-urlはcommand全体に1つだけ指定するため、OzoneとAWSという異なるendpoint間の直接コピーにはrcloneを使用する。

sudo apt update
sudo apt install -y rclone
rclone version
rclone config

対話画面で次の2つを作成する。

remote名 type / provider endpoint region path style
ozone S3 / Other http://ozone1:9878 us-east-1 有効
aws S3 / AWS 空欄 ap-northeast-1 無効

ozoneにはOzone S3 credentialを設定する。awsはIAM Roleまたは既存のAWS profileを使う。rclone configにはsecretが含まれるため、権限を確認する。

rclone config file
chmod 600 "$(rclone config file | tail -n 1)"
rclone lsd ozone:
rclone lsd aws:

systemdやsparkユーザーから実行する場合は、それぞれが読める専用configを作る。個人ユーザーのconfigを全ユーザーから読める権限に変更しない。

rawを1日分コピーする

最初にsyslogとauthlogを1日分コピーする。syncではなくcopyを使い、AWS側の余分なobjectを自動削除しない。

rclone copy \
  ozone:log-raw/syslog/2026/09/15 \
  "aws:${AWS_RAW_BUCKET}/syslog/2026/09/15" \
  --transfers 8 \
  --checkers 16 \
  --progress

rclone copy \
  ozone:log-raw/authlog/2026/09/15 \
  "aws:${AWS_RAW_BUCKET}/authlog/2026/09/15" \
  --transfers 8 \
  --checkers 16 \
  --progress

Ozoneから一度操作ホストへdownloadし、そこからAWSへuploadされるため、操作ホストのnetwork帯域とAWS data transferを事前に確認する。

rawの移行結果を確認する

異なるS3実装間ではmultipart uploadのETagが一致しないことがあるため、ETagだけを同一性判定に使わない。まずobject数と合計sizeを確認する。

rclone size ozone:log-raw/syslog/2026/09/15
rclone size "aws:${AWS_RAW_BUCKET}/syslog/2026/09/15"

rclone size ozone:log-raw/authlog/2026/09/15
rclone size "aws:${AWS_RAW_BUCKET}/authlog/2026/09/15"

さらに、sourceに存在するobjectがtargetに同じsizeで存在することを確認する。

rclone check \
  ozone:log-raw/syslog/2026/09/15 \
  "aws:${AWS_RAW_BUCKET}/syslog/2026/09/15" \
  --one-way \
  --size-only

rclone check \
  ozone:log-raw/authlog/2026/09/15 \
  "aws:${AWS_RAW_BUCKET}/authlog/2026/09/15" \
  --one-way \
  --size-only

最終確認では、両方からsample objectを取得してSHA-256を比較するか、Sparkでraw record数とJSON parse後の集計値を比較する。

全期間はprefix単位でコピーする。

rclone copy \
  ozone:log-raw/syslog \
  "aws:${AWS_RAW_BUCKET}/syslog" \
  --transfers 8 \
  --checkers 16 \
  --log-file "${HOME}/rclone-ozone-to-aws-syslog.log" \
  --log-level INFO

rclone copy \
  ozone:log-raw/authlog \
  "aws:${AWS_RAW_BUCKET}/authlog" \
  --transfers 8 \
  --checkers 16 \
  --log-file "${HOME}/rclone-ozone-to-aws-authlog.log" \
  --log-level INFO

初回コピー後、cutover直前に同じcopyを再実行して増分を追従する。

AWS Glue CatalogをSparkへ追加する

Iceberg 1.10.1に合わせたiceberg-aws-bundleをSparkのclasspathへ追加する。

sudo install -d -m 755 /opt/spark/extra-jars
sudo curl -fLo /opt/spark/extra-jars/iceberg-aws-bundle-1.10.1.jar \
  https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-aws-bundle/1.10.1/iceberg-aws-bundle-1.10.1.jar

jar tf /opt/spark/extra-jars/iceberg-aws-bundle-1.10.1.jar \
  | grep 'org/apache/iceberg/aws/glue/GlueCatalog.class'

Spark起動optionへglue_prodを追加する。既存のhive_prodとozone_s3は残す。

--jars /opt/spark/extra-jars/iceberg-aws-bundle-1.10.1.jar
--conf spark.sql.catalog.glue_prod=org.apache.iceberg.spark.SparkCatalog
--conf spark.sql.catalog.glue_prod.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog
--conf spark.sql.catalog.glue_prod.io-impl=org.apache.iceberg.aws.s3.S3FileIO
--conf spark.sql.catalog.glue_prod.warehouse=s3://<YOUR_UNIQUE_ICEBERG_BUCKET>/warehouse
--conf spark.sql.catalog.glue_prod.client.region=ap-northeast-1

実際の起動scriptでは<YOUR_UNIQUE_ICEBERG_BUCKET>を${AWS_ICEBERG_BUCKET}の値へ置き換える。AWS SDKが参照するcredentialをdriverとexecutorの両方へ渡す。local mode以外では、executor nodeからOzone S3 GatewayとAWS S3の両方へ接続できることも確認する。

AWS側Icebergテーブルを作成する

Glue namespaceと2つのテーブルを作成する。schema、partition spec、table propertyはOzone側のSHOW CREATE TABLEを確認して合わせる。

sudo -u spark /usr/local/bin/spark-sql-iceberg-aws <<EOF
CREATE NAMESPACE IF NOT EXISTS glue_prod.${GLUE_DATABASE};

CREATE TABLE IF NOT EXISTS glue_prod.${GLUE_DATABASE}.syslog_iceberg (
  host string,
  ts timestamp_ntz,
  severity int,
  program string,
  msg string,
  dt date,
  hr int
)
USING iceberg
PARTITIONED BY (days(ts), host)
LOCATION 's3://${AWS_ICEBERG_BUCKET}/warehouse/${GLUE_DATABASE}/syslog_iceberg'
TBLPROPERTIES (
  'format-version'='2',
  'write.parquet.compression-codec'='zstd'
);

CREATE TABLE IF NOT EXISTS glue_prod.${GLUE_DATABASE}.authlog_iceberg (
  host string,
  ts timestamp_ntz,
  severity int,
  program string,
  msg string,
  dt date,
  hr int
)
USING iceberg
PARTITIONED BY (days(ts), host)
LOCATION 's3://${AWS_ICEBERG_BUCKET}/warehouse/${GLUE_DATABASE}/authlog_iceberg'
TBLPROPERTIES (
  'format-version'='2',
  'write.parquet.compression-codec'='zstd'
);
EOF

Icebergを1日分移行する

Spark SQLからOzone側とAWS側の両方を参照し、1日分を論理コピーする。

sudo -u spark /usr/local/bin/spark-sql-iceberg-aws <<EOF
SET spark.sql.session.timeZone=Asia/Tokyo;

DELETE FROM glue_prod.${GLUE_DATABASE}.syslog_iceberg
WHERE dt = DATE '2026-09-15';

INSERT INTO glue_prod.${GLUE_DATABASE}.syslog_iceberg
SELECT host, ts, severity, program, msg, dt, hr
FROM ozone_s3.logs_s3.syslog_iceberg
WHERE dt = DATE '2026-09-15';

DELETE FROM glue_prod.${GLUE_DATABASE}.authlog_iceberg
WHERE dt = DATE '2026-09-15';

INSERT INTO glue_prod.${GLUE_DATABASE}.authlog_iceberg
SELECT host, ts, severity, program, msg, dt, hr
FROM ozone_s3.logs_s3.authlog_iceberg
WHERE dt = DATE '2026-09-15';
EOF

全期間はdt単位で古い日から実行する。一度に全件を投入せず、失敗した日だけ再実行できるようにする。

OzoneとAWSのIcebergを比較する

sudo -u spark /usr/local/bin/spark-sql-iceberg-aws <<EOF
SELECT 'ozone' AS src, COUNT(*) AS cnt, MIN(ts) AS min_ts, MAX(ts) AS max_ts
FROM ozone_s3.logs_s3.syslog_iceberg
WHERE dt = DATE '2026-09-15'
UNION ALL
SELECT 'aws' AS src, COUNT(*) AS cnt, MIN(ts) AS min_ts, MAX(ts) AS max_ts
FROM glue_prod.${GLUE_DATABASE}.syslog_iceberg
WHERE dt = DATE '2026-09-15';
EOF

authlogも同じ方法で確認する。さらにhost、program、severity、dt、hr単位でEXCEPTを双方向に実行し、差分が0行になることを確認する。

AWS S3上にdata fileとmetadataが生成されたことも確認する。

aws s3 ls \
  "s3://${AWS_ICEBERG_BUCKET}/warehouse/${GLUE_DATABASE}/syslog_iceberg/" \
  --recursive \
  --profile "${AWS_PROFILE}"

AWSへ切り替える

移行期間中はOzoneを正本としてAWSへ追従させる。

hdfsex-ozone-to-aws.png

導入は次の順で行う。

  1. Ozoneへの新規書き込みを停止する
  2. rawのrclone copyを再実行する
  3. 最終日までのIceberg論理コピーを実行する
  4. rawのobject数・sizeとIcebergの集計差分を確認する
  5. Trino、Athena、日次batchの参照先をAWS側へ変更する
  6. AWS側だけに新規データが入ることを確認する
  7. rollback期間中はOzoneをread-onlyで保持する

AWS移行後に問題が起きた場合は参照先をOzoneへ戻す。AWS側だけに追加された期間がある場合は、その期間をOzone側へ論理コピーしてから書き込み先を戻す。

TrinoをAWS S3 Icebergへ接続する

Trinoの設定変更は必要か

必要である。

Ozone側ではHive MetastoreとOzone S3 Gatewayを使用したが、AWS側では次へ変更する。

項目 Ozone側 AWS側
Iceberg catalog Hive Metastore AWS Glue Data Catalog
data storage Ozone S3 Gateway Amazon S3
endpoint http://ozone1:9878 AWS S3 endpoint
認証 Ozone access key AWS IAM credential
path style 有効 通常は無効

既存のiceberg_ozoneを上書きせず、AWS確認用にiceberg_aws catalogを追加する。

iceberg_ozone = Ozone Iceberg、rollback用
iceberg_aws   = AWS Glue + S3 Iceberg、移行先

以下はTrino 476の3 node clusterを前提とする。設定はCoordinatorと全Workerへ同じ内容を配置する。

AWS credentialをsystemdへ渡す

bare metalの検証環境でaccess keyを使用する例である。productionではIAM Roles Anywhere、EC2 instance profileなどの短期credentialを優先する。

sudo tee /etc/trino/aws.env >/dev/null <<'EOF'
AWS_REGION=ap-northeast-1
AWS_DEFAULT_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=<TRINO_AWS_ACCESS_KEY_ID>
AWS_SECRET_ACCESS_KEY=<TRINO_AWS_SECRET_ACCESS_KEY>
EOF

sudo chown root:trino /etc/trino/aws.env
sudo chmod 640 /etc/trino/aws.env

temporary credentialを使用する場合はAWS_SESSION_TOKENも追加する。各nodeのTrino systemd unitへ設定する。

sudo systemctl edit trino
[Service]
EnvironmentFile=/etc/trino/aws.env

catalog fileやGitへaccess keyとsecret keyを直接記載しない。

AWS用Iceberg catalogを追加する

各Trino nodeに/opt/trino/etc/catalog/iceberg_aws.propertiesを作成する。

sudo tee /opt/trino/etc/catalog/iceberg_aws.properties >/dev/null <<'EOF'
connector.name=iceberg
iceberg.catalog.type=glue
hive.metastore.glue.region=ap-northeast-1

fs.native-s3.enabled=true
s3.region=ap-northeast-1

iceberg.file-format=PARQUET
iceberg.compression-codec=ZSTD
EOF

sudo chown trino:trino /opt/trino/etc/catalog/iceberg_aws.properties
sudo chmod 640 /opt/trino/etc/catalog/iceberg_aws.properties

同一AWS accountのGlueを使う場合、iceberg.catalog.type=glueとregionを指定する。cross-accountの場合はGlue catalog ID、IAM role、trust policyも別途設定する。

Trino 476ではfs.native-s3.enabled=trueを使用する。新しいTrinoではfs.s3.enabled=trueへproperty名が変更されているため、upgrade時はcatalog fileも更新する。

IAM権限を確認する

Trino用IAM principalには、読み取りだけなら少なくとも次が必要である。

  • glue:GetDatabase、glue:GetDatabases
  • glue:GetTable、glue:GetTables、glue:GetTableVersion、glue:GetTableVersions
  • 対象bucketのs3:ListBucket
  • Iceberg warehouse prefixのs3:GetObject

TrinoからINSERT、DELETE、OPTIMIZEなども実行する場合は、GlueのCreate/Update/Delete系とS3 Put/Deleteも追加する。まずread-onlyで接続確認し、必要な操作だけ権限を追加する。

全Trino nodeへ配布して再起動する

iceberg_aws.properties、/etc/trino/aws.env、systemd drop-inをtrino1、trino2、trino3へ配置する。

sudo systemctl daemon-reload
sudo systemctl restart trino
sudo systemctl status trino --no-pager
sudo journalctl -u trino -n 200 --no-pager

Coordinatorだけに設定すると、query planningは成功してもWorkerのS3 readで失敗する。全WorkerからGlue APIとS3のHTTPS endpointへ接続できることを確認する。

TrinoからAWS側を確認する

SHOW CATALOGS;
SHOW SCHEMAS FROM iceberg_aws;
SHOW TABLES FROM iceberg_aws.logs;

SELECT
  dt,
  COUNT(*) AS cnt,
  MIN(ts) AS min_ts,
  MAX(ts) AS max_ts
FROM iceberg_aws.logs.syslog_iceberg
GROUP BY dt
ORDER BY dt DESC
LIMIT 7;

authlogも確認する。

SELECT dt, COUNT(*) AS cnt
FROM iceberg_aws.logs.authlog_iceberg
GROUP BY dt
ORDER BY dt DESC
LIMIT 7;

Flinkから直接書き込むrealtime tableを作成した場合は、同じcatalogから確認できる。

SELECT dt, hr, COUNT(*) AS cnt
FROM iceberg_aws.logs.syslog_events
GROUP BY dt, hr
ORDER BY dt DESC, hr DESC
LIMIT 24;

snapshotも確認する。

SELECT committed_at, snapshot_id, operation
FROM iceberg_aws.logs."syslog_iceberg$snapshots"
ORDER BY committed_at DESC
LIMIT 10;

Ozone側とAWS側を比較する

SELECT 'ozone' AS src, COUNT(*) AS cnt
FROM iceberg_ozone.logs_s3.syslog_iceberg
WHERE dt = DATE '2026-09-15'
UNION ALL
SELECT 'aws' AS src, COUNT(*) AS cnt
FROM iceberg_aws.logs.syslog_iceberg
WHERE dt = DATE '2026-09-15';

件数だけでなくMIN(ts)、MAX(ts)、host/program/severity/hr別の分布も比較する。

GrafanaをAWS側へ切り替える

接続先のTrino Coordinatorは変更せず、SQL内のcatalogとschemaを変更する。

- FROM iceberg_ozone.logs_s3.syslog_iceberg
+ FROM iceberg_aws.logs.syslog_iceberg

- FROM iceberg_ozone.logs_s3.authlog_iceberg
+ FROM iceberg_aws.logs.authlog_iceberg

dashboardを複製し、Ozone版とAWS版を同じ期間で比較してから本番dashboardを切り替える。AWS S3を自宅Trinoから読む場合は、internet回線のlatency、data transfer、Athenaとの役割分担も確認する。

ZeppelinからAWS S3 Icebergを参照する

ZeppelinもS3移行後のIcebergを参照できる。ZeppelinからS3へ直接接続するのではなく、既存と同様にTrino JDBCを経由する。

この構成では、AWS credential、Glue接続設定、S3 filesystem設定を持つのはTrinoである。通常のJDBC通信では、Zeppelin側にAWS access keyやhadoop-awsを追加する必要はない。ZeppelinからはTrino Coordinatorへのnetwork到達性とTrino JDBC Driverが必要になる。

Trinoのspooling protocolを有効にしている場合、JDBC clientがspooled resultをobject storageから取得するため、Zeppelin hostからspooling用storageへのnetwork到達性と認証も必要になる。Iceberg data bucketへの直接アクセスとは分けて設計する。

AWS用Interpreterを追加する

既存のHDFS/Ozone用Interpreterを上書きせず、ZeppelinのWeb UIからAWS確認用Interpreterを追加する。

Interpreter → Create New

Interpreter Name  : trino_aws
Interpreter Group : jdbc

propertiesは次のように設定する。

default.driver=io.trino.jdbc.TrinoDriver
default.url=jdbc:trino://trino1:8080/iceberg_aws/logs
default.user=zeppelin
default.validationQuery=SELECT 1
default.testOnBorrow=true

TrinoでTLSを有効にしている場合は、実際のHTTPS portと証明書検証方式に合わせる。

default.url=jdbc:trino://trino1:8443/iceberg_aws/logs?SSL=true

password認証、JWT、OAuth 2.0などを有効にしている環境では、Trinoの認証方式に対応するJDBC propertyを追加する。passwordやtokenをNotebook本文へ書かず、ZeppelinのCredential機能または保護されたInterpreter設定を使用する。

DependenciesのArtifactには、Trino clusterと同じversionのJDBC Driverを設定する。

io.trino:trino-jdbc:476

JARを手動配置する場合は、Zeppelin hostで次のように配置する。

cd /tmp
curl -fLO https://repo1.maven.org/maven2/io/trino/trino-jdbc/476/trino-jdbc-476.jar
sudo install -o zeppelin -g zeppelin -m 0644 \
  trino-jdbc-476.jar \
  /opt/zeppelin/lib/trino-jdbc-476.jar
sudo systemctl restart zeppelin

Artifact設定と手動配置を重複して行う必要はない。利用中のZeppelinのdependency解決方式に合わせて、どちらか一方を選ぶ。

Zeppelinから接続を確認する

Notebookでtrino_aws Interpreterを指定し、default catalogとschemaを確認する。

%trino_aws
SELECT current_catalog, current_schema;

想定結果は次である。

iceberg_aws | logs

table一覧と日別件数を確認する。

%trino_aws
SHOW TABLES;

SELECT dt, COUNT(*) AS cnt
FROM syslog_iceberg
WHERE dt >= current_date - INTERVAL '7' DAY
GROUP BY dt
ORDER BY dt;

JDBC URLでiceberg_aws/logsをdefaultにしているため、syslog_icebergのようにtable名だけでも参照できる。移行比較ではcatalogとschemaを明示する。

%trino_aws
SELECT 'ozone' AS src, COUNT(*) AS cnt
FROM iceberg_ozone.logs_s3.syslog_iceberg
WHERE dt = current_date - INTERVAL '1' DAY
UNION ALL
SELECT 'aws' AS src, COUNT(*) AS cnt
FROM iceberg_aws.logs.syslog_iceberg
WHERE dt = current_date - INTERVAL '1' DAY;

Flinkが作成したrealtime tableも同じInterpreterから参照できる。

%trino_aws
SELECT dt, hr, COUNT(*) AS cnt
FROM iceberg_aws.logs.syslog_events
GROUP BY dt, hr
ORDER BY dt DESC, hr DESC
LIMIT 48;

Zeppelin側でAWS S3を参照できない場合

次の順で切り分ける。

  1. Zeppelin hostからTrino Coordinatorへ接続できるか
  2. JDBC DriverとTrino clusterのversionが一致しているか
  3. default.urlのcatalogがiceberg_aws、schemaがlogsになっているか
  4. Trino CLIから同じSQLを実行できるか
  5. Trino全WorkerにGlue/S3設定とAWS credentialがあるか
  6. Trinoのaccess controlでZeppelin userにiceberg_aws.logsのSELECT権限があるか

ZeppelinからTrinoへ接続できるのにS3 objectの読み取りで失敗する場合、問題はZeppelinではなくTrino Worker側のIAM、region、S3 filesystem設定である可能性が高い。

Zeppelinのrollback

AWS用Interpreterを別名で追加しているため、問題がある場合はNotebookの先頭を旧Interpreterへ戻す。

-%trino_aws
+%trino_ozone

旧InterpreterとOzone/HDFS catalogは、AWS側の比較と観察期間が終わるまで削除しない。

Trinoのrollback

AWS側で問題が発生した場合はSQLの参照先をiceberg_ozone.logs_s3へ戻す。catalogを別名で残しているため、Trino設定を再度書き換えなくても参照先を切り戻せる。

通常時   : iceberg_aws.logs.*
rollback : iceberg_ozone.logs_s3.*

まとめ

ローカルS3からAWS S3への移行では、rawとIcebergを同じ方法でコピーしない。

rawはobject数、合計size、sample checksumを確認する。Icebergは日付単位で論理コピーし、件数、時刻範囲、集計差分を確認する。cutover直前に増分を追従し、一定期間Ozoneをread-onlyで保持することでrollback経路も残せる。

Iceberg warehouseの物理コピーではなく、AWS側でdata file、manifest、metadataを再生成することが重要である。

TrinoではOzone用catalogを上書きせず、Glue Catalogとnative S3 filesystemを使用するiceberg_awsを追加した。GrafanaやZeppelinはCoordinatorを変更せず、SQLのcatalog名を切り替える。

参考資料

関連記事

実機検証について

本記事の手順は、執筆時点では実機環境での一連の動作検証をまだ完了していない。掲載している設定値、command、IAM権限、service名、package構成は設計例を含むため、利用するApache Ozone、AWS S3、AWS Glue、Spark、Iceberg、Trinoなどのversionと実環境の構成に合わせた確認が必要である。

実施する場合は、検証環境でbackupとrollback手順を用意し、Ozone側を保持したままobject数、size、checksum、Icebergの集計結果を比較してから切り替える。AWS利用料金にも注意し、実機検証の結果に応じて本記事を更新する予定である。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?