puppet 日本語 Wiki はじめました

Posted by Gosuke Miyashita Sat, 24 Mar 2007 18:02:23 GMT

略して パペウィキ弊社 の社内ウィキはペパウィキですが、一切関係ありません。

やはりブログは情報整理に向いてないので、ウィキで整理してみることにしました。

このブログで書いたことも、順次移していきます。(元々このブログは Trac Wiki Formatting で書いてるので、移すのが楽。)

どなたでも編集できますので、お気づきの点などあれば、直接編集しちゃってくださいませ。

puppetrun を試すならやっぱ trunk 版の方がよさげ

Posted by Gosuke Miyashita Sat, 24 Mar 2007 14:21:07 GMT

puppet 今試すなら バージョン 0.22.1 を使え、そして gem で入れるな というエントリを書いたわけですが、puppetrun で特に exec を使って puppet クライアントで何かコマンドを実行させたい、ということであれば、今は trunk 版を使ったほうがいいかも。

理由。まず以下の様な単純なコマンドを実行させる site.pp をつくる。

exec { 'touch':
  path    => '/bin',
  command => 'touch /tmp/puppet',
}

で、puppetmasterd を puppet サーバで起動。

$ sudo puppetmasterd

次に puppet クライアント側で puppetd を起動。

$ sudo puppetd --listen --no-client --server kenny.southpark -v 

そして、puppet サーバ側で puppetrun を起動して、設定した exec をクライアントで実行させる。

$ sudo puppetrun --host cartman.southpark

すると、0.22.1 では、クライアント側の puppetd がハングした状態になります。strace で見ると、以下の記述が延々と表示されるという状態に。

rt_sigprocmask(SIG_SETMASK, [], ULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], ULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], ULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], ULL, 8) = 0
... (以下繰り返し)

0.22.1 と 0.22.2 の間で、lib/puppet/type/exec.rb にかなり修正が入ってるので、おそらく 0.22.2 では大丈夫だろうけど、前エントリ で書いたように、0.22.2 ではそもそも puppetd がエラーで起動できない、という問題がある。なので、trunk 版を使うのがいい、という結論になりました。trunk 版だと問題なく実行できることを確認済み。

ただ、これも 前エントリ で書いたように、puppetrun に以下の一行を追加しないと動かないので注意。 fix された。自分の修正内容と違うけど。

require 'puppet/network/client/runner'

まだ実戦投入はやめておいた方がよさそうかな…。まだ検証段階なのでいいのですが。

puppet 今試すなら バージョン 0.22.1 を使え、そして gem で入れるな

Posted by Gosuke Miyashita Sat, 24 Mar 2007 05:49:40 GMT

追記
これに関連した続きエントリ書きました

gem がだめなわけは、puppetrun が入らないから。(0.22.1, 0.22.2 で確認。)puppetrun 使わないなら gem で構わないけど。metadata 覗いたら、executables の中に puppetrun がない。こんな感じ。

executables:
- puppet
- puppetd
- puppetmasterd
- puppetdoc
- puppetca  

とりあえずチケットに入れておいた

あと、最新のバージョン 0.22.2 だと、以下のエラーが出る。

$ sudo puppetd --listen --no-client -v
/usr/lib/ruby/site_ruby/1.8/puppet/util/config.rb:29:in `[]': Undefined configuration parameter 'authconfig' (ArgumentError)
        from /usr/lib/ruby/site_ruby/1.8/puppet.rb:83:in `[]'
        from /usr/bin/puppetd:360

--listen オプション使うときには、/etc/puppet/namespaceauth.conf が必要で、authconfig にはこのパスがセットされるはずなんだけど、セットされていないためのエラーっぽい。これは trunk では直ってる。

もうひとつ、puppetrun 実行時のエラー。

$ sudo puppetrun --host kenny.southpark
Failed to load ruby LDAP library. LDAP functionality will not be available
/usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/core_ext/module/introspection.rb:5:in `parent': private method `split' called for :Client:Symbol (NoMethodError)
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:463:in `const_missing'
        from /usr/local/bin/puppetrun:343
        from /usr/local/bin/puppetrun:335:in `fork'
        from /usr/local/bin/puppetrun:335
kenny.southpark finished with exit code 1 

これは puppetrun に以下の一行を追加すれば直る。

require 'puppet/network/client/runner'

trunk でも直ってないようなので、こちらもチケットに入れた fix された。自分の修正内容と違うけど。

Trac の Wiki を emacs で直接編集

Posted by Gosuke Miyashita Tue, 20 Mar 2007 17:19:09 GMT

emacs trac-wiki mode なんてものがあったんですね。これは便利。

セットアップや設定方法なんかは上のリンクを参照すれば分かるので省略。

M-x trac-wiki を実行すると、まずはプロジェクト名を聞いてくる。

http://mizzy.org/img/emacs_trac_00.jpg

次に認証のためのユーザ名。

http://mizzy.org/img/emacs_trac_01.jpg

そしてパスワード。

http://mizzy.org/img/emacs_trac_02.jpg

編集する Wiki ページ名を聞いてくる。タブで Trac 上にある Wiki ページ一覧を表示してくれたり、補完してくれたりする。

http://mizzy.org/img/emacs_trac_03.jpg

Wiki ページを開くとこんな感じ。

http://mizzy.org/img/emacs_trac_04.jpg

C-c C-c で Trac に保存。

まあ、Firefox 拡張の It's All Text! 使えば、Trac に限らず任意のエディタで編集できるのですが、ブラウザで開く手間が省けるのはいいですね。Emacs-w3m を利用したプレビュー表示にも対応してたりとか、他にも色々便利な機能があります。詳しくは 開発元サイト 参照。

puppet の実行ファイル

Posted by Gosuke Miyashita Tue, 20 Mar 2007 15:34:33 GMT

Puppet Executables より。またもや超意訳、というかメモ。

puppet

スタンドアロンなインタプリタ。manifest ファイルを直接読んで、自ホストに適用する。あまり使うことはないと思う。

puppetca

SSLv3 証明書ハンドリングのためのコマンド。この辺参照

puppetd

puppet クライアント側で実行するデーモン。デフォルトでは、puppet サーバに対して定期的に問い合わせに行くけれど、

$ puppetd --listen --no-client

と実行することで、puppet サーバからキックされるのを待ち受ける状態になる。(サーバは後述の puppetrun を実行してキックする。)

puppetdoc

puppet ソースからドキュメントを抽出するためのツール。これもあまり使わないと思う。

puppetmasterd

puppet サーバ側で起動するデーモン。

puppetrun

puppet クライアントをサーバ側からキックする時に使うコマンド。

$ puppetrun --host hostA --host hostB

という感じで特定のクライアントのみキックできるし、

$ puppetrun --all --parallel 5

とかですべてのクライアントをキックする(ただし同時にキックするのは 5 クライアント)といったことができる。

$ puppetrun --class web

とかで web クラスのクライアントのみキックとかもできる。ただし、--all や --class は、クライアントホストを LDAP で管理している場合のみ。

うちではこれをメインに使うことになりそう。サーバの数が数百台とかあるから、クライアントから定期的にポーリングされる負荷も馬鹿にならないし、いっぺんにファイルとりにこられたりすると、とんでもないことになるので。

puppet の通信の仕組みにちょっと立ち入ってみる

Posted by Gosuke Miyashita Tue, 20 Mar 2007 15:08:03 GMT

puppet のクライアント/サーバ間通信は https + XMLRPC で、認証は SSLv3 の証明書認証が利用されています。

通常、SSLv3 で証明書認証とかいうと、CA とか、自己署名証明書とか、色々めんどくさかったりしますが、puppet はこの辺りはほとんど自動で処理してくれるので、とても楽です。

例えば、puppet サーバ側では、puppetmasterd をはじめて起動した時に、CA 関連ファイルや自己署名証明書などを、/etc/puppet/ssl 以下に勝手に作ってくれます。

$ ls -R /etc/puppet/ssl
/etc/puppet/ssl:
ca/  certs/  csr_kenny.southpark.pem  private/  private_keys/  public_keys/

/etc/puppet/ssl/ca:
ca_crl.pem  ca_key.pem  inventory.txt  requests/  signed/
ca_crt.pem  ca_pub.pem  private/       serial

/etc/puppet/ssl/ca/private:
ca.pass

/etc/puppet/ssl/ca/requests:

/etc/puppet/ssl/ca/signed:
kenny.southpark.pem

/etc/puppet/ssl/certs:
ca.pem  kenny.southpark.pem

/etc/puppet/ssl/private:

/etc/puppet/ssl/private_keys:
kenny.southpark.pem

/etc/puppet/ssl/public_keys:
kenny.southpark.pem 

あれ、CA 証明書っぽいものが二つある、と思ったら、ca/ca_crt.pem と certs/ca.pem はまったく同じものでした。

また、CA 証明書とは別に、kenny.southpark.pem というものができていますが、これはおそらく、自身が puppet クライアントになる時に利用するものと思われます。

CA 証明書の中身を覗いてみるとこんな感じ。

$ sudo openssl x509 -text -in /etc/puppet/ssl/ca/ca_crt.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 0 (0x0)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: CN=kenny.southpark
        Validity
            Not Before: Mar 20 14:29:16 2007 GMT
            Not After : Mar 18 14:29:16 2012 GMT
        Subject: CN=kenny.southpark
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:ea:83:02:5a:83:08:02:c8:bc:cd:d0:26:07:e7:
                    44:f7:a0:0e:0f:26:23:82:ba:e4:ed:d7:c8:88:c6:
                    43:b7:0a:5d:16:39:a2:6a:48:f9:8f:a5:9d:35:2f:
                    24:1e:ec:38:6b:73:0f:23:17:84:70:7e:08:08:96:
                    bd:e6:51:53:f2:fe:1d:ec:2f:d0:9a:5b:3d:ea:92:
                    8a:39:f5:ff:02:ff:6b:e4:d2:ef:9f:d2:c3:d6:35:
                    d8:5c:51:42:d9:16:59:62:c5:da:9a:9d:cd:f7:91:
                    a7:06:0b:28:8e:7f:4a:52:bc:5f:c3:5c:cb:b3:e3:
                    81:d0:1b:ca:b6:7f:73:b2:3f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            Netscape Comment:
            Puppet Ruby/OpenSSL Generated Certificate
            X509v3 Basic Constraints: critical
            CA:TRUE
            X509v3 Subject Key Identifier:
            82:0D:36:AD:29:30:30:2D:CC:2D:EB:EA:F9:32:07:44:80:11:D3:E6
            X509v3 Key Usage:
            Certificate Sign, CRL Sign
    Signature Algorithm: sha1WithRSAEncryption
        e0:0b:a7:28:39:8e:09:cc:91:85:ce:13:19:c1:9b:ba:21:c3:
        d8:09:c2:ee:93:ac:8d:76:91:18:7a:31:01:fc:55:8b:84:e6:
        69:3f:f5:a3:62:ce:cc:af:87:21:42:d4:0d:ab:02:62:26:4f:
        c2:f4:a2:22:4f:52:a5:06:bd:88:4c:65:89:9e:98:4c:cb:82:
        ce:09:50:e0:4b:67:59:1e:d7:26:75:2f:6f:3d:d3:d4:92:55:
        79:06:5e:56:39:2b:15:b0:67:d9:00:79:09:37:86:1a:a1:30:
        e0:ce:e8:2b:0a:16:92:73:a3:b8:1f:16:c8:60:f7:7d:c5:24:
        09:66
-----BEGIN CERTIFICATE-----
MIICIzCCAYygAwIBAgIBADANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA9rZW5u
eS5zb3V0aHBhcmswHhcNMDcwMzIwMTQyOTE2WhcNMTIwMzE4MTQyOTE2WjAaMRgw
FgYDVQQDDA9rZW5ueS5zb3V0aHBhcmswgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
AoGBAOqDAlqDCALIvM3QJgfnRPegDg8mI4K65O3XyIjGQ7cKXRY5ompI+Y+lnTUv
JB7sOGtzDyMXhHB+CAiWveZRU/L+Hewv0JpbPeqSijn1/wL/a+TS75/Sw9Y12FxR
QtkWWWLF2pqdzfeRpwYLKI5/SlK8X8Ncy7PjgdAbyrZ/c7I/AgMBAAGjeTB3MDgG
CWCGSAGG+EIBDQQrFilQdXBwZXQgUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
aWZpY2F0ZTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSCDTatKTAwLcwt6+r5
MgdEgBHT5jALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEFBQADgYEA4AunKDmOCcyR
hc4TGcGbuiHD2AnC7pOsjXaRGHoxAfxVi4TmaT/1o2LOzK+HIULUDasCYiZPwvSi
Ik9SpQa9iExliZ6YTMuCzglQ4EtnWR7XJnUvbz3T1JJVeQZeVjkrFbBn2QB5CTeG
GqEw4M7oKwoWknOjuB8WyGD3fcUkCWY=
-----END CERTIFICATE-----    

次にクライアント側ですが、こちらもはじめて puppetd(クライアント側で起動するデーモン)を実行した時に、秘密鍵、公開鍵、CSR を自動的に作成し、サーバに対して CSR への署名を求めることが、起動時のメッセージから読み取れます。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
err: No certificate; running with reduced functionality.
info: Creating a new SSL key at /var/lib/puppet/ssl/private_keys/cartman.southpark.pem
info: Creating a new certificate request for cartman.southpark
info: Requesting certificate
warning: peer certificate won't be verified in this SSL session
notice: Did not receive certificate

サーバ側では、証明書リクエストが来ていることを、次のようなコマンドで確認できます。

$ sudo puppetca --list
cartman.southpark

これに署名するには、

$ sudo puppetca --sign cartman.southpark

と実行するだけです。これで puppet クライアント/サーバ間で無事通信できるようになります。

セキュアな通信が割りと簡単に実現できていい感じ。

puppet でファイルが変更されたら指定したコマンドを実行するレシピ

Posted by Gosuke Miyashita Mon, 19 Mar 2007 12:02:10 GMT

puppet で ファイルの配布 ができたので、次はファイルが変更されたら特定のコマンドを実行、にチャレンジ。これは FAQ にやり方書いてました。

puppet サーバで管理している /etc/httpd/conf.d/ 以下のファイルが変更されたら、puppet クライアント上のファイルを更新して httpd を再起動するレシピはこんな感じ。

class web {
  define httpd {
    $path = '/etc/httpd/conf.d'
    file { $path:
      source  => 'puppet://mizzy.org/files/etc/httpd/conf.d',
      recurse => 'true',
    }
    exec { 'httpd restart':
      command     => '/etc/init.d/httpd restart',
      subscribe   => File[$path],
      refreshonly => true
    }
  }

  httpd { 'httpd settings': }
}

node 'www.mizzy.org' {
  include web
}

/etc/httpd/cond.d/perl.conf を変更して puppet クライアント上で puppetd --test を実行するとこんな感じに。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
info: Caching configuration at /var/lib/puppet/localconfig.yaml
notice: Starting configuration run
info: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf: Removing old backup of type file
notice: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf/source: source changed '{md5}b78c3e53dd7fef842c99f105e9e4204f' to '{md5}a28770c2cdfc4c23faa2ea41b2e67397'
info: //www.mizzy.org/web/httpd[httpd settings]/file=/etc/httpd/conf.d/perl.conf: Scheduling refresh of exec[httpd restart]
notice: //www.mizzy.org/web/httpd[httpd settings]/exec=/etc/init.d/httpd restart: Triggering 'refresh' from 1 dependencies
notice: Finished configuration run in 7.42 seconds    

ファイルが更新されてない場合はこうなる。

$ sudo /usr/sbin/puppetd --server mizzy.org --test
info: Caching configuration at /var/lib/puppet/localconfig.yaml
notice: Starting configuration run
notice: Finished configuration run in 6.80 second

puppet file server

Posted by Gosuke Miyashita Mon, 19 Mar 2007 10:22:17 GMT

puppet サーバ上のファイルをクライアントに配布するには、file server 機能を利用するらしい。というわけで、ドキュメント File Serving Configuration から要点を抜き出してみる。

/etc/puppet/fileserver.conf の設定

[module]
    path /path/to/files
    allow *.domain.com
    deny *.wireless.domain.com

こう設定すると、

/path/to/files/sudoers

というファイルを

puppet://server/module/sudoers

で取得できるようになる。

manifest の設定

"the Puppet language" が記述される設定ファイルを manifest と呼ぶらしい。要は puppet クライアントをどう管理するか、が記述された設定ファイルですね。(上の /etc/puppet/fileserver.conf は manifest ではない。)

puppet file server 上のファイルを配布するには、以下の様な設定を manifest に記述。

# copy a remote file to /etc/sudoers
file { "/etc/sudoers":
    mode   => 440,
    owner  => root,
    group  => root,
    source => "puppet://server/module/sudoers"
}

source がポイント。

詳細は File Serving Configuration を参照。

puppet の言語構造

Posted by Gosuke Miyashita Mon, 19 Mar 2007 04:34:13 GMT

Installation Guide を読めば、とりあえず puppet を動かすことはできるけど、やりたいことをやろうと思ってもすぐにできるわけでもない。というわけで、ドキュメントをちゃんと読んでみることにした。

まずは puppet の設定ファイルで使われている内部言語の理解から、ということで、Language Structures を超意訳してみる。

Types

puppet 設定の基本構成単位。管理されるコンピュータ上のオブジェクト(ファイルとかパッケージとか)を表すもので、あらかじめ用意されたビルトインタイプ以外にも、自ら定義することも可能。

file { "/etc/passwd": owner => root, mode => 644 } 
package { apache: install => true }

詳しくは Type Reference を参照。

Assignment

変数が利用できる。

$variable = value
$x = foo
$y = bar
$z = "$x$y"

Bringing Config files together

設定ファイルに、別の設定ファイルをインポートできる。

import "filename"

正規表現も利用可能。

import "classes/*"
import "packages/[a-z]*"

Scope

{ } によってスコープが形成される。

変数は一度割り当てられると、同一スコープ内では変更できないが、サブスコープ内では同一名の変数を割り当てることができる。

$var = value

# override $var
define testing {
    $var = othervalue
}

Components

ここでいう Components とは、自分で定義する Type のことっぽい。Components の定義と利用は以下の様な感じ。

define svnserve($source, $path, $user = false, $password = false) {
    file { $path:
        create => directory,
        owner => root,
        group => root
    }
    $svncmd = $user ? {
        false => "/usr/bin/svn co --non-interactive $source/$name .",
        default => "/usr/bin/svn co --non-interactive --username $user --password '$password' $source/$name ."
    }   
    exec { $svncmd: 
        cwd => $path,
        require => file[$path],
        creates => "$path/.svn"
    }   
}

svnserve { dist:
    source => "https://reductivelabs.com/svn",
    path => "/dist",
    user => "puppet",
    password => "password"
}

svnserve { "dist/config/apps/puppet":
    source => "https://reductivelabs.com/svn",
    path => "/etc/puppet",
    user => "puppet",
    password => "password"
}

利用する時はビルトインタイプと構文上の違いはない。

Server Classes

Class を定義してインクルードすることができる。

class  [inherits ] { ... }

継承も可能。

# really simple example
class solaris {
    file {
        "/etc/passwd": owner => root, group => root, mode => 644;
        "/etc/shadow": owner => root, group => root, mode => 440
    }
}

class solworkstation inherits solaris {
    file {
        "/etc/sudoers": owner => root, group => root, mode => 440;
        "/bin/sudo": owner => root, group => root, mode => 4111
    }
}

include solworkstation

以下の例だと、$operatingsystem の値と同名の Class と、$hostname に応じた Class がインクルードされる。

include $operatingsystem, $hostname ? {
    myhost => classA, default => classB
}

$operatingsystem とか $hostname とかは、Facterというライブラリを使ってプリセットされているみたい。

Classes vs. Components

Classes と Components の違いは以下の通り。

  • Classes はシングルトンなので、ホスト上でひとつしかないものを定義するのに利用する(OSの種類とか、特定のパッケージとかサービスとか。)
  • Components はホスト上で複数あるオブジェクト(バーチャルホストなど)を定義するのに利用する。

あと、Classes は引数を受け取れない、という違いもある。

Subclssing

Class は継承ができる。

class unix {
    file { "/etc/sudoers":
        owner => root,
        group => root,
        mode => 440
    }
}

class bsd inherits unix {
    File["/etc/sudoers"] {
        group => wheel
    }
}

Using Classes Outside of Puppet

puppet サーバで設定された Class 名が、puppet クライアントの /etc/puppet/classes.txt に保存されるので、それを外部プログラムなどから読み込んで利用したりできるよ、とうことらしい。

FC4 で yum insall した puppet の場合は、/var/lib/puppet/classes.txt に保存されていた。

Nodes

node  { ... }

特定のホストに適用する設定を割り当てる。

以下の例だと、file type はすべてのホストに割り当てられるけど、webserver class と dbserver class の中に書かれた設定は、それぞれ特定のホストにのみ割り当てられる。

class webserver { ... }
class dbserver { ... }

file { "/etc/sudoers": mode => 440 } # apply to everyone

node host1, host2 {
    include webserver
}
node host3, host4 {
    include dbserver
}

node は継承することも可能。

node base {
    include $operatingsystem
}

node kirby inherits base {
    include webserver
}

FQDN で指定する時は、シングルクォートで囲む。

node 'host.domain.com' {
    ...
}

Conditionals

条件指定が可能。

以下の例は $os が何かによって、 $owner に入る値が変わる。

define testing(os) {
    $owner = $os ? {
        sunos => adm,
        redhat => bin,
        default => root
    }
    file { "/some/file": owner => $owner }
}

以下の例は $operatingsystem が何かによって、適用する class が変わる。

case $operatingsystem {
    sunos:      { solaris {} } # apply the solaris class
    redhat:     { redhat  {} } # apply the redhat class
    default:    { generic {} } # apply the generic class
}

Reserved words

true, define, inherits, class は予約語。

Comments

sh スタイルのコメントが利用可。

puppet の node 設定ではまる

Posted by Gosuke Miyashita Sun, 18 Mar 2007 13:10:23 GMT

といったあたりを読みながら puppet を試していたのですが、node の設定ではまったのでメモ。

pueppt では、

node nag.example.com {
  include yum-rawhide
  include horde-db-pg
  include horde-nag
}

といった設定でターゲットとなるホストと、そのホストでどのようなタスクを実行するかを定義できるのですが、これで puppetmasterd を実行すると、

Syntax error at '.' at /etc/puppet/manifests/site.pp:5 

と怒られます。そこで、

node 'nag.example.com' {
  include yum-rawhide
  include horde-db-pg
  include horde-nag
}

とクォートしてあげると OK でした。最初に挙げた URL にあるチュートリアルの例ではクォートされておらず、そのままやるとはまりますのでご注意を。

追記
Language Structures を読んだら、「You can specify fully-qualified node names, but you have to single-quote the names:」ってちゃんと書いてあった。

Older posts: 1 2 3 4 5 ... 27