ECRからECSへのdockerイメージのpullをNatGateway経由からVPCエンドポイント経由へ切り替える

弊社プロジェクトの多くは、ECSを使って運用しているサービスが多いですが、今回はその運用過程で、デプロイの回数が増える時に、費用が嵩むポイントがあり、改善を行ったので、その記録を書きたいと思います。


## 背景
- デプロイの度にECRからECSへdockerイメージをpullする際に、通信がNatGatewayを通っていたので従量課金が嵩んでいた（NatGatewayの通信量は嵩むと意外とかかってしまう）
- ECRからECSへdockerイメージをpullするための通信は通信費の安いVPCエンドポイント経由に変更することでコストを抑える
- それ以外のプライベートサブネットからの通信（外部APIへの通信など）は引き続きNatGatewayを経由するままにしたい


## 最終的に作成するVPCエンドポイント
- 最終的には以下の３つのVPCエンドポイントの作成が必要
    - com.amazonaws.region.ecr.dkr(Interfacetタイプ)
    - com.amazonaws.region.ecr.api(Interfaceタイプ)
    - com.amazonaws.ap-northeast-1.s3(Gatewayタイプ)
- S3にECR Docker レイヤーイメージが保管されているので、ダウンロードされる際は常にS3へのアクセスが必要なためS3へのアクセスもVPCエンドポイント経由に設定しなければならない。そうしないと、イメージがpullできずに失敗しまった。
- なので、S3へのアクセスをVPCエンドポイント経由にし、ルーティング設定への追加も忘れないようにする。

## そもそもVPCエンドポイントとは
https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/endpoint-services-overview.html
https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpc-endpoints.html

- VPCエンドポイントを作成することで、VPC内のインスタンスとVPC外のサービスをプライベート接続でセキュアに通信できるようになる
- セキュリティの問題などでインターネットに接続せずにAWSのサービスと接続したい場合に利用
- VPCエンドポイントがなければIGWやNatGateway経由でVPC外のリソースにアクセスするのがデフォルト

- 	Interfaceタイプとgatewayタイプがある
https://dev.classmethod.jp/articles/vpc-endpoint-gateway-type/
    - Interfaceタイプ
        - https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpce-interface.html
        - PrivateLink の実体はVPC内のENI(Elastic Network Interface) 
        - Private Link Endpointを設定するとVPC内でプライベートIP付きのENIが作成される。
        - PrivateLink自体がIPアドレスを持ってVPCの中にエンドポイントが出来る
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/e38362c5-738c-4a0b-e0fc-e3c3b92e6f0e.png)



    - gatewayタイプ
        - AmazonS3 または DynamoDB の接続のみ(https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpce-gateway.html)
        - 基本はVPCのルートテーブル(ルーティング設定)を書き換えてのゲートウェイ経由でサービスへアクセスするように設定しないとVPCエンドポイント経由にならない。
            - その際に、紐付けたいサブネットと、ルートテーブルを選択してエンドポイントと紐付けると、それぞれのルーティングテーブルに値が自動で追加される
                        <img width="2364" alt="image.png (53.3 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/18/78280/bd3dee11-2afe-4a6e-a900-03e9a4c9b830.png">

       ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/007a567d-418b-3453-4b92-08b1ebfb3955.png)

## VPCエンドポイントの作成(ECRへのアクセスのためのinterfaceタイプ)

### create endpoint
- AWSサービス
- サービスの選択
	- com.amazonaws.ap-northeast-1.ecr.dkr
	- com.amazonaws.ap-northeast-1.ecr.api
	- それぞれで作る
	<img width="2586" alt="image.png (193.0 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/17/78280/118e3b08-99f4-4580-842f-3b9b0c8c283a.png">

- VPCを選択

- サブネットを選択
    - privateサブネットを紐付け
    - 今回はECRからECSへのimageのpullの経路をNATからVPCエンドポイントに切り替えるためECSが配置されるprivateサブネットを紐付けて、そこからの通信を受け付けるようにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/7aa06dd7-2540-64b0-6a0e-a67178dff401.png)


- プライベート DNS 名を有効にする

- セキュリティーグループを選択
    - セキュリティーグループを新規作成しておきそれを選択する
        - インバウンドルール
            - ソースにはECSにアタッチしているセキュリティーグループを紐づける
            - ルールはECSからのインバウンド通信（ポート443）を許可するルールを追加
            - この2つを入れることでECSからの通信のみが経由するように限定することができる
        　　<img width="1172" alt="image.png (17.8 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/17/78280/f7935955-781a-4763-9f38-7f0a9458a7fc.png">

        - アウトバウンドルール
            - すべて
            ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/d107df7c-284d-d366-7949-a7187e0a667f.png)

- VPCエンドポイントのアクセス権限について
    - 今回アクセス権限はフルアクセスで許可している。フルアクセスで許可しても、ルートテーブル（ルーティング設定）を設定しないと、VPC内のリソースから他のリソースへのアクセスはinternet gateway経由になってしまうのでルーティング設定もセットでやることに注意
 
>フルアクセス - VPC 内のすべてのユーザーまたはサービスが、どの AWS アカウントの認証情報を使用しても、この AWS のサービスのすべてのリソースへアクセスすることが可能です。アクセスを可能にするためには、すべてのポリシー (IAM ユーザーポリシー、VPC エンドポイントポリシー、AWS のサービス特有のポリシー (例: Amazon S3 バケットポリシー、S3 ACL ポリシー など)) が、必要な権限を付与する必要があります。


## VPCエンドポイントの作成（S3へのアクセスのためのgatewayタイプ）

### create endpoint
- AWSサービスのリストからcom.amazonaws.region.s3を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/797fedb5-4c51-30d8-4880-0ca20db79efd.png)
- ECSクラスタが属するVPCを選択
- プライベートサブネットに紐づくルートテーブルを全て選択してcreate
    - 今回はprivateサブネットに配置されているECSコンテナからS3へのアクセスをVPCエンドポイント経由で行いたいので、ルーティング設定は全てのプライベートサブネットに紐づけた。

- ポリシーはフルアクセス

### VPCエンドポイント(gatewayタイプ)作成後
- サブネットのルートテーブルを見てみると、S3 Gatewayのエンドポイントが一番下に追加されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2367608/472a0c52-0c00-b70f-6122-6a168aced1f6.png)

- これら設定によりECSからS3へのアクセスはVPCエンドポイントを通るようになる


## まとめ
- VPCエンドポイント経由でECRのイメージをプルしてくることができるので、費用が安くなった。
- ECSからS3・ECRへのアクセス以外は、NatGateway経由のまま。


本当にVPCエンドポイント経由で通信しているかはAWS CloudTrail等で確認してみてください。