AWS Lake Formation CDK（Cloud Development Kit）とは？

__データレイクを自動化して利用しようとした所、__
__AWS Lake Formation CDKというものがあり、とても、便利だと思いましたので、ご紹介致します。__

AWS Lake Formation CDKは、AWS Cloud Development Kit（AWS CDK）を使用してLake Formationリソースを構築するためのツールキットであり、Lake Formationに関連するAWSリソースをプログラムで作成することができます。Lake Formation CDKを使用することで、Lake Formationのデータカタログ、データベース、テーブル、およびデータアクセスの制御などの機能を自動化できます。

AWS Lake Formation
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920213/e0a14a3a-c463-c184-3b0b-d160c77e1f91.png)
https://aws.amazon.com/jp/lake-formation/


AWS CDKは、開発者がプログラミング言語（TypeScript、JavaScript、Python、Java、C＃）でクラウドインフラストラクチャをコード化し、AWSのAPIを使用してアプリケーションを構築できる開発フレームワークです。Lake Formation CDKは、このAWS CDKを使用して、Lake Formationのリソースをプログラムで構築するためのライブラリを提供します。

Lake Formation CDKは、Lake Formationのリソースを自動的に作成し、バージョン管理、再利用、および単一のリポジトリで管理することができます。Lake Formation CDKは、AWS CDKの構文とリソース定義を使用してLake Formationリソースを定義し、AWS CDKを使用して、AWSのCloudFormationスタックを作成および展開します。これにより、Lake Formationリソースの構成とセットアップを自動化し、開発者がリソースを手動で作成する必要がなくなります。

AWS CDK（Cloud Development Kit）は、AWSリソースのプロビジョニングを行うためのフレームワークです。CDKを使用することで、TypeScriptをベースにしたプログラミング言語でAWSリソースをコード化することができます。

AWS Lake Formation CDKを使用する方法
=
__1.	CDKのインストール__
AWS CDKをインストールする必要があります。
npmを使用してCDKをインストールします。

~~~
npm install -g aws-cdk
~~~
__2.	TypeScriptプロジェクトの作成__
TypeScriptプロジェクトを作成する必要があります。
新しいディレクトリを作成します。
~~~
mkdir my-lake-formation-cdk-project
cd my-lake-formation-cdk-project
~~~
TypeScriptプロジェクトを初期化します。
~~~
cdk init --language typescript
~~~
これにより、CDKアプリケーションの雛形が作成されます。

__3.	AWS Lake Formationモジュールのインストール__
AWS Lake Formation CDKモジュールをインストールする必要があります。
必要なモジュールをインストールします。
~~~
npm install @aws-cdk/aws-lakeformation
~~~
__4.	CDKアプリケーションのコード化__
AWS Lake Formation CDKアプリケーションのコードを書きます。
アプリケーションのスタックを作成し、Lake Formationデータレイクを定義することができます。
~~~
import * as cdk from '@aws-cdk/core';
import * as lakeformation from '@aws-cdk/aws-lakeformation';

export class MyLakeFormationCDKAppStack extends cdk.Stack {
//scope: CDK Construct クラスのインスタンス。この引数には、スタックが作成されるAWSリソースの親を表すConstructを指定します。
//id: スタックの一意の識別子。この引数には、スタックに対する一意のIDを指定します。
//props: 任意のスタックプロパティを指定するためのオプションの引数。
この引数には、スタック名や環境変数、AWSリソースの定義など、スタックに関する詳細な情報を含めることができます。
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Lake Formation Data Lake definition
    const dataLake = new lakeformation.CfnDataLakeSettings(this, 'MyDataLakeSettings', {
      admins: [{
        dataLakePrincipalIdentifier: 'arn:aws:iam::111111111111:role/LakeFormationAdmin'
      }]
    });
  }
}
~~~
上記の例では、adminsにLake Formationデータレイクの管理者として設定するIAMロールのARNを指定しています。

__5.	CDKアプリケーションのビルドとデプロイ__
CDKアプリケーションをビルドし、AWSにデプロイする必要があります。
アプリケーションをビルドします。
~~~
npm run build
~~~
アプリケーションをデプロイするために、次のコマンドを使用します。
~~~
cdk deploy
~~~
このコマンドを実行すると、AWSにスタックがデプロイされます。
デプロイには、AWSアカウントに対して適切なアクセス許可が必要です。

__6.	アプリケーションの削除__
 AWS Lake Formation CDKアプリケーションを削除する場合は、次のコマンドを実行します。
~~~
cdk destroy
~~~
このコマンドを実行すると、CDKスタックが削除されます。
以上が、AWS Lake Formation CDKを使用するための基本的な手順です。

AWS Lake Formation CDK（Cloud Development Kit）を使用して、AWS Lake Formationサービスの構成を定義するTypeScriptの例
--
~~~
import * as cdk from 'aws-cdk-lib';
import * as lakeformation from 'aws-cdk-lib/aws-lakeformation';
import * as iam from 'aws-cdk-lib/aws-iam';

const app = new cdk.App();

// AWS Lake Formationのデータベースを作成
const database = new lakeformation.CfnDataLakeSettings(app, 'Database', {
  adminResourceRole: 'arn:aws:iam::123456789012:role/lakeformation-admin-role',
  trustedResourceOwners: ['123456789012'],
});

// AWS Lake Formationのリソースアクセスを制御するIAMロールを作成
const lakeFormationRole = new iam.Role(app, 'LakeFormationRole', {
  assumedBy: new iam.ServicePrincipal('lakeformation.amazonaws.com'),
});

// IAMロールにポリシーを追加して、AWS Lake FormationサービスのAPIへのアクセスを許可
lakeFormationRole.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
//ソースには「*」が指定されているため、すべてのLake Formationリソースにアクセスが許可されます
  resources: ['*'],
  actions: [
    'lakeformation:GetDataLakeSettings',
    'lakeformation:GetEffectivePermissionsForPath',
    'lakeformation:GrantPermissions',
    'lakeformation:RevokePermissions',
  ],
}));

// AWS Lake Formationサービスによって管理されるS3バケットを作成
const s3Bucket = new s3.Bucket(app, 'LakeFormationBucket');

// S3バケットにデータを格納するためのIAMロールを作成
const s3Role = new iam.Role(app, 'S3Role', {
  assumedBy: new iam.ServicePrincipal('s3.amazonaws.com'),
});

// IAMロールにポリシーを追加して、S3バケットへのアクセスを許可
s3Role.addToPolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  resources: [s3Bucket.bucketArn],
  actions: ['s3:*'],
}));

// AWS Lake Formationサービスを使用して、S3バケットにデータをインポート
const importTask = new lakeformation.CfnDataLakeSettings.ImportCatalogToDataLake(app, 'ImportTask', {
  catalogId: '123456789012',
  resourceArn: s3Bucket.bucketArn,
  roleArn: s3Role.roleArn,
});

// CDKスタックをデプロイ
cdk.Tags.of(app).add('Stack', 'LakeFormationCDKExample');
app.synth();
~~~
この例では、AWS Lake Formationのデータベース、リソースアクセスを制御するIAMロール、AWS Lake Formationサービスによって管理されるS3バケット、およびS3バケットにデータをインポートするためのタスクを定義しています。また、CDKスタックにStackタグを追加しています。この例では、AWS CDKが提供するs3モジュールも使用しています。

サンプルコード
--
__TypeScriptを使用してAWS CDKでLake Formationデータカタログを作成する__
この例では、Amazon S3バケットとGlueデータベースおよびテーブルを作成し、SELECT権限を持つロールに対してLake Formationアクセス許可を設定します。

このスタックをビルドしてAWS CDKアプリケーションとしてデプロイすると、指定したリソースが作成され、SELECT権限を持つロールに対してLake Formationアクセス許可が設定されます。

~~~
    // ライブラリのインポート　CDKの必要なモジュールをインポートしています。
import * as cdk from 'aws-cdk-lib';
import * as lakeformation from 'aws-cdk-lib/aws-lakeformation';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as glue from 'aws-cdk-lib/aws-glue';

    // LakeFormationStackクラスを定義
　 // このクラスは、cdk.Stackを継承しており、AWSリソースの構築とCDKスタックの設定を実行します。

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

    // Create an S3 bucket
/*
この部分では、S3バケットを作成しています。
Bucketクラスのコンストラクタには、親スタック（this）、バケット名（'MyDataBucket'）、
そしてremovalPolicyプロパティを指定しています。
removalPolicyプロパティは、CDKスタックが削除されたときに、
どのようにバケットを扱うかを指定します。
この場合、DESTROYを指定しているため、スタックを削除するときにバケットも削除されます。
*/
    const dataBucket = new s3.Bucket(this, 'MyDataBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Create a Lake Formation data catalog
/*
ここでは、Lake Formationデータカタログを作成しています。
CfnDataCatalogクラスのコンストラクタには、親スタック（this）、データカタログ名（'MyDataCatalog'）、
そしてnameプロパティを指定しています。
*/
    const dataCatalog = new lakeformation.CfnDataCatalog(this, 'MyDataCatalog', {
      name: 'my-data-catalog',
    });

    // Create a Glue database
/*
AWS Glueのデータベースを作成しています。
AWS Glueデータベースは、データカタログに保存されるメタデータのセットで、
データカタログは、AWS上で管理されるデータリポジトリであり、
Amazon S3やRDSなどの外部データストアからデータのメタデータを抽出して集約します。

このコードでは、AWS CloudFormationを使用してAWS Glueデータベースを作成しています。 
glue.CfnDatabaseクラスは、AWS GlueデータベースのCloudFormationリソースを表します。
 catalogIdプロパティは、データカタログのIDを指定します。 
databaseInputプロパティは、データベースの名前を含むオブジェクトです。
データベース名は、nameプロパティによって指定されます。
この例では、データベース名はmy-glue-databaseとして指定されています。
*/
    const dataBase = new glue.CfnDatabase(this, 'MyGlueDatabase', {
      catalogId: dataCatalog.attrCatalogId,
      databaseInput: {
        name: 'my-glue-database',
      },
    });

    // Create a Glue table
/*
このコードブロックでは、Glueテーブルを作成しています。このテーブルは、S3バケットに保存されたデータを表します。

まず、glue.CfnTableを使用してテーブルを作成します。
引数として、スタックのコンストラクターで作成したLakeFormationデータカタログのARN、
および前のステップで作成したGlueデータベース名を指定します。

tableInputオブジェクトを使用して、テーブルの詳細を定義します。
nameプロパティは、テーブルの名前を指定します。
parametersプロパティは、Parquet形式でデータが保存されていることを示すclassificationおよび圧縮形式を指定します。
この例では、Snappy圧縮を使用しています。
*/
    const dataTable = new glue.CfnTable(this, 'MyGlueTable', {
      catalogId: dataCatalog.attrCatalogId,
      databaseName: dataBase.attrName,
      tableInput: {
        name: 'my-glue-table',
        parameters: {
          classification: 'parquet',
          compressionType: 'snappy',
        },
/*
次に、storageDescriptorプロパティで、テーブルのストレージの詳細を指定します。

inputFormatとoutputFormatは、データの読み込みと書き込みに使用されるHadoopファイル形式を指定します。

org.apache.hadoop.mapred.TextInputFormatは、Hadoop MapReduceフレームワークで使用されるテキスト形式のファイルを表し、
これは一般的にCSVファイルやTSVファイルなどの形式のデータを指します。

org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormatは、Hiveデータウェアハウスで使用される、
テキスト形式でデータを出力するフォーマットです。これは、Hiveデータベースと統合するために使用されることが多いです。

locationプロパティは、データが保存されているS3バケットのURLを指定します。
columnsプロパティは、テーブルの列名とデータ型を指定します。
この例では、col1列が文字列型であり、col2列が整数型であることを示しています。

最後に、serdeInfoプロパティは、Parquetフォーマットでデータをシリアライズするために使用されるHive SerDeの詳細を指定します。
serializationLibraryプロパティは、SerDeライブラリの名前を指定します。
この例では、ParquetHiveSerDeを使用しています。
parametersプロパティは、Parquetフォーマットのバージョンを指定しています。
この例では、バージョン1を指定しています。

ParquetHiveSerDeは、Apache Parquetフォーマットで書かれたデータを読み書きするための
Apache Hive用のデータシリアライザ/デシリアライザです。
Hiveは、大量の構造化データを処理するためのデータウェアハウジングプラットフォームであり、
ParquetHiveSerDeはHiveの内部で使用されるSerDeの1つです。
ParquetHiveSerDeは、Parquetフォーマットの圧縮形式、圧縮アルゴリズム、
スキーマなどの情報を含むメタデータを処理することができ、高速でスケーラブルなデータ処理を実現します。
*/
        storageDescriptor: {
          location: dataBucket.s3UrlForObject(),
          inputFormat: 'org.apache.hadoop.mapred.TextInputFormat',
          outputFormat: 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat',
          compressed: false,
          columns: [
            { name: 'col1', type: 'string' },
            { name: 'col2', type: 'int' },
          ],
          serdeInfo: {
            serializationLibrary: 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe',
            parameters: {
              'serialization.format': '1',
            },
          },
        },
      },
    });

    // Grant SELECT permission to a role
   //Lake Formationデータカタログに対してSELECT権限を持つロールを作成します。
    const dataLakeFormationPermission = new lakeformation.CfnPermissions(this, 'MyLakeFormationPermission', {
      resourceArn: dataCatalog.attrArn,
      permissions: ['SELECT'],
      principal: {
        dataLakePrincipalIdentifier: 'arn:aws:iam::123456789012:role/my-lake-formation-role',
      },
    });
  }
}
~~~


※スタックをビルドするためには、AWS CDK CLIをインストールし、cdk synthコマンドを使用して、CloudFormationテンプレートを生成する必要があります。テンプレートをデプロイするには、cdk deployコマンドを使用します。

LakeFormationStack
--
AWS CDKを使用してAWS Lake Formationサービスを構成するためのスタックです。このスタックを使用して、S3バケット、Lake Formationデータカタログ、Glueデータベース、Glueテーブルを作成し、さらにIAMロールに必要な権限を付与できます。

LakeFormationStack使用手順

1.aws-cdk-libパッケージをインストールします。
Node.jsパッケージマネージャーであるnpmを使用してインストールできます。
~~~
npm install aws-cdk-lib
~~~

2.LakeFormationStack.tsファイルを作成します。

3.LakeFormationStackクラスをインポートします。
~~~
import { LakeFormationStack } from './LakeFormationStack';
~~~

4.LakeFormationStackインスタンスを作成します。
~~~
const app = new cdk.App();
const stack = new LakeFormationStack(app, 'MyLakeFormationStack');
~~~

S3バケットの作成
~~~
const dataBucket = new s3.Bucket(this, 'MyDataBucket', {...})
~~~
MyDataBucketという名前の新しいS3バケットが作成されます。

Lake Formationデータカタログの作成
~~~
const dataCatalog = new lakeformation.CfnDataCatalog(this, 'MyDataCatalog', {...})
~~~
MyDataCatalogという名前の新しいLake Formationデータカタログが作成されます。

Glueデータベースの作成
~~~
const dataBase = new glue.CfnDatabase(this, 'MyGlueDatabase', {...})
~~~
MyGlueDatabaseという名前の新しいGlueデータベースが作成されます。

Glueテーブルの作成
~~~
const dataTable = new glue.CfnTable(this, 'MyGlueTable', {...})
~~~
MyGlueTableという名前の新しいGlueテーブルが作成されます。

上記のスタックを使用してAWS Lake Formationサービスを構成したい場合、以下のようにCloudFormationテンプレートを作成し、AWS CDKのcdk deployコマンドを使用してスタックをデプロイすることができます。
~~~
import * as cdk from 'aws-cdk-lib';
import { LakeFormationStack } from './lake-formation-stack';

const app = new cdk.App();
new LakeFormationStack(app, 'LakeFormationStack');
~~~
上記の例では、LakeFormationStackという名前の新しいAWS CDKアプリケーションを作成し、LakeFormationStackという名前の新しいスタックを作成しています。このスタックをデプロイするには、cdk deployコマンドを使用します。

5.AWS CDK CLIを使用して、スタックをデプロイします。
~~~
cdk deploy MyLakeFormationStack
~~~
LakeFormationStackによって作成されたAWSリソースがデプロイされます。必要に応じて、スタックをカスタマイズして、他の構成オプションを追加できます。