読者です 読者をやめる 読者になる 読者になる

めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

アプリケーション環境構築の自動化をまじめに考えてみる(2)

今回は・・・

前回につづいて、アプリケーションの導入と環境設定の自動化を考えます。

アプリケーションの設定に関しては、

(1) リファレンス環境を用意して、手動で設定・テストする。
(2) 設定内容をバージョン管理システムに登録する。
(3) 新規環境から、バージョン管理システムに登録された内容を取得して自動設定できるようにする。

という流れを考えてみます。まずは試しに、PostgreSQLの設定をGithubに登録してみましょう。

PostgreSQLとGithubという選択に深い意味はありません。特にGithubは、そもそもアプリケーションの設定管理のためのツールではないので、やってみたらいろいろ不便な点も見えてくるはずです。逆にそこから、アプリケーション設定のバージョン管理に必要な要素を考えられたらいいかも・・・という意図です。

リファレンス環境の用意とgithub登録

はじめに、前回のツール(virt-construct.py)と設定(vm01.conf)を利用して、仮想マシンvm01を用意します。vm01にログインしたら、普通にPostgreSQLをインストールして、DBの初期化とpostgresのパスワード設定まで行います。

[root@vm01 ~]# yum -y install postgresql-server
[root@vm01 ~]# service postgresql initdb
[root@vm01 ~]# service postgresql start
[root@vm01 ~]# su - postgres -c "psql -c \"ALTER USER postgres encrypted password 'pas4pgsql'\""
[root@vm01 ~]# service postgresql stop

続いて、設定ファイル「postgresql.conf」「pg_hba.conf」を編集しますが、その前に、これらのファイルをローカルのgitでバージョン管理できるようにします。

[root@vm01 ~]# cd /var/lib/pgsql
[root@vm01 pgsql]# git init
[root@vm01 pgsql]# git add data/postgresql.conf 
[root@vm01 pgsql]# git add data/pg_hba.conf 
[root@vm01 pgsql]# git commit -m "initial status"

ここで、おもむろに「postgresql.conf」「pg_hba.conf」を任意に編集して、納得のいく設定ができたらgitにcommitして、タグ(devlopment_1.0)を振っておきます。

[root@vm01 pgsql]# git commit -a -m "log and security settings for development environment"
[root@vm01 pgsql]# git tag development_1.0

ちなみにここでは、ログ出力設定とパスワード認証設定を行いました。

[root@vm01 pgsql]# git show
commit 62e22ce98d9354bfa42444416b8a72747de85136
Author: root <root@vm01.(none)>
Date:   Thu Aug 23 13:51:31 2012 +0900

    log and security settings for development environment

diff --git a/data/pg_hba.conf b/data/pg_hba.conf
index fb080ea..014eb16 100644
--- a/data/pg_hba.conf
+++ b/data/pg_hba.conf
@@ -67,8 +67,8 @@
 # TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
 
 # "local" is for Unix domain socket connections only
-local   all         all                               ident
+local   all         all                               md5
 # IPv4 local connections:
-host    all         all         127.0.0.1/32          ident
+host    all         all         127.0.0.1/32          md5
 # IPv6 local connections:
-host    all         all         ::1/128               ident
+host    all         all         ::1/128               md5
diff --git a/data/postgresql.conf b/data/postgresql.conf
index 8c99f80..cd64a2c 100644
--- a/data/postgresql.conf
+++ b/data/postgresql.conf
@@ -499,3 +499,12 @@ default_text_search_config = 'pg_catalog.simple'
 #------------------------------------------------------------------------------
 
 #custom_variable_classes = ''          # list of custom variable class names
+
+log_destination = 'syslog'
+syslog_facility = 'LOCAL0'
+syslog_ident = 'postgres'
+log_line_prefix = '%u %d '
+log_connections = on
+log_disconnections = on
+log_statement = 'all'
+

最後にこれらをgithubにpushしておきます。ここでは、githubに新規のリポジトリ「https://github.com/enakai00/pgsql_configs.git」を作成してあるものとします。(pushするためのSSH鍵の設定などは、githubの入門ページなどよしなに参照してください。)

[root@vm01 pgsql]# git remote add origin git@github.com:enakai00/pgsql_configs.git 
[root@vm01 pgsql]# git push -u origin master
[root@vm01 pgsql]# git push --tags

リファレンス環境の再現スクリプト

新規にRHELをインストールした環境に対して、PostgreSQLをインストールして、githubにあげた設定を自動適用するスクリプトを用意します。さっくりとこんな感じで。

pgsql_deploy.sh

#!/bin/sh -x

GitRepository=$1    # Repository URL
ConfigTag=$2        # Restore Tag
RepoName=${GitRepository##*/}
RepoName=${RepoName%\.git}

# restore configs to /tmp/gittmp/$RepoName
function git_restore {
    rm -rf /tmp/gittmp
    mkdir -p /tmp/gittmp
    cd /tmp/gittmp
    git clone $GitRepository
    cd $RepoName
    if [[ ! -z $ConfigTag ]]; then
        git checkout $ConfigTag
    fi
}

yum -y install postgresql-server
service postgresql initdb
service postgresql start
su - postgres -c \
    "psql -c \"ALTER USER postgres encrypted password 'pas4pgsql'\""
service postgresql stop

git_restore

cp -rv /tmp/gittmp/$RepoName/* /var/lib/pgsql/
restorecon -r /var/lib/pgsql
chkconfig postgresql on

使い方は、次のようにリポジトリのURLと適用したいタグを指定します。

./deploy_psql.sh https://github.com/enakai00/pgsql_configs.git development_1.0

そして、このスクリプトをKVMホストの/var/www/html/scripts/以下に保存して、「http:///scripts/deploy_pgsql.sh」からダウンロードできる状態にしておきます。

アプリケーション環境の自動再現

これまでに用意した道具を使って、アプリケーション環境の自動再現を行なってみましょう。次の設定ファイルからvirt-construct.pyを実行して、新たな仮想マシンvm02を自動構築します。

vm02.conf

[variables]
#
# Generic variables referenced as ${variable}
#
vmname=vm02
hostname=vm02
diskpath=/var/lib/libvirt/images/vm02.img
ip=192.168.122.198

vcpus=2
ram=1024
disksize=8
network=network:default
os-variant=rhel6
url=http://binaries.nrt.redhat.com/contents/RHEL/6/3/x86_64/default/
netmask=255.255.255.0
gateway=192.168.122.1
nameserver=192.168.122.1 

# PostgreSQL deployment data
pgsql_deployscript=http://192.168.122.1/scripts/deploy_pgsql.sh
pgsql_gitrepo=https://github.com/enakai00/pgsql_configs.git
pgsql_gittag=development_1.0

[virt-install]
#
# virt-install options except ks.cfg
# --noautoconsole --noreboot is automatically added
#
--name ${vmname}
--vcpus ${vcpus}
--ram ${ram}
--disk path=${diskpath},size=${disksize},sparse=false
--network ${network}
--os-variant ${os-variant}
--location ${url}

[kickstart]
#
# ks.cfg contents
#
url --url=${url}
lang ja_JP.UTF-8
keyboard jp106
network --onboot yes --device eth0 --bootproto static --ip ${ip} --netmask ${netmask} --gateway ${gateway} --nameserver ${nameserver} --hostname ${hostname}
rootpw passw0rd
timezone --isUtc Asia/Tokyo
bootloader --location=mbr
zerombr
clearpart --initlabel --drives=vda
part /boot --fstype=ext4 --size=500
part swap --size=1024
part / --fstype=ext4 --grow --size=200
reboot
%packages
@base
@core
@japanese-support
git	# mandatory to use configserver
%end

%post --log=/root/anaconda-post.log
set -x
cat <<EOF > /etc/yum.repos.d/base.repo
\[baseos]
name="Repository for base OS"
baseurl=${url}
gpgcheck=0
enabled=1
EOF

# PostgreSQL deployment
curl ${pgsql_deployscript} -o /tmp/tmp$$
. /tmp/tmp$$ ${pgsql_gitrepo} ${pgsql_gittag}
rm /tmp/tmp$$
%end

この設定ファイルでは、ks.cfgの%postセクションの最後で、先に作成したdeploy_pgsql.shをダウンロードして実行しています。これにより、RHELのインストールと同時にPostgreSQLのインストールと環境設定まで行われることになります。

$ sudo ./virt-construct.py -c vm02.conf

インストール完了後にvm02にログインして、%postの実行ログを見るとこんな感じ。

[root@vm02 ~]# cat anaconda-post.log 
+ cat
+ curl http://192.168.122.1/scripts/deploy_pgsql.sh -o /tmp/tmp10124
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
101   709  101   709    0     0  55941      0 --:--:-- --:--:-- --:--:--  692k
+ . /tmp/tmp10124 https://github.com/enakai00/pgsql_configs.git development_1.0
++ GitRepository=https://github.com/enakai00/pgsql_configs.git
++ ConfigTag=development_1.0
++ RepoName=pgsql_configs.git
++ RepoName=pgsql_configs
++ yum -y install postgresql-server
Loaded plugins: product-id, security, subscription-manager
(中略)
Installed products updated.
  Verifying  : postgresql-libs-8.4.11-1.el6_2.x86_64                        1/3 
  Verifying  : postgresql-server-8.4.11-1.el6_2.x86_64                      2/3 
  Verifying  : postgresql-8.4.11-1.el6_2.x86_64                             3/3 

Installed:
  postgresql-server.x86_64 0:8.4.11-1.el6_2                                     

Dependency Installed:
  postgresql.x86_64 0:8.4.11-1.el6_2   postgresql-libs.x86_64 0:8.4.11-1.el6_2  

Complete!
++ service postgresql initdb
Initializing database:                                     [  OK  ]
++ service postgresql start
Starting postgresql service:                               [  OK  ]
++ su - postgres -c 'psql -c "ALTER USER postgres encrypted password '\''pas4pgsql'\''"'
ALTER ROLE
++ service postgresql stop
Stopping postgresql service:                               [  OK  ]
++ git_restore
++ rm -rf /tmp/gittmp
++ mkdir -p /tmp/gittmp
++ cd /tmp/gittmp
++ git clone https://github.com/enakai00/pgsql_configs.git
Initialized empty Git repository in /tmp/gittmp/pgsql_configs/.git/
++ cd pgsql_configs
++ [[ ! -z development_1.0 ]]
++ git checkout development_1.0
Note: checking out 'development_1.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 62e22ce... log and security settings for development environment
++ cp -rv /tmp/gittmp/pgsql_configs/data /var/lib/pgsql/
`/tmp/gittmp/pgsql_configs/data/postgresql.conf' -> `/var/lib/pgsql/data/postgresql.conf'
`/tmp/gittmp/pgsql_configs/data/pg_hba.conf' -> `/var/lib/pgsql/data/pg_hba.conf'
++ restorecon -r /var/lib/pgsql
++ chkconfig postgresql on
+ rm /tmp/tmp10124

[root@vm02 ~]# tail /var/lib/pgsql/data/postgresql.conf /var/lib/pgsql/data/pg_hba.conf 
==> /var/lib/pgsql/data/postgresql.conf <==
#custom_variable_classes = ''		# list of custom variable class names

log_destination = 'syslog'
syslog_facility = 'LOCAL0'
syslog_ident = 'postgres'
log_line_prefix = '%u %d '
log_connections = on
log_disconnections = on
log_statement = 'all'

==> /var/lib/pgsql/data/pg_hba.conf <==

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               md5
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5

vm01からgithubにpushしておいた設定が再現されていることが分かります。

考察

この手法の便利なところは、vm01でさまざまな設定変更を行った場合でも、変更後の状態をgithubにpushしてタグを振っておけば、vm02.confの変数指定(pgsql_gittag=development_1.0)で任意のタグの状態を再現できるところです。PostgreSQLを使った開発中アプリケーションのテストを行う際に、任意の設定のPostgreSQL環境をすぐに再現して、きれいな状態でテストを実行できます。また、ご存知の通りgitは分散バージョン管理システムですので、(多少のgitの知識があれば)vm02で設定変更を行なって、それをgithubにpushすることも可能です。

一方、改善点としては、deploy_pgsql.sh自体に環境再現のロジックが埋め込まれていて、このシェルそのもののメンテナンスを誤ると、正しく環境が再現できなくなる恐れがあります。また、gitでは、ファイルのオーナ情報やハードリンク情報は保存できない点にも注意が必要です。この例では、コピー先のファイルのオーナ情報を保存する形でコピーすることで対応していますが、すべての場合にこれでうまくいくわけではありません。結局のところ、deploy_pgsql.shに人依存の「職人技」が残ってしまう可能性があるということでしょうか。。。

根本の問題は、使用するアプリケーションごとに、deploy_hogehoge.shを作りこまないといけない点。本来は、アプリケーションの提供者がアプリケーション標準のツールとして、このような道具を用意することですが、なかなか標準化は難しそうです。

この後は、普段から使用しているアプリケーション環境にこの手法を適用して、しばし、メリット/デメリットをみてみることにします。