Amazon EC2 Container Service 実践入門の前に
この記事はサーバーワークス Advent Calendar 2016の24日目の記事です。
qiita.com
お久しぶりの更新です。お元気でしたか?サーバーワークスの中の人でもOBでもありませんが、個人的に仲良くしていただいているので、参加してみることにしました。中の人達と違って芸人的な要素はないですが、お手柔らかによろしくお願いします。
はじめに
この題材を選んだのは、最近ようやくDockerを使って何かをしてみようかと思い始めたのがきっかけです。ハマるポイントがあればサービスでも使っていきたいなと思っているので、基礎から始めたいと思います。
そして、サーバーワークスさんとは切っても切れないAWS、自分もとある書籍を共著させていただいているAWSということで、「Amazon EC2 Container Service (ECS)」をほぼ初めて触ってみます。
Amazon EC2 Container Service (ECS)
EC2上で利用できるDockerのクラスタリングサービス。ELBやAutoScalingなど他のサービスとの組み合わせで、いい感じにDockerを用いたシステムを構築することができます。
ひとまずGetting Startedをやってみる
リポジトリ設定
何はなくとも、Management ConsoleでECSのメニューを開きましょう。
このような画面が出てきますので、「Get Started」しちゃいましょう。(注)言語は英語になっています
サンプルアプリを使ったECSとイメージ配置用のプライベートリポジトリであるECR(EC2 Contaier Registry)の設置をしてしまうか?と聞かれるので、チェックを入れたまま進みましょう。
リポジトリ名を聞かれるので、好きな名前を入力します。ここでは、namespaceとして「matetsu」を、リポジトリ名としてはひとまず「ecs-sample」として作っています。
設定が完了すると、ECRへのログイン方法やイメージのビルド、からのECRへのイメージの登録方法が表示されます。作業をしているPCでDockerやAWS CLIのインストールや初期設定がしてない場合は、ここでやってしまいましょう(本記事では省略)。AWS CLIは特に設定済みであっても、なるべく常に最新版を利用するようにしておきましょう。
表示された手順に従ってコマンドを実行していきましょう。
イメージの作成とアップロード (ちょっとCLI操作)
(1) docker loginコマンド(認証情報付き)の取得
$ aws ecr get-login --region ap-northeast-1 docker login -u [ユーザ名] -p [めちゃくちゃ長いパスワード] -e none https://[ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com
こんな感じで出力されますので、出力をコピーして実行しましょう。
(2) docker loginコマンドの実行
$ docker login -u [ユーザ名] -p [めちゃくちゃ長いパスワード] -e none https://[ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com Login Succeeded
「Login Succeeded」と出力されればログイン成功です。
(3) Dockerfileからイメージを作成
超簡易的だけど、Dockerfileはこんな感じ。
FROM amazonlinux:latest RUN yum update -y && \ yum install nginx -y && \ date +%s > /usr/share/nginx/html/index.html && \ yum clean all && \ rm -rf /var/cache/yum EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
これを使ってイメージ作成。
$ docker build -t matetsu/ecs-sample . Sending build context to Docker daemon 6.144 kB Step 1 : FROM amazonlinux:latest latest: Pulling from library/amazonlinux 8e3fa21c4cc4: Pull complete Digest: sha256:f1d4ae3f7261a72e98c6ebefe9985cf10a0ea5bd762585a43e0700ed99863807 Status: Downloaded newer image for amazonlinux:latest ---> 5b52b314511a Step 2 : RUN yum update -y && yum install nginx -y && date +%s > /usr/share/nginx/html/index.html && yum clean all && rm -rf /var/cache/yum ---> Running in b889b04f755b (yum途中経過省略) ---> bad3749e433c Removing intermediate container b889b04f755b Step 3 : EXPOSE 80 ---> Running in a6ee101a6b56 ---> 44a602686c42 Removing intermediate container a6ee101a6b56 Step 4 : CMD nginx -g daemon off; ---> Running in 7e740836ca4e ---> 8c9087605ba1 Removing intermediate container 7e740836ca4e Successfully built 8c9087605ba1 $ docker images [~/works/.../ecs/test1] REPOSITORY TAG IMAGE ID CREATED SIZE matetsu/ecs-sample latest 8c9087605ba1 About a minute ago 385.1 MB amazonlinux latest 5b52b314511a 4 weeks ago 292.3 MB
(4) イメージのタグ付け
$ docker tag matetsu/ecs-sample:latest [ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/matetsu/ecs-sample:latest
(5) イメージをリポジトリへpush
$ docker push [ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/matetsu/ecs-sample:latest
ECSに関連する項目の設定
再びGUIでの操作に戻ってきました。次はTask Definitionの設定です。
「Advanced Option」なるものもあるようですが、今回はすべてデフォルトで行ってみようと思います(ここで設定しているのはDocker Composeのcompoe.ymlで定義しているものと同じような感じなんですかね)。次はServiceの設定です。
基本はデフォルトですが、ELBは使っておきたいので「No ELB」から「sample-app:80」に変更しておきます。次はクラスタの設定です。
基本デフォルトで、コンテナインスタンス(Docker Host)用のRoleは新しく作成することにしています。これで設定は終わりで、後は設置項目の確認とLaunch待ちです。
ECSとEC2周りのリソースが出来上がるとこんな感じになります。
出来上がったリソースなどの確認
サービスの確認
もろもろのリソース作成が完了下画面に、「View Service」なんてボタンがあるわけですので、早速確認してみましょう。
Serviceの詳細ページが表示され、Taskが実行中であることが確認できます。
実際にECSで稼働しているwebページにアクセスしてみる
かんたんに確認するために、起動されたELBのDNS名にアクセスしてみましょう。
イメージを作成したときのdate +%sの実行結果であろう値が確認できました。
Getting Startedを使ったからナビがあってそれに従えば必要なものがすべて準備されたのでよかったけど、ナビがないとなると結構大変な作業ですね、これ。。。
rolling updateをしてみる
ただ動かすだけだと何もしていないことになるので、まずはrolling updateを試してみましょう。
rolling updateをする場合は、ServiceのDeployment OptionにあるminimumHealthyPercentとmaximumPercentが肝になるようです。 (参照: AWS Black Belt Online Seminar 2016 Amazon EC2 Container Service /
Amazon ECS launches new deployment capabilities; CloudWatch metrics; Singapore and Frankfurt regions | AWS Compute Blog )
- min:50% / max: 100%
- リソースを効率的に使いながら、まずはTaskをDesiredの半分に減らして新規TaskをDesiredの半分数追加し、残りの半分を入れ替える
- min: 100% / max: 200%
- Desiredと同量のTaskを一気に追加し、倍量になったところで古い方を一気に落とす
ひとまず、1つしかTaskを動かしていないので、後者の富豪型(現状の設定もそれ)でやってみることにする
Docket Imageの更新
更新されたことがわかるようにイメージをこのようにする。
FROM matetsu/ecs-sample:latest RUN yum update -y && \ yum install nginx -y && \ date +%s > /usr/share/nginx/html/index.html && \ echo " updated" >> /usr/share/nginx/html/index.html && \ yum clean all && \ rm -rf /var/cache/yum EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
timestampが変更になるのと、「 updated」をいう文言を追加している。
$ docker build -t matetsu/ecs-sample:0.2.0 . (略)
新イメージができたので、先程のようにECRにpushする。
$ docker tag matetsu/ecs-sample:0.2.0 [ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/matetsu/ecs-sample:0.2.0 [~/works/.../ecs/test1] $ docker push [ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/matetsu/ecs-sample:0.2.0
Task Definitionの新revisionの追加
Task Definisionに新しいRevisionを追加することでrolling updateを実行することができる。が、Container Instanceが1台のままだとポートが衝突してしまうためにコンテナを起動できない。
まずはInstanceのDesired Countを2にしておく。
このあとでTask DefinitionのRevision追加する。対象のTask Definitionを選択して「Create new revision」。
Containerの部分のリンクをクリックすると、コンテナイメージの指定などを変更できる。
イメージのタグを変更し、revisionの変わったTask Definitionを作成する。
Serviceの更新
追加したTask DefinitionのRevisionを適用するために、Serviceの更新を行います。
Task Definitionを「console-sample-app-static:[最新のrevision]」(色々と試行錯誤で作り直したので2ではない)に変更して適用します。Min/Maxは富豪型にするため、変更していません。
これで、しばらくまっていると、新旧両方へのアクセスができる状態になり、更に待つと古い方は表示されなくなります。この間にサービスダウンは発生しないので、実際のサービスに適用するときもうれしいですね。
今回は状況ややっていることを確認しながらの実施だったので手動で行いましたが、手動での適用は事故を起こしたり時間がかかってしまうので、実際に運用する場合はコマンドラインやスクリプトなどを用いて事故が起こらないようにする必要があるでしょうね、
最後に
まだまだほんの初歩的な使い方をしてみただけで全然実践的な内容になっていませんが、まずは触ってみることでDockerイメージさえ整えば何かしらサービスにおm利用できそうなイメージが湧いてきました。もう少し深く使ってみて、続編がかけるようにしたいと思います。ECSについてはriywoさんのBlackBeltのスライド、Dockerについては前佛さんのスライドを見てもっと勉強します。
P.S. 反省点
ほとんどDockerを触ってこなかったのでここまでやるだけでも結構大変だったのですが、初心者の割にDockerの基本的な部分をすっ飛ばして書いてしまったのは反省してます。また、基本的にはGetting Startedやっただけで、おまけ的にrolling updateを付け足した感じになってしまったのも、コンテンツとしてはちょっと物足りな鋳物になってしまったと思っています
ただ、明日の最終日は最近話題のkokexaさんが鉄板ネタで攻めてきてくださるので、素敵な締めに期待したいと思います。