ラベル supervisor の投稿を表示しています。 すべての投稿を表示
ラベル supervisor の投稿を表示しています。 すべての投稿を表示

2014年2月13日木曜日

Dockerってなんじゃ?(Supervisorで複数のサービス起動)




Dockerネタです。
前回の記事で、DockerでSSHサーバとして起動しましたが、通常いろいろなサービスを起動したコンテナを使うことの方が多いと思います。

Dockerでは起動時に1つのCMDしか指定できないようで、前回のやり方では1つのサービスしか起動できません。 このような場合は、Supervisorを利用するといいようです。 

たとえば、sshdとhttpdをサービス起動したコンテナの場合、コンテナ内のsupervisordがsshdとhttpdを管理し、dockerがsupervisordを使ってサービス起動するというイメージです。



それでは早速試してみます。
コンテナは前回と同じcentosをつかいます。



コンテナの起動


コンテナを立ちあげてコンソールにアクセスします。
# docker run -t -i centos /bin/bash



sshとhttpdのインストール


コンテナに入ったらまず、必要なsshdやhttpd、supervisorインストール用のeasy?installなどのプログラムを準備します。
-bash-4.1# yum install passwd openssh openssh-clients openssh-server httpd vim python-setuptools -y


sshdの設定をします。
-bash-4.1# vim /etc/ssh/sshd_config
#UsePAM no
UsePAM yes
↓
UsePAM no
#UsePAM yes


rootユーザのパスワードを設定します。
-bash-4.1# passwd


httpdのインデックスページを用意します。
-bash-4.1# -bash-4.1# echo moge > /var/www/html/index.html


Supervisorのインストール


supervisorをインストールします。
-bash-4.1# easy_install supervisor


supervisorの起動スクリプトを用意します。
-bash-4.1# vim /etc/init.d/supervisord
#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/init.d/functions

RETVAL=0
prog="supervisord"
pidfile="/tmp/supervisord.pid"
lockfile="/var/lock/subsys/supervisord"

start()
{
   echo -n $"Starting $prog: "
   daemon --pidfile $pidfile supervisord
   RETVAL=$?
   echo
   [ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop()
{
   echo -n $"Shutting down $prog: "
   killproc -p ${pidfile} /usr/bin/supervisord
   RETVAL=$?
   echo
   if [ $RETVAL -eq 0 ] ; then
      rm -f ${lockfile} ${pidfile}
   fi
}
case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  status)
    status $prog
  ;;
  restart)
    stop
    start
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac
# chmod 755 /etc/init.d/supervisord



Supervisorの設定


supervisorの設定ファイルを用意します。
-bash-4.1#  echo_supervisord_conf > /etc/supervisord.conf
-bash-4.1#  echo "[include]" >> /etc/supervisord.conf
-bash-4.1#  echo "files = supervisord/conf/*.conf" >> /etc/supervisord.conf
-bash-4.1#  mkdir -p  /etc/supervisord/conf/


設定を記載します。 ここでポイントは、supervisord自身のnodaemon=trueという項目です。
これによって、supervisordがフォアグラウンド起動します。
-bash-4.1#  vim /etc/supervisord/conf/service.conf
[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true

[program:httpd]
command=/usr/sbin/httpd -c "ErrorLog /dev/stdout" -DFOREGROUND
redirect_stderr=true


ここで、コンテナを抜けます。
-bash-4.1# exit



コンテナイメージの作成


ホスト側で、一度コミットします。
# docker ps -a
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                                          NAMES
c118bcc97b1e        centos:6.4                  /bin/bash              3 hours ago         Exit 0

# docker commit c118bcc97b1e memorycraft/centos



コンテナの起動


それでは、コミットしたイメージで新しいコンテナを起動してみます。
このとき、起動するコマンドに/usr/bin/supervisordを指定し、開放ポートに22と80を2つ指定します。
# docker run -d -p 22 -p 80 memorycraft/centos /usr/bin/supervisord



確認


それではコンテナに対してsshとhttpでアクセスしてみます。
docker ps -aで、ポートマッピングの状況がわかります。

# docker ps -a
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                                          NAMES
337f5660c4d0        memorycraft/centos:latest   /usr/bin/supervisord   47 minutes ago      Up 47 minutes       0.0.0.0:49173->22/tcp, 0.0.0.0:49174->80/tcp   stoic_bell
c118bcc97b1e        centos:6.4                  /bin/bash              3 hours ago         Exit 0                                                             sad_torvalds


マッピングされたポートをつかってsshアクセスしてみます。
# ssh root@127.0.0.1 -p 49173
The authenticity of host '[127.0.0.1]:49173 ([127.0.0.1]:49173)' can't be established.
RSA key fingerprint is 59:de:98:f5:21:15:bc:40:c1:29:8d:76:84:eb:59:05.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[127.0.0.1]:49173' (RSA) to the list of known hosts.
root@127.0.0.1's password:

アクセスできました!

続けて、httpです。
マッピングされたポートをつかってブラウザアクセスしてみます。




おお!確認できました!

これで複数のサービスが起動したコンテナを作れます。
今回は、以上です。


2014年1月16日木曜日

SQSってなんじゃ?(supervisordでSQS)

いまさらですが、SQS+supervisordです。

supervisorはプログラムの起動監視と、自動起動/復帰などを行ってくれるツールです。
これをつかってSQSの受信処理プログラムをワーカーとして管理してみます。


受信テスト用のスクリプトを作成


メッセージの受信は、一度に最大の10件まで、ポーリング20秒で受信したメッセージをログファイルに出力するようにします。
また、今回はログの出力タイミングがわかりやすいように、1回のポーリング後10秒間sleepしています。
$ vim /home/ec2-user/svsqs.rb
#!/usr/local/bin/ruby

require 'aws-sdk'
require 'logger'

access_key = 'XXXXXXXXXXXXXXXX'
secret_key = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
queue_url = 'https://sqs.ap-northeast-1.amazonaws.com/ZZZZZZZZZZZ/svsqs'

log = Logger.new("/home/ec2-user/test.log");

AWS.config(:access_key_id => access_key,
  :secret_access_key => secret_key,
  :region => "ap-northeast-1")
sqs = AWS::SQS.new

while true
  messages = sqs.queues[queue_url].receive_message({:limit => 10, :wait_time_seconds => 20}).map do |m|
    json = JSON.parse(m.body)
    log.debug("#{$$} #{json['msg']}")
    m.delete()
  end
  log.debug("#{$$} -------")
  sleep 10
end
$ chmod 755 /home/ec2-user/svsqs.rb



supervisorのインストールと設定


次に、supervisorをインストールして、上記のスクリプトの起動管理するように設定します。
# easy_install supervisor
# vim /etc/init.d/supervisord

次にsupervisor自体の起動スクリプトをつくってサービス登録します。
#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/init.d/functions

RETVAL=0
prog="supervisord"
pidfile="/tmp/supervisord.pid"
lockfile="/var/lock/subsys/supervisord"

start()
{
   echo -n $"Starting $prog: "
   daemon --pidfile $pidfile supervisord
   RETVAL=$?
   echo
   [ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop()
{
   echo -n $"Shutting down $prog: "
   killproc -p ${pidfile} /usr/bin/supervisord
   RETVAL=$?
   echo
   if [ $RETVAL -eq 0 ] ; then
      rm -f ${lockfile} ${pidfile}
   fi
}
case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  status)
    status $prog
  ;;
  restart)
    stop
    start
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac


# chmod 755 /etc/init.d/supervisord
# chkconfig --add supervisord
# chkconfig supervisord on
# chkconfig --list



監視対象プロセスの設定


子設定ファイルの読込み設定

主設定ファイルの末尾に、アプリケーションごとの設定ファイルをインクルードするように設定しておきます。
# echo_supervisord_conf > /etc/supervisord.conf
# echo "[include]" >> /etc/supervisord.conf
# echo "files = supervisord/conf/*.conf" >> /etc/supervisord.conf

子設定ファイルの作成

svsqsという名前で最初に書いたスクリプトの起動設定をします。 自動起動や、自動復帰をONにします。
# mkdir -p  /etc/supervisord/conf/
# vim /etc/supervisord/conf/svtest.conf
[program:svsqs]
command = /home/ec2-user/svsqs.rb
process_name = svsqs
autostart   = true
autorestart = true



supervisorのデーモン起動


ここまで設定できたらsupervisord自体を起動します。
# service supervisord start



supervisorのコンソールでstop/startテスト


supervisorctlというコマンドで管理対象プロセスの操作や状態確認が簡単にできます。
 supervisorが起動すると、autostartがONになっているため対象のスクリプトも起動していることが分かります。
# supervisorctl
svtest                           RUNNING    pid 18770, uptime 15:44:07
supervisor> stop svtest
svtest: stopped
supervisor> status
svtest                           STOPPED    Jan 16 05:12 AM
supervisor> start svtest
svtest: started
supervisor>
supervisor>
supervisor> status
svtest                           RUNNING    pid 10876, uptime 0:00:03
supervisor>
supervisor>
supervisor> exit



自動復帰の確認


プロセスを強制的に落としてみます。
するとsupervisorにより、新しいプロセスとして自動復帰します。
# ps -ax | grep svtest
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
10876 ?        S      0:00 /bin/sh /home/ec2-user/svsqs.rb
10892 pts/0    D+     0:00 grep svtest

# kill -9 10876
# ps -ax | grep svtest
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
10898 ?        S      0:00 /bin/sh /home/ec2-user/svsqs.rb
10901 pts/0    S+     0:00 grep svtest



メッセージの確認


このプログラムで扱うSQSのキューに対し、いくつかメッセージを送ってみると、受信できているのがわかります。
# tail -1000f test.log
D, [2014-01-16T07:02:28.085909 #13119] DEBUG -- : 10898 aaaaaa
D, [2014-01-16T07:02:28.176748 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:38.347694 #13119] DEBUG -- : 10898 bbbbbbb
D, [2014-01-16T07:02:38.364416 #13119] DEBUG -- : 10898 cccccccc
D, [2014-01-16T07:02:38.414742 #13119] DEBUG -- : 10898 ddddddd
D, [2014-01-16T07:02:38.466001 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:48.655003 #13119] DEBUG -- : 10898 eeeeeee
D, [2014-01-16T07:02:48.666323 #13119] DEBUG -- : 10898 ffffffff
D, [2014-01-16T07:02:48.718459 #13119] DEBUG -- : 10898 gggggggg
D, [2014-01-16T07:02:48.771584 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:02:58.947327 #13119] DEBUG -- : 10898 hhhhhhhh
D, [2014-01-16T07:02:58.957724 #13119] DEBUG -- : 10898 iiiiiii
D, [2014-01-16T07:02:59.023820 #13119] DEBUG -- : 10898 -------
D, [2014-01-16T07:03:09.171886 #13119] DEBUG -- : 10898 jjjjjjj



複数プロセス


次に、このプログラムを並列で複数のワーカーとして起動管理するようにしてみます。
# vim /etc/supervisord/conf/svsqs.conf

複数のプロセスとして管理するには、numprocsというパラメータを2以上に設定します。
また、このときprocess_nameにはワーカーの番号を含める必要があるため、
supervisorの特殊変数 %(program_name)%(process_num)を利用します。
[program:svsqs]
command = /home/ec2-user/svsqs.rb
process_name = %(program_name)s_%(process_num)02d
numprocs = 2
autostart   = true
autorestart = true

設定を変えたので再起動し、プロセスを見てみると、2つ起動しているのが分かります。
# /etc/init.d/supervisord restart

supervisorctlでは、先ほど設定した名前でワーカー名が動的に付与されているのが分かります。
[root@ip-10-160-79-47 ec2-user]# supervisorctl
svsqs:svsqs_00                   RUNNING    pid 14286, uptime 0:36:24
svsqs:svsqs_01                   RUNNING    pid 14287, uptime 0:36:24

プロセスを落としてみると、自動で2プロセスにもどります。
#
# ps -ax | grep rb
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
14286 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14287 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14516 pts/0    S+     0:00 grep rb
#
# kill -9 14286
#
# ps -ax | grep rb
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
14287 ?        Sl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb
14526 ?        Rl     0:00 /usr/local/bin/ruby /home/ec2-user/svsqs.rb

また、ログをみてみると、2つのプロセスできちんと動作しているようです。
# tail -1000f test.log
D, [2014-01-16T07:25:13.175073 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:23.311352 #14286] DEBUG -- : 14286 aaaaaaaa
D, [2014-01-16T07:25:23.326240 #14286] DEBUG -- : 14286 bbbbbbbb
D, [2014-01-16T07:25:23.393122 #14286] DEBUG -- : 14286 ccccccc
D, [2014-01-16T07:25:23.441076 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:28.144026 #14287] DEBUG -- : 14287 ddddddd
D, [2014-01-16T07:25:28.153058 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:33.682118 #14286] DEBUG -- : 14286 eeeeeee
D, [2014-01-16T07:25:33.735474 #14286] DEBUG -- : 14286 fffffff
D, [2014-01-16T07:25:33.827446 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:42.971976 #14287] DEBUG -- : 14287 ggggggg
D, [2014-01-16T07:25:42.986925 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:25:44.555526 #14286] DEBUG -- : 14286 hhhhhhh
D, [2014-01-16T07:25:44.606725 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:25:53.106090 #14287] DEBUG -- : 14287 jjjjjjjj
D, [2014-01-16T07:25:53.118289 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:26:01.609948 #14286] DEBUG -- : 14286 kkkkkkkk
D, [2014-01-16T07:26:01.738742 #14286] DEBUG -- : 14286 -------
D, [2014-01-16T07:26:04.564231 #14287] DEBUG -- : 14287 llllllll
D, [2014-01-16T07:26:28.385778 #14287] DEBUG -- : 14287 -------
D, [2014-01-16T07:26:34.210485 #14526] DEBUG -- : 14526 mmmmm
D, [2014-01-16T07:26:34.301180 #14526] DEBUG -- : 14526 -------
D, [2014-01-16T07:26:39.204945 #14287] DEBUG -- : 14287 nnnnn
D, [2014-01-16T07:26:39.224593 #14287] DEBUG -- : 14287 -------

こんな感じで、仮にプログラムがエラーでオチたりした場合でも、常に指定したプロセス数に起動しなおしてくれると助かります。

以上です。