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


これはただの集団 Advent Calendar 2020の10日目の記事です。

ある日の公園

息子氏(6)「今日も鬼滅ごっこしよ〜」

友人A「いいよ〜」

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

息子氏「穴があったら…入りたい!

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

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

ふむ、穴があったら入りたい

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

とにかく良い感じです。

まずは穴(Fargate)がないと入れない

作ります。AWS環境をご用意ください。
そしてハンズオンします。Fargateがたったかと思います。
AWS Summit 2020用の資料なので消される可能性がありますが、これもAdvent Calendar 2020用の記事なので許してください。

Fargateに入るには

「SSHの環境を設定してそこからコンテナに入る」という手があります。
しかし、穴があったら入りたいとはいうものの、極力穴(SSHポート)は開けたくありません
そこで、セッションマネージャーを使います。
セッションマネージャーとはSSMエージェントを入れた環境にAWSマネジメントコンソールからSSHっぽくログインできる代物です。

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

STEP1 Dockerfileの修正

Dockerfileにssm-agentをインストールする処理を追加します。
今回は上記のハンズオンをベースに作業していますが、適宜使いたい環境にあわせて読み替えてください。
※ sampleがalpineなのでソースからbuildして対応してますが、接続を試すだけならば普通にssm-agentがパッケージ提供されているイメージで試すことをおすすめします。

↓↓↓↓ここを追加
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 ハイブリッドアクティベーションという機能を使って行います。
これはオンプレミスのサーバーをSystems Manager管理化におくことのできる機能で、Fargateにも使えます。
通常のAmazon EC2 インスタンスへのアクセスは、追加料金なしでご利用いただけますが、ハイブリッドアクティベーションするとお金がかかります。ぐぬぅ。
ターミナルでコマンドを叩いて、

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

出てきた、ActivationIdActivationCodeをメモります。

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

穴に入れるようになった

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できるようになったり、Fargateプラットフォームバージョン1.4が出たり(EFSも使えるようになったよ!)、色々ありました。
Fargate SpotをCloudFormationで扱えるようにもなりましたし、ますます楽しくなってきましたね。

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