2017年1月31日火曜日

JOC Cockpit のLDAP認証を試す

下記ページを参考に、JOC Cockpit のLDAP認証を試してみます。
https://kb.sos-berlin.com/display/PKB/Authentication+and+Authorization+-+Configuration
JOC Cockpit の認証は、shiro.ini で設定します。
shiro.ini には、デフォルトで複数の Role が定義されており、ユーザによって使用できる機能を制限できます。
詳細は下記ページを参照
https://kb.sos-berlin.com/display/PKB/Authentication+and+Authorization+-+Permissions+for+the+JOC+Cockpit+Web+Service
テスト環境は以下のとおり。dockerコンテナ4台で試します。
  • Dockerホスト(CentOS7.3)
    • docker1.10.3
    • docker-compose1.10.0
  • Dockerコンテナ(Debian8)
    • JobSchedulerMaster1.11.0-R3
    • JOC Cockpit1.11.0-R3 
    • MariaDB10.1
    • OpenLDAP2.4.40


LDAPのユーザ登録


DockerHUBのイメージを使用して OpenLDAPサーバを起動しました。
ドメインは "dc=example, dc=local" とします。
[root@centos0702 ldap]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
45be5aba3636        dinkel/openldap     "/entrypoint.sh slapd"   22 hours ago        Up 30 minutes       0.0.0.0:389->389/tcp   ldap_server_1

下記のユニットを登録します。
[root@centos0702 ldap]# cat unit.ldif
dn: ou=Users,dc=example,dc=local
objectclass: organizationalUnit
ou: Users

dn: ou=Groups,dc=example,dc=local
objectclass: organizationalUnit
ou: Groups

dn: ou=Computers,dc=example,dc=local
objectclass: organizationalUnit
ou: Computers
[root@centos0702 ldap]# ldapadd -x -w p@ssw0rd -D "cn=admin,dc=example,dc=local" -f unit.ldif
adding new entry "ou=Users,dc=example,dc=local"

adding new entry "ou=Groups,dc=example,dc=local"

adding new entry "ou=Computers,dc=example,dc=local"


上記で登録した Users にテスト用のユーザを1人登録します。
後述のJOC Cockpit の設定で、「LDAPのgidNumber」 と 「JOC Cockpit の Role」 を紐つけるように設定します。
[root@centos0702 ldap]# ldapadd -x -w p@ssw0rd -D "cn=admin,dc=example,dc=local" -f user.ldif
adding new entry "uid=dev01,ou=Users,dc=example,dc=local"


登録した dev01 ユーザを検索してみます。
[root@centos0702 ldap]# ldapsearch -x -D "uid=dev01,ou=Users,dc=example,dc=local" -w p@ssw0rd -b "ou=Users,dc=example,dc=local" "(&(objectClass=posixAccount)(uid=dev01))"
# extended LDIF
#
# LDAPv3
# base <ou=Users,dc=example,dc=local> with scope subtree
# filter: (&(objectClass=posixAccount)(uid=dev01))
# requesting: ALL
#

# dev01, Users, example.local
dn: uid=dev01,ou=Users,dc=example,dc=local
objectClass: posixAccount
objectClass: inetOrgPerson
sn: dev01-sn
cn: dev01-cn
displayName: develop01
uid: dev01
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/dev01
loginShell: /bin/bash
userPassword:: e0NSWVBUfU9Kd0FkMkJjdGo1aXc=
mail: dev01@example.local

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

JOC Cockpit のLDAP認証設定


JOC Cockpit の認証設定は、shiro.ini に記載されています。
設定ファイルのデフォルトの格納場所は、以下のとおり。
/home/[install user]/sos-berlin.com/joc/resources/joc/shiro.ini
今回は、以下の PATH に格納しています。
/root/sos-berlin.com/joc/resources/joc/shiro.ini 
デフォルトのshiro.ini では、[user] に root ユーザが定義されています。
LDAP認証に変更すると、この root ユーザは使用不可になります。
[user]は、変更せずに残します。

[Role]には、"administrator"や"application_manager" などが、あらかじめ定義されているので、ユーザごとに割り当てる Role を変更して使用可能なJOCの機能を制限することにします。
[Role]も変更せずに残します。

[main]は、[user]で定義したユーザでログインできるような設定になっているので、以下のようにしてLDAP認証に変更します。
[main]

ldapRealm = com.sos.auth.shiro.SOSLdapAuthorizingRealm

ldapRealm.userDnTemplate = uid={0},ou=Users,dc=example,dc=local
ldapRealm.searchBase = ou=Users,dc=example,dc=local
ldapRealm.contextFactory.url = ldap://ldap_server_1:389

ldapRealm.groupNameAttribute = gidNumber
#ldapRealm.userNameAttribute = uid
ldapRealm.userSearchFilter = (&(objectClass=posixAccount)(uid=%s))

# Mapping of a LDAP group to roles. You can assign more than one role with separator sign |
ldapRealm.groupRolesMap = \
"1000":"administrator|application_manager", \
"1001":"application_manager", \
"1002":"it_operator"

rolePermissionResolver = com.sos.auth.shiro.SOSPermissionResolverAdapter
rolePermissionResolver.ini = $iniRealm
ldapRealm.rolePermissionResolver = $rolePermissionResolver

securityManager.realms = $ldapRealm
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager

#Session timeout in milliseconds
securityManager.sessionManager.globalSessionTimeout = 1800000

ldapRealm.userDnTemplate は、LDAP サーバーからユーザーを取得する DN テンプレートです。{0}は、JOC Cockpitログイン画面で入力したユーザIDが入ります。
ldapRealm.searchBaseは、ユーザーを検索するLDAP ディレクトリーのルートを設定します。
ldapRealm.contextFactory.urlは、LDAPサーバのURLを設定します。
ldapRealm.groupNameAttributeは、ldapRealm.groupRolesMapで紐つけるLDAP属性(gidNumber)を指定 ldapRealm.groupRolesMapは、LDAP属性の gidNumber と JOCのRole を紐つけます。複数のロールを紐つける場合は "|" で区切ります。

このLDAP用の shiro.ini をコンテナにコピーして JocCockpit を再起動します。
[root@centos0702 sosjs11]# docker cp ./shiro.ini.ldap sosjs11_joc_cockpit_1:/root/sos-berlin.com/joc/resources/joc/shiro.ini
[root@centos0702 sosjs11]# docker exec sosjs11_joc_cockpit_1 /etc/init.d/joc restart                                      Stopping Jetty: OK
Starting Jetty: . . . . . OK Sun Jan 29 02:57:32 UTC 2017

ログイン確認


コンテナの状態を確認します。
[root@centos0702 sosjs11]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                         NAMES
fd455e36a585        js_master           "bash /opt/startup_sc"   16 hours ago        Up 3 minutes        0.0.0.0:4444->4444/tcp, 0.0.0.0:40444->40444/tcp, 48444/tcp   sosjs11_master_1
b51cc531a282        joc_cockpit         "bash /opt/startup_jo"   16 hours ago        Up 3 minutes        0.0.0.0:4446->4446/tcp, 0.0.0.0:40446->40446/tcp              sosjs11_joc_cockpit_1
7c09a173ee7a        mariadb             "docker-entrypoint.sh"   16 hours ago        Up 3 minutes        3306/tcp                                                      sosjs11_db_1
45be5aba3636        dinkel/openldap     "/entrypoint.sh slapd"   23 hours ago        Up About an hour    0.0.0.0:389->389/tcp                                          ldap_server_1

下記URLでログインします。
http://<DockerホストのIPアドレス>:4446/
ログイン画面で、上記で登録したLDAPユーザの dev01/p@ssw0rd を入力してログインします。


ログインに成功して、右上の[dev01] > [プロファイル] を選択すると、下図のように使用可能な機能を確認できます。








2017年1月30日月曜日

プロセスが使用中のファイルやポートを調べる


lsof コマンドを使用すると、プロセスが使用しているポートやファイルを調べることができる。

CentOS7の最小構成ではインストールされないので、使用したい場合は yum でインストールする
[root@centos0702 ~]# yum install lsof

例えば、sshd のプロセスID を指定して lsof  コマンドを実行すると以下のように表示されます。
[root@centos0702 ~]# ps -ef | grep sshd
root      1469     1  0 08:32 ?        00:00:00 /usr/sbin/sshd
root      2330  1469  0 08:33 ?        00:00:00 sshd: root@pts/0
root      2409  2338  0 08:42 pts/0    00:00:00 grep --color=auto sshd
[root@centos0702 ~]# lsof -p 1469
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
sshd    1469 root  cwd    DIR  253,1     4096      128 /
sshd    1469 root  rtd    DIR  253,1     4096      128 /
sshd    1469 root  txt    REG  253,1   819640 17591824 /usr/sbin/sshd
sshd    1469 root  mem    REG  253,1    62184 16878909 /usr/lib64/libnss_files-2.17.so
sshd    1469 root  mem    REG  253,1    44448 16884063 /usr/lib64/librt-2.17.so
sshd    1469 root  mem    REG  253,1    15688 17008660 /usr/lib64/libkeyutils.so.1.5
sshd    1469 root  mem    REG  253,1    62744 17320724 /usr/lib64/libkrb5support.so.0.1
sshd    1469 root  mem    REG  253,1    11384 16878845 /usr/lib64/libfreebl3.so
sshd    1469 root  mem    REG  253,1   143944 16884059 /usr/lib64/libpthread-2.17.so
sshd    1469 root  mem    REG  253,1   251784 16919798 /usr/lib64/libnspr4.so
sshd    1469 root  mem    REG  253,1    20016 16919799 /usr/lib64/libplc4.so
sshd    1469 root  mem    REG  253,1    15768 16919800 /usr/lib64/libplds4.so
sshd    1469 root  mem    REG  253,1   182072 16919803 /usr/lib64/libnssutil3.so
sshd    1469 root  mem    REG  253,1  1220224 17262239 /usr/lib64/libnss3.so
sshd    1469 root  mem    REG  253,1   164048 17144122 /usr/lib64/libsmime3.so
sshd    1469 root  mem    REG  253,1   276760 17265665 /usr/lib64/libssl3.so
sshd    1469 root  mem    REG  253,1   121296 16973518 /usr/lib64/libsasl2.so.3.0.0
sshd    1469 root  mem    REG  253,1   398264 16919783 /usr/lib64/libpcre.so.1.2.0
sshd    1469 root  mem    REG  253,1  2118128 16878889 /usr/lib64/libc-2.17.so
sshd    1469 root  mem    REG  253,1    15848 16919805 /usr/lib64/libcom_err.so.2.1
sshd    1469 root  mem    REG  253,1   202568 17144047 /usr/lib64/libk5crypto.so.3.1
sshd    1469 root  mem    REG  253,1   959008 17320722 /usr/lib64/libkrb5.so.3.3
sshd    1469 root  mem    REG  253,1   324888 17144043 /usr/lib64/libgssapi_krb5.so.2.2
sshd    1469 root  mem    REG  253,1   111080 16884061 /usr/lib64/libresolv-2.17.so
sshd    1469 root  mem    REG  253,1    41080 16878893 /usr/lib64/libcrypt-2.17.so
sshd    1469 root  mem    REG  253,1   113584 16878899 /usr/lib64/libnsl-2.17.so
sshd    1469 root  mem    REG  253,1    90664 16919795 /usr/lib64/libz.so.1.2.7
sshd    1469 root  mem    REG  253,1    14872 16884131 /usr/lib64/libutil-2.17.so
sshd    1469 root  mem    REG  253,1    61872 16973540 /usr/lib64/liblber-2.4.so.2.10.3
sshd    1469 root  mem    REG  253,1   344280 16973542 /usr/lib64/libldap-2.4.so.2.10.3
sshd    1469 root  mem    REG  253,1    19776 16878895 /usr/lib64/libdl-2.17.so
sshd    1469 root  mem    REG  253,1  2025472 17144063 /usr/lib64/libcrypto.so.1.0.1e
sshd    1469 root  mem    REG  253,1    23968 16919827 /usr/lib64/libcap-ng.so.0.0.0
sshd    1469 root  mem    REG  253,1   155744 16919792 /usr/lib64/libselinux.so.1
sshd    1469 root  mem    REG  253,1    61672 17217839 /usr/lib64/libpam.so.0.83.1
sshd    1469 root  mem    REG  253,1   122936 16919829 /usr/lib64/libaudit.so.1.0.0
sshd    1469 root  mem    REG  253,1    42520 16996864 /usr/lib64/libwrap.so.0.7.6
sshd    1469 root  mem    REG  253,1    11328 17309963 /usr/lib64/libfipscheck.so.1.2.1
sshd    1469 root  mem    REG  253,1   155464 16878881 /usr/lib64/ld-2.17.so
sshd    1469 root    0u   CHR    1,3      0t0     1028 /dev/null
sshd    1469 root    1u   CHR    1,3      0t0     1028 /dev/null
sshd    1469 root    2u   CHR    1,3      0t0     1028 /dev/null
sshd    1469 root    3u  IPv4  17560      0t0      TCP *:ssh (LISTEN)
sshd    1469 root    4u  IPv6  17562      0t0      TCP *:ssh (LISTEN)



[参考ページ]




2017年1月29日日曜日

JobScheduler のXMLコマンドをcurlで実行する


JobSchedulerのOrderを登録したい場合は以下のようにします。
下記例のコマンドは、JobSchedulerEngine(ver1.10.6) をインストールしたサーバで実行しています。
[root@centos0702 sosjs]# curl -v -XPOST -d '<add_order job_chain="/test/job_chain3" at="now"/>' http://localhost:40444/jobscheduler/engine-cpp
* About to connect() to localhost port 40444 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 40444 (#0)
> POST /jobscheduler/engine-cpp HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:40444
> Accept: */*
> Content-Length: 50
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 50 out of 50 bytes
< HTTP/1.1 200 OK
< Content-Type: text/xml;charset=ISO-8859-1
< Date: Wed, 25 Jan 2017 11:26:35 GMT
< Transfer-Encoding: chunked
< Server: Jetty(8.1.16.v20140903)
<
<?xml version="1.0" encoding="ISO-8859-1"?>
<spooler>
   <answer time="2017-01-25T11:26:34.949Z">
      <ok>
         <order created="2017-01-25T11:26:34.951Z"
                id="4"
                initial_state="job01"
                job="/test/job01"
                job_chain="/test/job_chain3"
                order="4"
                path="/"
                priority="0"
                state="job01">
            <file_based state="not_initialized">
               <requisites/>
            </file_based>
         </order>
      </ok>
   </answer>
</spooler>
* Connection #0 to host localhost left intact

履歴を見る場合は以下のようにします。
[root@centos0702 sosjs]# curl -v -XPOST -d '<show_history job="/test/job01" what="job_chains"/>' http://localhost:40444/jobscheduler/engine-cpp
* About to connect() to localhost port 40444 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 40444 (#0)
> POST /jobscheduler/engine-cpp HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:40444
> Accept: */*
> Content-Length: 51
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 51 out of 51 bytes
< HTTP/1.1 200 OK
< Content-Type: text/xml;charset=ISO-8859-1
< Date: Wed, 25 Jan 2017 11:26:10 GMT
< Transfer-Encoding: chunked
< Server: Jetty(8.1.16.v20140903)
<
<?xml version="1.0" encoding="ISO-8859-1"?>
<spooler>
   <answer time="2017-01-25T11:26:10.359Z">
      <history>
         <history.entry cause="order"
                        end_time="2017-01-25T10:21:13.000Z"
                        error="0"
                        exit_code="0"
                        id="5"
                        job_name="test/job01"
                        pid="452"
                        spooler_id="scheduler"
                        start_time="2017-01-25T10:21:13.000Z"
                        steps="1"
                        task="5"/>
         <history.entry cause="order"
                        end_time="2017-01-25T10:12:28.000Z"
                        error="0"
                        exit_code="0"
                        id="4"
                        job_name="test/job01"
                        pid="449"
                        spooler_id="scheduler"
                        start_time="2017-01-25T10:12:27.000Z"
                        steps="1"
                        task="4"/>
      </history>
   </answer>
</spooler>
* Connection #0 to host localhost left intact



[参考ページ]





2017年1月28日土曜日

Pound と Apache で docker-compose(version2) を試す


下記のdocker-compose の日本語ドキュメントを参考にして、試してみました。
http://docs.docker.jp/index.html 
Pound コンテナ1個と Apache のコンテナを複数作成して、負荷分散してみます。
Dockerホストの環境は以下のとおり。
  • CentOS7
  • docker1.10.3
  • docker-compose1.10.0


docker-compose 設定


docke-compose でコンテナを作成して、動作確認できるように準備します。

ディレクトリ・ファイル構成


テスト用に作成したファイルは以下のとおり。
demo ディレクトリ以下に配置しました。
デフォルトだと、ディレクトリ名の demo が docker-compose のプロジェクト名として使用され、コンテナ名などに設定されます。
[root@centos0702 docker]# tree -F demo
demo
├── docker-compose-scale.yml
├── docker-compose.yml
├── http/
│   ├── Dockerfile
│   └── entry.sh*
└── pound/
    ├── Dockerfile
    └── entry.sh*

2 directories, 6 files
[root@centos0702 docker]# ls -Rl demo
demo:
合計 8
-rw-r--r-- 1 root root 114  1月 22 11:21 docker-compose-scale.yml
-rw-r--r-- 1 root root 233  1月 22 10:41 docker-compose.yml
drwxr-xr-x 2 root root  38  1月 22 11:19 http
drwxr-xr-x 2 root root  38  1月 22 11:21 pound

demo/http:
合計 8
-rw-r--r-- 1 root root  98  1月 21 22:46 Dockerfile
-rwxr-xr-x 1 root root 395  1月 22 11:19 entry.sh

demo/pound:
合計 8
-rw-r--r-- 1 root root  203  1月 22 11:20 Dockerfile
-rwxr-xr-x 1 root root 1400  1月 22 11:17 entry.sh

Webコンテナ


Webコンテナ構築用の Dockerfile は以下のとおり。
centos6 に apache をインストールして /entry.sh を ENTRYPOINT に設定します。
[root@centos0702 demo]# cat ./http/Dockerfile
FROM centos:6
MAINTAINER blue21
RUN yum -y install httpd
COPY entry.sh /
ENTRYPOINT ["/entry.sh"]

entry.sh の内容は以下のとおり。
コンテナのホスト名を index.html で返すようにして、Apache を起動します。
[root@centos0702 demo]# cat ./http/entry.sh
#!/bin/bash
###################################
# WebコンテナのEntryPoint
###################################

#----------------------------------
# 1. ホスト名を返す index.html 作成
#----------------------------------
uname -n > /var/www/html/index.html

#----------------------------------
# 2. ApacheHTTP 起動
#----------------------------------
/usr/sbin/httpd -D FOREGROUND

Poundコンテナ


Pound コンテナ構築用の Dockerfile は以下のとおり。
CentOS6 に Pound をインストールして /entry.sh を ENTRYPOINT に設定します。
[root@centos0702 demo]# cat ./pound/Dockerfile
FROM centos:6
MAINTAINER blue21
RUN yum -y install epel-release
RUN yum -y install Pound
COPY entry.sh /
ENTRYPOINT ["/entry.sh"]
# entry.sh の引数を指定する(Wbeコンテナの数)
CMD ["1"]

entry.sh の内容は以下のとおり。
/etc/pound.cfg を作成して、Pound を起動します。
バックエンドの数は、entry.sh の引数で指定します。
[root@centos0702 demo]# cat ./pound/entry.sh
#!/bin/bash
###################################
# PoundコンテナのEntryPoint
#
#   $1 : webコンテナ数
#
###################################

CONFIG_FILE='/etc/pound.cfg'
PARAMS="-f ${CONFIG_FILE}"

#----------------------------------
# 1. pound 設定ファイルの作成
#----------------------------------
cat<<EOF > ${CONFIG_FILE}
User "pound"
Group "pound"
Daemon 0
LogLevel 3
LogFacility local1
Alive 25

ListenHTTP
        Address 0.0.0.0
        Port    80
End
Service
        HeadRequire "Host: .*"
EOF

# 引数で指定された数のバックエンドを設定
#   コンテナ名で名前解決して IPアドレスを取得する
#   コンテナ名は <プロジェクト名>-<サービス名>-<連番>
#   プロジェクト名とサービス名は、docker-compose.yml で環境変数に設定
BACKEND_MAX=$1
BACKEND_HOSTNAME="${POUND_PROJECT_NAME}_${POUND_BACKEND_NAME}"
for ((i=1; i < ${BACKEND_MAX}+1; i++)); do
    ip=`host -4 -t a ${BACKEND_HOSTNAME}_${i} | awk '{print $4}'`
    echo "        BackEnd"               >> ${CONFIG_FILE}
    echo "                Address ${ip}" >> ${CONFIG_FILE}
    echo "                Port    80"    >> ${CONFIG_FILE}
    echo "        End"                   >> ${CONFIG_FILE}
done

echo "End" >> ${CONFIG_FILE}

#----------------------------------
# 2. pound の起動
#----------------------------------
/usr/sbin/pound ${PARAMS}

基本構成(docker-compose.yml)


コンテナの基本構成を定義します。デフォルトで、このファイルが使用されます。
pound コンテナと web コンテナが 1個づつです。
pound コンテナは、entry.sh の渡す環境変数を定義し、webコンテナが先に起動するように依存関係を設定しています。
[root@centos0702 demo]# cat docker-compose.yml
version: '2'
services:
  web:
    build: ./http
    image: centos6_http
  pound:
    build: ./pound
    image: centos6_pound
    environment:
      - POUND_PROJECT_NAME=demo
      - POUND_BACKEND_NAME=web
    depends_on:
      - web

スケールアウト構成(docker-compose-scale.yml)


webコンテナが2台にスケールアウトしたときの構成を定義します。
上記の基本構成との差分のみ設定しています。
command で entry.sh の引数 を 2 に変更し、WEBコンテナ2台をバックエンドにします。
80 ポートを公開して外部から pound コンテナにアクセスできるようにします。
[root@centos0702 demo]# cat docker-compose-scale.yml
version: '2'
services:
  pound:
    environment:
      - DEBUG=on
    ports:
      - "80:80"
    command: [ "2" ]


動作確認


準備ができたので、docker-compose コマンドを実行して試していきます。
docker-compose.yml のあるディレクトリで docker-compose コマンドを実行します。

コンテナのイメージ作成


webコンテナとpoundコンテナのイメージを作成してローカルに保存します。
[root@centos0702 demo]# docker-compose build
Building web
Step 1 : FROM centos:6
 ---> 8315978ceaaa
Step 2 : MAINTAINER blue21
 ---> Running in c9f0ef882d96
 ---> 9de1ba110090
~省略~
Removing intermediate container 458db4b56969
Step 7 : CMD 1
 ---> Running in 36c142efba74
 ---> 104519202f48
Removing intermediate container 36c142efba74
Successfully built 104519202f48

ローカルのイメージを確認します。centos6_http と centos6_pound が作成されたイメージです。
[root@centos0702 demo]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos6_pound       latest              104519202f48        3 minutes ago       547.6 MB
centos6_http        latest              5f6b06a8687e        9 minutes ago       501.9 MB

基本構成のコンテナ起動


デタッチモードでコンテナを起動します。依存関係を設定しているので webコンテナ→pound コンテナの順番で起動します。
[root@centos0702 demo]# docker-compose up -d
Creating network "demo_default" with the default driver
Creating demo_web_1
Creating demo_pound_1

コンテナの状態を確認します。
webコンテナとpoundコンテナが1台づつ起動しています。
コンテナ名は、自動的に設定されます。
[root@centos0702 demo]# docker-compose ps
    Name         Command     State   Ports
------------------------------------------
demo_pound_1   /entry.sh 1   Up
demo_web_1     /entry.sh     Up

webコンテナでコマンドを実行して、ホスト名を確認します。
[root@centos0702 demo]# docker-compose exec web uname -n
af210e87d396

pound コンテナでコマンド実行して、pound経由でwebコンテナにリクエストしてみます。
webコンテナのホスト名が表示されたらOKです。
[root@centos0702 demo]# docker-compose exec pound curl -s http://localhost
af210e87d396

webコンテナのスケールアウト


webコンテナを2台に増やしてみます。
[root@centos0702 demo]# docker-compose scale web=2
Creating and starting demo_web_2 ... done

コンテナを確認すると web コンテナが1台追加されて2台に増えています。
[root@centos0702 demo]# docker-compose ps
    Name         Command     State   Ports
------------------------------------------
demo_pound_1   /entry.sh 1   Up
demo_web_1     /entry.sh     Up
demo_web_2     /entry.sh     Up


pound コンテナの再構築


バックエンドが2台になるようにpoundコンテナを再構築します。
まず、スケールアウト用の差分設定をマージして設定内容を確認してみます
[root@centos0702 demo]# docker-compose -f docker-compose.yml -f docker-compose-scale.yml config
networks: {}
services:
  pound:
    build:
      context: /root/workspace/docker/demo/pound
    command:
    - '2'
    depends_on:
    - web
    environment:
      DEBUG: 'on'
      POUND_BACKEND_NAME: web
      POUND_PROJECT_NAME: demo
    image: centos6_pound
    ports:
    - 80:80
  web:
    build:
      context: /root/workspace/docker/demo/http
    image: centos6_http
version: '2.0'
volumes: {}

pound コンテナを作り直して置き換えます。
--no-deps を指定すると依存関係を無視して pound だけ再構築します。
[root@centos0702 demo]# docker-compose -f docker-compose.yml -f docker-compose-scale.yml up -d --no-deps pound
Recreating demo_pound_1

コンテナを確認します。
entry.sh の引数が "2" になり、80ポートが公開されています。
[root@centos0702 demo]# docker-compose ps
    Name         Command     State         Ports
-------------------------------------------------------
demo_pound_1   /entry.sh 2   Up      0.0.0.0:80->80/tcp
demo_web_1     /entry.sh     Up
demo_web_2     /entry.sh     Up

Dockerホストからリクエストすると、poundコンテナが負荷分散してwebコンテナ2台のホスト名が表示されます。
[root@centos0702 demo]# curl -s http://localhost
4bd9e6481714
[root@centos0702 demo]# curl -s http://localhost
af210e87d396
[root@centos0702 demo]# curl -s http://localhost
4bd9e6481714
[root@centos0702 demo]# curl -s http://localhost
4bd9e6481714
[root@centos0702 demo]# curl -s http://localhost
af210e87d396

pound の設定ファイルを見ると、バックエンドが2台になっています。
[root@centos0702 demo]# docker-compose exec pound cat /etc/pound.cfg
User "pound"
Group "pound"
Daemon 0
LogLevel 3
LogFacility local1
Alive 25

ListenHTTP
        Address 0.0.0.0
        Port    80
End
Service
        HeadRequire "Host: .*"
        BackEnd
                Address 172.18.0.2
                Port    80
        End
        BackEnd
                Address 172.18.0.4
                Port    80
        End
End

コンテナの破棄


以下のようにコンテナを破棄できます。
起動中のコンテナを停止して削除します。
[root@centos0702 demo]# docker-compose down
Stopping demo_pound_1 ... done
Stopping demo_web_2 ... done
Stopping demo_web_1 ... done
Removing demo_pound_1 ... done
Removing demo_web_2 ... done
Removing demo_web_1 ... done
Removing network demo_default







2017年1月27日金曜日

docker-compose でJobSchedulerAgnet クラスタを試す

下記ページを参考に、JobSchedulerAgnetクラスタを試してみます。
https://kb.sos-berlin.com/display/PKB/How+to+use+Agents+with+Fixed+Priority+Scheduling+and+Round-Robin+Scheduling
docker-compose で JobScheduler Agent を使う」で構築したテスト環境を使用します。


docker-compose でテスト環境の起動


docker-compose でテスト環境を起動して、js_agnet コンテナを2台に増やします。
[root@centos0702 sosjs]# docker-compose up -d
Creating sosjs_db_1
Creating sosjs_js_agent_1
Creating sosjs_datastore_1
Creating sosjs_jobscheduler_1
[root@centos0702 sosjs]# docker-compose scale js_agent=2
Creating and starting sosjs_js_agent_2 ... done

コンテナの状態を確認します。
[root@centos0702 sosjs]# docker-compose ps
        Name                      Command               State                               Ports
----------------------------------------------------------------------------------------------------------------------------
sosjs_datastore_1      /bin/true                        Exit 0
sosjs_db_1             docker-entrypoint.sh mysqld      Up       3306/tcp
sosjs_jobscheduler_1   bash /opt/startup_scheduler.sh   Up       0.0.0.0:40444->40444/tcp, 0.0.0.0:4444->4444/tcp, 48444/tcp
sosjs_js_agent_1       /root/jobscheduler_agent/b ...   Up
sosjs_js_agent_2       /root/jobscheduler_agent/b ...   Up

js_agentコンテナの IPアドレスを確認します。
[root@centos0702 sosjs]# docker inspect sosjs_js_agent_1 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAddress": "172.17.0.3",
[root@centos0702 sosjs]# docker inspect sosjs_js_agent_2 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.5",
                    "IPAddress": "172.17.0.5",

プロセスクラスを定義


js_agentコンテナでジョブを実行するためにプロセスクラスを定義します。
以下は、Primary/Fallback型です。通常は sosjs_js_agent_1 でジョブを実行します。
sosjs_js_agent_1 がダウンすると、 sosjs_js_agnet_2 でジョブを実行します。
sosjs_js_agnet_1 が復旧しれば、sosjs_js_agnet_1 でジョブが実行されます。
[root@centos0702 sosjs]# cat ./live/test/fallback.process_class.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<process_class>
    <remote_schedulers select="first">
        <remote_scheduler  remote_scheduler="http://172.17.0.3:4445"/>
        <remote_scheduler  remote_scheduler="http://172.17.0.5:4445"/>
    </remote_schedulers>
</process_class>

以下は、Raundrobin型です。 sosjs_js_agent_1 と sosjs_js_agent_2 を交互に使用してジョブを実行します。
[root@centos0702 sosjs]# cat ./live/test/raundrobin.process_class.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<process_class>
    <remote_schedulers select="next">
        <remote_scheduler  remote_scheduler="http://172.17.0.3:4445"/>
        <remote_scheduler  remote_scheduler="http://172.17.0.5:4445"/>
    </remote_schedulers>
</process_class>

JobChain を定義


上記のプロセスクラスを使うJobChainを定義します。
job_chain1 は Primary/Fallback 型です。
[root@centos0702 sosjs]# cat ./live/test/job_chain1.job_chain.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain  process_class="fallback">
    <job_chain_node  state="job01" job="job01" next_state="success" error_state="error"/>
    <job_chain_node  state="success"/>
    <job_chain_node  state="error"/>
</job_chain>

job_chain2 は Raundrobin 型です。
[root@centos0702 sosjs]# cat ./live/test/job_chain2.job_chain.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain  process_class="raundrobin">
    <job_chain_node  state="job01" job="job01" next_state="success" error_state="error"/>
    <job_chain_node  state="success"/>
    <job_chain_node  state="error"/>
</job_chain>

ジョブはIPアドレスを表示します。
[root@centos0702 sosjs]# cat ./live/test/job01.job.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<job  order="yes">
    <script  language="shell">
        <![CDATA[
ip a
        ]]>
    </script>
    <run_time />
</job>

Primary/Fallback型の動作確認


sosjs_js_agent_1 と sosjs_js_agnet_2 が起動している状態で、job_chain1 を実行してログを見てみます。
何回実行しても sosjs_js_agent_1 でジョブが実行されます。
2017-01-24 05:29:13.507Z [info]   (Task test/job01:5) SCHEDULER-842  Task is going to process Order test/job_chain1:2, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/fallback
2017-01-24 05:29:13.509Z [info]   (Task test/job01:5) 
2017-01-24 05:29:13.509Z [info]   (Task test/job01:5) Task test/job01:5 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:29:22.519Z [info]   (Task test/job01:5) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.3:4445
2017-01-24 05:29:22.519Z [info]   (Task test/job01:5) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:29:24.838Z [info]   (Task test/job01:5) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:29:24.853Z [info]   (Task test/job01:5) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:29:24.873Z [info]   (Task test/job01:5) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:29:24.890Z [info]   (Task test/job01:5) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:29:24.906Z [info]   (Task test/job01:5) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:29:24.921Z [info]   (Task test/job01:5) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:29:24.936Z [info]   (Task test/job01:5) [stdout] 18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:29:24.954Z [info]   (Task test/job01:5) [stdout]     link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:29:24.972Z [info]   (Task test/job01:5) [stdout]     inet 172.17.0.3/16 scope global eth0
2017-01-24 05:29:24.990Z [info]   (Task test/job01:5) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:29:25.007Z [info]   (Task test/job01:5) [stdout]     inet6 fe80::42:acff:fe11:3/64 scope link 
2017-01-24 05:29:25.022Z [info]   (Task test/job01:5) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:29:25.196Z [info]   (Task test/job01:5) SCHEDULER-843  Task has ended processing of Order test/job_chain1:2, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:29:25.289Z [info]   set_state success
2017-01-24 05:29:25.324Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:29:25.324Z [info]   SCHEDULER-940  Removing order from job chain

sosjs_js_agent_1 を停止します。
[root@centos0702 sosjs]# docker stop sosjs_js_agent_1
sosjs_js_agent_1
[root@centos0702 sosjs]# docker-compose ps
        Name                      Command                State                                Ports
------------------------------------------------------------------------------------------------------------------------------
sosjs_datastore_1      /bin/true                        Exit 0
sosjs_db_1             docker-entrypoint.sh mysqld      Up         3306/tcp
sosjs_jobscheduler_1   bash /opt/startup_scheduler.sh   Up         0.0.0.0:40444->40444/tcp, 0.0.0.0:4444->4444/tcp, 48444/tcp
sosjs_js_agent_1       /root/jobscheduler_agent/b ...   Exit 137
sosjs_js_agent_2       /root/jobscheduler_agent/b ...   Up

job_chain1 を実行してログを見てみます。
sosjs_js_agnet_1 にアクセスできないので sosjs_js_agnet_2 でジョブを実行しています。
2017-01-24 05:34:33.204Z [info]   (Task test/job01:7) SCHEDULER-842  Task is going to process Order test/job_chain1:4, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/fallback
2017-01-24 05:34:33.206Z [info]   (Task test/job01:7) 
2017-01-24 05:34:33.206Z [info]   (Task test/job01:7) Task test/job01:7 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:34:36.726Z [WARN]   (Task test/job01:7) SCHEDULER-488  This remote JobScheduler 'Agent(0,http://172.17.0.3:4445,None)' is not accessible: spray.can.Http$ConnectionAttemptFailedException: Connection attempt to 172.17.0.3:4445 failed
2017-01-24 05:34:40.536Z [info]   (Task test/job01:7) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.5:4445
2017-01-24 05:34:40.537Z [info]   (Task test/job01:7) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:34:41.807Z [info]   (Task test/job01:7) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:34:41.829Z [info]   (Task test/job01:7) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:34:41.848Z [info]   (Task test/job01:7) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:34:41.905Z [info]   (Task test/job01:7) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:34:41.952Z [info]   (Task test/job01:7) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:34:42.016Z [info]   (Task test/job01:7) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:34:42.043Z [info]   (Task test/job01:7) [stdout] 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:34:42.070Z [info]   (Task test/job01:7) [stdout]     link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:34:42.095Z [info]   (Task test/job01:7) [stdout]     inet 172.17.0.5/16 scope global eth0
2017-01-24 05:34:42.119Z [info]   (Task test/job01:7) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:34:42.143Z [info]   (Task test/job01:7) [stdout]     inet6 fe80::42:acff:fe11:5/64 scope link 
2017-01-24 05:34:42.162Z [info]   (Task test/job01:7) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:34:42.283Z [info]   (Task test/job01:7) SCHEDULER-843  Task has ended processing of Order test/job_chain1:4, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:34:42.284Z [info]   set_state success
2017-01-24 05:34:42.284Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:34:42.285Z [info]   SCHEDULER-940  Removing order from job chain

sosjs_js_agnet_1 を起動して復旧します。
[root@centos0702 sosjs]# docker start sosjs_js_agent_1
sosjs_js_agent_1
[root@centos0702 sosjs]# docker-compose ps
        Name                      Command               State                               Ports
----------------------------------------------------------------------------------------------------------------------------
sosjs_datastore_1      /bin/true                        Exit 0
sosjs_db_1             docker-entrypoint.sh mysqld      Up       3306/tcp
sosjs_jobscheduler_1   bash /opt/startup_scheduler.sh   Up       0.0.0.0:40444->40444/tcp, 0.0.0.0:4444->4444/tcp, 48444/tcp
sosjs_js_agent_1       /root/jobscheduler_agent/b ...   Up
sosjs_js_agent_2       /root/jobscheduler_agent/b ...   Up

job_chain1 を実行します。
sosjs_js_agent_1 でジョブが実行されます。
2017-01-24 05:42:40.483Z [info]   (Task test/job01:8) SCHEDULER-842  Task is going to process Order test/job_chain1:5, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/fallback
2017-01-24 05:42:40.484Z [info]   (Task test/job01:8) 
2017-01-24 05:42:40.484Z [info]   (Task test/job01:8) Task test/job01:8 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:42:41.698Z [info]   (Task test/job01:8) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.3:4445
2017-01-24 05:42:41.698Z [info]   (Task test/job01:8) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:42:42.574Z [info]   (Task test/job01:8) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:42:42.597Z [info]   (Task test/job01:8) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:42:42.616Z [info]   (Task test/job01:8) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:42:42.634Z [info]   (Task test/job01:8) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:42:42.665Z [info]   (Task test/job01:8) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:42:42.687Z [info]   (Task test/job01:8) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:42:42.714Z [info]   (Task test/job01:8) [stdout] 26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:42:42.745Z [info]   (Task test/job01:8) [stdout]     link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:42:42.768Z [info]   (Task test/job01:8) [stdout]     inet 172.17.0.3/16 scope global eth0
2017-01-24 05:42:42.797Z [info]   (Task test/job01:8) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:42:42.839Z [info]   (Task test/job01:8) [stdout]     inet6 fe80::42:acff:fe11:3/64 scope link 
2017-01-24 05:42:42.862Z [info]   (Task test/job01:8) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:42:43.015Z [info]   (Task test/job01:8) SCHEDULER-843  Task has ended processing of Order test/job_chain1:5, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:42:43.025Z [info]   set_state success
2017-01-24 05:42:43.026Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:42:43.026Z [info]   SCHEDULER-940  Removing order from job chain

Raundrobin型の動作確認


sosjs_js_agent_1 と sosjs_js_agnet_2 が起動している状態で、job_chain2 を実行してログを見てみます。
1回名は sosjs_js_agnet_1 でジョブが実行されました。
2017-01-24 05:45:40.868Z [info]   (Task test/job01:9) SCHEDULER-842  Task is going to process Order test/job_chain2:6, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/raundrobin
2017-01-24 05:45:40.869Z [info]   (Task test/job01:9) 
2017-01-24 05:45:40.869Z [info]   (Task test/job01:9) Task test/job01:9 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:45:40.998Z [info]   (Task test/job01:9) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.3:4445
2017-01-24 05:45:40.998Z [info]   (Task test/job01:9) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:45:41.311Z [info]   (Task test/job01:9) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:45:41.323Z [info]   (Task test/job01:9) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:45:41.338Z [info]   (Task test/job01:9) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:45:41.859Z [info]   (Task test/job01:9) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:45:41.875Z [info]   (Task test/job01:9) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:45:41.889Z [info]   (Task test/job01:9) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:45:41.905Z [info]   (Task test/job01:9) [stdout] 26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:45:41.918Z [info]   (Task test/job01:9) [stdout]     link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:45:41.930Z [info]   (Task test/job01:9) [stdout]     inet 172.17.0.3/16 scope global eth0
2017-01-24 05:45:41.942Z [info]   (Task test/job01:9) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:45:41.965Z [info]   (Task test/job01:9) [stdout]     inet6 fe80::42:acff:fe11:3/64 scope link 
2017-01-24 05:45:41.977Z [info]   (Task test/job01:9) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:45:42.017Z [info]   (Task test/job01:9) SCHEDULER-843  Task has ended processing of Order test/job_chain2:6, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:45:42.018Z [info]   set_state success
2017-01-24 05:45:42.018Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:45:42.018Z [info]   SCHEDULER-940  Removing order from job chain

2回目は、sosjs_js_agnet_2 でジョブが実行されました。
2017-01-24 05:46:45.830Z [info]   (Task test/job01:10) SCHEDULER-842  Task is going to process Order test/job_chain2:7, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/raundrobin
2017-01-24 05:46:45.831Z [info]   (Task test/job01:10) 
2017-01-24 05:46:45.831Z [info]   (Task test/job01:10) Task test/job01:10 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:46:45.949Z [info]   (Task test/job01:10) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.5:4445
2017-01-24 05:46:45.950Z [info]   (Task test/job01:10) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:46:46.313Z [info]   (Task test/job01:10) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:46:46.330Z [info]   (Task test/job01:10) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:46:46.348Z [info]   (Task test/job01:10) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:46:46.361Z [info]   (Task test/job01:10) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:46:46.373Z [info]   (Task test/job01:10) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:46:46.384Z [info]   (Task test/job01:10) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:46:46.396Z [info]   (Task test/job01:10) [stdout] 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:46:46.408Z [info]   (Task test/job01:10) [stdout]     link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:46:46.421Z [info]   (Task test/job01:10) [stdout]     inet 172.17.0.5/16 scope global eth0
2017-01-24 05:46:46.657Z [info]   (Task test/job01:10) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:46:46.675Z [info]   (Task test/job01:10) [stdout]     inet6 fe80::42:acff:fe11:5/64 scope link 
2017-01-24 05:46:46.693Z [info]   (Task test/job01:10) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:46:46.738Z [info]   (Task test/job01:10) SCHEDULER-843  Task has ended processing of Order test/job_chain2:7, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:46:46.739Z [info]   set_state success
2017-01-24 05:46:46.739Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:46:46.739Z [info]   SCHEDULER-940  Removing order from job chain

sosjs_js_agnet_1 を停止します。
[root@centos0702 sosjs]# docker stop sosjs_js_agent_1
sosjs_js_agent_1
[root@centos0702 sosjs]# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                                         NAMES
4779e1feeeb3        js_agent                   "/root/jobscheduler_a"   37 minutes ago      Up 37 minutes                                                                     sosjs_js_agent_2
e0c8b2f803c6        floedermann/jobscheduler   "bash /opt/startup_sc"   55 minutes ago      Up 55 minutes       0.0.0.0:4444->4444/tcp, 0.0.0.0:40444->40444/tcp, 48444/tcp   sosjs_jobscheduler_1
42db58764992        mariadb                    "docker-entrypoint.sh"   55 minutes ago      Up 55 minutes       3306/tcp                                                      sosjs_db_1

job_chain2 を実行してみます。
sosjs_js_agnet_1 にアクセスできなければ、sosjs_js_agnet_2 でジョブを実行します。
2017-01-24 05:49:25.811Z [info]   (Task test/job01:11) SCHEDULER-842  Task is going to process Order test/job_chain2:8, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444', Order's Process_class test/raundrobin
2017-01-24 05:49:25.812Z [info]   (Task test/job01:11) 
2017-01-24 05:49:25.812Z [info]   (Task test/job01:11) Task test/job01:11 - Protocol starts in /opt/jobscheduler/data/scheduler/logs/task.test,job01.log
2017-01-24 05:49:28.871Z [WARN]   (Task test/job01:11) SCHEDULER-488  This remote JobScheduler 'Agent(0,http://172.17.0.3:4445,None)' is not accessible: spray.can.Http$ConnectionAttemptFailedException: Connection attempt to 172.17.0.3:4445 failed
2017-01-24 05:49:29.000Z [info]   (Task test/job01:11) SCHEDULER-726  Task runs on remote scheduler http://172.17.0.5:4445
2017-01-24 05:49:29.000Z [info]   (Task test/job01:11) SCHEDULER-918  state=starting (at=never)
2017-01-24 05:49:29.223Z [info]   (Task test/job01:11) [stdout] 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
2017-01-24 05:49:29.234Z [info]   (Task test/job01:11) [stdout]     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2017-01-24 05:49:29.249Z [info]   (Task test/job01:11) [stdout]     inet 127.0.0.1/8 scope host lo
2017-01-24 05:49:29.266Z [info]   (Task test/job01:11) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:49:29.290Z [info]   (Task test/job01:11) [stdout]     inet6 ::1/128 scope host 
2017-01-24 05:49:29.303Z [info]   (Task test/job01:11) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:49:29.317Z [info]   (Task test/job01:11) [stdout] 24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
2017-01-24 05:49:29.334Z [info]   (Task test/job01:11) [stdout]     link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
2017-01-24 05:49:29.346Z [info]   (Task test/job01:11) [stdout]     inet 172.17.0.5/16 scope global eth0
2017-01-24 05:49:29.360Z [info]   (Task test/job01:11) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:49:29.373Z [info]   (Task test/job01:11) [stdout]     inet6 fe80::42:acff:fe11:5/64 scope link 
2017-01-24 05:49:29.385Z [info]   (Task test/job01:11) [stdout]        valid_lft forever preferred_lft forever
2017-01-24 05:49:29.421Z [info]   (Task test/job01:11) SCHEDULER-843  Task has ended processing of Order test/job_chain2:8, state=job01, on JobScheduler 'http://e0c8b2f803c6:4444'
2017-01-24 05:49:29.422Z [info]   set_state success
2017-01-24 05:49:29.422Z [info]   SCHEDULER-945  No further job in job chain - order has been carried out
2017-01-24 05:49:29.422Z [info]   SCHEDULER-940  Removing order from job chain







2017年1月26日木曜日

docker-compose で JobScheduler Agent を使う


docker-comose で JobScheduler のテスト環境を作る」で構築した JobSchedulerのテスト環境に JobSchedulerAgent をインストールしたコンテナを追加します。


JobScheduler Agent のイメージ作成


JobScheduler Agent の Dockerfile を作成します。
内容は以下のとおり。
[root@centos0702 js_agent]# cat Dockerfile
FROM java:8-jre
WORKDIR /root

RUN wget https://download.sos-berlin.com/JobScheduler.1.10/jobscheduler_unix_universal_agent.1.10.0.tar.gz && \
tar xfvz jobscheduler_unix_universal_agent.1.10.0.tar.gz

CMD ["/root/jobscheduler_agent/bin/jobscheduler_agent.sh", "start_docker"]

イメージを作成します。
[root@centos0702 js_agent]# docker build -t js_agent .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM java:8-jre
 ---> e44d62cf8862
Step 2 : WORKDIR /root
 ---> Using cache
 ---> 929d91235aed
Step 3 : RUN wget https://download.sos-berlin.com/JobScheduler.1.10/jobscheduler_unix_universal_agent.1.10.0.tar.gz && tar xfvz jobscheduler_unix_universal_agent.1.10.0.tar.gz
 ---> Using cache
 ---> ba19b86027e9
Step 4 : CMD /root/jobscheduler_agent/bin/jobscheduler_agent.sh start_docker
 ---> Using cache
 ---> df211a9ec34d
Successfully built df211a9ec34d

イメージを確認します。
[root@centos0702 js_agent]# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
js_agent                             latest              df211a9ec34d        About an hour ago   445.8 MB

docker-compose に追加


「docker-comose で JobScheduler のテスト環境を作る」で作成した docker-compose.yml に JobSchedulerAgent のコンテナを追加します。(赤字部分)
[root@centos0702 sosjs]# cat docker-compose.yml
jobscheduler:
  image: floedermann/jobscheduler
  links:
    - db:mysql
  volumes_from:
    - datastore
  ports:
    - "4444:4444"
    - "40444:40444"

db:
  image: mariadb
  environment:
    MYSQL_USER: jobscheduler
    MYSQL_PASSWORD: jobscheduler
    MYSQL_ROOT_PASSWORD: scheduler
    MYSQL_DATABASE: jobscheduler

datastore:
   image: busybox
   command: /bin/true
   volumes:
     - ./live:/opt/jobscheduler/data/scheduler/config/live

js_agent:
   image: js_agent

コンテナの起動


JobScheduler のテスト環境を起動します。
[root@centos0702 sosjs]# docker-compose up -d
Creating sosjs_datastore_1
Creating sosjs_db_1
Creating sosjs_js_agent_1
Creating sosjs_jobscheduler_1

コンテナの状態を確認します。 sosjs_js_agent_1 がJobSchedulerAngetコンテナです。
[root@centos0702 sosjs]# docker-compose ps
            Name                         Command                         State                          Ports
-------------------------------------------------------------------------------------------------------------------------
sosjs_datastore_1              /bin/true                      Exit 0
sosjs_db_1                     docker-entrypoint.sh mysqld    Up                             3306/tcp
sosjs_jobscheduler_1           bash                           Up                             0.0.0.0:40444->40444/tcp,
                               /opt/startup_scheduler.sh                                     0.0.0.0:4444->4444/tcp,
                                                                                             48444/tcp
sosjs_js_agent_1               /root/jobscheduler_agent/b     Up
                               ...

sosjs_js_agent_1 のIPアドレスを確認します。
[root@centos0702 sosjs]# docker inspect sosjs_js_agent_1 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.4",
                    "IPAddress": "172.17.0.4",

JOB動作確認


sosjs_js_agent_1 でジョブを実行するために、プロセスクラスを定義します。
[root@centos0702 sosjs]# cat ./live/js_agent01.process_class.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<process_class  max_processes="10" remote_scheduler="http://172.17.0.4:4445"/>

sosjs_js_agent_1 で実行する JobChain と Job を定義します。
Job は IPアドレスを表示します。
[root@centos0702 sosjs]# cat ./live/job_chain1.job_chain.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain  process_class="js_agent01">
    <job_chain_node  state="job01" job="job01" next_state="success" error_state="error"/>
    <job_chain_node  state="success"/>
    <job_chain_node  state="error"/>
</job_chain>
[root@centos0702 sosjs]# cat ./live/job01.job.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<job  order="yes">
    <script  language="shell">
        <![CDATA[
ip a
        ]]>
    </script>
    <run_time />
</job>

JOC でJobChainを実行して確認してみます。
プロセスクラスは下図のとおり


JobChain は下図のとおり


Job実行結果を見ると下図のとおり。
sosjs_js_agent_1 のIPアドレスが表示されます。






2017年1月25日水曜日

docker-comose で JobScheduler のテスト環境を作る


DockerHUB で公開している SOS JobScheduler のイメージを使って簡単にテスト環境を作れます。

使用した環境は以下のとおり。VirtualBoxの仮想マシンを使用しています。
  • Dockerホスト: CentOS7.3
  • Docker: 1.10.3

docker-compose インストール


まず、Dockerホストに docker-compose をインストールします。
[root@centos0702 sosjs]# pip install docker-compose

docker-compose.yml 作成


次に docker-compose の 設定ファイルを作成します。
今回は、sosjs ディレクトリを作って、そこに設定ファイルを作りました。
[root@centos0702 sosjs]# cat docker-compose.yml
jobscheduler:
  image: floedermann/jobscheduler
  links:
    - db:mysql
  volumes_from:
    - datastore
  ports:
    - "4444:4444"
    - "40444:40444"

db:
  image: mariadb
  environment:
    MYSQL_USER: jobscheduler
    MYSQL_PASSWORD: jobscheduler
    MYSQL_ROOT_PASSWORD: scheduler
    MYSQL_DATABASE: jobscheduler

datastore:
   image: busybox
   command: /bin/true
   volumes:
     - /opt/jobscheduler/data/scheduler/config/live

dockerコンテナ起動


上記の docker-compose.yml があるディレクトリで下記コマンドを実行すると、DockerHUBからイメージをダウンロードしてDockerコンテナが起動します。
[root@centos0702 sosjs]# docker-compose up -d
Pulling db (mariadb:latest)...
Trying to pull repository docker.io/library/mariadb ...
latest: Pulling from docker.io/library/mariadb
5040bd298390: Pull complete
55370df68315: Pull complete
fad5195d69cc: Pull complete
a1034a5fbbfc: Pull complete
eb46f36a6163: Pull complete
de7067e4ea0a: Pull complete
fc40d1291bb9: Pull complete
aff5d18aeeef: Pull complete
1c729aed3f3d: Pull complete
ed7e90870837: Pull complete
8ae91f5b8acf: Pull complete
aa554fbac13d: Pull complete
Digest: sha256:ed04792bb13c111cbd1743c2921ea6cf777051a7f7f51f7b134efec9af7afdad
Status: Downloaded newer image for docker.io/mariadb:latest
Pulling datastore (busybox:latest)...
Trying to pull repository docker.io/library/busybox ...
latest: Pulling from docker.io/library/busybox
4b0bc1c4050b: Pull complete
Digest: sha256:817a12c32a39bbe394944ba49de563e085f1d3c5266eb8e9723256bc4448680e
Status: Downloaded newer image for docker.io/busybox:latest
Pulling jobscheduler (floedermann/jobscheduler:latest)...
Trying to pull repository docker.io/floedermann/jobscheduler ...
latest: Pulling from docker.io/floedermann/jobscheduler
386a066cd84a: Pull complete
75ea84187083: Pull complete
88b459c9f665: Pull complete
690dbea0e4ca: Pull complete
7e401cdd6f18: Pull complete
a58186ddf9a0: Pull complete
49999ed55bc4: Pull complete
eb40561aad8f: Pull complete
5e1e63d48c1f: Pull complete
09d7ed6ff6b2: Pull complete
6ba4b48aec7a: Pull complete
f8db429f8b8b: Pull complete
Digest: sha256:79e7ce0cf75c6f3ceddb36c4f1d26a8cf907e8504a77c5afb402c59efd5d5290
Status: Downloaded newer image for docker.io/floedermann/jobscheduler:latest
Creating sosjs_datastore_1
Creating sosjs_db_1
Creating sosjs_jobscheduler_1

これでテスト環境の出来上がりです。Dockerコンテナは3つ作成されました。
[root@centos0702 sosjs]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                     PORTS                                                         NAMES
d176b06f4975        floedermann/jobscheduler   "bash /opt/startup_sc"   5 minutes ago       Up 5 minutes               0.0.0.0:4444->4444/tcp, 0.0.0.0:40444->40444/tcp, 48444/tcp   sosjs_jobscheduler_1
028298731ab1        mariadb                    "docker-entrypoint.sh"   5 minutes ago       Up 5 minutes               3306/tcp                                                      sosjs_db_1
969de82ce298        busybox                    "/bin/true"              5 minutes ago       Exited (0) 5 minutes ago                                                                 sosjs_datastore_1

sosjs_jobscheduler_1とsosjs_db_1 は Up しています。
sosjs_datastore_1 は live フォルダを Dockerホストのディレクトリにマウントするだけなので、Status は Exited でOKです。

JobSchedulerの起動に成功していれば、以下のようにログが表示されます。
[root@centos0702 sosjs]# docker logs sosjs_jobscheduler_1 2>&1 | tail
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8f284b8000)
        libstdc++.so.6 => /opt/jobscheduler/scheduler/lib/libstdc++.so.6 (0x00007f8f281a1000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8f27ea0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8f27af5000)
        libgcc_s.so.1 => /opt/jobscheduler/scheduler/lib/libgcc_s.so.1 (0x00007f8f278de000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8f29311000)
Starting JobScheduler...
[ Processing finished ]
[ Writing the uninstaller data ... ]
[ Automated installation done ]

JOCへのアクセス


JOC にアクセスしたい場合は下記URLです。
http://<DockerホストのIPアドレス>:4444/
下図のように JOC が表示されます。
JobScheduler のバージョンは、1.10.6 です。


liveフォルダでのJOB定義


JOEは付属していないので、エディタでJOB定義のXMLファイル作成して live フォルダに格納します。
jobschedulerコンテナの live フォルダは、Dockerホストにマウントされています。
下記コマンドで、マウント先のディレクトリを探します。
[root@centos0702 sosjs]# docker inspect sosjs_jobscheduler_1 | grep -A 10 '"Mounts": '
        "Mounts": [
            {
                "Name": "8d80484c3b0c346960bfb10f49eb634b55e726e53096af5e49392ffee849e55c",
                "Source": "/var/lib/docker/volumes/8d80484c3b0c346960bfb10f49eb634b55e726e53096af5e49392ffee849e55c/_data",
                "Destination": "/opt/jobscheduler/data/scheduler/config/live",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

赤字部分が、Dockerホストのマウント先です。
ここに ジョブ定義の xml ファイルなどを格納すればテストできます。
[root@centos0702 sosjs]# ls /var/lib/docker/volumes/8d80484c3b0c346960bfb10f49eb634b55e726e53096af5e49392ffee849e55c/_data
sos

コンテナの入れ替え


liveフォルダのマウント先がわかりずらいので任意の場所に変更してみます。
docker-compose.yml を修正します。
下記の例では、docker-compose.yml と同じ場所にある live ディレクトリにマウントします。
datastore:
   image: busybox
   command: /bin/true
   volumes:
     - ./live:/opt/jobscheduler/data/scheduler/config/live

下記コマンドを実行するとコンテナを作り直して、入れ替えてくれます。
[root@centos0702 sosjs]# docker-compose up -d
sosjs_db_1 is up-to-date
Recreating sosjs_datastore_1
Recreating sosjs_jobscheduler_1

これで、JOB定義を置く場所が、./live ディレクトリに変更になります。
[root@centos0702 sosjs]# ls -l
合計 4
-rw-r--r-- 1 root root 473  1月 24 09:44 docker-compose.yml
drwxr-xr-x 5 root root  48  1月 23 22:53 live

コンテナへのアクセス


デフォルトは英語環境なので、日本語環境に設定変更したい場合などはJobSchedulerコンテナに入ります。
JobSchedulerのDockerコンテナに入りたい場合は以下のようにします。
JobScheduler は /opt と /root/install にインストールされています。
[root@centos0702 sosjs]# docker exec -it sosjs_jobscheduler_1 /bin/bash
root@d176b06f4975:/# ls /opt/
jobscheduler  startup_scheduler.sh

DB(mariadb)のDockerコンテナに入りたい場合は以下のようにします。
mysql コマンドでDBに接続できます。
[root@centos0702 sosjs]# docker exec -it sosjs_db_1 /bin/bash
root@028298731ab1:/# env
MARIADB_MAJOR=10.1
HOSTNAME=028298731ab1
MYSQL_DATABASE=jobscheduler
MYSQL_PASSWORD=jobscheduler
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
GPG_KEYS=199369E5404BD5FC7D2FE43BCBCB082A1BB943DB       430BDF5C56E7C94E848EE60C1C4CBDCDCD2EFD2A        4D1BB29D63D98E422B2113B19334A25F8507EFA5
PWD=/
SHLVL=1
HOME=/root
GOSU_VERSION=1.7
MYSQL_USER=jobscheduler
MARIADB_VERSION=10.1.21+maria-1~jessie
MYSQL_ROOT_PASSWORD=scheduler
_=/usr/bin/env
root@028298731ab1:/# mysql --user=jobscheduler --password=jobscheduler jobscheduler
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 24
Server version: 10.1.21-MariaDB-1~jessie mariadb.org binary distribution

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [jobscheduler]> 

コンテナの起動/停止


テスト環境コンテナは、以下のコマンドで一括して停止できます。
[root@centos0702 sosjs]# docker-compose stop
Stopping sosjs_jobscheduler_1 ... done
Stopping sosjs_db_1 ... done
[root@centos0702 sosjs]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                        PORTS               NAMES
d176b06f4975        floedermann/jobscheduler   "bash /opt/startup_sc"   22 minutes ago      Exited (137) 14 seconds ago                       sosjs_jobscheduler_1
028298731ab1        mariadb                    "docker-entrypoint.sh"   22 minutes ago      Exited (0) 10 seconds ago                         sosjs_db_1
969de82ce298        busybox                    "/bin/true"              22 minutes ago      Exited (0) 22 minutes ago                         sosjs_datastore_1

一括して開始したい場合は、以下のコマンドです。
[root@centos0702 sosjs]# docker-compose start
Starting db ... done
Starting datastore ... done
Starting jobscheduler ... done
[root@centos0702 sosjs]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                      PORTS                                                         NAMES
d176b06f4975        floedermann/jobscheduler   "bash /opt/startup_sc"   23 minutes ago      Up 14 seconds               0.0.0.0:4444->4444/tcp, 0.0.0.0:40444->40444/tcp, 48444/tcp   sosjs_jobscheduler_1
028298731ab1        mariadb                    "docker-entrypoint.sh"   23 minutes ago      Up 19 seconds               3306/tcp                                                      sosjs_db_1
969de82ce298        busybox                    "/bin/true"              23 minutes ago      Exited (0) 19 seconds ago                                                                 sosjs_datastore_1

コンテナの状態は "docker-compose ps" でも確認できます。
なお、"docker-compose stop" したあと "docker-compose start" した場合、jobscheduler が起動しないので(link を使ってるから?)、stop したら "docker-compose up -d"  で起動します。

コンテナの破棄


テスト環境が不要になったら、下記コマンドで 一括コンテナを削除できます。
[root@centos0702 sosjs]# docker-compose stop
Stopping sosjs_jobscheduler_1 ... done
Stopping sosjs_db_1 ... done
[root@centos0702 sosjs]# docker-compose rm
Going to remove sosjs_jobscheduler_1, sosjs_db_1, sosjs_datastore_1
Are you sure? [yN] y
Removing sosjs_jobscheduler_1 ... done
Removing sosjs_db_1 ... done
Removing sosjs_datastore_1 ... done

"docker-compose down" を実行すると、stop と rm を実施してくれます。




2017年1月24日火曜日

Docker コンテナなら誰でも AmazonLinux が使える


DockerHUB には Official な AmazonLinux イメージがあります。

AWSのアカウントは不要なので、誰でも使えます。

以下のようにしてイメージをローカルにダウンロードできます。
[root@centos0702 ~]# docker pull amazonlinux
Using default tag: latest
Trying to pull repository docker.io/library/amazonlinux ...
latest: Pulling from docker.io/library/amazonlinux
c9141092a50d: Pull complete
Digest: sha256:2010c88ac1e7c118d61793eec71dcfe0e276d72b38dd86bd3e49da1f8c48bf54
Status: Downloaded newer image for docker.io/amazonlinux:latest
[root@centos0702 ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
centos6_ec2             2                   58e51bade44e        33 hours ago        633 MB
docker.io/amazonlinux   latest              8ae6f52035b5        3 weeks ago         292.3 MB
docker.io/centos        6                   8315978ceaaa        11 weeks ago        194.6 MB

コンテナを起動して、OSバージョンを確認してみます。
[root@centos0702 ~]# docker run -it amazonlinux /bin/bash
bash-4.2# cat /etc/system-release
Amazon Linux AMI release 2016.09

軽量すぎて、psやvi、more コマンドがないので、インストールします。
bash-4.2# yum install util-linux procps vi

コマンドがどのパッケージに含まれているかは、ホストのCentOSで調べます。
[root@centos0702 ~]# rpm -qf /usr/bin/vi
vim-minimal-7.4.160-1.el7_3.1.x86_64





2017年1月23日月曜日

EC2(CentOS6) で RunCommand を試す

EC2(CentOS6)の構築を Terraform と Ansible でやってみる」で作ったEC2インスタンスで、RunCommand を試してみます。
EC2インスタンスには、Amazon SSM Agent をインストール済みです。
また、EC2インスタンスには AdministratorAccess ポリシーを設定しています。

今回は、awscli で試します。
下記のマニュアルを参考にしました。


1.RunCommad が使用できるECインスタンスを確認


ssmエージェントが動いてるEC2インスタンスを確認します。
下記のコマンドを実行して、表示されたインスタンスは、RunCommand が使用できます。
[root@centos0702 codedeploy]# aws ssm describe-instance-information --output text --query "InstanceInformationList[*]"
2.0.617.1       ip-10-0-10-133.ec2.internal     10.0.10.133     i-0640ff2f366174074     True    1484800160.37   Online  CentOS  Linux   6.7 (Final)     EC2Instance
2.0.617.1       ip-10-0-11-52.ec2.internal      10.0.11.52      i-083f2235b506dfd49     True    1484800159.83   Online  CentOS  Linux   6.7 (Final)     EC2Instance

インスタンスIDを指定して詳細を見たい場合は下記コマンドです。
[root@centos0702 codedeploy]# aws ssm describe-instance-information --instance-information-filter-list key=InstanceIds,valueSet=i-0640ff2f366174074
{
    "InstanceInformationList": [
        {
            "IsLatestVersion": true,
            "ComputerName": "ip-10-0-10-133.ec2.internal",
            "PingStatus": "Online",
            "InstanceId": "i-0640ff2f366174074",
            "IPAddress": "10.0.10.133",
            "ResourceType": "EC2Instance",
            "AgentVersion": "2.0.617.1",
            "PlatformVersion": "6.7 (Final)",
            "PlatformName": "CentOS",
            "PlatformType": "Linux",
            "LastPingDateTime": 1484800160.367
        }
    ]
}


2.コマンドを実行する


インスタンスIDを指定して ifconfig コマンドを実行してみます。
[root@centos0702 codedeploy]# aws ssm send-command --instance-ids i-0640ff2f366174074 --document-name "AWS-RunShellScript" --comment "IP config" --parameters commands=ifconfig
{
    "Command": {
        "Comment": "IP config",
        "Status": "Pending",
        "MaxErrors": "0",
        "Parameters": {
            "commands": [
                "ifconfig"
            ]
        },
        "ExpiresAfter": 1484804322.856,
        "ServiceRole": "",
        "DocumentName": "AWS-RunShellScript",
        "TargetCount": 1,
        "OutputS3BucketName": "",
        "NotificationConfig": {
            "NotificationArn": "",
            "NotificationEvents": [],
            "NotificationType": ""
        },
        "CompletedCount": 0,
        "Targets": [],
        "StatusDetails": "Pending",
        "ErrorCount": 0,
        "OutputS3KeyPrefix": "",
        "RequestedDateTime": 1484800722.856,
        "CommandId": "3a812382-f60f-430b-9bfe-54f26a3bea4c",
        "InstanceIds": [
            "i-0640ff2f366174074"
        ],
        "MaxConcurrency": "50"
    }
}

コマンドが正常終了したかステータスを確認します。
上記の CommandId を指定します。
[root@centos0702 codedeploy]# aws ssm list-commands --command-id 3a812382-f60f-430b-9bfe-54f26a3bea4c
{
    "Commands": [
        {
            "Comment": "IP config",
            "Status": "Success",
            "MaxErrors": "0",
            "Parameters": {
                "commands": [
                    "ifconfig"
                ]
            },
            "ExpiresAfter": 1484804322.856,
            "ServiceRole": "",
            "DocumentName": "AWS-RunShellScript",
            "TargetCount": 1,
            "OutputS3BucketName": "",
            "NotificationConfig": {
                "NotificationArn": "",
                "NotificationEvents": [],
                "NotificationType": ""
            },
            "CompletedCount": 1,
            "Targets": [],
            "StatusDetails": "Success",
            "ErrorCount": 0,
            "OutputS3KeyPrefix": "",
            "RequestedDateTime": 1484800722.856,
            "CommandId": "3a812382-f60f-430b-9bfe-54f26a3bea4c",
            "InstanceIds": [
                "i-0640ff2f366174074"
            ],
            "MaxConcurrency": "50"
        }
    ]
}

Status が Success なので ifconfig コマンドの実行は正常終了したようです。
ifconfig コマンドの標準出力をみたい場合は以下のとおり。
Output が ifconfig の標準出力です。
[root@centos0702 codedeploy]# aws ssm list-command-invocations --command-id 3a812382-f60f-430b-9bfe-54f26a3bea4c --details
{
    "CommandInvocations": [
        {
            "Comment": "IP config",
            "Status": "Success",
            "CommandPlugins": [
                {
                    "Status": "Success",
                    "ResponseStartDateTime": 1484800723.395,
                    "StandardErrorUrl": "",
                    "OutputS3BucketName": "",
                    "OutputS3Region": "us-east-1",
                    "OutputS3KeyPrefix": "",
                    "ResponseCode": 0,
                    "Output": "eth0      Link encap:Ethernet  HWaddr 0A:48:F5:B1:B3:96  \n          inet addr:10.0.10.133  Bcast:10.0.10.255  Mask:255.255.255.0\n          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1\n          RX packets:1682 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:1963 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:429330 (419.2 KiB)  TX bytes:323357 (315.7 KiB)\n          Interrupt:160 \n\nlo        Link encap:Local Loopback  \n          inet addr:127.0.0.1  Mask:255.0.0.0\n          UP LOOPBACK RUNNING  MTU:65536  Metric:1\n          RX packets:0 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:0 \n          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)\n\n",
                    "ResponseFinishDateTime": 1484800723.402,
                    "StatusDetails": "Success",
                    "StandardOutputUrl": "",
                    "Name": "aws:runShellScript"
                }
            ],
            "ServiceRole": "",
            "InstanceId": "i-0640ff2f366174074",
            "DocumentName": "AWS-RunShellScript",
            "NotificationConfig": {
                "NotificationArn": "",
                "NotificationEvents": [],
                "NotificationType": ""
            },
            "StatusDetails": "Success",
            "StandardOutputUrl": "",
            "StandardErrorUrl": "",
            "InstanceName": "",
            "CommandId": "3a812382-f60f-430b-9bfe-54f26a3bea4c",
            "RequestedDateTime": 1484800722.962
        }
    ]
}


3. 複数のインスタンでコマンドを実行


TAGを指定して、複数のインスタンスでコマンドを実行してみます。
下記は、Groupタグに "demo" が設定されたインスタンスでコマンドを実行します。
[root@centos0702 codedeploy]# aws ssm send-command --targets "Key=tag:Group,Values=demo" --document-name "AWS-RunShellScript" --comment "hostname" --parameters "commands=uname -n"
{
    "Command": {
        "Comment": "hostname",
        "Status": "Pending",
        "MaxErrors": "0",
        "Parameters": {
            "commands": [
                "uname -n"
            ]
        },
        "ExpiresAfter": 1484806220.112,
        "ServiceRole": "",
        "DocumentName": "AWS-RunShellScript",
        "TargetCount": 0,
        "OutputS3BucketName": "",
        "NotificationConfig": {
            "NotificationArn": "",
            "NotificationEvents": [],
            "NotificationType": ""
        },
        "CompletedCount": 0,
        "Targets": [
            {
                "Values": [
                    "demo"
                ],
                "Key": "tag:Group"
            }
        ],
        "StatusDetails": "Pending",
        "ErrorCount": 0,
        "OutputS3KeyPrefix": "",
        "RequestedDateTime": 1484802620.112,
        "CommandId": "725c31fa-eb3c-4aed-bee5-568492969d52",
        "InstanceIds": [],
        "MaxConcurrency": "50"
    }
}

コマンド実行結果の詳細は以下のとおり。
[root@centos0702 codedeploy]# aws ssm list-command-invocations --command-id 725c31fa-eb3c-4aed-bee5-568492969d52 --details                                 {
    "CommandInvocations": [
        {
            "Comment": "hostname",
            "Status": "Success",
            "CommandPlugins": [
                {
                    "Status": "Success",
                    "ResponseStartDateTime": 1484802620.708,
                    "StandardErrorUrl": "",
                    "OutputS3BucketName": "",
                    "OutputS3Region": "us-east-1",
                    "OutputS3KeyPrefix": "",
                    "ResponseCode": 0,
                    "Output": "ip-10-0-10-133.ec2.internal\n",
                    "ResponseFinishDateTime": 1484802620.712,
                    "StatusDetails": "Success",
                    "StandardOutputUrl": "",
                    "Name": "aws:runShellScript"
                }
            ],
            "ServiceRole": "",
            "InstanceId": "i-0640ff2f366174074",
            "DocumentName": "AWS-RunShellScript",
            "NotificationConfig": {
                "NotificationArn": "",
                "NotificationEvents": [],
                "NotificationType": ""
            },
            "StatusDetails": "Success",
            "StandardOutputUrl": "",
            "StandardErrorUrl": "",
            "InstanceName": "ip-10-0-10-133.ec2.internal",
            "CommandId": "725c31fa-eb3c-4aed-bee5-568492969d52",
            "RequestedDateTime": 1484802620.349
        },
        {
            "Comment": "hostname",
            "Status": "Success",
            "CommandPlugins": [
                {
                    "Status": "Success",
                    "ResponseStartDateTime": 1484802620.577,
                    "StandardErrorUrl": "",
                    "OutputS3BucketName": "",
                    "OutputS3Region": "us-east-1",
                    "OutputS3KeyPrefix": "",
                    "ResponseCode": 0,
                    "Output": "ip-10-0-11-52.ec2.internal\n",
                    "ResponseFinishDateTime": 1484802620.581,
                    "StatusDetails": "Success",
                    "StandardOutputUrl": "",
                    "Name": "aws:runShellScript"
                }
            ],
            "ServiceRole": "",
            "InstanceId": "i-083f2235b506dfd49",
            "DocumentName": "AWS-RunShellScript",
            "NotificationConfig": {
                "NotificationArn": "",
                "NotificationEvents": [],
                "NotificationType": ""
            },
            "StatusDetails": "Success",
            "StandardOutputUrl": "",
            "StandardErrorUrl": "",
            "InstanceName": "ip-10-0-11-52.ec2.internal",
            "CommandId": "725c31fa-eb3c-4aed-bee5-568492969d52",
            "RequestedDateTime": 1484802620.252
        }
    ]
}


4. AWSコンソールでコマンド履歴を見る


AWSコンソールでコマンド履歴をみると下図のとおり。



コマンドの出力内容を見たい場合は、[出力の表示]をクリックします。





2017年1月22日日曜日

EC2(CentOS6) で CodeDeploy を試す

EC2(CentOS6)の構築を Terraform と Ansible でやってみる」で作ったEC2インスタンスで、CodeDeploy を試してみます。
EC2インスタンスには、CodeDeploy Agent をインストール済みです。
また、AdministratorAccess ポリシーを設定しています。

CodeDeploy の使用方法は、以下のページを参考にしました。
今回は、S3からアプリケーションをデプロイします。


1. IAM ロールの作成


CodeDeploy 用にIAMロールを作成します。
管理ポリシーに AWSCodeDeployRole を割り当てました。


信頼関係も修正します。


信頼関係の設定内容は以下のとおり。
us-east-1 で CodeDeploy を使用するので、"codedeploy.us-east-1.amazonaws.com" を指定しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "codedeploy.us-east-1.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}


2. アプリケーションの登録


デプロイするアプリケーションを登録します。
[カスタムプロパティ]を選択して、[ウォークスルーのスキップ]ボタンをクリックします。


[アプリケーション名]、[デプロイグループ名] を入力します。
[アプリケーション名]は、s3 にファイルをアップロードするときに使用します。


デプロイ先のEC2インスタンスを指定します。
今回は、Nameタグが centos6 のサーバにデプロイします。


デプロイ設定は、デフォルト値を使用します。


トリガーと警報は、今回、使用しないので、設定しません。


ロールバックは、[デプロイが失敗したときロールバックする] を選択します。


サービスロールは、上記で作成したIAMロールを選択し、[アプリケーションの作成]ボタンをクリックします。


アプリケーションの作成に成功したら、下図のように表示されます。



3. S3バケットの作成


デプロイするファイルをアップロードする S3バケットを用意します。
今回は、バケット名を blue21-deploy にしました。



4. デプロイの実施


上記でAWSの準備ができたので、デプロイを実施します。

4.1. アプリケーションの用意


お試し用のアプリケーションを用意します。
[root@centos0702 codedeploy]# tree -F demo_v1
demo_v1
├── appspec.yml
├── conf/
│   ├── 012.conf
│   ├── 345.conf
│   ├── abc.conf
│   └── def.conf
├── sample01.txt
├── sample02.txt
└── scripts/
    ├── after_install.sh*
    ├── start.sh*
    └── stop.sh*

2 directories, 10 files

[root@centos0702 codedeploy]# ls -Rl demo_v1/
demo_v1/:
合計 12
-rw-r--r-- 1 root root 1016  1月 19 10:13 appspec.yml
drwxr-xr-x 2 root root   66  1月 19 09:01 conf
-rw-r--r-- 1 root root    9  1月 18 15:06 sample01.txt
-rw-r--r-- 1 root root    9  1月 18 15:06 sample02.txt
drwxr-xr-x 2 root root   58  1月 19 09:36 scripts

demo_v1/conf:
合計 16
-rw-r--r-- 1 root root 4  1月 19 08:49 012.conf
-rw-r--r-- 1 root root 4  1月 19 08:49 345.conf
-rw-r--r-- 1 root root 4  1月 19 08:49 abc.conf
-rw-r--r-- 1 root root 4  1月 19 08:49 def.conf

demo_v1/scripts:
合計 12
-rwxr-xr-x 1 root root 195  1月 19 09:36 after_install.sh
-rwxr-xr-x 1 root root 195  1月 19 09:36 start.sh
-rwxr-xr-x 1 root root 195  1月 19 09:36 stop.sh

appspec.yml の書き方は、下記ページが参考になります。
今回は、以下のようにしました。
[root@centos0702 codedeploy]# cat demo_v1/appspec.yml
version: 0.0
os: linux
files:
  - source: /sample01.txt
    destination: /opt/sample
  - source: /sample02.txt
    destination: /opt/sample
  - source: /conf
    destination: /opt/sample/conf
permissions:
  # 拡張子が ".txt" のファイル
  - object: /opt/sample
    pattern: "*.txt"
    owner: centos
    group: centos
    mode: 644
    type:
      - file
  # conf ディレクトリ
  - object: /opt/sample
    pattern: "conf"
    owner: centos
    group: centos
    mode: 755
    type:
      - directory
  # conf ディレクトリの abc.conf, def.conf を除くファイル
  - object: /opt/sample/conf
    pattern: "**"
    except: [abc.conf,def.conf]
    owner: centos
    group: centos
    mode: 400
    type:
      - file
hooks:
  ApplicationStop:
    - location: scripts/stop.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/after_install.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 300
      runas: root

スクリプトの内容は、全部同じです。
今回は、実行されたのを確認したいだけなので、
パスと実行時間、/opt/sample のls結果を /tmp/debug.log に出力します。
[root@centos0702 codedeploy]# cat demo_v1/scripts/stop.sh
#!/bin/bash
LOG=/tmp/debug.log
DIR=/opt/sample
echo "$0" >> ${LOG}
date      >> ${LOG}
if [ -d ${DIR} ]; then
    ls -Rl ${DIR} >> ${LOG}
else
    echo "${DIR} directory not found." >> ${LOG}
fi

4.2. アプリケーションを s3 にアップロード


上記のアプリケーションを s3 にアップロードします。
アップロードに成功すると、デプロイの実行方法が表示されます。
[root@centos0702 codedeploy]# aws deploy push --application-nam demo_v1 --s3-location s3://blue21-deploy/demo_v1.zip --source ./demo_v1/
To deploy with this revision, run:
aws deploy create-deployment --application-name demo_v1 --s3-location bucket=blue21-deploy,key=demo_v1.zip,bundleType=zip,eTag=d3a7dd6fb72f89f207aa1b7762da0a43 --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>

このコマンドを実行すると、自動的に zip 形式にアーカイブされ、s3 にアップロードされます。
awscliコマンドの結果を、AWSコンソールで確認してみます。
アップロードしたファイルは、[CodeDeploy] > [アプリケーション] > [demo_v1] > [リビジョン] に表示されます。
[リビジョン]の初期状態は、下図のように何も表示されていません。


awscliコマンドを実行してアップロードに成功すると、下図のように[リビジョン]にS3のファイルが表示されます。 


s3 には、アップロードしたファイルが格納されています。



4.3. デプロイの実行


[リビジョン]が登録できたので、デプロイを実行できます。
AWSコンソールの[リビジョン]からでもデプロイできますが、今回は、awscli で実施します。
[root@centos0702 codedeploy]# aws deploy create-deployment --application-name demo_v1 --s3-location bucket=blue21-deploy,key=demo_v1.zip,bundleType=zip,eTag=d3a7dd6fb72f89f207aa1b7762da0a43 --deployment-group-name demo --description "デモ"
{
    "deploymentId": "d-0P2O9RD8K"
}

AWSコンソールからデプロイしたい場合は、[リビジョン] の [このリビジョンのデプロイ] ボタンをクリックします。



4.4. デプロイの確認


デプロイの進行状況をAWSコンソールで確認すると、下図のとおり。
上記の awscli コマンドを実行すると、ステータスが "進行中" になります。


デプロイが正常終了すると、ステータスが "正常" になります。


メニューで [デプロイ] を選択すると、下図のように詳細を確認できます。
エラーの場合は、ここで、メッセージを確認できます。


4.5. サーバの確認


サーバにログインして、デプロイ内容を確認してみます。
デプロイ先の /opt/sample を見ると、以下のとおり。
存在しないディレクトリは作成してくれました。
[root@ip-10-0-10-133 ~]# ls -alR /opt/sample
/opt/sample:
total 20
drwxr-xr-x  3 root   root   4096 2017-01-19 10:49 .
drwxr-xr-x. 5 root   root   4096 2017-01-19 10:49 ..
drwxr-xr-x  2 centos centos 4096 2017-01-19 10:49 conf
-rw-r--r--  1 centos centos    9 2017-01-19 10:49 sample01.txt
-rw-r--r--  1 centos centos    9 2017-01-19 10:49 sample02.txt

/opt/sample/conf:
total 24
drwxr-xr-x 2 centos centos 4096 2017-01-19 10:49 .
drwxr-xr-x 3 root   root   4096 2017-01-19 10:49 ..
-r-------- 1 centos centos    4 2017-01-19 10:49 012.conf
-r-------- 1 centos centos    4 2017-01-19 10:49 345.conf
-rw-r--r-- 1 root   root      4 2017-01-19 10:49 abc.conf
-rw-r--r-- 1 root   root      4 2017-01-19 10:49 def.conf

debug.log を見ると、/opt/codedeploy-agent 配下に s3 からダウンロードした zip ファイルが解凍されたみたい。
[root@ip-10-0-10-133 ~]# cat /tmp/debug.log
/opt/codedeploy-agent/deployment-root/b32cea05-5b83-4c32-9afb-de20014b4882/d-GP5DVXR8K/deployment-archive/scripts/stop.sh
2017年  1月 19日 木曜日 10:49:02 JST
/opt/sample directory not found.
/opt/codedeploy-agent/deployment-root/b32cea05-5b83-4c32-9afb-de20014b4882/d-Q5868AP8K/deployment-archive/scripts/after_install.sh
2017年  1月 19日 木曜日 10:49:08 JST
/opt/sample:
total 12
drwxr-xr-x 2 centos centos 4096 2017-01-19 10:49 conf
-rw-r--r-- 1 centos centos    9 2017-01-19 10:49 sample01.txt
-rw-r--r-- 1 centos centos    9 2017-01-19 10:49 sample02.txt

/opt/sample/conf:
total 16
-r-------- 1 centos centos 4 2017-01-19 10:49 012.conf
-r-------- 1 centos centos 4 2017-01-19 10:49 345.conf
-rw-r--r-- 1 root   root   4 2017-01-19 10:49 abc.conf
-rw-r--r-- 1 root   root   4 2017-01-19 10:49 def.conf
/opt/codedeploy-agent/deployment-root/b32cea05-5b83-4c32-9afb-de20014b4882/d-Q5868AP8K/deployment-archive/scripts/start.sh
2017年  1月 19日 木曜日 10:49:10 JST
/opt/sample:
total 12
drwxr-xr-x 2 centos centos 4096 2017-01-19 10:49 conf
-rw-r--r-- 1 centos centos    9 2017-01-19 10:49 sample01.txt
-rw-r--r-- 1 centos centos    9 2017-01-19 10:49 sample02.txt

/opt/sample/conf:
total 16
-r-------- 1 centos centos 4 2017-01-19 10:49 012.conf
-r-------- 1 centos centos 4 2017-01-19 10:49 345.conf
-rw-r--r-- 1 root   root   4 2017-01-19 10:49 abc.conf
-rw-r--r-- 1 root   root   4 2017-01-19 10:49 def.conf

CodeDeploy Agent のログは、以下にあります。
デプロイに失敗した場合は、これを参照
[root@ip-10-0-10-133 ~]# ls /var/log/aws/codedeploy-agent/
codedeploy-agent.log  codedeploy-agent.log.age


5. デプロイの自動化


S3に push したら (上記の4.2)、自動的に デプロイが実行されるようにもできるようです。

CodePipeline を使って、S3への push を検知したら自動的にデプロイを実行するように設定します。
手順は、下記ページが参考になります。






2017年1月21日土曜日

sshログインできるテスト環境を Docker で作る (packer+ansible編)

sshログインできるテスト環境をDockerで作る (Dokerfile編)」 で構築した Dockerコンテナと同じものを、Packer + Ansible で構築してみます。


1. Ansible の Playbook 作成


Docker 用に Ansible の Playbook を作成します。
内容は以下のとおり。
[root@centos0702 packer]# cat centos6_ec2.yml
- hosts: all
  connection: docker

  tasks:

    - name: install package
      yum: name={{item}} state=latest
      with_items:
        - cloud-init
        - iptables-ipv6
        - openssh-server
        - openssh-clients
        - sudo

    - name: reinstall glibc-common
      shell: yum -y reinstall glibc-common

    - name: change /etc/sudoers
      lineinfile: >
        dest='/etc/sudoers'
        regexp='^# (%wheel.ALL=\(ALL\).NOPASSWD: ALL)$'
        line='\1'
        backrefs=yes

    # パスワード暗号化 : python -c "import crypt, getpass, pwd; print crypt.crypt('p@ssw0rd', '\$6\$salt1234\$')"
    - name: add centos user
      user: >
        name=centos
        groups=wheel
        createhome=yes
        home=/home/centos
        password=$6$salt1234$sv0i3N5lezqgOuRzpaTKuS431i5yVnqiJoiJJ8L/fAHSmYw2sD9IS0gsNEeUzDvW.4HODNlu0hEYUU5xIZnCG1
        shell=/bin/bash

    - name: start service sshd
      service: name=sshd state=started

    - name: stop service sshd
      service: name=sshd state=stopped

    - name: copy to /etc/selinux/config
      copy: >
        src=/root/workspace/docker/selinux_config
        dest=/etc/selinux/config
        owner=root
        group=root
        mode=0644

    - name: create directory /home/centos/.ssh
      file: >
        path=/home/centos/.ssh
        owner=centos
        group=centos
        mode=0700
        state=directory

    - name: copy to /home/centos/.ssh/authorized_keys
      copy: >
        src=/root/workspace/docker/authorized_keys
        dest=/home/centos/.ssh/authorized_keys
        owner=centos
        group=centos
        mode=0600


2. Packer のテンプレート作成


次のように動作するPacker のテンプレートを作成します。
  1. centos:6 のイメージから Dockerコンテナを起動します。
  2. 上記で作成した Ansibleの Playbook を実行します。(Ansible はホスト側で実行します。)
  3. Ansibleの実行が完了したら、Dockerコンテナをコミットして、タグ名を設定します。
テンプレートの内容は以下のとおり。
[root@centos0702 packer]# cat centos6_ec2.json
{
      "variables": {
          "ansible_host": "centos6"
      },
      "builders":[{
          "type": "docker",
          "image": "centos:6",
          "commit": "true",
          "run_command": [ "-d", "-i", "-t", "--name", "{{user `ansible_host`}}", "{{.Image}}", "/bin/bash" ],
          "changes": ["CMD /usr/sbin/sshd -D"]
      }],
      "provisioners":[{
          "type": "ansible",
          "playbook_file": "centos6_ec2.yml",
          "extra_arguments": [
              "--extra-vars",
              "ansible_host={{user `ansible_host`}} ansible_connection=docker"
          ]
      }],
      "post-processors": [{
        "type": "docker-tag",
        "repository": "centos6_ec2",
        "tag": "2"
      }]
}


3. Dockerイメージの作成


Packer を実行して、Dockerイメージを作成します。
[root@centos0702 packer]# packer build ./centos6_ec2.json
docker output will be in this color.

==> docker: Creating a temporary directory for sharing data...
==> docker: Pulling Docker image: centos:6
    docker: Trying to pull repository docker.io/library/centos ...
    docker: 6: Pulling from docker.io/library/centos
    docker: Digest: sha256:1092df198d3da4faccc0660941b763ce5adf133b0ec71701b760d6f173c1f47b
    docker: Status: Image is up to date for docker.io/centos:6
==> docker: Starting docker container...
    docker: Run command: docker run -v /root/.packer.d/tmp/packer-docker592982584:/packer-files -d -i -t --name centos6 centos:6 /bin/bash
    docker: Container ID: 16ad609b19d65f381ce7feb77f9c9e30447615644096ec3c35d840eafc15d973
==> docker: Provisioning with Ansible...
    docker:
    docker: PLAY [all] *********************************************************************
    docker:
    docker: TASK [setup] *******************************************************************
    docker: ok: [default]
    docker:
    docker: TASK [install package] *********************************************************
    docker: changed: [default] => (item=[u'cloud-init', u'iptables-ipv6', u'openssh-server', u'openssh-clients', u'sudo'])
    docker:
    docker: TASK [reinstall glibc-common] **************************************************
    docker: changed: [default]
    docker:  [WARNING]: Consider using yum module rather than running yum
    docker:
    docker: TASK [change /etc/sudoers] *****************************************************
    docker: changed: [default]
    docker:
    docker: TASK [add centos user] *********************************************************
    docker: changed: [default]
    docker:
    docker: TASK [start service sshd] ******************************************************
    docker: changed: [default]
    docker:
    docker: TASK [stop service sshd] *******************************************************
    docker: changed: [default]
    docker:
    docker: TASK [copy to /etc/selinux/config] *********************************************
    docker: changed: [default]
    docker:
    docker: TASK [create directory /home/centos/.ssh] **************************************
    docker: changed: [default]
    docker:
    docker: TASK [copy to /home/centos/.ssh/authorized_keys] *******************************
    docker: changed: [default]
    docker:
    docker: PLAY RECAP *********************************************************************
    docker: default                    : ok=10   changed=9    unreachable=0    failed=0
    docker:
==> docker: Committing the container
    docker: Image ID: sha256:58e51bade44e19ca54e521209b34ee4c8cb784b77998b7c96a5e4bf38baa833f
==> docker: Killing the container: 16ad609b19d65f381ce7feb77f9c9e30447615644096ec3c35d840eafc15d973
==> docker: Running post-processor: docker-tag
    docker (docker-tag): Tagging image: sha256:58e51bade44e19ca54e521209b34ee4c8cb784b77998b7c96a5e4bf38baa833f
    docker (docker-tag): Repository: centos6_ec2:2
Build 'docker' finished.

==> Builds finished. The artifacts of successful builds are:
--> docker: Imported Docker image: sha256:58e51bade44e19ca54e521209b34ee4c8cb784b77998b7c96a5e4bf38baa833f
--> docker: Imported Docker image: centos6_ec2:2

Docker イメージを確認します。
[root@centos0702 packer]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos6_ec2         2                   58e51bade44e        30 seconds ago      633 MB
centos6_sshd        1                   7eb9929a5863        About an hour ago   657.4 MB
docker.io/centos    6                   8315978ceaaa        10 weeks ago        194.6 MB


4. Docker コンテナの動作確認


Docker コンテナを起動します。
[root@centos0702 packer]# docker run -d centos6_ec2:2
a13c24ba353bb36584feeb16e291a70206d00bc374303c599097219419929a06
[root@centos0702 packer]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
a13c24ba353b        centos6_ec2:2       "/bin/sh -c '/usr/sbi"   5 seconds ago       Up 3 seconds                            compassionate_boyd

Docker コンテナのIPアドレスを確認します。
[root@centos0702 packer]# docker inspect a13c24ba353b | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAddress": "172.17.0.3",

ssh ログインと sudo できるか確認します。
[root@centos0702 packer]# ssh -l centos -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 172.17.0.3
Warning: Permanently added '172.17.0.3' (RSA) to the list of known hosts.
[centos@a13c24ba353b ~]$ sudo id
uid=0(root) gid=0(root) 所属グループ=0(root)
[centos@a13c24ba353b ~]$ exit
logout
Connection to 172.17.0.3 closed.