Amazon Data Lake ～ demo

https://github.com/aws-samples/amazon-s3-datalake-handson/tree/master/JP

#1.cloudformationで事前準備#

CloudFormation を使い VPC と EC2 を作成。
VPC内に2分おきに10件前後のログを、10分おきに300件のエラーログを出力し続ける EC2 を作成。
構築した EC2 上に、ログ収集ソフトウェアの Fluentd のインストール、設定を行う。
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/2850d2a0-b67b-7a3a-2495-12518a724cf3.png)


```yaml
Parameters:
  InstanceType:
    Description: EC2 instance type
    Type: String
    Default: t2.micro
    AllowedValues:
      - t1.micro
      - t2.micro
    ConstraintDescription: must be a valid EC2 instance type.
  KeyPair:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: "AWS::EC2::KeyPair::KeyName"
    MinLength: '1'
    MaxLength: '255'
    AllowedPattern: '[\x20-\x7E]*'
    ConstraintDescription: can contain only ASCII characters.
Resources:
# Create VPC
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/24
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      InstanceTenancy: default
      Tags:
      - Key: Name
        Value: handson-minilake
# Create Public RouteTable
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
      - Key: Name
        Value: handson-minilake
# Create Public Subnet A
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: 10.0.0.0/27
      AvailabilityZone: "ap-northeast-1a"
      Tags:
      - Key: Name
        Value: handson-minilake
  PubSubnetARouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTable
# Create InternetGateway
  myInternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
      - Key: Name
        Value: handson-minilake
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref myInternetGateway
  myRoute:
    Type: AWS::EC2::Route
    DependsOn: myInternetGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref myInternetGateway
  MyEIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc
  ElasticIPAssociate:
    DependsOn: MyEC2Instance
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt MyEIP.AllocationId
      InstanceId: !Ref MyEC2Instance
  MyEC2Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: ami-0c67dfaea448e590a
      InstanceType: t2.micro
      SubnetId: !Ref PublicSubnetA
      KeyName :
        Ref: KeyPair
      SecurityGroupIds:
        - Ref: MyEC2SecurityGroup
      Tags:
        - Key: Name
          Value: handson-minilake
  MyEC2SecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupName: handson-minilake-sg
      GroupDescription: Enable SSH access via port 22
      VpcId: !Ref MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp:
            '0.0.0.0/0'
        - IpProtocol: tcp
          FromPort: '5439'
          ToPort: '5439'
          CidrIp:
            '0.0.0.0/0'
Outputs:
  AllowIPAddress:
    Description: EC2 PublicIP
    Value: !Join
      - ','
      - - !Ref MyEIP
```

ログが2分おきに出力されていることを確認する。

```
$ sudo su -
# tail -f /root/es-demo/testapp.log
```

この後のセクションでセッションマネージャを利用するために、以下のIAMポリシーを付与したIAMロールを作成し、EC2にアタッチします。

`AmazonEC2RoleforSSM`

ログ収集ソフトウェアの Fluentd をインストール、設定していく。

```
#redhat-lsb-core と gccをインストール
yum -y install redhat-lsb-core gcc

#td-agent をインストール
rpm -ivh http://packages.treasuredata.com.s3.amazonaws.com/3/redhat/6/x86_64/td-agent-3.1.1-0.el6.x86_64.rpm

#TD_AGENT_USER=agent の部分を TD_AGENT_USER=root に変更。
vi /etc/init.d/td-agent

#Fluentd の自動起動設定
chkconfig td-agent on
```



#2.アプリケーションログの永続化と長期間データの分析と可視化#

ストリームデータを Kinesis Data Firehose に送信後、 S3に保存することで長期保存する。
S3に保存したデータをAthenaを用いて、アドホックな分析を行い、 QuickSightで可視化する。
![キャプチャ8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/bf12eda9-e4d7-d321-0306-e859098738fb.png)


##S3##
S3バケットを作成しておく。

##Kinesis Data Firehose##
Kinesis Data Firehose を作成します。

・Step 1: Name and source
  [Delivery stream name] に「 minilake1（任意）」

・Step 2: Process records
  [Data transformation] を [Disabled] 、 [Record format conversion] を [Disabled] 

・Step 3: Choose a destination
  [S3 bucket] は 先程作成しておいたS3バケットを選択。 [Prefix] に「 minilake-in1/ 」を入力。

・Step 4: Configure settings
　[Buffer interval] を「 60 seconds」
　※バッファリングは、 Buffer size か Buffer interval のいずれかの条件がみたされるとS3に配信される。
　[Permissions] で [Create or update IAM role]

・Step 5: Review
　[Create delivery stream] 

以下のIAMポリシーを付与したIAMロールを追加し、EC2にアタッチします。

`AmazonKinesisFirehoseFullAccess`

Fluentd から Kinesis Data Firehose にログデータを送信するための設定を行います。

```
##Kinesis Data Firehose のプラグインをインストール。
sudo su -
td-agent-gem install fluent-plugin-kinesis -v 2.1.0

##プラグインのインストールを確認。
td-agent-gem list | grep plugin-kinesis
````

下記のファイルを編集する。

```/etc/td-agent/td-agent.conf
<source>
  @type tail
  path /root/es-demo/testapp.log
  pos_file /var/log/td-agent/testapp.log.pos
  format /^\[(?<timestamp>[^ ]* [^ ]*)\] (?<alarmlevel>[^ ]*) *? (?<host>[^ ]*) * (?<user>[^ ]*) * (?<number>.*) \[(?<text>.*)\]$/
  time_format %d/%b/%Y:%H:%M:%S %z
  types size:integer, status:integer, reqtime:float, runtime:float, time:time
  tag testappec2.log
</source>

<match testappec2.log>
  @type copy
  <store>
    @type kinesis_firehose
    delivery_stream_name minilake1
    flush_interval 1s
  </store>
</match>
```

```/etc/init.d/td-agent

##14 行目辺りに以下の行を追加する。
export AWS_REGION="ap-northeast-1"
```

Fluentd を再起動する。

```
/etc/init.d/td-agent restart
```

S3 にデータが出力されていることを確認する。
Kinesis Data Firehose で、作成した Delivery stream の「 minilake1（任意）」を選択し、 [Monitoring] タブでカウントされているか確認する。


##Glue Crawler##

S3 上に出力されたデータに対して、Glue のクローラ機能を使って、テーブルを自動作成し、クエリが実行できるようにします。


以下のIAMポリシーを付与したIAMロールを追加し、EC2にアタッチする。。

`AWSGlueServiceRole`
`AmazonS3ReadOnlyAccess`

更に「信頼関係」で"Service"に glue を追加しておく。

```
「{
		"Version": "2012-10-17",
		"Statement": [
   		{
     		"Effect": "Allow",
     		"Principal": {
       		"Service": [             
         		"glue.amazonaws.com",
         		"ec2.amazonaws.com"
       		]                        
     		},
     		"Action": "sts:AssumeRole"
   		}
 		]
}」
```

Glueの画面へ移動し、「クローラ」を次の要件で作成します。

・クローラの情報
　minilake-in1
・Crawler source type
　Data stores
・データストア
　S3: s3://naatahandson2020/minilake-in1
・IAM ロール
　arn:aws:iam::268546037544:role/handson
・スケジュール
　オンデマンドで実行
・出力
　minilake

作成されたら「クローラ」の実行をクリック。
![tempsnip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/5dd7dd32-f921-7d09-139a-49ebfeb216eb.png)

左側の「テーブル」をクリックし作成されていることを確認することと、テーブル名の箇所をクリックし、スキーマ定義を確認します。

##Athena##

[Settings]で、[Queryresult location]にS3を指定します。
![tempsnip333.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/36329287-7a3c-94be-e824-ca9577eac9f1.png)

[Database] ：「 minilake（任意）」
[TAbles]:「 minilake_in1（任意）」
テーブル名の右端の [点マーク] をクリックし、 [Preview table] をクリックと、クエリ結果が画面下部に表示されるはずです。
![tempsnip200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/96ffbffe-f8fb-7e4d-63c5-3dd25538262d.png)

`SELECT * FROM "minilake"."minilake_in1" limit 10;`

`SELECT * FROM "minilake"."minilake_in1" where partition_0 = '2020' AND partition_1 = '10' AND partition_2 = '21';`

##QuickSight##

エディションはエンタープライズを利用します。
QuickSightを既に一度作成済の場合は、「セキュリティとアクセス権限」を確認します。
![スクリーンショット 2020-10-22 22.52.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/eca99604-d51f-a884-1385-a8f835259828.png)

Athenaにチェックを入れ、次の画面で表示されるS3バケットにチェックを入れ、更新します。
![スクリーンショット 2020-10-22 22.56.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/6f686888-5e4d-27de-2f97-5868d9272fe8.png)

[新しい分析] -[新しいデータセット] の順にクリックし、
[Athena] で[データソース名] を入力後、[データソース名] をクリック。
![スクリーンショット 2020-10-22 23.00.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b9a92d38-b5a1-6cf0-6371-dcd42c065a3e.png)

先程作成したAthena1のDatabaseを選択。
![スクリーンショット 2020-10-22 23.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/8453a318-4b39-49cf-223e-74990db33c82.png)

「迅速な分析のために SPICE へインポートを選択。
![スクリーンショット 2020-10-22 23.19.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/ac10cf6e-8aa0-a8a1-6a2f-eef3ee22400c.png)

[インポートの完了] がポップアップされたら準備完了です。 
[フィールドリスト] や [ビジュアルタイプ] を適当に選び、データが可視化されていることを確認してください。



#3.クラウド DWH を使用したデータ分析#

ヒント：[Redshift Spectrumと Athenaの違いを探ってみた](https://qiita.com/kitaj/items/f6a1367f071cbe8e09e6)

ストリームデータを Kinesis Data Firehose に送信後、 S3 に保存することで長期保存する。
Redshift Spectrum を用いて、クエリを実行する。
なお、QuickSight で可視化する作業については、省略します。

![スクリーンショット 2020-10-23 110548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/086adfde-db2a-caa3-2176-7bd168a50e2f.png)

##CloudFormatin##

CloudFormatinで、
これまでに作成した VPC にプライベートサブネットを作成するのと、 
Redshift に設定するセキュリティグループも同時に作成します。

```
Parameters:
  VpcId:
    Description: select handson-minilake vpc id
    Type: "AWS::EC2::VPC::Id"
  EC2SecurityGroupId:
    Description: select EC2 Security Group ID
    Type: "AWS::EC2::SecurityGroup::Id"
Resources:
# Create Public RouteTable
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VpcId
      Tags:
      - Key: Name
        Value: handson-minilake-private-rt
# Create Private Subnet A
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcId
      CidrBlock: 10.0.0.32/27
      AvailabilityZone: "ap-northeast-1a"
      Tags:
      - Key: Name
        Value: handson-minilake-private-sub
# Associate with Private subnet and route table for private subnet
  PriSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable
# Create EIP
  MyEIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc
# Create NATGateway
  myNATGateway:
    Type: "AWS::EC2::NatGateway"
    DependsOn: 
      - MyEIP
      - PrivateSubnet
    Properties:
      AllocationId: !GetAtt MyEIP.AllocationId
      SubnetId: !Ref PrivateSubnet
      Tags:
      - Key: Name
        Value: handson-minilake-nat
# set NAT as default gateway on route table for private subnet
  myPrivateRoute:
    Type: AWS::EC2::Route
    DependsOn: myNATGateway
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref myNATGateway
# create sg for RS
  myRSSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupName: handson-minilake-sg-private
      GroupDescription: Enable SSH access via port 5439
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '5439'
          ToPort: '5439'
          SourceSecurityGroupId: !Ref EC2SecurityGroupId
```


##Redshift##

「設定」から「サブネットグループ」をクリックし、「クラスターサブネットグループの作成」で、次の要件で作成する。

- 名前：handson-minilake-dwh（任意）
- VPC ID：「 VPC ID 」
- アベイラビリティゾーン：ap-northeast-1a
- サブネットID：メモした「 サブネット ID 」を選択し、 [追加] をクリック

「クラスター」の「クラスター」より、「クラスターの作成」で、次の要件で作成する。

- クラスター識別子：handson-minilake-dwh（任意）
- このクラスターを何に使用する予定ですか?：無料トライアル
- データベース名：db
- データベースポート：5439 （デフォルト）
- マスターユーザー名：admin
- マスターユーザーのパスワード：MyPassword1
- [追加設定] の [デフォルトを使用] のラジオボタンをオフにし、[ネットワークとセキュリティ] にて以下の値を入力。
 -- Virtual Private Cloud (VPC) : 「 VPC ID 」
 -- VPC セキュリティグループ : handson-minilake-sg-private

Redshift → S3 にアクセスするための、IAMロールを作成し、Redshiftのクラスターのアタッチします。
[ユースケースの選択] は、 [Redshift - Customizable] 。

`AmazonS3ReadOnlyAccess`

[エディタ] を選択し、作成したインスタンスへの接続情報を入力し、 [データベースに接続] し、クエリを実行してみる。

```
##先にロード対象のテーブルを作成
create table ec2log ( timestamp varchar, alarmlevel varchar, host varchar, number int2, text varchar );

##S3 からデータを COPY
copy ec2log from 's3://[S3 BUCKET NAME]/minilake-in1' format as json 'auto' iam_role '[IAM ROLE ARN]';

##（例1） テーブルの全件数が返ってくるクエリ##
select count(timestamp) from ec2log;

##（例2） アラームレベル毎の集計値が返ってくるクエリ##
select alarmlevel, count(alarmlevel) from ec2log group by alarmlevel;
```