穴(Fargate)があったら入り(SSHし)たい！

これは[ただの集団 Advent Calendar 2020](https://adventar.org/calendars/5581)の10日目の記事です。

### ある日の公園
息子氏(6)「今日も鬼滅ごっこしよ〜」

友人A「いいよ〜」

友人B「ぼく炭治郎！水の呼吸 壱ノ型 水面斬りっ！」
友人A「雷の呼吸 壱ノ型 霹靂一閃…！」

息子氏「**穴があったら…入りたい！**」

え〜、なんで？(´ºωº｀)
お友達みんなカッコいい技なのに…

※ Google先生に「煉獄杏寿郎 穴があったら入りたい」で聞いてみると大人気のシーンらしい…

### ふむ、穴があったら入りたい
無理やり流行に乗りましたが、**穴(Fargate)があったら入り(SSHし)たい**ですよね。
今日は良い感じのお試しFargate環境を作って、良い感じにSSHします。

とにかく良い感じです。

### まずは穴(Fargate)がないと入れない
作ります。AWS環境をご用意ください。
そして[ハンズオン](https://ecs-for-aws-summit-online.workshop.aws/)します。Fargateがたったかと思います。
AWS Summit 2020用の資料なので消される可能性がありますが、これも**Advent Calendar 2020**用の記事なので許してください。

### Fargateに入るには
「SSHの環境を設定してそこからコンテナに入る」という手があります。
しかし、穴があったら入りたいとはいうものの、極力**穴(SSHポート)は開けたくありません**。
そこで、[セッションマネージャー](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html)を使います。
セッションマネージャーとは**SSMエージェント**を入れた環境に**AWSマネジメントコンソールから**SSHっぽくログインできる代物です。

それでは設定をしていきましょう。

### STEP1 Dockerfileの修正
Dockerfileにssm-agentをインストールする処理を追加します。
今回は上記のハンズオンをベースに作業していますが、適宜使いたい環境にあわせて読み替えてください。
※ sampleがalpineなのでソースからbuildして対応してますが、接続を試すだけならば普通に[ssm-agentがパッケージ提供されているイメージ](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-manual-agent-install.html)で試すことをおすすめします。

```Dockerfile
↓↓↓↓ここを追加
FROM golang:1.12-alpine as ssm-agent-builder
ARG VERSION=2.3.1205.0

RUN set -ex && apk add --no-cache make git gcc libc-dev curl bash && \
    curl -sLO https://github.com/aws/amazon-ssm-agent/archive/${VERSION}.tar.gz && \
    mkdir -p /go/src/github.com && \
    tar xzf ${VERSION}.tar.gz && \
    mv amazon-ssm-agent-${VERSION} /go/src/github.com/amazon-ssm-agent && \
    cd /go/src/github.com/amazon-ssm-agent && \
    echo ${VERSION} > /go/src/github.com/amazon-ssm-agent/VERSION && \
    gofmt -w agent && make checkstyle || ./Tools/bin/goimports -w agent && \
    make build-linux
↑↑↑↑

FROM ruby:2.5.8-alpine

RUN apk --no-cache add --update build-base libffi-dev mariadb-dev mariadb-client tzdata bash && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata && \
    rm -rf /var/cache/apk/*

↓↓↓↓ここも追加（変更箇所がわかりやすいように分けましたが、上のRUNコマンドと適宜マージしてください）
RUN set -ex && apk add --no-cache sudo ca-certificates && \
    adduser -D ssm-user && echo "ssm-user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ssm-agent-users && \
    mkdir -p /etc/amazon/ssm

COPY --from=ssm-agent-builder /go/src/github.com/amazon-ssm-agent/bin/linux_amd64/ /usr/bin
COPY --from=ssm-agent-builder /go/src/github.com/amazon-ssm-agent/bin/amazon-ssm-agent.json.template /etc/amazon/ssm/amazon-ssm-agent.json
COPY --from=ssm-agent-builder /go/src/github.com/amazon-ssm-agent/bin/seelog_unix.xml /etc/amazon/ssm/seelog.xml
↑↑↑↑

WORKDIR /app

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN bundle install

COPY . /app

EXPOSE 80

COPY sql/schema.sql /schema.sql

COPY startup.sh /startup.sh
RUN chmod 744 /startup.sh
CMD ["/startup.sh"]
```

### STEP2 ハイブリッドアクティベーションを作成する
**Fargate**にセッションマネージャーで接続するときは、[AWS Systems Manager ハイブリッドアクティベーション](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/activations.html)という機能を使って行います。
これはオンプレミスのサーバーをSystems Manager管理化におくことのできる機能で、Fargateにも使えます。
通常の**Amazon EC2 インスタンスへのアクセスは、追加料金なしでご利用いただけます**が、ハイブリッドアクティベーションするとお金がかかります。ぐぬぅ。
ターミナルでコマンドを叩いて、

```
aws ssm create-activation \
  --default-instance-name "FargateSSMTest" \
  --description "FargateSSMTest" \
  --iam-role "service-role/AmazonEC2RunCommandRoleForManagedInstances" \
  --registration-limit 5
```

出てきた、**ActivationId**、**ActivationCode**をメモります。

### STEP3 startup.shの修正
```startup.sh
#!/usr/bin/env bash

↓↓↓↓ここを追加
export ACTIVATE_CODE="メモったActivationCode"
export ACTIVATE_ID="メモったActivationId"
amazon-ssm-agent -register -code "${ACTIVATE_CODE}" -id "${ACTIVATE_ID}" -region "us-east-1" -y
nohup amazon-ssm-agent > /dev/null &
↑↑↑↑

mysql -h ${DB_HOST} -u ${DB_USER} -p${DB_PASS} < /schema.sql
bundle exec ruby /app/myapp.rb -o 0.0.0.0 -e production
```

修正したらECRにpushし直します。

### STEP4 ecsTaskExecutionRoleにRoleを追加する
おそらく手順通りやっていれば**ecsTaskExecutionRole**を使っていると思うので、ここにSSM用のポリシーを追加します。
今回はマネジメントコンソールでポチポチします。

AmazonSSMManagedInstanceCore
AmazonSSMAutomationRole
AmazonSSMDirectoryServiceAccess

![スクリーンショット 2020-12-10 11.00.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924321/f7bac3fe-4ba6-6cf7-dc88-fc143dd7b5c1.png)

### 穴に入れるようになった
AWS Systems Managerからセッションマネージャーを選び、セッションを開始するを選択してみましょう。
Fargateと思われる対象がリストアップされると思うので、選択してセッションを開始します。
FargateからRDSにつないでみたり**やりたい放題**できます。やったね。

```
/app $ mysql -h hogehoge.us-east-1.rds.amazonaws.com -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 62
Server version: 5.7.22-log Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| innodb             |
| mysql              |
| performance_schema |
| simplechat         |
| sys                |
+--------------------+
6 rows in set (0.002 sec)

MySQL [(none)]>
```

### 考慮する点
**startup.sh**内でregisterしているので、デプロイするたびにマネージドインスタンスが増えます。
DRAINING時に**deregister-managed-instance**するなりしたほうが良いと思われます。
（手で消してもいいけど）

### 2020年のAWSコンテナの振り返り
2020年は[ECSでCanaryできる](https://aws.amazon.com/jp/about-aws/whats-new/2020/02/amazon-elastic-container-service-support-canary-deployments/)ようになったり、[Fargateプラットフォームバージョン1.4](https://aws.amazon.com/jp/about-aws/whats-new/2020/04/aws-fargate-launches-platform-version-14/)が出たり(**EFSも使えるように**なったよ！)、色々ありました。
[Fargate SpotをCloudFormationで扱える](https://aws.amazon.com/jp/about-aws/whats-new/2020/10/aws-fargate-spot-for-amazon-ecs-now-supported-in-aws-cloudformation/)ようにもなりましたし、ますます楽しくなってきましたね。

来年もAWSのマネージドサービスを使い倒して、楽しいサービスを作っていきましょうね！