Amazon ECRプルスルーキャッシュリポジトリをVPCエンドポイント経由で試す

# はじめに

Amazon ECRにはプルスルーキャッシュリポジトリという機能があります。
こちらの機能利用し、VPCエンドポイント経由でPublicレジストリからイメージをPullしてみます。

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-ecr-cache-repositories/

## プルスルーキャッシュリポジトリとは

簡単に言うと、ECRプライベートレジストリ内にパブリックレジストリのリポジトリをキャッシュすることができ、24時間に1回同期も行ってくれるという機能です。
以下公式ドキュメントから引用です。

>Amazon ECR は、プライベート Amazon ECR レジストリのリモートパブリックレジストリ内のリポジトリのキャッシュをサポートします。Amazon ECR は現在、Amazon ECR パブリックおよび Quay のプルスルーキャッシュルールの作成をサポートしています。外部パブリックレジストリのプルスルーキャッシュが作成されたら、Amazon ECR プライベートレジストリ URI を使用して、その外部パブリックレジストリからイメージをプルするだけで、Amazon ECR はリポジトリを作成し、そのイメージをキャッシュします。キャッシュされたイメージが Amazon ECR プライベートレジストリ URI を使用してプルされると、Amazon ECR はリモートレジストリをチェックしてイメージの新しいバージョンがあるかどうかを確認し、24 時間ごとに 1 回までプライベートレジストリを更新します。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/pull-through-cache.html

## 試してみる

以下の構成を試してみます。
踏み台からPrivateSubnetにあるEC2に入り、VPCエンドポイントとプライベートレジストリを経由してパブリックレジストリにあるイメージをPullします。
以下のVPCエンドポイントを作成しました。

- com.amazonaws.ap-northeast-1.ecr.dkr
- com.amazonaws.ap-northeast-1.ecr.api
- com.amazonaws.ap-northeast-1.s3

![Qiita_構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/58b9f58c-9f4d-7405-f53a-b04ce6698e14.png)

※注意
公式ドキュメントにも記載がありますが、最初のpullはNat Gatewayを経由する必要があります。

> 初めてプルスルーキャッシュルールを使用してイメージをプルするとき、AWS PrivateLink を使って、インターフェイス VPC エンドポイントを使用するように Amazon ECR を設定した場合、NAT ゲートウェイを使用して、同じ VPC 内にパブリックサブネットを作成し、プルが機能するように、プライベートサブネットから NAT ゲートウェイへのすべてのアウトバウンドトラフィックをインターネットにルーティングする必要があります。その後のイメージプルでは、これは必要ありません。

### プルスルーキャッシュリポジトリ有効化
マネコンから有効化します。
「ECS → Private registry → Pull through cache」からプルスルーキャッシュルールを作成します。
設定は以下のようにします

- パブリックレジストリ(ECR Public or Quay)
    - ECR Public
- ソースレジストリURL(固定)
    - public.ecr.aws
- Amazon ECR リポジトリ名前空間(デフォルト)
    - ecr-public

![qiita_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/dc7f8839-a16c-2746-7fba-175146d12973.png)


### イメージをPull

Private Subnetにあるインスタンスに入り、ECRにログインします。

```sh
$ aws ecr get-login-password \
	--region <region> | docker login \
	--username AWS \
	--password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com
> Login Succeeded
```

ログインできたため、VPCエンドポイント経由でECRに接続できていることが確認できました。

次に、パブリックリポジトリから直接イメージをPullしてみます。

```sh
$ docker pull public.ecr.aws/amazonlinux/amazonlinux:latest
> Error response from daemon: Get "https://public.ecr.aws/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
```

接続できずpullができないことが確認できました。

最後にプライベートリポジトリ経由でpullしてみます。
指定方法は`<プライベートリポジトリ>/<リポジトリ名前空間>/<パブリックイメージ>`のような形です。

```sh
$ docker pull aws_account_id.dkr.ecr.region.amazonaws.com/ecr-public/amazonlinux/amazonlinux:latest
> latest: Pulling from ecr-public/amazonlinux/amazonlinux
f964900200fc: Pull complete
Digest: sha256:1dbd901e3a2464e81481e78836d46f79d1d16072b8fe0cd7f1d660dc2b668fa7
Status: Downloaded newer image for aws_account_id.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public/amazonlinux/amazonlinux:latest
aws_account_id.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public/amazonlinux/amazonlinux:latest
```

pullすることができました！
マネコンから確認すると、リポジトリが生成されイメージが落ちてきていることがわかります。
![qiita_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/5f3efc58-ee7e-da15-e791-1cda8b43831f.png)

# まとめ

VPCエンドポイント経由でPublicイメージをpullできることを確認しました。これにより、2回目以降はパブリックなイメージを使用する際にPrivate Subnetからnatなしで利用できます。

# 参考

https://dev.classmethod.jp/articles/ecr-pull-through-cache-repositories/

https://aws.amazon.com/jp/blogs/aws/announcing-pull-through-cache-repositories-for-amazon-elastic-container-registry/