S3上の長期保存ログ削除でハマった話

## はじめに
- 現在AWSシステムのインフラ維持管理を担当しているが、S3上に長期保管しているログの削除運用においてハマったポイントと対策方針について共有します

## 該当条件(主に本投稿を確認頂きたい方)
- S3に対し<font color="Salmon">**「バージョニング(世代管理)」**</font>を有効化し利用している
- S3に対し<font color="Salmon">**「ライフサイクルルール」**</font>を設定し、オブジェクトの削除を行っている

## 何が起こっていたのか
- S3上に長期保管要件があるデータを保管しており、保存要件の期間を過ぎたログが自動でファイルデータごと削除される運用を想定し、予め以下のようなS3ライフサイクルルールを実装していた

（設定イメージ抜粋)
<table>
	<tbody>
		<tr>
			<td>ライフサイクルルール番号</td>
			<td>設定分類</td>
			<td>項目</td>
			<td>値</td>
		</tr>
		<tr>
			<td rowspan="2">ルール1</td>
			<td>ライフサイクルルールのアクション</td>
			<td>オブジェクトの現行バージョンを有効期限切れにする</td>
			<td>有効(チェックを入れる)</td>
		</tr>
		<tr>
			<td>オブジェクトの現行バージョンを有効期限切れにする</td>
			<td>オブジェクト作成後の日数</td>
			<td>365</td>
        </tr>
	</tbody>
</table>


- 実際はAWSコンソール上も過去のファイルは通常表示されないが、<font color="Salmon">**見えていないだけで本来削除されるべき実態のファイルは残り続けている状態だった**</font>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/7b0e5e30-8101-78ca-60e0-c632489fdc5c.png)


## 【結論】本来どうすればよかったのか（設定方針）

### (1)設計ポイント
- 有効期限切れとなったデータ含め完全削除するためには以下2種類のS3ライフサイクルルールの設定が必要となる

| ライフサイクルルール番号 | ルール概要 | ルール目的 |
|:-:|:-:|:-:|
| ルール1 | 過去バージョンのオブジェクト(実態ファイル含め)を削除するためのルール | 過去バージョンの実態ファイルを削除する |
| ルール2 | 有効期限切れのオブジェクト削除マーカーを削除するためのルール   | 最新バージョンである「削除マーカー」自体を削除する|

- 具体的には以下のような2種類のライフライクルルールを設定することで有効期限切れとなった全てのデータを削除することが可能となる（※<font color="Deepskyblue">青字：ルール追加箇所</font>、<font color="Salmon">赤字：既存ルール変更箇所</font>）


<table>
	<tbody>
		<tr>
			<td>ライフサイクルルール番号</td>
			<td>設定分類</td>
			<td>項目</td>
			<td>値</td>
		</tr>
		<tr>
			<td rowspan="4">ルール1</td>
			<td rowspan="2">ライフサイクルルールのアクション</td>
			<td>オブジェクトの現行バージョンを有効期限切れにする</td>
			<td>有効(チェックを入れる)</td>
		</tr>
		<tr>
			<td><font color="Salmon">オブジェクトの非現行バージョンを完全に削除</font></td>
			<td><font color="Salmon">有効(チェックを入れる)</font></td>
		</tr>
		<tr>
			<td>オブジェクトの現行バージョンの有効期限が切れる</td>
			<td>オブジェクト作成後の日数</td>
			<td>365</td>
		</tr>
		<tr>
			<td><font color="Salmon">オブジェクトの非現行バージョンを完全に削除</font></td>
			<td><font color="Salmon">オブジェクトが現行バージョンでなくなってからの日数</font></td>
			<td><font color="Salmon">1</font></td>
		</tr>
		<tr >
			<td rowspan="2"><font color="Deepskyblue">ルール2</font></td>
			<td><font color="Deepskyblue">ライフサイクルルールのアクション</font></td>
			<td><font color="Deepskyblue">有効期限切れのオブジェクト削除マーカーまたは不完全なマルチパートアップロードを削除</font></td>
			<td><font color="Deepskyblue">有効(チェックを入れる)</font></td>
		</tr>
		<tr>
			<td><font color="Deepskyblue">有効期限切れのオブジェクト削除マーカーまたは不完全なマルチパートアップロードを削除</font></td>
			<td><font color="Deepskyblue">期限切れのオブジェクト削除マーカーを削除する</font></td>
			<td><font color="Deepskyblue">有効(チェックを入れる)</font></td>
		</tr>
	</tbody>
</table>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/dbfc23a3-ef83-6fd5-f05a-2aad39a4a3ca.png)


（設定イメージ例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/6c120c7c-d334-8bd9-20b2-8dd8a625a4ee.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/64936957-ff13-ba4d-ab07-a474abd8e1af.png)


### (2)その他考慮ポイント
- オブジェクトストレージに「フォルダ」という概念は本来無く、ファイル管理をしやすくするためAWSコンソール上で「フォルダを作成」をすると、**0バイトのフォルダオブジェクト**を作成して、**疑似的にフォルダ(プレフィックス)のように見せている**
  - (必須ではないが)フォルダもS3ライフサイクルルールの削除対象として扱われるため、実ファイルのみ削除対象とするためには、削除対象の最小サイズを「1バイト」と設定する（設定しない場合、フォルダ(プレフィックス)配下のデータが0個(0バイト)になったタイミングで該当のフォルダはライフサイクルルールにより削除される)
- ルール1だけ設定した場合、削除マーカーが残り続けるためルール2を追加設定することで完全に関連データを削除させる
  - 削除マーカー自体は0バイトで特に容量を圧迫することはなく残しても問題ないと判断する場合、設定必須ではない

## 最後に
- 「削除マーカー」といった固有の概念もあり、S3上のバージョン管理されたファイルを自動削除させるための運用設計がわかりづらいと感じたため、本投稿にてまとめました
-  今後同じ過ちを繰り返す人が少しでも減らせることができれば幸いです

## [参考]その他用語説明・補足など
- 削除マーカーとは？
(公式マニュアル)

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/DeleteMarker.html

- オブジェクトの有効期限とは？
(公式マニュアル)

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html

- 過去バージョンのファイルを確認するためには？
     - [オブジェクト]タブ上の「バージョンの表示」を選択することで確認することが可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/22be09df-6290-4f7d-b8b3-66e091c7da87.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932264/4be9eed3-b04a-d375-eec6-42d8cacd4388.png)