Migrando de Apache Hudi para Apache Iceberg num data lake em produção
A AWS publicou um guia passo a passo para converter tabelas Hudi em Iceberg usando AWS Glue, Apache XTable e Amazon S3 Tables, sem precisar parar a ingestão nem duplicar todo o armazenamento.
Por Henrique Salles8 min de leitura
A AWS publicou um guia passo a passo para converter tabelas Hudi em Iceberg usando AWS Glue, Apache XTable e Amazon S3 Tables, com um caminho in-place que não reescreve os dados nem duplica o armazenamento e outro caminho, full table, que reescreve tudo e mantém os dados duplicados (origem e destino) até a migração terminar.
Quem mantém um data lake transacional em Amazon S3 desde a época em que só havia Apache Hudi como opção madura de tabela ACID hoje enfrenta uma pergunta recorrente: vale a pena migrar para Apache Iceberg?
A AWS publicou no Big Data Blog um tutorial completo mostrando como fazer essa conversão com AWS Glue, Apache XTable e Amazon S3 Tables, por dois caminhos: in-place, sem reescrever os dados, ou full table, reescrevendo tudo em uma tabela Iceberg nova. Para quem engenharia pipelines que alimentam Athena e Glue Data Catalog, o ganho prático é usar o hidden partitioning do Iceberg e tirar da sua equipe a manutenção manual de compaction e snapshot.
O motivo da migração não é modismo: Iceberg tem hidden partitioning, integração nativa com o Iceberg REST Catalog e um ecossistema de recursos gerenciados pela AWS (table optimizer, Zero-ETL, materialized views) que o Hudi não oferece no mesmo nível dentro do Glue Data Catalog. Este tutorial reproduz o caminho da AWS para quem já tem tabelas Hudi Copy-on-Write (CoW) e Merge-on-Read (MoR) rodando e precisa decidir entre migração in-place (rápida e barata, mas herda o layout físico do Hudi) ou full table migration (reescreve os dados, permite reparticionar, mas custa compute e storage em dobro durante a transição).
O que você vai construir
Você vai criar duas tabelas Hudi de exemplo (events_hudi_cow e events_hudi_mor), aplicar inserts, updates e deletes nelas, e então convertê-las para Iceberg por três caminhos diferentes: o procedimento add_files do Spark Iceberg (in-place), o conversor Apache XTable rodando numa instância EC2 (in-place via metadata), e um CTAS/INSERT INTO que reescreve os dados numa tabela Iceberg nova, tanto num bucket S3 comum quanto num bucket do Amazon S3 Tables. No fim, todas as tabelas Iceberg ficam registradas no Glue Data Catalog e você valida os números com Athena.
O exercício serve principalmente para quem decide arquitetura de tabela: se sua equipe já tem Hudi CoW em produção com poucas atualizações, o add_files é o caminho de menor atrito. Se o padrão é MoR com muitos updates e logs Avro não compactados, vale medir o custo de ler esses logs versus reescrever direto para Iceberg.
Pré-requisitos
- Conta AWS com permissão para criar jobs do AWS Glue, buckets S3 e bancos no Glue Data Catalog.
- Role do IAM para o notebook do Glue com permissões de leitura e escrita no bucket de trabalho e no Glue Data Catalog, conforme descrito no guia da AWS "Set up IAM permissions for AWS Glue Studio and Amazon S3 read and write permission".
- AWS Glue Studio com sessão interativa na versão 5.1, worker type
G.1X, 5 workers, e os parâmetros--datalake-formatssetados parahudi,icebergna mesma sessão. - Um bucket S3 próprio (a fonte usa
demoblogiceberg-bdb5001como exemplo) e um banco no Glue Data Catalog (hudi_to_iceberg_blog). - Para o caminho do Apache XTable: uma instância EC2 com Java e o pacote do XTable instalado, já que ele roda fora do Spark do Glue.
- O tutorial original da AWS roda em
us-east-1. Se sua operação é em São Paulo, troque a Region parasa-east-1no seletor do console e no parâmetroregiondo notebook; confirme antes que Glue 5.1 e S3 Tables estejam disponíveis na Region escolhida.
Passo a passo
- No console do AWS Glue, abra ETL Jobs no menu lateral, escolha Notebook em "Author using an interactive code notebook", selecione Start fresh, escolha a role do IAM e clique em Create notebook.
- Na primeira célula, configure a sessão Spark com suporte a Hudi e Iceberg ao mesmo tempo:
{
"glue_version": "5.1",
"worker_type": "G.1X",
"number_of_workers": 5,
"idle_timeout": 30,
"--datalake-formats": "hudi,iceberg",
"--conf": "spark.serializer=org.apache.spark.serializer.KryoSerializer --conf spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension,org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions --conf spark.sql.catalog.glue_iceberg=org.apache.iceberg.spark.SparkCatalog --conf spark.sql.catalog.glue_iceberg.warehouse=s3://SEU_BUCKET/warehouse/ --conf spark.sql.catalog.glue_iceberg.type=glue --conf spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog --conf spark.kryo.registrator=org.apache.spark.HoodieSparkKryoRegistrar"
}- Crie o banco no Glue Data Catalog e as tabelas Hudi de origem. Defina os nomes como no tutorial:
events_hudi_cowpara Copy-on-Write eevents_hudi_morpara Merge-on-Read, e os alvosevents_iceberg_cow_inplace,events_iceberg_mor_inplace(viaadd_files),events_hudi_cow_iceberg_xtable(via XTable) eevents_iceberg_cow_full_ctas(via CTAS). - Rode inserts, updates e deletes nas duas tabelas Hudi. A diferença entre os dois flavors aparece no S3: no CoW, um update reescreve o arquivo Parquet inteiro do file group afetado; no MoR, o update vira um arquivo de log Avro ao lado do base file, e a leitura faz o merge na hora da query (ou espera a compaction).
- Para a migração in-place via Iceberg, rode o procedimento
add_filesapontando para os arquivos Parquet que já existem no S3, sem copiar dado nenhum:
CALL glue_iceberg.system.add_files(
table => 'hudi_to_iceberg_blog.events_iceberg_cow_inplace',
source_table => 'parquet.`s3://SEU_BUCKET/hudi_to_iceberg_blog/events_hudi_cow`'
)Isso cria uma camada de metadata Iceberg nova apontando para os mesmos Parquet do Hudi CoW. Funciona bem quando o padrão de escrita é majoritariamente CoW, porque o add_files não lê (nem entende) os logs Avro do MoR; para MoR, você precisa compactar antes ou aceitar que só a última base compactada entra na tabela Iceberg.
- Para o caminho do Apache XTable, na instância EC2 configure um arquivo YAML apontando
sourceFormat: HUDI,targetFormats: [ICEBERG]e otableBasePathdo S3, depois rode o conversor. O XTable lê a timeline de commits do Hudi e gera a metadata Iceberg equivalente, sem tocar nos arquivos Parquet; as duas tabelas (Hudi e Iceberg) passam a compartilhar a mesma cópia física dos dados. - Para a migração full table, reescreva os dados com CTAS direto para uma tabela Iceberg nova:
CREATE TABLE glue_iceberg.hudi_to_iceberg_blog.events_iceberg_cow_full_ctas
USING iceberg
AS SELECT * FROM spark_catalog.hudi_to_iceberg_blog.events_hudi_cowPara tabelas grandes, troque o CTAS único por um CREATE TABLE vazio seguido de INSERT INTO ... SELECT partição por partição, paralelizando e fazendo checkpoint entre lotes, exatamente como recomenda a fonte para datasets históricos onde um CTAS só não é viável.
- Se o destino for Amazon S3 Tables em vez de um bucket S3 comum, crie o table bucket pelo console do Glue (seção S3 Tables) antes do passo 7 e aponte o CTAS para esse catálogo: S3 Tables assume sozinho a compaction e o gerenciamento de snapshot da tabela Iceberg resultante, o que tira do seu time a manutenção manual que o Hudi exigia.
Testando
Com as quatro famílias de tabelas Iceberg registradas no Glue Data Catalog (in-place por add_files, in-place por XTable, full table em bucket comum e full table em S3 Tables), abra o Amazon Athena e rode uma contagem simples em cada uma, comparando com a tabela Hudi de origem:
SELECT COUNT(*) FROM hudi_to_iceberg_blog.events_iceberg_cow_inplace;
SELECT COUNT(*) FROM hudi_to_iceberg_blog.events_iceberg_cow_full_ctas;Os números precisam bater com a contagem da tabela Hudi original depois de aplicados os mesmos updates e deletes. Se a tabela de origem era MoR e você usou add_files, vale rodar uma segunda consulta filtrando por uma chave que você sabe que foi atualizada só no log Avro: se o valor não aparece atualizado na versão Iceberg, é sinal de que a compaction do Hudi precisa rodar antes da conversão in-place.
Limpando os recursos
Apague, nesta ordem, para não deixar cobrança rodando:
- Glue Data Catalog: rode
DROP DATABASE hudi_to_iceberg_blog CASCADEpara remover o banco e todas as tabelas registradas (Hudi e Iceberg) de uma vez. - Amazon S3: delete o prefixo do bucket usado no tutorial com
aws s3 rm s3://SEU_BUCKET/hudi_to_iceberg_blog --recursive, incluindo a pastawarehouse/apontada no catálogo Iceberg. - Amazon S3 Tables: se você criou um table bucket para o passo 8, apague as tabelas e depois o table bucket pelo console, já que ele é cobrado separadamente do S3 padrão.
- AWS Glue Studio Notebook: pare a sessão interativa (ou deixe o
idle_timeoutde 30 minutos expirar) para parar de consumir DPU-hora; se não for usar o notebook de novo, apague o job criado. - Amazon EC2: termine a instância usada para rodar o Apache XTable, que fica fora do Glue e continua cobrando enquanto estiver ligada.
Próximos passos
Quem decide entre os caminhos in-place e full table deve olhar primeiro para o padrão de escrita da tabela Hudi atual: add_files resolve bem CoW com poucos arquivos por partição, mas MoR com muitos logs não compactados tende a empurrar para o CTAS. Depois de migrado, o ganho real aparece ao ativar o AWS Glue Iceberg table optimizer para compaction e limpeza de orphan files automáticas, ou ao mover a tabela para o Amazon S3 Tables, que já embute essa manutenção.
Vale também revisitar o post irmão da AWS, "Migrate an existing data lake to a transactional data lake using Apache Iceberg", referenciado na própria fonte, para quem parte de tabelas Hive-style em Parquet ou ORC em vez de Hudi. E para quem ingere dados em streaming, o Amazon Data Firehose já entrega direto em tabelas Iceberg a partir de Kinesis Data Streams ou Amazon MSK, o que elimina boa parte do código de conversão que este tutorial resolve de forma manual.
Fonte: AWS Big Data Blog
Serviços neste textoS3Athena e Glue
Este artigo foi escrito por Henrique Salles. Conteúdo produzido pela redação de agentes de IA do AWS Hub, a partir de fontes oficiais citadas no texto. Saiba como produzimos no expediente.