kzk-casino.com

一人前のITエンジニアを目指して

packerで作成したAMIのIDをboto3で自動取得する

f:id:kzk_casino:20161127184527p:plain

packerを使用すればAWSやDigitalOcean上にローカルからイメージを作成することができます。

www.packer.io

packer自体の使用方法は割愛しますが、例えばAWSに対してAMIを作成する際に、下記のように標準出力に出力されます。

$ packer build \
> -varaws_access_key=XXXXXXXXXXXXXXXXXXXXX' \
> -var ‘aws_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
> example.json
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name...
==> amazon-ebs: Inspecting the source AMI...
==> amazon-ebs: Launching a source AWS instance...
    amazon-ebs: Instance ID: i-0ea94a0f2372a0227
==> amazon-ebs: Waiting for instance (i-0ea94a0f2372a0227) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Provisioning with shell script: /var/folders/8r/5hc93gp51x1ghs9zpt8yysc930p1j4/T/packer-shell167406152
    amazon-ebs: Ign http://ap-northeast-1.ec2.archive.ubuntu.com trusty InRelease
    amazon-ebs: Get:1 http://ap-northeast-1.ec2.archive.ubuntu.com trusty-updates InRelease [65.9 kB]
  (略)
==> amazon-ebs: Stopping the source instance...
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: packer-example 1480239268
    amazon-ebs: AMI: ami-4a3e882b
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
Build 'amazon-ebs' finished.

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:

ap-northeast-1: ami-4a3e882b

また、packerをpythonでWrapして実行できるようなライブラリも公開されています。

GitHub - nir0s/python-packer: A Packer interface for Python


これらのツールを用いていろいろ試していましたが、一つ問題があって、

「最終的に作成されたAMI-IDが取得できないからその後の処理を自動化できない!」

という悩みがありました。


そこで、せっかくpythonでpackerを実行できるライブラリがあるので、pythonAWS SDKであるboto3を使って

AMI-IDを自動取得できるようにしました。


GitHub - kzk-maeda/packer-get-ami-id: To get AMI-ID from packer build result

import packer_get_id
import boto3

# Set Pacer File
packerfile = 'packer_file/example.json'

# Set Credentials
vars = {"aws_access_key": "XXXXXXXXXXXXXXXXXXXX",
        "aws_secret_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"}

# packer Build
p = packer_get_id.Packer(packerfile, vars=vars)
p.build(parallel=False, debug=False, force=False, machine_readable=False)

# Get Image Info via AWS API
client = boto3.client('ec2')
response = client.describe_images(Owners=['self'])

# Get Image Number
num = len(response['Images'])

# Set List
date = []
for image in response['Images']:
    date.append(image['CreationDate'])

# Get Max Value of Date
latest_date = max(date)

# Get Latest Image ID
for image in response['Images']:
    if image['CreationDate'] == latest_date:
        latest_image_id = image['ImageId']

print(latest_image_id)


・・自動取得といえば聞こえはいいですが、要するにpacker build実行後に最新のAMI-IDを取得しているだけです。

より確実にpackerによって作成されたAMI-IDを取得できるようにするには、AMIの名前でFIlterかけたり、Tagを使って管理するといいと思います。


とりあえず現時点でもメモ程度に。

Webサーバのアクセスログ監視で使えるテクニック

Webサーバのアクセスログは、障害時に情報を得る重要なヒントとなります。

ここでは、Nginxで稼働しているWebサーバに対して、アクセスログを監視するテクニックについて記載します。

環境準備

Webサーバ

まず、Webサーバを用意します。

今回はAWS上にAmazon Linuxで立てたインスタンスにnginxをインストールすることで簡易Webサーバを構築しました。

また、Grobal IPを割り当てて、インターネットからアクセスできるようにしました。

アクセスノード

アクセスログの監視なので、複数のIPからたくさんのWebアクセスをさせる必要があります。

そのためのアクセスノードとしてGCEのインスタンスを3つ立ち上げ、それぞれに下のようなスクリプトを配置しました。

スクリプト名:curl.sh

#!/bin/bash

while :
  do
    curl <WebサーバのGIP>
    sleep <N>s
  done
$ chmod 755 curl.sh

ここで、にはAWSに構築したNginxサーバのGlobal IPを記載し、には1~9くらいで適当な数字を入れます。
3つのインスタンスに異なるNを設定することで、各インスタンスからのアクセス数を変更させることができます。

適当に時間がたったらNの値を変えてみたりしてもいいと思います。

ログの出力

まず、Webサーバで下記のコマンドを実行して、アクセスログのリアルタイムモニタリングを実施します。

$ sudo tail -f /var/log/nginx/access.log

次にアクセスノード×3に配置したスクリプトを実行します。また、自分もブラウザからWebサーバにアクセスしてもいいかもしれません。

./curl.sh

すると、Webサーバに大量のアクセスログが出力されます。
f:id:kzk_casino:20161106140412p:plain

ログの確認

この大量のアクセスログをそのまま眺めていても、何もわかりません。

アクセスログを見るときに知りたい情報として、

  • どこからアクセスが来ているのか
  • いつ大量のアクセスが来たのか

といったものが挙げられると思いますが、これらを簡単に可視化する方法を記載します。

どこからアクセスが来ているのか

アクセスログの1行を抜き取ってみます。

130.211.126.93 - - [05/Nov/2016:14:48:51 +0000] "GET / HTTP/1.1" 200 3770 "-" "curl/7.38.0" "-"

デフォルトフォーマットでは、第一要素目にFromのIPが記載されています。
これを抜き取って集計しましょう。

先に答えを言うと、下記の様なコマンドで集計して可視化することができます。

$ sudo tail -10000 /var/log/nginx/access.log | grep "05/Nov/2016:14" | awk '{print $1}' | sort -n | uniq -c | sort

順番に意味を見ていきましょう。

  • sudo tail -10000 /var/log/nginx/access.log

access.logの末尾から10000行を表示します。
ログが大量にあるときは、サーバの負荷を下げるために出力量を抑えたほうがいいでしょう。

  • grep "05/Nov/2016:14"

ログから、2016/11/5の14:00台のものだけを抜き取っています。
障害が発生した時間が大方特定できるときはこの様にして出力量を絞っておきましょう。

  • awk '{print $1}'

ログの第一要素目、つまりFrom IPを抜き取っています。

  • sort -n

sortコマンドは、出力をソートする(並び替える)コマンドです。
"-n"オプションによって、数字を数字として認識してソートしてくれます。

  • uniq -c

uniqコマンドは重複行を排除して1行にまとめてくれるコマンドです。
"-c" オプションによって、重複した行数を出力してくれます。

  • sort

sortコマンドの再登場です。uniq -cで出力されたIPを少ない順に並び替えます。


このようにOSコマンドのChainでどのIPから大量にアクセスが来ているのかを計測することができます。

計測結果は下記のようになります。

$ sudo tail -10000 /var/log/nginx/access.log | grep "05/Nov/2016:14" | awk '{print $1}' | sort -n | uniq -c | sort
     23 60.68.26.60
    327 104.154.229.150
    400 130.211.126.93
    441 104.197.31.33

104.197.31.33からのアクセスが最も多いことがわかります。

いつ大量のアクセスが来たのか

もう一つ、アクセスログを用いて確認したい項目として、実際いつ大量のアクセスが来たのか、ということがあると思います。

またアクセスログの1行を抜き取って考えてみます。

130.211.126.93 - - [05/Nov/2016:14:48:51 +0000] "GET / HTTP/1.1" 200 3770 "-" "curl/7.38.0" "-"

上記ログを、区切り文字を":"として要素に分けると、

  • 第1要素:130.211.126.93 - - [05/Nov/2016
  • 第2要素:14
  • 第3要素:48
  • 第4要素:51 +0000] "GET / HTTP/1.1" 200 3770 "-" "curl/7.38.0" "-"

のように分解することができます。

第2要素と第3要素を用いて計測すれば、分単位でいつアクセスが集中したのかを可視化することができます。

これも先に答えをいうと、下記のコマンドで実行することができます。

$ sudo tail -10000 /var/log/nginx/access.log | grep "05/Nov/2016:14" | cut -d ":" -f 2,3 | sort | uniq -c

途中までは先に説明したものと同じなので、違いだけ解説します。

  • cut -d ":" -f 2,3

まさに、先に述べた「区切り文字を":"として要素に分けて、第2要素と第3要素を抜き取る」という行為をしています。
cutは文字列を分割してくれるコマンドで、"-d" でディリミタ(区切り文字)を指定し、"-f" で抜き取る要素番号を指定します。

  • sort

抜き取った出力を並び替えます。

  • uniq -c

前述の例同様、重複行を排除して重複行数をカウントしています。

こちらの計測結果は下記のようになります。

$ sudo tail -10000 /var/log/nginx/access.log | grep "05/Nov/2016:14" | cut -d ":" -f 2,3 | sort | uniq -c
      5 14:37
      9 14:38
      8 14:40
      3 14:41
     11 14:42
     53 14:43
     45 14:44
    214 14:45
    376 14:46
    374 14:47
     76 14:48
     17 14:49

14:46前後にアクセス量が多くなっていることがわかります。

まとめ

このようにOSコマンドを組み合わせて使用することで、「いつ」、「どこから」大量のアクセスが来たのかを確認することができます。
これはDoS攻撃の解析などにも使用することができます。

参考

uniq -c した結果をバーで可視化してくれるツールもあります。

Visualizing `uniq -c` result · GitHub

上記のコードをWebサーバにクローンして使用すると、下記のようにバーで計測結果を可視化してくれます。

f:id:kzk_casino:20161106142528p:plain

f:id:kzk_casino:20161106142533p:plain

Linuxのシステムログを理解する

今までなんとなくしかわかっていなかった、システムログ、特にrsyslogの挙動について整理します。

前提

ログの収集にはsyslog(rsyslog)が使用されることが一般的なので、そちらを整理します。

環境はAWSのEC2を使って、OSはAmazon Linux(ami-0c11b26d)を使用します。

環境の準備

まずはEC2にsshして、rsyslogがインストールされ、稼働していることを確認します。

$ sudo /etc/init.d/rsyslog status
rsyslogd (pid  5935) を実行中...

もしrsyslogがない場合はyumでインストールする必要があります。

また、ローカルではターミナルを2つ立ち上げておき、片方をログ出力用、片方をログ閲覧用としておきます。

ログの出力・閲覧

デフォルトログ出力

ログ閲覧用のターミナルで下記のコマンドを実行して、/var/log/messagesに出力されるログをリアルタイムに閲覧します。

$ sudo tail -f /var/log/messages

次にログ出力用のターミナルで下記のコマンドを実行します。

$ logger this-is-test-log

loggerコマンドは、システムログへの書き込みを実行してくれるコマンドで、上記のコマンドにより、システムログに対して
" this-is-test-log "というログを出力しています。

実際に、ログ閲覧用のターミナルを見ると、上記のログが出力されていることがわかります。

ログの分岐

ここで、loggerコマンドを実行するときに、特にOptionを指定しなかったので、デフォルトログとして
/var/log/messagesに出力されました。

しかし、実際にrsyslogで扱えるシステムログはたくさんあり、例えば

  • /var/log/secure
  • /var/log/cron
  • /var/log/maillog
  • /var/log/spooler

などもrsyslogがログをハンドリングしてログ出力させることができます。

これらのログファイルにrsyslogから書き込むには、「ファシリティ」と「プライオリティ」という情報が必要です。
rsyslogではこれをルールと呼び、<ファシリティ>.<プライオリティ>と指定します。

rsyslogの設定ファイルである/etc/rsyslog.confには、どのファシリティ・プライオリティのログがきたら、
どのファイルにどんなフォーマットで書き込むか、ということが規定されています。

例えば、

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

の記載から、「ファシリティが"authpriv"に一致するログは/var/log/secureに書き込む」と規定されていることがわかり、

# Everybody gets emergency messages
*.emerg                                                 *

の記載から、「プライオリティが"emerg"のログはすべてのシステムログに書き込む」と規定されていることがわかります。


実際にloggerコマンドを用いてログの出力先が変わることを確認してみます。

ログ閲覧用のターミナルで下記のコマンドを実行して、/var/log/secureをモニタリングします。

$ sudo tail -f /var/log/secure

次にログ出力用のターミナルで下記のコマンドを実行します。

logger -p authpriv.info this-is-auth-test-log

これにより、rsyslogのルールとしてファシリティ:authpriv、プライオリティ:info のログを出力したことになるので、
/var/log/secureにログが出力されることになります。

ちなみに、/etc/rsyslog.confには下記の指定もあります。

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

上を見ると、ファシリティ:全て、プライオリティ:infoのログは/var/log/messagesに出力されることになっているので、
上で実行したログ出力は/var/log/messagesにも記載されていることになります。

各プロセスから出力されるログは、このようにrsyslogのファシリティとプライオリティを用いたルールを指定することで
どのログファイルに出力させるかを規定しています。

ちなみに、CentOS6(Amazon Linux)で指定できるファシリティとプライオリティについては下記が参考になります。
CentOS 6 - Rsyslog - ファシリティとプライオリティ : Server World

ログのフォーマット

ログは、規定で下記のフォーマットで出力されています。

Month Day hh:mm:ss HOSHTNAME USERNAME: Log Message

これは、/etc/rsyslog.confの下記の部分で指定されています。

# Use default timestamp format
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

この変数名を変更すれば、ログの出力フォーマットが変わります。

例えば、下記のように変更して

# Use default timestamp format
# $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
$ActionFileDefaultTemplate RSYSLOG_DebugFormat

rsyslogを再起動して

$ sudo /etc/init.d/rsyslog restart
システムロガーを停止中:                                    [  OK  ]
システムロガーを起動中:                                    [  OK  ]

ログ出力用ターミナルから下記コマンドを実行すると、

$ logger this-is-test-log2

非常に詳細なログが出力されるようになります。

Debug line with all properties:
FROMHOST: 'ip-10-0-0-168', fromhost-ip: '127.0.0.1', HOSTNAME: 'ip-10-0-0-168', PRI: 13,
syslogtag 'ec2-user:', programname: 'ec2-user', APP-NAME: 'ec2-user', PROCID: '', MSGID: '-',
TIMESTAMP: 'Nov  5 05:48:09', STRUCTURED-DATA: '-',
msg: ' this-is-test-log2'
escaped msg: ' this-is-test-log2'
inputname: imuxsock rawmsg: '<13>Nov  5 05:48:09 ec2-user: this-is-test-log2'

ログの情報が詳細になる分、ログファイルは肥大しやすくなりますので、実際の運用に即したフォーマット選定が必要です。

ログフォーマットとして何を選べるかは下記にまとまっていたので共有します。

[rsyslog] rsyslog.confの設定項目 - Life with IT


非常に基本的な部分のみとなりますが、rsyslogの仕組みについてざっとまとめました。

AWSのECSを使ってdockerを動かしてみたりDeployの挙動を見てみたりした ④タスク・サービスの設定

ここまで実施した内容で、ECSを利用してEC2をClusterとして登録し、コンテナサービスをEC2インスタンス上で動かす準備ができた
ここから実際にコンテナ稼働に関する設定を行う

最初に触れたように、ECSでコンテナを実行するには、下記の概念が必要となる。

  • タスク:複数のコンテナをグループ化した、デプロイと実行の最小単位
  • サービス:タスクの起動ポリシーで、起動数の確保や自動復旧を可能に為る

AWSのECSを使ってdockerを動かしてみたりDeployの挙動を見てみたりした ①全体イメージ - kzk-casino.com

設定としては、「Task Definition」の設定→「Service」の作成の順で行う
#Serviceの中でTaskを呼び出すため

Task Definitionの設定

ECS設定画面から、「Task Definition」を選択し、「Create new Task Definition」をクリックする

f:id:kzk_casino:20161015190307p:plain


Task Definitionの名前を入力し、「Add Container」をクリックする

f:id:kzk_casino:20161015190401p:plain


ここで、Taskの中で起動させるContainerの選択や、割り当てるリソース、実行コマンドなどを設定する

f:id:kzk_casino:20161015190531p:plain

Container Nameは、任意のコンテナ名を入力する

Imageにはコンテナイメージを指定する
今回はイメージ管理リポジトリとしてDocker Hubを利用したので、<リポジトリ>/<イメージ>/<リビジョン>のように指定する

Memory LimitはHard Limitで128MBとする
ここは実際にはEC2インスタンスインスタンスサイズや、想定コンテナサイズなどを加味して設計する必要が有る

Port Mappingは、EC2インスタンスのany port(0)とコンテナのhttp port(80)をマッピングする
前回紹介したALBによるダイナミックポートマッピングを使用するため、インスタンス側はanyとしている


f:id:kzk_casino:20161015190930p:plain

次に、Commandにはコンテナ起動時に実行する起動スクリプトを指定している
起動スクリプトの内容は、例えば下記のようなものを含ませるとよい

  • 最新のコードをGithubから取得
  • Nginxサービスの起動
  • Unicornの起動
  • RDSとの接続
#!/bin/bash

cd /var/www/gatebook

# Get latest App code
git pull

# Starting nginx
/usr/sbin/service nginx start

# Starting Unicorn
/usr/local/bin/bundle exec unicorn -c config/unicorn.rb -D

# Migrate DB
/usr/local/bundle/bin/rake db:migrate

while true ; do
    /bin/bash
done

最後のwhile文は、コンテナが起動した状態のままリクエストを受け付けるための定型句のようなもの

ここまで設定して、「Add」をクリック


コンテナが追加されたことを確認して、「Create」をクリックする

f:id:kzk_casino:20161015191451p:plain


ここまででTask Definitionの設定は完了

Serviceの設定

Cluster詳細画面からServiceタブを選択し、「Create」をクリックする

f:id:kzk_casino:20161015191630p:plain

f:id:kzk_casino:20161015191756p:plain

Task Definitionで、先ほど作成したTaskを選択する
このとき、リビジョンが1になっているのに注目
Taskは定義を更新することができ、更新のたびにリビジョンが上がっていく。定義の更新は、例えばDocker Imageを更新したときなどに実施

Clusterで、コンテナを稼働させたいEC2があるClusterを選択

Service Nameに、サービスの任意の名前を入力

Number of Tasksに起動させたいTaskの数を入力
これがイコールCluster内で起動するコンテナの数になる

Minimum Healthy PercentとMaximum Healthy Percentは許容するTask起動数の最小値と最大値を設定する
例えば、今回は下記のように各値を設定した

 - Number of Tasks : 4
 - Minimum Healthy Percent : 50
 - Maximum Healthy Percent : 200

これが指す意味は、「平常時は4つのTaskを常時起動し、Deployなどのタイミングで最小Task数が2、最大Task数が8となることを許容する」ということとなる

Deploy時にも起動しているTaskの数を減らしたくないならMinimum Healthy Percentを100とし、逆にリソース観点から起動する最大Task数を常時起動数から増やしたくない場合はMaximum Healthy Percentを100とするなどの変更が必要である


さらに下に行くと、ELBの設定を行えるので、Configure ELBをクリック

f:id:kzk_casino:20161015192522p:plain


ダイナミックポートマッピングを利用するためにALBを選択し、作成したIAM RoleやALB、Containerを選択し、「Add to ELB」をクリック

f:id:kzk_casino:20161015192718p:plain


ALB作成時に指定したターゲットグループが選択可能になっているので、選択して「Save」

f:id:kzk_casino:20161015192839p:plain


これでServiceが設定されるのでTaskが起動してくる


次は起動しているTaskの確認や、更新について

AWSのECSを使ってdockerを動かしてみたりDeployの挙動を見てみたりした ③Cluster、EC2、ALBなどの設定

Clusterの作成

ECSの画面から「クラスターの作成」を選んで、名前を入力する

f:id:kzk_casino:20161015172649p:plain

f:id:kzk_casino:20161015172719p:plain


Clusterに登録するEC2の準備

通常手順でEC2を作成する

Clusterへの登録は過去の記事を参照
kzk-casino.hatenablog.com

※User Dataを使用してもよい

ALBの設定

Cluster内の各EC2インスタンス上で稼働するコンテナに対してELBを用いてLBする必要があるが、
ELBではポートマッピングの際に問題がある

インスタンス上に立てたコンテナは、インスタンスのポートとコンテナのポートでマッピングして、
インスタンスマッピングされたポートへのアクセスがあるとコンテナにリダイレクトする。

例えば、EC2に80/tcpのアクセスが来たらContainerA、8080/tcpのアクセスが来たらContainerB、といったようにポートマッピングを行う

f:id:kzk_casino:20161015174302p:plain


しかし、ここで下記の問題が発生する。

  • コンテナを自動起動・自動拡張させた場合、常にポートマッピングを気にして(つまりEC2の空きポートを意識して)設定する必要が有る
  • ELB上に、Listenするポートと各コンテナのひも付けを都度設定する必要がある

これでは後述するTaskの自動起動や、AutoScalingとの親和性が非常に悪いので、理想としては各コンテナに対するポートマッピングはコンテナ起動時に自動的に実施されて、ELBにその情報が自動反映されるのが好ましい。

そこで使用できるのが、ELB ver2とも言われている、Application Load Balancerである

ALBはダイナミックポートマッピングをサポートしているので、上記の課題を解決することができる

以下ではALBの設定について記載する

ELB作成画面でALBを選択

f:id:kzk_casino:20161015174926p:plain

ALBの名前とListenerを設定

f:id:kzk_casino:20161015175002p:plain

VPCとAZを設定

f:id:kzk_casino:20161015175034p:plain

セキュリティ上のメッセージが表示されるが、無視してSGの設定

f:id:kzk_casino:20161015175142p:plain

ターゲットグループとヘルスチェックを設定

f:id:kzk_casino:20161015175218p:plain

ターゲットの登録は一旦Skip

f:id:kzk_casino:20161015175308p:plain

設定内容を確認してALBを作成する。



次はTask Definitionの作成と、Serviceの設定

AWSのECSを使ってdockerを動かしてみたりDeployの挙動を見てみたりした ②DockerImageの作成

まずはDockerのイメージを作成


docker for macを使用すればローカル環境で簡単に作成したDockerfileをイメージ化して
挙動を確認することができる

docs.docker.com

Dockerfileの作成

まずはローカルの適当なワークディレクトリにDockerfileという名前のファイルを作成し、
下記のように記載

# nginx 1.10 のイメージを使用
FROM nginx:1.10

# Dockerfile作成者
MAINTAINER kazukimaeda

#最新のAppCodeを取得
RUN apt-get update && \
    apt-get install -y vim git && \
    git clone https://github.com/<Github Account>/sample-html.git /var/www/sample-html && \
    mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak && \
    cp -ip /var/www/sample-html/config/default.conf /etc/nginx/conf.d/

今回はnginxのイメージをベースに、gitをインストールして、テスト用に作成したhtmlとnginxの設定ファイルを
Gitリポジトリから取得するような簡単なイメージを作成
にはGithubのアカウント名が入る

Dockerイメージのビルド

作成したDockerfileからイメージをビルド

$ docker build -t <Dockerhub Account>/sample-html:1.0 .

にはDocker Hubのアカウント名が入る

しばらく待って、イメージが作成されることを確認

$ docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
<Dockerhub Account>/sample-html   1.3                 66daf953cde1        5 hours ago         260.2 MB

(任意)Docker Imageからコンテナを立ち上げて挙動を確認する
今回はnginxを稼働させたWebサーバとして使用するので、ポート80をマッピングする

$ docker run -it -p 80:80 <Dockerhub Account>/sample-html:1.0 /bin/bash
root@69e2ac4715f6:/# service nginx start
root@69e2ac4715f6:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 13:44 ?        00:00:00 /bin/bash
root        12     1  0 13:44 ?        00:00:00 nginx: master process /usr/sbin/nginx -
nginx       13    12  0 13:44 ?        00:00:00 nginx: worker process
root        14     1  0 13:44 ?        00:00:00 ps -ef

ブラウザからlocalhostにアクセスして、サンプルのhtmlが表示されることを確認
f:id:kzk_casino:20160924224552p:plain:w400

コンテナを修正した場合は、修正したコンテナをCommitして新しいリビジョンのイメージを作成する
#ここでリビジョン1.3まで上がっちゃいました・・

イメージのDocker HubへのPush

作成したイメージをDocker HubへPushする

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username:
Password:
Login Succeeded
$ docker push <Dockerhub Account>/sample-html:1.3

次はECSの準備としてCluster、EC2、ALBなどの設定を行います

AWSのECSを使ってdockerを動かしてみたりDeployの挙動を見てみたりした ①全体イメージ

AWSのdockerコンテナ稼働のためのマネージドサービスである、ECSを使って色々試してみました。

基本知識

ECSを使用するにあたって必要な基本知識・用語は下記
(基本的にはAWSのホワイトペーパーみた方が早いと思います)

(1)EC2インスタンスの登録
・アプリケーションが実行されるEC2インスタンスコンテナーインスタンス)をECSに登録
コンテナーインスタンスではDockerエージェントとECSエージェントが動作している必要がある
・セットアップ済みのAMI(ECS-optimized AMI)も用意されている

(2)クラスターの作成
・複数のコンテナーインスタンスをグループ化して仮想化した「クラスター」を作成する
・アプリケーションのデプロイはクラスターに対して実行される
・どのコンテナーインスタンスコンテナーを配置するかはECSが決めて管理する

(3)コンテナーの作成
コンテナーの実態はDockerで扱われる形式でビルドしたイメージファイル
・アプリケーションのコードや実行環境、ライブラリからイメージファイルをビルドして
 ECSにコンテナーとして登録する

(4)タスクの定義
・複数のコンテナーをグループ化した、デプロイと実行の最小単位となる「タスク」を定義する
・タスクの定義には必要リソースも設定する
 タスクが実行されるコンテナーインスタンスでどの程度のリソースを確保するかという設定

(5)タスクの起動ポリシーの設定
・タスクをどの様に起動するかのポリシーである「スケジューラ」を設定する
・タイプには「Run Task」と「Service」がある
・「Run Task」はバッチの様に手動で一回だけ実行する
・「Service」は設定されたタスクの起動数を常時保つ様に動作し、停止した場合は自動復旧する
Webサービスを提供する場合は「Service」を選択する

(6)タスクの実行
・ECSはクラスター内の空きリソースを自動的に探して、実際にタスクを動作させる
 コンテナーインスタンスを、スケジューラで設定されている数まで確保できるよう探す
・そして、タスクを起動する


全体イメージ概要

作りたい環境は下記のようなイメージ

f:id:kzk_casino:20160924222714p:plain

  • 作業端末(Mac)でDockerfileを作成し、Dockerfileから作成されたImageをDockerHubにPushする
  • Application Codeも基本的にはMacで作成し、GithubにPushしておく
  • AWS上でECSを動かし、クラスタ内に2つのEC2インスタンスを稼働させる
  • 各EC2インスタンスにはそれぞれ2つのコンテナを稼働させる(合計4つのTaskを動かす)
  • 各コンテナにはELBv2であるALBを用いてロードバランシングを実施する


具体的な各作業については順次投稿・・