2011年4月25日月曜日

Fabricで複数サーバのyumパッケージ更新を効率化

こんにちは。ikuyamadaです。

FabricというPythonのライブラリをご存知ですか?Fabricは、SSH経由で任意のコマンドを実行するPythonスクリプトを簡単に記述できるようにするためのライブラリです。

Fabricを使うと、従来はシェルスクリプト等で行っていた、ソフトウェアの複数サーバへのデプロイやシステム管理などを簡単なPythonのスクリプトで自動化することが出来ます。

例えば、通常のコマンド実行は、run("ls")などと書けばできますし、その他、管理者権限のコマンドを実行するsudoや任意のファイルをコピーするputなど、様々な関数が用意されています。

今回は、Fabricの紹介も兼ねて、弊社で実際に用いているFabricを用いたyumによるパッケージ更新スクリプトについて紹介と思います。この簡単なスクリプトを使うと、複数のサーバへのyumのパッケージ更新を、内容を確認しながらインタラクティブに行えるようになります。

(この記事は、先月にLinux Gazette誌に投稿した「Applying Yum Package Updates to Multiple Servers Using Fabric」を翻訳、編集したものです)

インストール


まずFabricをインストールする必要があります。easy_installpipでインストール可能です。

CentOSの場合は、下記のように、まずEPELおよびPython 2.6をインストールした後、easy_installFabricを導入します。
EPELをインストール:
# sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
Python 2.6をインストール:
# sudo yum -y install gcc python26 python26-devel python26-distribute
Fabricをインストール:
# sudo easy_install-2.6 fabric

スクリプト

それではスクリプトを紹介します。任意のディレクトリにfabfile.pyというファイルを作成し、下記の内容をペーストしてください。
#!/usr/bin/env python2.6

from fabric.api import *
from fabric.contrib.console import confirm

env.warn_only = True

def update():
    if run("yum check-update").return_code != 0:
        if confirm("execute yum update?", default=False) == True:
            sudo("yum -y update")
このスクリプトでは各サーバにSSHで接続、yum check-updateを実行し、アップデートがあった場合に、アップデートの内容を表示して、yum -y updateを実行するかどうか問い合せます。

内部的には、yum check-updateがパッケージの更新があった場合に返り値として0以外を返すため、それを利用して、パッケージ更新があるかないかを検出しています。
また、Fabricはコマンドの返り値が0以外であった場合にデフォルトで終了してしまうため、env.warn_only = Trueとすることで、終了しないように設定しています。

それでは、早速実行してみます。fabfile.pyを作成したディレクトリで下記のコマンドを実行してみてください。
# fab -H HOST_NAME1,HOST_NAME2 update
(HOST_NAME1, HOST_NAME2にホスト名を入力してください)

そうすると、下記のような形で、Fabricがパッケージ更新があるかをチェックし、更新がある場合、更新を行うかどうかを問い合せます。
[qui-gon.ikuya.net] Executing task 'update'
[qui-gon.ikuya.net] run: yum check-update
[qui-gon.ikuya.net] out: Loaded plugins: fastestmirror
[qui-gon.ikuya.net] out:
[qui-gon.ikuya.net] out: bind-libs.x86_64                        30:9.3.6-4.P1.el5_5.3            updates
(snip)
[qui-gon.ikuya.net] out: udev.x86_64                             095-14.21.el5_5.1                updates

Warning: run() encountered an error (return code 100) while executing 'yum check-update'

execute yum update? [y/N]

また、下記のような形でfabfile.py内に予めホスト名を設定しておくこともできます。
#!/usr/bin/env python2.6

from fabric.api import env, run, sudo
from fabric.contrib.console import confirm

env.hosts = [
    "HOST_NAME1",
    "HOST_NAME2"
]
(略)

最後に

今回はFabricを使ってyumのパッケージ更新スクリプトを紹介しました。もしFabricに興味を持たれた場合は、Fabricのオフィシャルドキュメントを参照してみてください。

2011年4月4日月曜日

PuppetでCentOSサーバ管理を自動化

こんにちは。ikuyamadaです。

今回は、独自のプログラミング言語を使ってサーバの状態を記述することで、サーバ管理を効率化することの出来るツール「Puppet」を使ったサーバ管理手法について紹介したいと思います。当社では、このPuppetを使うことで、かなりサーバ管理を効率的に管理することができるようになりました。皆さんもぜひ一度使ってみてください。

(この記事は2月にLinux Gazette誌に寄稿した「Automating virtual server administration using Puppet」を翻訳し編集したものです)

イントロダクション


サーバ環境をXenやKVMなどで構築すると、使用する仮想サーバの台数は多くなりがちです。用途ごとに仮想サーバを切り分けることで、サーバ資源をより有効に使用できたり、障害の原因を切り分けられるなどのメリットがありますが、反面、サーバのインストールや運用にはより多くの手間がかかるようになります。また、cronやapacheなど、複数のサーバで使用されている設定を変更するのも大変です。

そこで、今回は、弊社のサーバ環境でも広範に使用されている「Puppet」というツールを使って、自動的にサーバ環境を構築・運用できる方法を紹介したいと思います。このツールは主に大規模サーバの管理を効率化するために作られたものですが、小規模なサーバ管理にも適しています。

掲載された設定例を使うことで、数行のコマンドを打つだけで、基本的なセキュリティ設定を含めた新しいサーバを簡単にセットアップすることができます。また、Puppetは自動的に設定をサーバ間で同期するため、設定を最新のものに保つこともできます。

ここで紹介するサーバの設定はCentOS 5.5でテストを行っています。

インストール


Puppetはクライアント/サーバモデルで動作します。各クライアントは定期的にマスターサーバと設定を同期します。このため、Puppetのインストールにはマスタサーバとクライアントサーバを1台ずつ用意する必要があります。

それではPuppetをインストールします。Fedora EPELがPuppetのYumパッケージを提供しているため、まずインストールします。
$ sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
そして、puppet-serverパッケージをマスターサーバに、puppetパッケージをクライアントサーバにインストールします。

マスターサーバ:
$ sudo yum -y install puppet-server
$ sudo service puppetmaster start

クライアントサーバ:
$ sudo yum -y install puppet
$ sudo service puppet start

Puppetの簡単な紹介


Puppetでは、全ての設定を「リソース」として記述します。リソースではファイルやソフトウェア・パッケージ、サービスなど様々なものを記述できます。例えば、下記のリソースは/etc/passwdがrootによって所有され、644のパーミッションを保持していることを示しています。
file { '/etc/passwd':
    owner   => root,
    mode    => 644,
}
また、下記の設定は、openssh-serverパッケージをインストールし、sshdサービスをデフォルトで有効化することを示しています。
package { 'openssh-server':
    ensure => installed,
}

service { 'sshd':
    enable  => true,
    ensure  => running,
    require => Package['openssh-server'],
}
それでは、これらの設定を適用してみたいと思います。Puppetは、デフォルトでsite.ppというファイルを使用します。まずはsite.ppを作成しましょう。下記の内容をマスターサーバの/etc/puppet/manifests/site.ppにペーストしてください。
file { '/etc/passwd':
    owner   => root,
    mode    => 644,
}

package { 'openssh-server':
    ensure => installed,
}

service { 'sshd':
    enable  => true,
    ensure  => running,
    require => Package['openssh-server'],
}
次にクライアントサーバをマスターサーバに登録する必要があります。下記のコマンドを順にクライアントサーバとマスターサーバで実行してください。

クライアントサーバ:
$ sudo puppetd --test --waitforcert 30 --server MASTER_SERVER_ADDRESS
マスターサーバ:
$ sudo puppetca --list
(クライアントサーバのアドレスが表示されます)
$ sudo puppetca --sign CLIENT_SERVER_ADDRESS
クライアントサーバのコンソールでしばらく待つと、Puppetが設定を同期するメッセージが表示されると思います。もし表示されない場合は、一旦コマンドをCtrl-Cで終了し、下記コマンドを再度実行してみてください。
$ sudo puppetd --test --server MASTER_SERVER_ADDRESS

最後に、Puppetにマスターサーバのアドレスを登録するため、クライアントサーバの/etc/puppet/puppet.confに下記の内容を記述してください。

クライアントサーバ:
[main]
server = MASTER_SERVER_ADDRESS
設定後、Puppetは30分ごとに自動的に設定を同期します。設定が成功していれば、/var/log/messagesでログを確認することができるはずです。
$ sudo tail /var/log/messages

設定例


この節では、いくつかの基本的な設定例を記述します。site.ppに記述することで使用することができます。

管理ユーザの追加

Puppetはユーザアカウントの管理を行えるuserリソースを提供しています。下記の設定で、サーバにadminユーザを追加します。
# Add "admin" account
user { 'admin':
     # home directory is /home/admin
    home       => '/home/admin',
    # manage the home directory by Puppet
    managehome => true,
    # the user belongs to wheel group
    groups     => ['wheel'],
    # hashed password text
    password   => 'PASSWORD_HASH',
}
PASSWORD_HASH/etc/shadow等で使われている基本的なパスワードハッシュです。Perl等で簡単に生成することが出来ます。
$ perl -wle 'print crypt "PASSWORD", "SALT"'
sudo

下記の設定はsudoパッケージをインストールし、augeasを使ってwheelユーザにsudoの実行権限を付与します。
# Install sudo package
package { 'sudo':
    ensure => installed,
}

# Allow users belonging wheel group to use sudo
augeas { 'sudowheel':
    context => '/files/etc/sudoers',
    changes => [
        'set spec[user = "%wheel"]/user %wheel',
        'set spec[user = "%wheel"]/host_group/host ALL',
        'set spec[user = "%wheel"]/host_group/command ALL',
        'set spec[user = "%wheel"]/host_group/command/runas_user ALL',
    ]
}
SSH

下記の設定はsshをサーバで有効化し、ssh経由でのrootログイン及び空パスワードでのログインを抑制します。
# Install openssh-server package
package { 'openssh-server':
    ensure => installed,
}

# Enable sshd service
service { 'sshd':
    # execute sshd on startup
    enable  => true,
    # ensure sshd running
    ensure  => running, 
    # require openssh-server before applying this config
    require => Package['openssh-server'],
}

# Change sshd configuration
augeas { 'sshd_config':
    context => '/files/etc/ssh/sshd_config',
    # restart sshd after applying this config
    notify  => Service['sshd'],
    changes => [
        # deny root logins and logins with empty passwords
        'set PermitRootLogin no',
        'set PermitEmptyPasswords no',
    ],
}
iptables

Puppetでiptablesを管理するにはpuppet-iptablesという外部モジュールをインストールする必要があります。下記のコマンドでGitHubからインストールします。(gitがない場合はインストールしてください)
$ cd /tmp
$ git clone https://github.com/kbarber/puppet-iptables.git
$ sudo mkdir -p /etc/puppet/modules
$ sudo mv puppet-iptables /etc/puppet/modules/
また、プラグインを追加するため、下記の設定をマスターサーバ・クライアントサーバ双方の/etc/puppet/puppet.confに追加する必要があります。
[main]
    libdir = /var/lib/puppet/lib

[puppetd]
    pluginsync=true
    plugindest=/var/lib/puppet/lib
これでiptablesリソースが使えるようになったはずです。

下記の設定は、内側からの接続、localhost、及びSSHのパケット以外を全てドロップする基本的なiptablesの設定を記述しています。
# Allow packets that belong to or related to an existing connection
iptables { 'allow established, related':
    state => ['ESTABLISHED', 'RELATED'],
    proto => 'all',
    jump  => 'ACCEPT',
}

# Allow all packets from localhost
iptables { 'allow localhost':
    source => '127.0.0.1',
    proto  => 'all',
    jump   => 'ACCEPT',
}

# Allow all packets to SSH
iptables { 'allow ssh':
    proto => 'tcp',
    dport => 22,
    jump  => 'ACCEPT',
}

# Drop all incoming packets by default
iptables { 'drop incoming packets':
    chain => 'INPUT',
    proto => 'all',
    jump  => 'DROP',
}

最後に


この記事では非常に基本的なPuppetの使用法及び設定例を紹介しました。もしPuppetにご興味を持たれた場合は、Puppetのオフィシャルドキュメントを参照してください。日本語のリソースでは、「オープンソースなシステム自動管理ツール Puppet」にもより詳しい情報があります。

2010年6月15日火曜日

Interop Tokyo 2010に出展

幕張メッセで開催されたInterop Tokyo 2010にて、慶應義塾大学W3C内にStudio Ousiaのブースを設け、弊社の開発中のプロダクト「Phroni」と「Weaver」のデモ展示及びプレゼンテーションを行いました。

プレゼンテーション:

ブースの様子:
送信者 Interop Tokyo 2010

発表の様子:
送信者 Interop Tokyo 2010

弊社ブースにお越しくださったみなさま、どうもありがとうございました。

2010年6月11日金曜日

Phroniを国際会議で発表

先日、弊社のプロダクト「Phroni」を、ギリシャのクレタ島で開催されたSemantic Webに関する国際会議「ESWC2010(Extended Semantic Web Conference 2010)」にて発表し、オライリーメディア社よりアワードをいただきました。
今回は発表の内容を簡単にご紹介します。

発表内容

ESWC2010はSemantic Webに関する国際的に著名な国際会議の一つです。今回は、弊社の技術を用いて、Web上の情報から動的に百科事典を生成するPhroniという開発中のサービスの一部を展示させていただきました。

発表スライド:
Phroni: Augmenting Wikipedia Using Mashups

View more presentations from ikuyamada.
発表資料:
Phroni: Augmenting Wikipedia Using Mashups
http://sites.google.com/a/fh-hannover.de/aimashup/home/phroni

会場の様子

会場:
送信者 ESWC2010
授賞式:
送信者 ESWC2010

今回の国際会議で得た知見を活かして、今後とも開発を頑張って続けていきたいと思います。