AWS
docker
systemd
ECS
AmazonLinux2

ECS上にamazonlinux2環境を構築するときの落とし穴

image.png

はじめに

皆さん、どうもです。k.s.ロジャースのやすもんです。
今回は、先日構築したECSのamazonlinux2環境でコンテナインスタンスがぶっ壊れるという落とし穴にハマったので、現象の共有と回避方法を書いていきたいと思います。

前提

  • AWSのECS上に構築する
  • イメージはamazonlinux2を利用
  • systemctlを利用してサービスの管理をしたい

ECS上に上記の前提でhttpdが動くコンテナを作成

まずはローカルで構築

適当にhttpdが動くdockerを用意します

# amazon linux
FROM amazonlinux:2

# httpd24
RUN yum -y install httpd

RUN systemctl enable httpd.service

ビルドしてコンテナ起動

$ docker build -t test:latest ./

$ docker run --privileged -d -t -p 8080:80 --name testapp test:latest /sbin/init

動作確認
image.png

ECSにデプロイする

ECRを作成して先程作ったイメージをアップロード
image.png

適当にクラスタを作成
image.png

タスク定義を作成
image.png
systemctlを利用するために特権付与し、コマンドで/sbin/initを指定

タスクを起動する
image.png

動作確認
image.png

落とし穴

一見、上記まで実行して「あれ?できてるやん?」て思うかもしれませんが、落とし穴はここからです

ECSを利用している方々は、CIを組んで自動でデプロイできる仕組みを作り、頻繁にイメージとコンテナが更新されるという運用をしている方が大半だと思います。

ということで、次に全く同じ構成で新しいタスク定義を作成して手動で更新してやりましょう
タスクを停止します
image.png

全く同じ内容でタスク定義を作成して、起動させます
image.png

すると、エラーが出てSTOPします
image.png

エラー内容は

CannotStartContainerError: API error (500): cgroups: cannot find cgroup mount destination: unknown 

ほう。。。cgroupをマウントできずにエラーとな。。。

色々調査して以下のような記事を見つけて対応しようと試みるも。。。
http://blog.livedoor.jp/kkss06122015-armadillo/archives/10167213.html

そもそも、ECSのインスタンスの/sys/fs/cgroup配下はからっぽ。。。
記述されているsudo mkdir /sys/fs/cgroup/systemdも権限エラーで実行できず、systemdを無理やり作ってマウントすることも不可でした。

どうやら、特権付与(privileged)をtrueにしてしまうと初回起動はするが、その後コンテナを更新したときにマウントエラーが発生し、以降コンテナが立ち上がらなくなるみたいだ・・・
そして、systemctlを利用するには、特権付与(privileged)をtrueにしないといけない。

特権付与(privileged)をtrueにせず、systemctlを使えようにする方法など色々調査して実験してみたが、この現象を回避する方法はなさそうだった。

回避方法

では、この落とし穴をどう回避するのかというと、docker経験者はピンとくるかもしれませんが、foreground固定します。
また、殆どの場合systemctlを利用したい場合は複数のサービスを起動させたいという理由があると思うので、以下のように記述します。

# amazon linux
FROM amazonlinux:2

# httpd24
RUN yum -y install httpd php-fpm

CMD /bin/bash -c "httpd && php-fpm && tail -f /dev/null"

こうすることで、systemctlを利用しないため、特権付与(privileged)が不要になります。
よって、コンテナを再作成したときのcgroupのマウントエラーが発生しなくなるという感じです。
補足ですが、Dockerfile上でCMDを指定したのでタスク定義で指定していたcommandの/sbin/initは不要になります。

最後に

今回はECS上にamazonlinux2を構築したときにハマった落とし穴を紹介しました。
実際に私自身この落とし穴に2~3日ハマって、systemctlは利用しないという結論に至りました。
もっとスマートな解決法を知っている方はコメント欄にて教えて頂きたいです!

Wantedlyでもブログ投稿してます

Techブログに加えて会社ブログなどもやっているので、気になった方はぜひ覗いてみてください。
https://www.wantedly.com/companies/ks-rogers