異なる AWS アカウント間での Amazon S3 のデータ同期を実施する #2 (AWS CLI 定期自動実行) 

# 1. はじめに

ある AWS アカウントの Amazon S3 バケットに保管されたデータを別の AWS アカウントの Amazon S3 バケットに定期的にコピーさせるためのセットアップ例です。

前回記事では AWS CloudShell を利用して「オンデマンド (手動)」で同期する手法をご紹介していましたが、今回はその応用編となる自動化 (バッチ処理) となります。

https://qiita.com/sanjushi003/items/6e72df957fd8ea7ac8ac

## 前提条件 (S3 バケット A へのアクセス制限)

今回は次のような特定の条件に向けて、AWS CLI を活用して S3 間でデータを「定期的に自動」で同期する手法をご紹介します。

- AWS アカウント A の Amazon S3 および他の AWS リソースに関する操作、変更は一切実施できない
- AWS アカウント A の S3 バケット A には、AWS アカウント B のユーザーだけがデータ取得 (List/Get) できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/4a62c404-1f54-a08b-744c-7f49805e61bd.png)


異なる AWS アカウント (クロスアカウント) 環境において S3 バケットのデータを自動取得する手法は数多く存在しますが、今回は上記の条件によって実現する手法はいくつか限られます。


</details>

<details><summary>パッと思いつくけど実装できない NG 例</summary>

::: note warn
- Amazon S3 の機能である S3 Replicaiton は送信元 (AWS アカウント A) 側での作業が必要
- AWS Data Sync によるデータ同期は送信元 (AWS アカウント A) 側での作業が必要
- etc..
:::

</details>

</details>

<details><summary> AWS アカウント A の S3 バケット A のバケットポリシー (実際の例) </summary>


```json: S3 バケットポリシー (AWS アカウント A)
{
"Effect": "Allow", "Principal": {
"AWS": "arn:aws:iam::<AWS アカウント B>:root" },
"Action": [ "s3:List*","s3:Get*" ],
"Resource": ["arn:aws:s3:::<バケット A>","arn:aws:s3:::<バケット A>/*"]
}
```



補記しておくと「root」と指定されていますが、実際には AWS アカウント全体 (ここでは 123456789) を意味しています。

```json: 指定する AWS アカウント全体が対象
{
"Principal": { "AWS": "arn:aws:iam::123456789012:root" }
```

[(参考) AWS JSON ポリシーの要素: Principal](
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-accounts)

つまり AWS アカウント「ルートユーザー」である必要はなく、指定されている「AWS アカウント全て」を対象にしています。もちろん今回の場合は S3 関連の操作をする権限 (S3 Get / List) は最低限必要となります。


</details>

# 2. 実装手順

今回の構成はとてもシンプルで原始的です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/2fc53aad-844a-9c14-a326-cd97bb468644.png)

[`s3sync`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/index.html) という便利な Amazon S3 の同期用の [AWS CLI コマンド](https://awscli.amazonaws.com/v2/documentation/api/latest/index.html#)があり、それを cron ジョブで定期実行 (バッチ処理) させます。

今回は AWS CLI 実行環境として新規で Amazon EC2 (Amazon Linux 2023) を作成しましたが、AWS CLI さえ定期実行できれば良いので代替案はいくつもありそうです。

<details><summary>ほかに思いついた代替ソリューション案</summary>

いずれも今回の実装例としてご紹介はしませんが、下記のような手法がありそうです。

:::note

- Linux OS ではなく Windows OS のタスクスケジューラー機能で AWS CLI を定期実行する

- Amazon EC2 ではなくオンプレミスのサーバーで AWS CLI を定期実行する

- AWS Lambda 関数として "s3sync" もしくは同様な S3 同期処理を実装し、Amazon EventBridge で定期実行する

:::

考えてみると他にも実装手法はありそうなので、環境や要件に応じて試していただければと思います。


</details>

## 2-1. データ送信先の S3 バケット作成

データ送信先の S3 バケットは、データ送信元の S3 バケットと同じリージョンで作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/6ac3c0fa-c594-040e-82fb-45137851e564.png)

## 2-2. Amazon EC2 の作成

バッチジョブ実行にしか利用しないので安価な `t3.nano` を選択しています。(2024 年 10 月時点で[オンデマンド利用が月額約 4.9 USD、1 時間 0.0068 USD](https://aws.amazon.com/jp/ec2/pricing/on-demand/) です。)

OS には [Amazon Linux 2023](https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/awscli2.html) を選択したので、`AWS CLI v2` がプリセットされています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/d560a81b-5326-3f77-acb8-0edeeea4bfd7.png)

次のステップでは `AWS CLI` から AWS アカウント (`AWS IAM ユーザー`) へのアクセスのために`アクセスキー`と`シークレットアクセスキー`が必要とります。未作成の場合は次を参考にしてください。

<details><summary>アクセスキーとシークレットアクセスキーの取得 (未取得の場合) </summary>

:::note warn

今回は検証ということでアクセス許可は比較的ゆるめになっています。

ただし本番環境で利用される際にはアクセス許可を必要最低限に絞ってより厳しくするなど、[AWS IAM でのセキュリティのベストプラクティス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html)に準拠することを推奨します。

:::

未作成の場合、AWS IAM ユーザーを作成していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/c9755552-467e-4be6-e097-0bd4c962b5fb.png)

`AmazonS3FullAccess`のポリシーをアタッチします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/f8fda50f-5079-5909-c1ad-dabafb741705.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/f694857d-b1e8-968c-2e2d-34e55f7e6042.png)

`アクセスキーを作成`を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/907345fe-cb8e-0b0c-61b7-3a347484f796.png)

`コマンドラインインターフェイス (CLI)`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/0ecd01fb-e954-cd1c-9ea7-cebe05a19c77.png)

`アクセスキー`と`シークレットアクセスキー`をコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/a440daed-d7a0-d3a1-8beb-1d023a6c1114.png)

</details>

## 2-3. AWS CLI の初期セットアップ

AWS CLI を実行する環境 (Amazon EC2 Linux) に AWS IAM ユーザーのアクセスキー、シークレットアクセスキーを登録します。

```: ルートユーザーとして実行 (任意)
$ sudo su
```

```: アクセス情報の登録
$ aws configure
AWS Access Key ID [None]: <アクセスキー>
AWS Secret Access Key [None]: <シークレットアクセスキー>
Default region name [None]: ap-northeast-1
Default output format [None]: 
```

```: 登録したアクセス情報の確認
$ aws configure
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/b65343ed-face-bc86-7c1e-2bbfdd30cf3c.png)

https://docs.aws.amazon.com/ja_jp/cli/v1/userguide/cli-configure-files.html#cli-configure-files-methods

## 2-４. cron ジョブのセットアップ

`Amazon Linux 2023` AMI には `cronie` パッケージがデフォルトでは入っていないのでインストールします。

```: cronie のインストール
$ sudo yum install cronie -y

...
Complete!
```

5 分おきに `s3sync` を実行するように設定します。

```: cron ジョブの設定
$ sudo crontab -e

*/5 * * * * aws s3 sync <source> <target>

# <source> は 送信元 S3 バケットの ARN
# <target> は 送信先 S3 バケットの ARN
```

```: 設定した cron ジョブの確認
$ sudo crontab -l
```

下図は設定されている cron ジョブです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/71b565ab-cfa1-08b3-c117-f09e1fa25be1.png)


```: cron サービスの再起動と確認
$ sudo service crond restart
$ systemctl crond.service
```

Active: active (running) と表示されているので、 cron サービスは正常に実行中であると確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/3e3a4580-fbad-0925-1ecd-f94cd3851193.png)

## 2-5. Amazon S3 同期の確認

いくつかのファイルとフォルダを送信元 S3 バケットにアップロードを続け、そのあと送信先 Amazon S3 バケットを確認しました。

想定通り 5 分間隔で同期されていました。これで完了です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/423c9022-5467-5ba4-5d08-e9ba60a0f3ac.png)


# 3. まとめ

ある特定のアクセス環境下において、異なる AWS アカウント同士での Amazon S3 のデータ同期を自動で定期実行する手法についてご紹介しました。

# 4. 関連ブログ

応用編として、Amazon S3 のデータ同期をメール通知させる手法について紹介しています。

https://qiita.com/sanjushi003/items/5f875edc95f24c600fd1

AWS CLI を AWS CloudShell 経由で手動実行する方法はこちらです。

https://qiita.com/sanjushi003/items/6e72df957fd8ea7ac8ac