AWS Fargateで動かしてるコンテナの中に入る方法

## はじめに

AWS Fargateの場合、トラブルがあった時に動かしてるコンテナの中に入ってなくて調査できないのが不便なのでコンテナに入る方法を調査した。

* 現時点(2020年9月)でAWS Fargateの独自機能でコンテナの中に入る方法はない
* コンテナにsshdをインストールする方法とssm-agentをインストールする方法がある

ssm-agentを使うとSSHのポートの開放やSSHする公開鍵の管理などをしなくて済むためssm-agentを使う方法で行った。

### コンテナにsshdをインストールする方法

1. SSHのポートを空けておく
1. コンテナの中の~/.ssh/authorzied_keysにsshするユーザーの公開鍵を追加しておく
1. コンテナの中にsshdをインストールしておいて、コンテナ起動時にsshdを立ち上げておく

#### メリット

* セッションマネージャーを使わないため、セッションマネージャーを使う料金はかからない

#### デメリット　

* SSHのポートを開放する必要がある
* SSHするユーザーの公開鍵を管理する必要がある 

### コンテナにssm-agentをインストールする方法

1. コンテナ起動時にハイブリッドアクティベーションでアクティベーションを作成して登録してssm-agentを起動
2. セッションマネージャーを使ってコンテナの中に入る

#### メリット

セッションマネージャーを使うので以下のメリットがある。

* SSHのポートを開放する必要がなくなる
* SSHするユーザーの公開鍵を管理する必要がなくなる　

#### デメリット

* 通常のAmazon EC2に対してセッションマネージャーを使う料金はかからないが、ハイブリッドアクティベーションを使って登録することから、オンプレミスインスタンス管理の扱いになるため利用料金がかかる

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/activations.html
> Amazon EC2 インスタンスへのアクセスは、追加料金なしでご利用いただけます。

## ソースコード

[https://github.com/f96q/fargate-ssm-sample](https://github.com/f96q/fargate-ssm-sample)

DockerfileとAWS Fargateで動かす環境を作るためのTerraform含む

## Dockerfile

Alpineで使う場合はssm-agentのパッケージがないのでソースから持ってきてビルドして設置する必要がある。

他のLinuxディストーションの場合はインストールできるssm-agentのパッケージを提供してる場合があるので、その場合はそのパッケージをインストールするだけで済む。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-manual-agent-install.html

```Dockerfile
ARG GOLANG_TAG=1.14.4-alpine3.12
ARG ALPINE_TAG=3.12

# ssm agenet builder
FROM golang:$GOLANG_TAG as ssm-agent-builder

ARG SSM_AGENT_VERSION=2.3.1205.0

RUN apk add --no-cache \
         'make~=4.3-r0' \
         'git~=2.26.2-r0' \
         'gcc~=9.3.0-r2' \
         'libc-dev~=0.7.2-r3' \
         'bash~=5.0.17-r0'

RUN wget -q https://github.com/aws/amazon-ssm-agent/archive/${SSM_AGENT_VERSION}.tar.gz && \
    mkdir -p /go/src/github.com && \
    tar xzf ${SSM_AGENT_VERSION}.tar.gz && \
    mv amazon-ssm-agent-${SSM_AGENT_VERSION} /go/src/github.com/amazon-ssm-agent && \
    echo ${SSM_AGENT_VERSION} > /go/src/github.com/amazon-ssm-agent/VERSION

WORKDIR /go/src/github.com/amazon-ssm-agent

RUN gofmt -w agent && make checkstyle || ./Tools/bin/goimports -w agent && \
    make build-linux

# merge image
FROM alpine:$ALPINE_TAG

RUN apk add --no-cache \
      'jq~=1' \
      'aws-cli~=1.18.55-r0' \
      'sudo~=1.9.0-r0'

RUN adduser -D ssm-user && \
    echo "Set disable_coredump false" >> /etc/sudo.conf && \
    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

COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]

CMD ["amazon-ssm-agent"]
```

```sh:docker-entrypoint.sh
#!/bin/sh

set -e


AWS_REGION=${AWS_REGION:-}
SSM_ACTIVATION=$(aws ssm create-activation --default-instance-name "fargate-ssm" --iam-role "service-role/AmazonEC2RunCommandRoleForManagedInstances" --registration-limit 1 --region $AWS_REGION)

export SSM_ACTIVATION_CODE=$(echo $SSM_ACTIVATION | jq -r .ActivationCode)
export SSM_ACTIVATION_ID=$(echo $SSM_ACTIVATION | jq -r .ActivationId)

amazon-ssm-agent -register -code $SSM_ACTIVATION_CODE -id $SSM_ACTIVATION_ID -region $AWS_REGION

exec "$@"
```

## 使い終わったら手動で行わないといけないこと

https://aws.amazon.com/jp/systems-manager/pricing/#On-Premises_Instance_Management

動かしてる時間課金されてしまうため以下を行う。

* ハイブリッドアクティベーションの削除
* 登録したインスタンスを外す