EBSスナップショットの自動化

EBSスナップショットの自動化サービスを使用してみました。

以前はLambdaで処理を回してましたが、
[Amazon Data Lifecycle Manager (Amazon DLM)](https://docs.aws.amazon.com/dlm/latest/APIReference/Welcome.html:embed:cite) を使用して、Amazon EBS ボリュームのスナップショットの作成、保持、削除を自動化できます。
スナップショット管理を自動化すると、次のことが可能になります。

* 定期的なバックアップスケジュールを実施して貴重なデータを保護する。
* 監査担当者または社内のコンプライアンスが必要とするバックアップを保持する。
* 古いバックアップを削除してストレージコストを削減する。

### 目的
- スケジュールドリブンでのEBSスナップショットの自動取得

### 対象
- 所有する全EBSVolume
- 下記をターゲットタグとする
  - key:Snapshot/value:true

### 管理世代
- 30日（ドラフト）
  - ここの値は監査部門と要調整

### 実行時間
- 23:45 UTC
  - DLMは負荷が集中しないようにanacronのように実行開始時間の幅が決まっており、DLM実行から1時間以内に処理が開始されます。

### 構成

```sh
dlm/
├── dlm_lifecycle_policy.tf
├── main.tf
├── script
│   └── create_target_tag.sh
└── terraform_remote_state.tf
```

<details><summary>main.tf</summary><div>

```json
provider "aws" {
  region  = "ap-northeast-1"
  profile = "terraform-user"
}

terraform {
  backend "s3" {
    bucket  = "terraform-xxxx"
    key     = "dlm/terraform.tfstate"
    region  = "ap-northeast-1"
    profile = "terraform-user"
  }
}
```
</div></details>

<details><summary>terraform_remote_state.tf</summary><div>

```json
data "terraform_remote_state" "dlm" {
  backend = "s3"

  config {
    bucket  = "terraform-xxxx"
    key     = "dlm/terraform.tfstate"
    region  = "ap-northeast-1"
    profile = "terraform-user"
  }
}
```
</div></details>

- 以下を実装
  - role
  - rolepolicy
  - lifecycle_policy
  - Amazon DLMを使用出来るようにIAMユーザへポリシーを作成しアタッチ

<details><summary>dlm_lifecycle_policy.tf</summary><div>

```json

resource "aws_iam_role" "dlm_lifecycle_role" {
  name = "dlm-lifecycle-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "dlm.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "dlm_lifecycle" {
  name = "dlm-lifecycle-policy"
  role = "${aws_iam_role.dlm_lifecycle_role.id}"

  policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "ec2:CreateSnapshot",
            "ec2:DeleteSnapshot",
            "ec2:DescribeVolumes",
            "ec2:DescribeSnapshots"
         ],
         "Resource": "*"
      },
      {
         "Effect": "Allow",
         "Action": [
            "ec2:CreateTags"
         ],
         "Resource": "arn:aws:ec2:*::snapshot/*"
      }
   ]
}
EOF
}

resource "aws_dlm_lifecycle_policy" "dlm_lifecycle_policy" {
  description        = "DLM lifecycle policy"
  execution_role_arn = "${aws_iam_role.dlm_lifecycle_role.arn}"
  state              = "ENABLED"

  policy_details {
    resource_types = ["VOLUME"]

    schedule {
      name = "30 days of daily snapshots"

      create_rule {
        interval      = 24
        interval_unit = "HOURS"
        times         = ["23:45"]
      }

      retain_rule {
        count = 30
      }

      tags_to_add = {
        SnapshotCreator = "DLM"
      }

      copy_tags = true
    }

    target_tags = {
      Snapshot = "true"
    }
  }
}

resource "aws_iam_policy" "using_dlm" {
  name        = "using-dlm"
  description = "Policy for using dlm"

  policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": "iam:PassRole",
         "Resource": "arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole"
      },
      {
         "Effect": "Allow",
         "Action": "dlm:*",
         "Resource": "*"
      }
   ]
}
EOF
}

resource "aws_iam_user_policy_attachment" "using_dlm_attach" {
  user       = "terraform-user"
  policy_arn = "${aws_iam_policy.using_dlm.arn}"
}
```
</div></details>

- 所有する全EBSVolumeにターゲットタグを追加

<details><summary>script/create_target_tag.sh</summary><div>

```sh
#!/bin/bash

#set -x

# awscliのバージョンは最新のにすること。
# jqをインストールし、profileは適宜変更すること。
# --dry-runで必要な権限があるか確認すること。必要な権限がある場合、エラー応答はDryRunOperationであり。それ以外の場合は、UnauthorizedOperationである。

for volumeid in `aws ec2 describe-volumes --profile ${AWS_PROFILE:-default} | jq -r '.Volumes[].VolumeId'`
do
	aws ec2 create-tags --resources $volumeid --tags "Key=Snapshot,Value=true" --profile ${AWS_PROFILE:-default}
done
```
</div></details>

### 確認
- 所有する全EBSVolumeに作成したターゲットタグが追加されてます。

```sh
✨~ $ aws ec2 describe-volumes --filters Name=tag:Snapshot,Values=true* --profile ${AWS_PROFILE:-default} | jq -r '.Volumes[].VolumeId' | wc -l
     1xxx
```

- スケジュール通りにSnapshotが取得出来たことを確認しました。

```
✨~ $ aws ec2 describe-snapshots --snapshot-ids snap-xxxxxxxxxxxxx | jq '.Snapshots[] | .StartTime, .State, .Progress'
"2019-02-07T00:13:53.000Z"
"completed"
"100%"
```


### 感想
今、無いものをなんとかして作りこむのも面白いですが、そこに使っていたコストを少なくし、他に充てることが出来るので、新しい技術はどんどん取り入れていきたいですね。