[新機能] Amazon Aurora PostgreSQL と Amazon Redshift の Zero-ETL 統合の試してみました

[新機能] Amazon Aurora PostgreSQL と Amazon Redshift の Zero-ETL 統合の試してみました

Clock Icon2024.10.27

AWS事業本部コンサルティング部の石川です。Amazon Aurora PostgreSQL と Amazon Redshift の Zero-ETL 統合の一般提供を開始しました。プレビュー版とはZero-ETLの設定画面やその流れがかなり変わっています。本日はこの新機能が動作する環境を構築し、データがニアリアルタイムで同期される事を検証しました。

https://aws.amazon.com/jp/about-aws/whats-new/2024/10/amazon-aurora-postgresql-zero-etl-integration-redshift-generally-available/

Amazon Aurora PostgreSQLのAmazon RedshiftとZero-ETL統合

この新機能は、複雑なETL(抽出・変換・ロード)パイプラインを構築・管理することなく、Aurora PostgreSQLのトランザクションデータをAmazon Redshiftで簡単にデータを連携できるようになるサービスです。

Zero-ETL統合の主な利点

  • ETLパイプラインの構築・管理が不要
  • ソースデータが自動的にAmazon Redshiftにレプリケーション
  • ニアリアルタイムでデータが更新され、タイムリーな分析が可能
  • 複数のデータソースを単一のデータウェアハウスに統合

一般提供で追加された主な機能

  1. 拡張DDLイベントサポート
    • データベース、スキーマ、テーブルの作成、変更、削除、名前変更に対応
    • カスケード操作を含む高度な関係性のサポート
  2. データタイプサポートの拡張
    • Aurora PostgreSQL互換で対応しているほとんどのデータタイプと値をサポート
    • TOASTを使用した大きなデータ値の対応
  3. 複数論理データベースのレプリケーション
    • 単一のZero-ETL統合で複数の論理データベースからのデータレプリケーションが可能
  4. セキュリティとコスト最適化
    • レプリケーションするデータの選択的指定が可能

事前準備

一般提供開始となった Zero-ETL 統合は、Aurora PostgreSQL互換バージョン16.4以上で利用可能です。今回は、同じAWSアカウント上のAmazon Aurora PostgreSQLとAmazon Redshift Provisionedを Zero-ETL 統合します。プレビュー版とはZero-ETLの設定画面やその流れがかなり変わっています。

Zero-ETLの要件のAmazon Aurora PostgreSQLとAmazon Redshift Provisionedの構築

Zero-ETLの要件のAmazon Aurora PostgreSQLとAmazon Redshift Provisionedの構築までをCDKでサクッと作成します。実際のコードはAppendex Ⅰをご覧ください。**CDKで実行しますが、15分30秒(930秒)**と結構時間がかかります。

amazon-aurota-postgres-amazon-redshift-zero-etl-1

当初は、CDKですべて構築を試みたのですが、Zero-ETLそのものの設定は、現時点では対応していないためマネジメントコンソールから設定します。

CDKのコードの中では、Amazon Aurora PostgreSQLとAmazon Redshift Provisionedの構築と下記のZero-ETLの要件を設定しています。

Amazon Aurora PostgreSQLのバージョン16.4以上

  • Aurora PostgreSQL互換バージョン16.4以上で利用可能

Amazon Aurora PostgreSQLのクラスターパラメータ設定

  • rds.logical_replication=1
  • aurora.enhanced_logical_replication=1
  • aurora.logical_replication_backup=0
  • aurora.logical_replication_globaldb=0

Amazon Redshift クラスタのDBパラメータ設定

  • enable_case_sensitive_identifierture

Amazon Aurora PostgreSQLのテーブルを作成する

事前準備として、postgreデータベースのpublicスキーマにdevices1、devices2、devices3を作成します。(不覚にも、最初はテーブルに対して、プライマリキーを設定していなかったため、同期が取れずエラーになります。後ほど、トラブルシューティングします。)

$ psql -h zeroetlauroraredshiftstac-auroraclusterwriteraa1ab-wz0ssq9a2c6t.cwufmclyfzur.ap-northeast-1.rds.amazonaws.com -U postgres -d postgres -p 5432
Password for user postgres: 
psql (15.8, server 16.4)
WARNING: psql major version 15, server major version 16.
         Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=> \d
Did not find any relations.
postgres=> 
postgres=> 
postgres=> \dl
      Large objects
 ID | Owner | Description 
----+-------+-------------
(0 rows)

postgres=> create table devices1 (id varchar(16), data_ts varchar(32));
CREATE TABLE
postgres=> create table devices2 (id varchar(16), data_ts varchar(32));
CREATE TABLE
postgres=> create table devices3 (id varchar(16), data_ts varchar(32));
CREATE TABLE
postgres=> \d
          List of relations
 Schema |   Name   | Type  |  Owner   
--------+----------+-------+----------
 public | devices1 | table | postgres
 public | devices2 | table | postgres
 public | devices3 | table | postgres
(3 rows)

Zero-ETL integrations の設定

マネジメントコンソールから設定します。

Amazon Aurora PostgreSQLからZero-ETL統合を作成する

準備が整いましたので、早速作成します。ナビゲーションペインで[ゼロETL統合]を選択し、 [Create zero-ETL integration]を選択。

Step1: 開始方法

Integration nameを入力します。

amazon-aurota-postgres-amazon-redshift-zero-etl-2

Step2: ソースの選択

連携元となるDynamoDBのテーブルを指定します。[RDS データベースの参照]を押します。

amazon-aurota-postgres-amazon-redshift-zero-etl-3

ダイアログに表示されたDB識別子の一覧の中からいずれかを選択します。

amazon-aurota-postgres-amazon-redshift-zero-etl-4

元の画面に戻ると、エラーメッセージ(パラメータ値の修正)と[修正をお願いする(再起動が必要)]オプションが表示されます。このオプションには、チェックを入れます。
その理由は、Zero-ETL 統合を設定するには、選択したAuroraクラスタが適切なパラメータ値になっている必要があります。[修正をお願いする(再起動が必要)] オプションを選択すると、自動的に設定してくれます。

amazon-aurota-postgres-amazon-redshift-zero-etl-5

次に進むとどのような変更を加えるのかの解説が表示されます。

amazon-aurota-postgres-amazon-redshift-zero-etl-6

Step3: ターゲットの選択

連携先となるRedshiftを指定します。[Redshift データウェアハウスの閲覧]を押します。

amazon-aurota-postgres-amazon-redshift-zero-etl-7

ダイアログに表示されたRedshiftの一覧の中からRedshiftを選択します。

amazon-aurota-postgres-amazon-redshift-zero-etl-8

元の画面に戻ると、エラーメッセージ(リソースポリシーの修正)と[修正をお願いする]オプションが表示されます。このオプションには、チェックを入れます。
その理由は、Zero-ETL 統合を設定するには、選択したRedshiftに適切なリソースポリシーが有効になっている必要があります。[修正をお願いする] オプションを選択すると、自動的に設定してくれます。

amazon-aurota-postgres-amazon-redshift-zero-etl-9

次に進むとどのような変更を加えるのかの解説が表示されます。

amazon-aurota-postgres-amazon-redshift-zero-etl-10

Step4: タグと暗号化の追加

そのままで構いません。

amazon-aurota-postgres-amazon-redshift-zero-etl-11

Step5: 確認して作成

内容を確認して、進むとZero-ETL 統合の作成します。

amazon-aurota-postgres-amazon-redshift-zero-etl-12

amazon-aurota-postgres-amazon-redshift-zero-etl-13

ステータスが「作成中」 となりました。

amazon-aurota-postgres-amazon-redshift-zero-etl-14

Zero-ETL 統合の作成が完了すると、ステータスが「アクティブ」 になります。

amazon-aurota-postgres-amazon-redshift-zero-etl-15

Zero-ETL 統合からデータベースの作成

Zero-ETL 統合が作成できたら、次はZero-ETL 統合からRedshiftのデータベースを作成します。データベースを作成するとその中にpublicスキーマがあり更にその下に連携したテーブルが作成され、そのテーブルにデータが連携されます。

amazon-aurota-postgres-amazon-redshift-zero-etl-16

Redshiftに作成したいデータベース名を指定します。

amazon-aurota-postgres-amazon-redshift-zero-etl-17

データベースを作成した直後から、データの連携が開始します。初期状態ですので、Table row countは、0件です。これで設定は完了です。

トラブルシューティング&動作確認

トラブル発生

いきなり、トラブルです。ステータスは「注意が必要」 、画面上部には 「PRIMARY_KEY_NOT_FOUND」 です。不覚にも、最初はテーブルに対して、プライマリキーを設定していなかったため、同期が取れずエラーになっていました。

amazon-aurota-postgres-amazon-redshift-zero-etl-18

統合メトリクスからもエラーを確認できます。

amazon-aurota-postgres-amazon-redshift-zero-etl-19

トラブルシューティング

まずは、Aurora PostgreSQLのテーブルにプライマリキーを設定して再作成します。

postgres=> create table devices1 (id varchar(16), data_ts varchar(32) PRIMARY KEY);
CREATE TABLE
postgres=> create table devices2 (id varchar(16), data_ts varchar(32) PRIMARY KEY);
CREATE TABLE
postgres=> create table devices3 (id varchar(16), data_ts varchar(32) PRIMARY KEY);
CREATE TABLE

新機能のフィルタ機能を使って、デバックしやすいようにdevices1テーブルのみを連携するように再設定します。

amazon-aurota-postgres-amazon-redshift-zero-etl-20

動作確認

Zero-ETL 統合の作成が完了すると、ステータスが「アクティブ」 になります。

amazon-aurota-postgres-amazon-redshift-zero-etl-21

Aurora PostgreSQLのテーブル(devices1)にレコードをINSERTします。

amazon-aurota-postgres-amazon-redshift-zero-etl-22

遅れること、数秒程度で、Redshiftから参照できました。

amazon-aurota-postgres-amazon-redshift-zero-etl-23

統合メトリクスからも 「テーブルの失敗」が0「レプリケートされたテーブル」が1になり、エラーが解消されたことを確認できます。また、新機能の連携対象テーブルのフィルタリングで、指定した1テーブルのみが連携されていることも確認できました。

amazon-aurota-postgres-amazon-redshift-zero-etl-24

最後に

手抜きをしたつもりのCDK化も、結局全部できないのかよって事が後でわかり、Zero-ETL統合のトラブルシューティングも経験して、良い検証になったと思います。CDK化しなかったら、かなり長いブログになったので良しとしよう。プレビューの機能で検証したことがある方も、今一度試してみると良いかもしれません。

この新機能により、企業はデータ分析プロセスを大幅に効率化し、リアルタイムに近いデータ分析を実現できます。Aurora PostgreSQLの拡張された論理レプリケーション機能を活用することで、従来のPostgreSQLレプリケーションの課題を克服し、優れたパフォーマンスと柔軟性を提供します。

合わせて読みたい

https://dev.classmethod.jp/articles/amazon-dynamodb-amazon-redshift-zero-etl/

Appendex Ⅰ

AWS CDKによるZero-ETL環境の構築

import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as redshift from 'aws-cdk-lib/aws-redshift';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import { Construct } from 'constructs';

export class ZeroEtlAuroraRedshiftStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPCの作成
    const vpc = new ec2.Vpc(this, 'ZeroEtlVpc', {
      maxAzs: 2,
    });

    // Redshift用のセキュリティグループを作成
    const redshiftSecurityGroup = new ec2.SecurityGroup(this, 'RedshiftSecurityGroup', {
      vpc,
      description: 'Security group for Redshift cluster',
      allowAllOutbound: true,
    });

    // Aurora PostgreSQLのパラメータグループの作成
    const auroraParamGroup = new rds.ParameterGroup(this, 'AuroraParamGroup', {
      engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_16_4 }),
      parameters: {
        'rds.logical_replication': '1',
        'aurora.enhanced_logical_replication': '1',
        'aurora.logical_replication_backup': '0',
        'aurora.logical_replication_globaldb': '0',
      },
    });

    // Aurora PostgreSQLクラスターの作成
    const auroraCluster = new rds.DatabaseCluster(this, 'AuroraCluster', {
      engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_16_4 }),
      vpc,
      vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      writer: rds.ClusterInstance.provisioned('Writer', {
        instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM),
      }),
      readers: [
        rds.ClusterInstance.provisioned('Reader1', {
          instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM),
        }),
      ],
    });

    // Redshiftのパラメータグループの作成
    const redshiftParamGroup = new redshift.CfnClusterParameterGroup(this, 'RedshiftParamGroup', {
      description: 'Parameter group for Redshift',
      parameterGroupFamily: 'redshift-1.0',
      parameters: [
        {
          parameterName: 'enable_case_sensitive_identifier',
          parameterValue: 'true',
        },
      ],
    });

    // Redshift用のIAMロールの作成
    const redshiftRole = new iam.Role(this, 'RedshiftRole', {
      assumedBy: new iam.ServicePrincipal('redshift.amazonaws.com'),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonRedshiftAllCommandsFullAccess'),
        iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonS3FullAccess'),
      ],
    });

    redshiftRole.addToPolicy(new iam.PolicyStatement({
      actions: ['sts:AssumeRole'],
      resources: [auroraCluster.clusterArn],
    }));

    // Redshift用のシークレットの作成
    const excludeRedshiftPasswordCharacters = '/@"\'\\:'
    const redshiftSecret = new secretsmanager.Secret(this, 'RedshiftSecret', {
      generateSecretString: {
        excludeCharacters: excludeRedshiftPasswordCharacters,
        generateStringKey: 'password',
        passwordLength: 32,
        requireEachIncludedType: true,
        secretStringTemplate: JSON.stringify({
          engine: 'redshift',
          username: 'root',
          port: 5439,
          dbname: 'dev'
        }),
        excludePunctuation: true,
        includeSpace: false,
      },
    });

    // Redshiftクラスターの作成
    const redshiftCluster = new redshift.CfnCluster(this, 'RedshiftCluster', {
      clusterType: 'single-node',
      nodeType: 'ra3.large',
      masterUsername: 'root',
      masterUserPassword: redshiftSecret.secretValueFromJson('password').unsafeUnwrap(),
      dbName: 'dev',
      vpcSecurityGroupIds: [redshiftSecurityGroup.securityGroupId],
      clusterParameterGroupName: redshiftParamGroup.ref,
      iamRoles: [redshiftRole.roleArn],
      encrypted: true,
      publiclyAccessible: false,
      clusterSubnetGroupName: new redshift.CfnClusterSubnetGroup(this, 'RedshiftSubnetGroup', {
        description: 'Subnet group for Redshift cluster',
        subnetIds: vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds,
      }).ref,
    });

    // 出力
    new cdk.CfnOutput(this, 'AuroraClusterEndpoint', {
      value: auroraCluster.clusterEndpoint.hostname,
      description: 'Aurora Cluster Endpoint',
    });

    new cdk.CfnOutput(this, 'RedshiftClusterEndpoint', {
      value: redshiftCluster.attrEndpointAddress,
      description: 'Redshift Cluster Endpoint',
    });
  }
}

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.