[ECS]プライベートサブネットでパブリックレジストリのイメージを利用してタスクを起動する

# はじめに
閲覧ありがとうございます、NTTデータ先端技術の@S-takahashi1129です。

ECSでのサービス作成の際、インターネットを経由せずにパブリックレジストリのコンテナイメージを利用する手順が思ったより手こずってしまったので自分なりに手順をまとめます。

今回の構成イメージは以下です。パブリックレジストリはVPCエンドポイントによるアクセスが現状では非対応です。
![VPCEを経由したパブリックレジストリ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/d29105ab-5e96-1d6e-a3d4-d33ad718c7df.png)


# VPCエンドポイントの作成
今回はプライベートサブネットからインターネットを経由せずECSを利用するので、VPCエンドポイントが必要です。

今回はFargateでホストされるECSタスクを利用するので、以下4つのVPCエンドポイントを作成します。
EC2でホストされる場合は必要なエンドポイントが違うようなので注意してください。

|  VPCエンドポイント  | 用途  |
| --- | ---|
| com.amazonaws.region.ecr.dkr　　|  Dockerレジストリに利用される（pushやpull等）|
| com.amazonaws.region.ecr.api　　|  ECRのapi呼び出しに利用される|
| com.amazonaws.region.s3     　　|  S3へのアクセスに利用される(イメージの保存先)  |
| com.amazonaws.region.logs　　   |  CloudWatchへログを送信する場合に利用される  |

Gateway型のS3エンドポイントを利用する場合はルートテーブルの設定をしてください。

VPCエンドポイントにアタッチするセキュリティグループではプライベートサブネットからの**ポート443**のインバウンドトラフィックを許可してください。

また、コンテナのイメージはS3バケット
`arn:aws:s3:::prod-<region>-starport-layer-bucket/*`
に格納されるため、こちらへのアクセスが拒否されていないVPCエンドポイントポリシーであることも確認してください。

作成したVPCエンドポイントは以下の通りです。

![ＶＰＣＥ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/f5df032d-ac84-b35b-3504-85a884533913.png)





# Pull Through cache(プルスルーキャッシュ)の設定
プルスルーキャッシュはパブリックレジストリのリポジトリをプライベートレジストリにキャッシュすることができるECRの機能です。

今回はプライベートサブネットのECSを使うため、プルスルーキャッシュによってプライベートレジストリにキャッシュされたパブリックレジストリのリポジトリをVPCエンドポイントで参照します。

なお、パブリックレジストリへのVPCエンドポイントによるアクセスは現在サポートされておらず、インターネットを経由しないアクセスはできないようです。

#### プルスルーキャッシュルールの追加
ECRのコンソールページへアクセスし、「Private registry」の「Settings」から
「Pull through cache」を選択し、ルールを追加します。

![プルスルーキャッシュルール追加.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/3c7bb36f-43a7-768d-b2e7-df6654b46d3e.png)

まず、使いたいイメージがあるレジストリを指定します。
今回はdocker公式のDocker Hubを指定します。

![ptc0.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/339e4331-07eb-1add-e27a-23924fc9af37.png)

Dockerが提供しているレジストリなど、シークレットの設定などが欲しいものを指定した場合は追加の設定ページが表示されます。

![ptc1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/9b745a77-e6e7-f429-be95-c56c51c35905.png)


次はリポジトリプレフィックスの指定です。任意の名前で構いませんが、今回はデフォルト設定でいきます。

![ptc2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/fc9cfc18-2cae-57f2-448d-8929e7f99b04.png)

最後にレビューで設定を確認し、問題なければ作成します。

![ptc3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/65d4af4f-125d-57a6-359c-adcc3e3492c5.png)


これにてプルスルーキャッシュの設定は完了です。

# ECS タスク定義の作成
ECSのコンソールページにアクセスし、「タスク定義」から「新しいタスク定義の作成」を選択肢、タスク定義を作成します。

![タスク1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/f2a31399-1a33-126f-fbe4-c68801fe20c5.png)

#### インフラストラクチャの要件
設定は任意の値を入力してください。
今回はFargateを使用するので、起動タイプをFargateにしています。

![タスク2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/64ef0d4d-a05b-2810-b761-4e672f943d91.png)

#### コンテナ
コンテナの詳細を指定する際、「イメージURI」を先ほど作成したプルスルーキャッシュを利用した形に書き換える必要があります。

![タスク3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/09aee577-cc81-3e66-5a04-323c07b41f4e.png)

まず、ECRのパブリックギャラリーにアクセスし、利用したいコンテナイメージのページを開きます。
**※パブリックギャラリーはECRのコンソールページからもアクセス可能です**

https://gallery.ecr.aws/

今回はhttpdの最新バージョンで作成してみます。
任意のバージョンを選んだら「Copy」を押してURIをコピーします。

![httpdギャラリー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/01abf91e-c88c-11a6-455b-84302322a321.png)

コピーしたパスは以下のようになっています
```
public.ecr.aws/docker/library/httpd:latest
```

このパスの**public.ecr.aws/docker**の部分を以下のように置き換えます
```
<アカウントID>.dkr.ecr.<region>.amazonaws.com/<プルスルーキャッシュのリポジトリプレフィックス>
```
具体的には以下のようなパスになります
```
111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/docker-hub/library/httpd:latest
```
プルスルーキャッシュのリポジトリプレフィックスは先ほど作成したものです。
上記のパスをタスク定義の「イメージURI」に貼り付けます

![タスク5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/eb03ac9f-0ce3-7b7b-d257-8097a518d8f8.png)

他の設定値の設定は任意です。


#### ECSタスク実行ロールへのECR操作権限の付与
ECSタスク実行のためのサービスロールはタスク定義作成時に「新しく作成」を指定（デフォルト）すると自動で**ecsTaskExecutionRole**というサービスロールがECSタスク作成されます。
このロールには**AmazonECSTaskExecutionRolePolicy**というマネージドポリシーがアタッチされています。
このマネージドポリシーにはECRのプライベートレジストリを読み取る権限はついているのですが、プライベートレジストリを作成する権限がついていません。

プルスルーキャッシュはプライベートレジストリにパブリックレジストリのリポジトリのイメージがプライベートリポジトリにコピーされるため、以下のような許可が必要です

| # | ポリシー名 |
|---|---|
|1|ecr:CreatePullThroughCacheRule|
|2|ecr:BatchImportUpstreamImage|
|3|ecr:CreateRepository|

今回はECRのフルアクセス権限を与えておきます。
![policy.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/44191499-0842-bfb3-948f-c4d6b05830d5.png)





# ECSクラスターの作成
ECSのコンソールページから「クラスター」を選択し、「クラスターの作成」を行います。

![cluster1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/551a36ec-3a4a-587c-b244-e0b3099412aa.png)

今回はFargateを利用するので「インフラストラクチャ」ではAWS Fargateを指定しています。

![cluster2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/c6a5c02e-640e-366e-16ec-3551d0b5e8de.png)

なお、クラスター作成の際はCoudFormationによりスタックが作成され、そのスタックによってクラスターが作成されるという処理が行われるので、操作しているユーザの権限にCloudFormationの操作権限が必要となります。




# クラスターのサービス作成
作成されたクラスターを開き、「サービス」タブから「作成」をクリックします

![service1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/21d4cecf-298b-375e-caab-ec4c2b1c63e9.png)


今回は以下のような設定でサービスを作成しました。
#### 環境
![service2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/978b5801-dfed-f3f6-39a0-4308b84e98d1.png)

#### デプロイ設定
![service3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/56db8116-bc1e-b80d-2dea-e210b0abb8f7.png)


#### ネットワーキング設定
![service4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/48e8f2a9-5a4a-acf6-fb3a-3e8236906d08.png)

なお、この時指定するセキュリティグループでは以下を満たすインバウンドルールが必要です。

|  設定項目  | 設定値  |
| --- | ---|
| Type　　|  HTTP|
| Protocol　　|  TCP|
| ポート範囲     　　|  80  |
| ソース　　   |  0.0.0.0/0 |

# サービスの作成を確認
サービスの作成が無事完了しました。

![deploy-done.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528603/c72969e5-bb74-b3b8-ab46-91e5297bf18f.png)

# おわりに
上記手順でパブリックレジストリのリポジトリのイメージをプライベートサブネットから利用することができました。

個人的な一番のつまりポイントはタスク実行ロールにECRの権限を与える必要がある部分でしょうか。

以上、ご参考になれば幸いです。