Amazon ECS CLI v2を試せなかった話

# はじめに
AWS re:Invent 2019で発表🎊された中でビビっと⚡️✨きた新機能を試そう❗️💪と思っていた、のですが…結果的に刺さる~~楽に試せる~~発表が🤔という感じでした…(会社でなら試しやすいけど個人だとちょっと面倒なのが多いイメージ)

re:Invent 2019で発表まとめブログ： [12/1](https://aws.amazon.com/jp/blogs/news/reinvnet-2019-12-1-summary/) [12/2](https://aws.amazon.com/jp/blogs/news/reinvnet-2019-12-2-summary/) [12/3](https://aws.amazon.com/jp/blogs/news/reinvnet-2019-12-3-summary/) [12/4](https://aws.amazon.com/jp/blogs/news/reinvnet-2019-12-4-summary/) [12/5](https://aws.amazon.com/jp/blogs/news/reinvnet-2019-12-5-summary/)

そんなアドベントカレンダーのネタを探して記事を彷徨っている中😔見つけたのがこの記事🔍

> Announcing the Amazon ECS CLI v2
> https://aws.amazon.com/jp/blogs/containers/announcing-the-amazon-ecs-cli-v2/

斜め読みした限りスゴそう🚀なのに、絶妙にスルー🙄されている感があって可哀そうなのでこれを試してみたいと思います💪

(絵文字の使用はPS4のゲームデスストランディングで届くメール調です)



# 概要を読む

(わたしの雑な和訳)

ECS CLIは2015年にリリースされてECSやECRの管理を簡単にすることができて便利だったよ。でも使っている人の要望を聞いてみると、ECSの低レイヤなんかを触る機能は要らないからもっとアプリ開発に焦点を当てた機能が欲しいってことだった。なんでECS CLI v2の理念として以下の4つを定めたよ

1. デフォルトでモダンアプリを作れるように
1. ユーザはインフラを考えるのではなくアーキテクチャの観点で考える
1. ECS CLIでの操作はデバッグやトラブルシューティングの助けとなるように
1. アプリの継続的デプロイができるように

ということで結構v1と違って、機能が"Opinionated"だよ。細かくいじれない代わりにイイ感で自動でやってあげるよ。あとアプリのライフサイクル全体をカバーするためにツールの守備広げますよー。

----

ふむふむ📕👀良いと思います❗️👍✨APIレベルの低レイヤの操作はAWS CLIでやればいいっしょ👊最近の開発ツールは"Opinionated"(日本語のイイ訳が思いつかない…直訳だとネガティブすぎるのでそのまま)なツールが人気ですね😸

# 試してみる

## CLIインストール

今の段階ではpreviewなのでバイナリ配布やHomebrewとかでインストールするのではなく、ソースからビルドしないといけないみたいです😅Gitでcloneします👥

```console
$ git clone https://github.com/aws/amazon-ecs-cli-v2

Cloning into 'amazon-ecs-cli-v2'...
<略>

$ cd amazon-ecs-cli-v2
```

イマドキはコンパイルもDockerで🐳準備不要だしローカルも汚れないし非常に良い世の中になりました😊Dockerインストールしていない方はインストールしましょう🛠

```console
$ docker build -t aws/amazon-ecs-cli-v2 . &&\
docker create -ti --name amazon-ecs-cli-v2-builder aws/amazon-ecs-cli-v2 &&\
docker cp amazon-ecs-cli-v2-builder:/aws-amazon-ecs-cli-v2/bin/local/ .
```

1. Dockerのイメージビルド
1. ビルドしたイメージからコンテナ作成
1. 作成コンテナからローカルにコンパイルされたバイナリコピー

という流れですね。ベースイメージのpull、コンパイルコンパイル結構時間かかります💦私の環境(MacBook Air 13' 2019、マンション共有回線)で6分ちょっとかかりました⏳

あと[`docker create`](https://docs.docker.com/engine/reference/commandline/create/#extended-description)コマンドって初めて見ました👀💦`docker run`と違ってコンテナをStop状態のまま作成するようですね。まさにこういうコンテナをコンパイル環境に使う場合には覚えておきたいコマンドですね💡

コンパイルが終わると`amazon-ecs-cli-v2/local`にバイナリが出来上がっています🎁

```console
$ cd local

$ ls -lah
total 144752
drwxr-xr-x   5 rinfield  staff   160B 12  7 11:42 .
drwxr-xr-x  28 rinfield  staff   896B 12  7 11:42 ..
-rwxr-xr-x   1 rinfield  staff    25M 12  7 11:40 ecs-preview
-rwxr-xr-x   1 rinfield  staff    25M 12  7 11:40 ecs-preview-amd64
-rwxr-xr-x   1 rinfield  staff    21M 12  7 11:41 ecs-preview.exe

$ file *
ecs-preview:       Mach-O 64-bit executable x86_64
ecs-preview-amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=Z3vZHn9Pj4OxFER6fLQa/DIdYnL8-CKUUPPhxJGBP/G32gLyDw6KnHuRLPt0qU/KsHT9s2VybijDaDnBYN-, not stripped
ecs-preview.exe:   PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows
```

おぉーさすがGo言語実装だけあって各プラットフォームへのクロスコンパイルされていますね👍✨

|ファイル|プラットフォーム|
|---|---|
|`ecs-preview`|macOS用|
|`ecs-preview-amd64`|Linux用|
|`ecs-preview.exe`|Windows用|

記事では`ecs-preview-amd64`のコマンドの例が載っていますがプラットフォームに合わせて読み替えましょう。

あと実行権限付与する記述が記事にありますが手元の環境ではすでに実行権限ついてますね

また記事では`/usr/local/bin/ecs`としてコピーしてますが、ディレクトリが汚れるのが嫌なので`ecs`にリネームしてPATH通します

```console
$ mv ecs-preview ecs

$ PATH="$PATH:$(pwd)"
```

実行できるか試してみましょう

```console
$ ecs --version
2019/12/07 12:18:26 ERROR: unable to resolve endpoint for service "ssm", region "", err: UnknownEndpointError: could not resolve endpoint
	partition: "aws", service: "ssm", region: "", known: [me-south-1 ap-northeast-1 ap-northeast-2 eu-north-1 eu-west-3 ap-southeast-1 eu-central-1 us-west-1 us-west-2 ap-south-1 ap-southeast-2 us-east-1 us-east-2 sa-east-1 ap-east-1 ca-central-1 eu-west-1 eu-west-2]
<略>
```

ありゃ。なんかエラー出ちゃいました。最近Mac買い換えてawscliの設定もしてないせいかな？(完全に当てずっぽう)

```console
$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

$ ecs --version
ecs-preview version: ca4f3e4
```

当てずっぽうだったけど直った！ECS CLI v2使うときはAWS CLIのプロファイル設定しましょう


## アプリ準備

ようやく本題のECS CLI v2使う…前に継続デプロイするための[サンプルアプリ](https://github.com/nathanpeck/archer-nyan-cat)をGithubでforkしましょう。

ちなみに試した時はFork数がゼロでした…ということは世界で初めて試した人間！？

```
$ cd ${良き場所}

$ git clone https://github.com/${あなたのID}/archer-nyan-cat.git

$ cd archer-nyan-cat
```

## initしてみる

`ecs init`叩いてみます
<img width="1319" alt="スクリーンショット 2019-12-07 13.16.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585/b965ad28-2a81-03d8-f400-cf49dca10a02.png">

> ? Which type of infrastructure pattern best represents your application?  [Use arrows to move, type to filter, ? for more help]

と聞かれましたが、現状は"Load Balanced Web App"しか選択できないようです。

入力待ちになりますが、ここまででCloudTrailを見て何が起こったか見てみましょう

- SSM Parameter Storeに2つパラメータが作成された
  - `/ecs-cli-v2/nyan-cat-project`
  - `/ecs-cli-v2/nyan-cat-project/applications/nyan-cat`
- CloudFormation Stack `nyan-cat-project-infrastructure-roles` が作成された
  - 管理用のロールが作成されたみたい
  - `AdministrationRole`
  - `ExecutionRole`
- CloudFormation StackSet `nyan-cat-project-infrastructure`が作成された
  - 以下のリソースを作成するテンプレート
      - KMS Key
      - S3 Bucket
      - ECRリポジトリ
  - Stack Instanceはナシ
      - ということはリソースは何も作られていない
      - > ✔ Created ECR repositories for application nyan-cat.
          - ってログ出てるのにな🤔

> ? Would you like to deploy a test environment? [? for help] (y/N)

と聞かれているので`y`と答えてみましょう

<img width="1310" alt="スクリーンショット 2019-12-07 14.01.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585/545f806c-26c9-ecb9-43b8-69535357726c.png">

うわっエラー出た…😱


## エラーを調べる…そしてYak Shavingへ

この処理はCloudFormationでやっているみたい…ログを確認

<img width="1036" alt="スクリーンショット 2019-12-07 14.07.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585/121d0497-0abe-4a22-724d-f454a6a13bd8.png">


AZの`ap-northeast-1a`がダメって怒られている…
えーと`ap-northeast-1a`の実体は…

```console
$ aws ec2 describe-availability-zones | jq '.AvailabilityZones[] | select(.ZoneName == "ap-northeast-1a") | .ZoneId'

"apne1-az3"
```

[`apne1-az3`でググってみる](https://www.google.com/search?q=apne1-az3)と…あーやっぱり古いAZでもうSubnetも作れないみたい…このアカウント作ったのかなーり前だからな…最近作ったアカウントであればこんなエラーにはならないはず…

そもそもSubnetの作成もできない`apne1-az3`のを返してくるCloudFormationテンプレートの`Fn::GetAZs`関数どうなん？と思って調べたら

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getavailabilityzones.html
> **重要**  
> EC2-Classic プラットフォームでは、Fn::GetAZs 関数はリージョンのすべてのアベイラビリティーゾーンを返します。EC2-VPC プラットフォームでは、Fn::GetAZs 関数はデフォルトのサブネットがあるアベイラビリティーゾーンのみを返します。デフォルトのサブネットがあるアベイラビリティーゾーンがない場合は、すべてのアベイラビリティーゾーンを返します。

ちゃんと書いてありました。なんとかできそう？

```console
$ aws ec2 describe-account-attributes | jq '.AccountAttributes[] | select(.AttributeName == "supported-platforms") | .AttributeValues[].AttributeValue'
"EC2"
"VPC"
```

アタシのアカウントはEC2-Classic環境でデフォルトVPC作んなきゃいけないのね。よっしゃ作ったろ

```
$ aws ec2 create-default-vpc

An error occurred (OperationNotPermitted) when calling the CreateDefaultVpc operation: Accounts on the EC2-Classic platform cannot create a default VPC.
```

なんだよもぅー！どうすりゃいいんだよ

EC2-Classic環境でデフォルトVPCを作成する
https://qiita.com/speg03/items/c82fd3247ebb4243b9d6

> EC2-Classicが利用できる環境ではデフォルトVPCが存在しません。そのような環境でデフォルトVPCを作成するには、AWSサポートへの依頼が必要になります。

# おわり

もうダメだー‼️💥💥💥
全然試せませんでしたがもう燃えつきました🔥🔥🔥🔥
(後半絵文字も無くなってるし…)

当初の予定と異なって古いAWSアカウントでハマった記事になってしまいました。ごめんなさい🙇‍♂️
古いAWSアカウントを嫌いになってもECS CLI v2は嫌いにならないでください

https://github.com/aws/containers-roadmap/issues/513
https://github.com/aws/amazon-ecs-cli-v2


この記事を書くにおいて以下の学びがありました

- ECS CLI v2はECS周りだけじゃなくてCloudFormationを使っていろんなリソースを作ってくれる(っぽい)
- 古いAWSアカウントを久しぶりに引っ張り出して最新のことをやろうとするのはやめよう


リージョン変えるなり、新しいAWSアカウント作るなりでまた今度トライするかもしれません…

ありがとうございました

# 追記
記事を公開したら[ECS CLI v2のコミッター](https://github.com/aws/amazon-ecs-cli-v2/graphs/contributors)のDavidさんからTwitterでメッセージもらえました✨

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ごめん！ap-northeast-1a問題はbugそうです。<br><br>調べています。<br><br>このCLIは本当に新しいですけどごめんなさい🙇‍♂️</p>&mdash; David Killmon 🪁 (@kohidave) <a href="https://twitter.com/kohidave/status/1204188355090505728?ref_src=twsrc%5Etfw">December 9, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">古いaccountがあったら、CLIを使えることはいいと思います。</p>&mdash; David Killmon 🪁 (@kohidave) <a href="https://twitter.com/kohidave/status/1204189719032033280?ref_src=twsrc%5Etfw">December 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Of course! We&#39;re definitely interested in any troubles our customers face - even if it&#39;s a corner case 😁 <br><br>I&#39;ll let you know when we fix this! Keep on blogging in the mean time, and sorry my Japanese is pretty rusty haha.</p>&mdash; David Killmon 🪁 (@kohidave) <a href="https://twitter.com/kohidave/status/1204274064631586817?ref_src=twsrc%5Etfw">December 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

全然だいじょうぶだよ！開発頑張って‼🚀