【New】Seekable OCIでECSのコンテナ起動を高速化しよう！🚀

## はじめに
2023/7/17に、AWSがオープンソース化したSeekable OCI(以下SOCI)がECS on Fargateで利用可能になったことが発表されました！

**約50％高速化出来るらしい**

SOCIを利用する事によってコンテナイメージ全体のダウンロードを待たずにコンテナを開始出来るようになり、**コンテナのデプロイとスケールアウトが高速化**出来るというものらしいです。

https://aws.amazon.com/jp/about-aws/whats-new/2023/07/aws-fargate-container-startup-seekable-oci/

全ECSユーザ必見のリリースだと思うので早速やってみようと思います。

## Seekable OCIとは
2022年の9/8にAWSによってオープンソース化され、**コンテナイメージの遅延読み込みを行う事でコンテナを高速に起動出来るた技術**です。既存のコンテナイメージにあるファイルのインデックス (SOCI インデックス) を作成することによって機能し、アーカイブ全体をダウンロードする前にコンテナイメージから個々のファイルを抽出できるようにし、コンテナを高速に起動するための重要な要素となっています。

https://aws.amazon.com/jp/about-aws/whats-new/2022/09/introducing-seekable-oci-lazy-loading-container-images/

**※遅延読み込みは、アプリケーションの起動と並行してレジストリからデータをダウンロードするアプローチ**

### 比較イメージ

![スクリーンショット 2023-07-18 20.28.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/8967c43a-70c6-4df1-917b-305710c09496.png)

![スクリーンショット 2023-07-18 20.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/33dc3cf4-d0cf-4639-9c0d-4959da0360ac.png)

## SOCIインデックスの作成パターン
SOCIのインデックスを作成する方法は2パターン紹介されています。

### パターン①AWS SOCI Index Builderで作成
AWS SOCI Index Builderは、 AWS クラウド内のコンテナイメージのインデックスを作成するためのサーバーレスソリューションで、公式よりCloudFomaritonテンプレートが用意されています。

https://aws-ia.github.io/cfn-ecr-aws-soci-index-builder/

### パターン②手動で作成
手動作成の場合、既存のECRリポジトリにあるコンテナイメージ含めSOCIインデックスを作成可能ですが、ローカルなどにsociを別途インストールする必要があります。soci-snapshottersociについては以下のリポジトリを参考にインストールしていきます。

https://github.com/awslabs/soci-snapshotter/tree/main

## やってみよう
公式ブログを参考に早速やってみようと思います。インデックスを付与したイメージをプッシュしてみようと思います。

https://aws.amazon.com/jp/blogs/aws/aws-fargate-enables-faster-container-startup-using-seekable-oci/

今回は公式ブログで紹介されている手動作成のパターンではなく、SOCI Index Builderを使用したパターンで試そうと思います。

SOCIインデックスとは
**コンテナイメージの遅延読み込みを可能にするアーティファクトで、インデックスマニフェストとzTOCで構成されます。**
※図の右部分

![soci-index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/ecdd4d09-d1cd-eb05-e5e3-17ab8744d97a.png)

※[参照](https://aws.amazon.com/jp/blogs/aws/aws-fargate-enables-faster-container-startup-using-seekable-oci/)

### 事前準備
- ECRイメージ作成

```sh
aws ecr create-repository --region us-east-1 --repository-name pytorch-soci
```

![スクリーンショット 2023-07-18 7.59.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/eb66bd83-d4ee-17f8-459a-c3a25df85dc3.png)

- 変数化
```
ECRSOCIURI=xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/pytorch-soci:latest
```

- サンプルアプリケーション用意
※サンプルで使われているイメージは以下より参照

https://github.com/aws/deep-learning-containers/blob/master/available_images.md

```
SAMPLE_IMAGE="763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-training:1.5.1-cpu-py36-ubuntu16.04" 
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com
docker pull --platform linux/amd64 $SAMPLE_IMAGE
```

- タグ付け
```
docker tag $SAMPLE_IMAGE $ECRSOCIURI
```

### AWS SOCI Index Builder作成

AWS SOCI Index Builderのアーキテクチャ

![aws_cfn_soci_index_builder_architecture_diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/b292f00c-4315-33bc-1da8-9d5bfcc4b75b.png)

https://aws-ia.github.io/cfn-ecr-aws-soci-index-builder/

CloudFromationより以下のURLのテンプレートを用いてスタックをデプロイ

```
https://aws-quickstart.s3.us-east-1.amazonaws.com/cfn-ecr-aws-soci-index-builder/templates/SociIndexBuilder.yml
```

![スクリーンショット 2023-07-18 8.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/5414aff3-946b-119e-9318-2fd943ac4d61.png)

### SociRepositoryImageTagFiltersを指定
パラメータにSociRepositoryImageTagFiltersの項目があります。このフィルターで指定されたタグにのみLambdaが実行される為、任意の値を指定しましょう。※今回はワイルドカードを指定しています。

![スクリーンショット 2023-07-18 8.34.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/d094f2f7-ccf5-c18f-06c8-30ff0a8d5749.png)


- 作成されるリソース群

![スクリーンショット 2023-07-18 11.01.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/5c95c1ef-b741-eeac-a445-fc63d4d65335.png)

- AWS::Events::Rule
- AWS::Lambda::Function
- AWS::Lambda::Permission
- AWS::IAM::Policy
- AWS::IAM::Role


■ EventBrigeのルール
以下のルールから分かるように、特定リージョンのECRにイメージがpushされたら実行されるルールのようです。※TargetはCloudFormationにて展開されたLambdaになります。Eventの検知条件は自身でカスタマイズして使いやすいようにしても良さそうですね。

```json
{
  "detail-type": ["ECR Image Action"],
  "source": ["aws.ecr"],
  "detail": {
    "result": ["SUCCESS"],
    "action-type": ["PUSH"]
  },
  "region": ["us-east-1"]
}
```

### イメージのプッシュ
ECRを作成したアカウントにログインし直してからプッシュしてください
```
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com
docker push $ECRSOCIURI
```

プッシュが完了しました。この段階では通常通りアーティファクトタイプはimageのものが存在するだけです。並行してEventBridgeがイメージのプッシュを検知してLambdaが実行されています。
![スクリーンショット 2023-07-18 8.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/1220cfa2-2517-1e47-604e-d2c1306ffef9.png)


暫くすると、アーティファクトタイプがSOCIインデックスとImageインデックスのものリポジトリにプッシュされました！アプリケーションの中身によると思いますが、Lambdaの実行完了にやや時間がかかった印象です。

![スクリーンショット_2023-07-18_8_44_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/0af9cd84-5a43-846d-2da2-e7a8f5f46b95.png)

## SOCIのパフォーマンス比較
※公式ブログより計測比較が掲載されていたのでそのまま引用

### SOCI インデックスなし
**起動開始から完了まで129秒**

```
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                                   DescribeTasks                                                                                   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
|             createdAt            |             startedAt             |                                                  taskArn                                                   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
|  2023-07-07T17:43:59.233000+00:00|  2023-07-07T17:46:09.856000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/dcdf19b6e66444aeb3bc607a3114fae0   |
|  2023-07-07T17:43:59.233000+00:00|  2023-07-07T17:46:09.459000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/9178b75c98ee4c4e8d9c681ddb26f2ca   |
|  2023-07-07T17:43:59.233000+00:00|  2023-07-07T17:46:21.645000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/7da51e036c414cbab7690409ce08cc99   |
|  2023-07-07T17:43:59.233000+00:00|  2023-07-07T17:46:00.606000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/5ee8f48194874e6dbba75a5ef753cad2   |
|  2023-07-07T17:43:59.233000+00:00|  2023-07-07T17:46:02.461000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/58531a9e94ed44deb5377fa997caec36   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
```

### SOCI インデックスあり
**起動開始から完了まで60秒**

```
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                                   DescribeTasks                                                                                   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
|             createdAt            |             startedAt             |                                                  taskArn                                                   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
|  2023-07-07T17:43:53.318000+00:00|  2023-07-07T17:44:51.076000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/c57d8cff6033494b97f6fd0e1b797b8f   |
|  2023-07-07T17:43:53.318000+00:00|  2023-07-07T17:44:52.212000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/6d168f9e99324a59bd6e28de36289456   |
|  2023-07-07T17:43:53.318000+00:00|  2023-07-07T17:45:05.443000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/4bdc43b4c1f84f8d9d40dbd1a41645da   |
|  2023-07-07T17:43:53.318000+00:00|  2023-07-07T17:44:50.618000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/43ea53ea84154d5aa90f8fdd7414c6df   |
|  2023-07-07T17:43:53.318000+00:00|  2023-07-07T17:44:50.777000+00:00 |  arn:aws:ecs:ap-southeast-1:xyz:task/demo-pytorch-soci-cluster/0731bea30d42449e9006a5d8902756d5   |
+----------------------------------+-----------------------------------+------------------------------------------------------------------------------------------------------------+
```

SOCIを用いることで、およそ**50％高速**に起動されたことが分かります。
かなりのパフォーマンス改善ですね！起動時間とスケールアウト時間がこれぐらい改善が見込めるというのはインパクトが大きいと思いますので是非導入を検討してみたいところです。

## 考慮事項(2023/7/18時点)
SOCIを利用する場合の考慮事項

- サポートされるFargateプラットフォームはLinuxプラットフォームのVersion`１．４．０`
    - Windowsコンテナを実行するタスクは未対応
- X86_64アーキテクチャのみサポート
    - armアーキテクチャは未対応
- タスク定義内の全てのコンテナイメージに対してSOCIインデックスが必要
- タスク定義にある全てのコンテナイメージはECRのプライベートリポジトリにある必要あり
- gzip圧縮を使用するコンテナイメージまたは、未圧縮のコンテナイメージがサポート対象
    - zstd圧縮は未対応
- ２５０MiBを超えるコンテナイメージでの利用を推奨
    - サイズが小さいイメージは高速化の効果を得られる可能性が低い
- タスク起動時間が変化する可能性があるため、ELBなどのヘルスチェック猶予期間などのタイムアウトの見直しが必要
- タスク内の何れかのコンテナイメージが上記考慮事項を満たさない場合、通常の方法でダウンロードされる

https://docs.aws.amazon.com/AmazonECS/latest/userguide/container-considerations.html#fargate-tasks-soci-images


## おわりに
今回はAWS SOCI Index Builderを使用してSOCIインデックスが付与されたイメージを作成するところまでを実施してみたました。かなりの高速化が見込めるので今後、実際複数の環境に組み込んで効果測定が出来るようになったら改めて記事化してみたいと思います！