Puppetのススメ<br />hbstudy#8<br />(株)paperboy&co. 宮下 剛輔<br />2010/02/23<br />
自己紹介<br />宮下 剛輔<br />mizzy, id:MIZZY<br />gosukenator(twitter, gmail)<br />http://mizzy.org/<br />ペパボで技術責任者というのをやってます<br /...
自己紹介<br />最近はまってること<br />WiiFitPlusで筋トレ<br />ホームベーカリーでパンを焼く<br />アサシンクリード2 シーケンス13プレイ中<br />ホットドクターペッパー牛乳<br />
Puppetのススメ<br />
アジェンダ<br />Puppetの概要<br />Puppetの動作概要<br />マニフェストの基礎<br />Puppetを動かしてみる<br />Puppetの使いどころ<br />Puppetを利用する上で知っておくべきこと<br /...
Puppetの概要<br />
Puppet情報リソース<br />http://reductivelabs.com/products/puppet/<br />http://gihyo.jp/admin/serial/01/puppet<br />http://trac.m...
Puppetとは?<br />Ruby製のシステム管理ツール<br />でも、使う上ではRubyかどうかはあまり関係ない<br />Facter(後述)の拡張時にはRubyの知識必要<br />
システム管理ツール?<br />Puppetはサーバの状態を定義し、維持するためのツール<br />以下はPuppetの対象外<br />ハードウェアの設置<br />ネットワーク接続<br />OSインストール/初期設定<br />ネットワー...
Puppetの対象範囲<br />OSインストール/ネットワーク設定/Puppetインストール後のフェーズがPuppetの対象範囲<br />パッケージインストール/設定<br />ユーザ追加<br />cron設定<br />パッケージアップ...
なぜPuppetが必要か?<br />手動作業に伴う問題<br />手作業は時間がかかる<br />手を動かしてる時間はもちろん<br />待ち時間も大幅に効率下げる要因<br />並行して別作業するのも大変<br />あるべき状態との乖離<b...
なぜPuppetが必要か?<br />他の自動化手法に伴う問題<br />カスタムスクリプトでの自動化<br />解読、メンテが大変<br />自由度が高すぎて、書く人のスキルの差によるばらつきが大きい<br />HDDイメージ複製、PXEブー...
Puppet導入のメリット<br />システム構築/アップデートの自動化<br />システムの状態を目に見える形で記録できる<br />マニフェストと呼ばれる独自言語による記述<br />システムのあるべき状態と実際の状態の乖離を防ぐ<br /...
Puppetの動作概要<br />
Puppetのネットワーク構成<br />puppetサーバ<br />(puppetmasterd)<br />実行結果レポート<br />マニフェストの取得と実行<br />puppetクライアント<br />(puppetd)<br />...
Puppet用語<br />マニフェスト<br />システムのあるべき状態が記述されたファイル<br />Puppetサーバで一括して維持管理する<br />Puppetクライアントで取得し、システムに適用<br />リソース<br />Pup...
Puppetの動作概要パターン1<br />puppetサーバ<br />(puppetmasterd)<br />③ 適用結果をレポート<br />① マニフェストを取りに行く(デフォルトは30分に1回)<br />puppetクライアント<...
Puppetの動作概要パターン2<br />puppetサーバ<br />(puppetmasterd)<br />④ 適用結果をレポート<br />② マニフェストを取りに行く<br />① サーバ上でpuppetrunを実行してpuppet...
マニフェストの基礎<br />
リソースの定義<br />リソースタイプ<br />リソースのタイトル<br />リソースの属性<br />file { '/etc/hosts':<br />    owner  => $default_owner,<br />    gro...
クラスでリソースをまとめる<br />「sudo」クラスを定義<br />class sudo{<br />package { ‘sudo’:<br />        ensure => latest,<br />        alias ...
クラスを継承する<br />base クラスを定義<br />class base { <br />    file { "/my/file":<br />        content => template("base.erb")<br /...
リソースの依存関係<br />file { '/etc/ssh':<br />    source  => puppet://server/module/ssh,<br />recurse => true,<br />notify  => Se...
Puppetを動かしてみる<br />
インストール<br />詳細は略。gihyo.jp 見てください。(といっても、古いのでそのまま利用できないかもですが。)<br />ちなみに、CentOSだとEPELリポジトリに割と新しめのパッケージがあります。<br />依存するパッケージ...
デフォルトの設定ファイルを削除<br />基本的に、設定は最低限必要なところだけすれば良いので、デフォルトの設定ファイル群は消してしまうのが吉<br />自分がタッチしてない余分なファイルがあると、その挙動に悩むこともあるし<br />というわ...
マニフェストを書く<br />簡単なマニフェストを書いてみる<br />まずはディレクトリ作成<br /># mkdir /etc/puppet/manifets<br />
マニフェストを書く<br />/etc/puppet/manifests/site.pp<br />file{ '/etc/passwd':<br />    owner => 'root',<br />    group => 'root',...
マニフェストを適用(スタンドアロン版)<br /># puppet /etc/puppet/manifests/site.pp<br />notice: //File[/etc/passwd]/mode: mode changed '777' ...
マニフェスト適用(クライアント/サーバ版)<br />サーバ起動<br /># /usr/sbin/puppetmasterd --verbose <br />  --no-daemonize --nonodes<br />info: Star...
マニフェストを適用(クライアント/サーバ版)<br />クライアントで適用<br /># /usr/sbin/puppetd --server puppet.hoge.com <br />--no-daemonize --verbose --o...
以上<br />簡単ですよね?<br />サーバとクライアントが別の場合は、証明書の署名が手順に入ります<br />/etc/puppet/autosign.confを設定すれば、署名手順は自動化できます<br />実運用では、デーモンとして常...
Puppetの使いどころ<br />
Puppetの使いどころ<br />大量にサーバがある<br />異なるOSや環境のサーバが混在<br />台数少なくても、同じような手順を何度も実行する可能性がある<br />開発環境、検証環境等の、ベースになる部分<br />自分以外の人も...
バージョン管理ツールによるトラッキング<br />なぜこんな設定してるんだろう?という瞬間ありませんか?<br />こんな時でも、バージョン管理ツールで誰がどんな意図で設定、あるいは修正したのかが記録されていると安心です<br />デプロイツー...
インクリメンタル/テスト駆動サーバ構築<br />テスト環境では、Puppetマニフェストを少しづつ書き足し、修正、テストしながら、構築すべき内容を詰めていく<br />Puppet化しておくと、一からつくりなおすのも簡単<br />マニフェス...
Puppetを利用する上で知っておくべきこと<br />
Puppetのコンセプトに馴染む<br />マニフェストでは、リソースとリソース間の関係を記述する<br />静的な状態を記述する<br />Puppetでどうシステムを管理するか、を考える場合、リソースとリソースの関係にブレイクダウンすること...
リソースとその関係へのブレイクダウン<br />例えばApacheの場合、以下のようなリソースへとブレイクダウンし、各リソースとその関係を記述する<br />パッケージ<br />サービス<br />設定ファイル群<br />バーチャルホスト<...
Apacheマニフェスト<br />package { ‘httpd’: ensure => installed }<br />service { ‘httpd’:<br />   enable => true,<br />   ensure ...
Apacheマニフェスト(つづき)<br />file {<br />   ‘/etc/httpd/conf.d/hoge.conf’:<br />       source => “puppet://$server/hoge.conf”,<b...
Apacheマニフェスト(つづき)<br />defineapache_module() {<br />   ....<br />}<br />apache_module { ‘rewrite’:<br />config => “puppet:...
Apacheマニフェスト(つづき)<br />definevirtual_host() {<br />    ...<br />}<br />virtual_host { ‘www.example.jp’:<br />docroot => ‘/...
マニフェストは宣言型言語<br />マニフェストは設定ではなく、言語である<br />手続型言語ではなく宣言型言語<br />「何を実行するか」ではなく最終的な「状態」を定義する<br />通常のシステム管理タスクは手続型なので、発想の転換が必...
手続型と宣言型<br />手続型<br />OpenSSHをインストールする<br />設定ファイルを修正する<br />サービスを起動する<br />宣言型<br />OpenSSHがインストールされた状態にする<br />設定ファイルの内容...
手続型と宣言型<br />同じことをしているように見えるが、実は異なる<br />手続型はプロセスを記述する<br />同じことを何度も繰り返すと、違った状態になることがあり得る<br />宣言型は最終的な状態を記述する<br />マニフェスト...
defined type<br />defineは関数/機能を定義しているように見えるけど、実際はリソースタイプを定義しているので注意<br />definevirtual_host() {<br />    ...<br />}<br />v...
クラスと継承<br />マニフェストにはクラスと継承があるけど、オブジェクト指向言語として十分な機能を備えてるわけではない<br />クラスはあくまでもリソースのコレクションにすぎない<br />
以上はPuppetBest Practices 3.0から<br />http://plathrop.tertiusfamily.net/puppet/best-practice-draft.html<br />
モジュールの活用<br />モジュールは、よく利用するマニフェストを汎用的に利用できるようにまとめたもの<br />よくある処理や、複雑な処理はモジュールとしてまとめるとすっきり<br />でも、本当に汎用的なモジュールを作成するのは難しい…コ...
iptablesモジュールの利用例<br />include'iptables'<br />file {<br />'/etc/iptables.d/filter':<br />        content => template('filt...
iptablesモジュールでやってること<br />iptablesパッケージのインストール<br />必要なファイルの配布<br />全サーバ共通ルールファイル<br />rebuild用スクリプト<br />ルールファイルをがっちゃんこして...
モジュール公開してるところ<br />http://reductivelabs.com/trac/puppet/wiki/PuppetModules<br />外部へのリンクもあり<br />http://github.com/n0ts/pup...
エラー通知<br />Puppetにはエラーだけ通知する仕組みがない?<br />tagmailは特定のクラスに関するログの通知先アドレスを指定できるが、エラーのみ通知、ということができない<br />という話をクックパッドテックライフLTで話...
syslogでエラー通知を分離<br />puppet.conf<br />[puppetd]<br />syslogfacility = local0<br />syslog.conf<br />local0.err <br />/var/l...
ノード情報の管理<br />シンプルなやりかたは、ノード情報をマニフェストに記述する<br />node‘www.hoge.com’ {<br />include‘base’<br />include‘www’<br />}<br />
ノード情報の管理<br />ExternalNode機能を使えば、既存で持ってるノード情報を使いまわせる<br />具体的には、ノード名を与えると、既存のノード情報を変換してYAML形式で出力するようなスクリプトを用意して、puppetに設定す...
External Nodeの設定例<br />/etc/puppet/puppet.confでの設定<br />[puppetmasterd]<br />external_nodes = <br /> /usr/bin/cobbler-ext-...
cobbler-ext-nodesの実行結果<br />$ cobbler-ext-nodes web-proxy.example.jp<br />classes: [base, web-proxy]<br />parameters: {fro...
Cobblerでノード情報管理<br />最近はCobblerを利用しているので、こいつのノード情報をマスターとしてます<br />cobbler-ext-nodesコマンドが付属してるので、Puppetと即連携可<br />Cobblerはd...
LDAPによるノード情報管理<br />puppetrun –all とか –class オプションの利用には、LDAPでノード情報を管理する必要がある<br />でも、あまりお勧めしない。めんどうだけどあまりメリットない。<br />pupp...
execは最小限に<br />Puppetマニフェストは基本的に、最終的な「状態」を定義するもの<br />なので、何度適用しても、最終的な状態は同じになる<br />ただしexecリソースは例外で、何を実行するかを定義する<br />副作用の...
execを濫用したマニフェスト<br />exec { 'sysctl add':<br />command => 'echo "net.ipv4.netfilter.ip_conntrack_max = 131072" >> /etc/sys...
execを適切に利用したマニフェスト<br />file {'/etc/sysctl.conf':<br />ensure  => present,<br />source  => "puppet://$server/sysctl.conf",...
Facterの活用<br />FacterというライブラリをPuppetは利用している<br />システムに関する情報(プロセッサアーキテクチャ,利用OSとそのバージョン,ドメイン名,FQDN,IPアドレスなど)を収集するための,クロスプラット...
Facter変数<br />$ facter<br />architecture => x86_64<br />domain => hoge.com<br />facterversion => 1.5.7<br />fqdn => puppet...
Facter変数を利用したマニフェスト例<br />$ntp_package= $operatingsystem? { <br />freebsd => 'openntpd',<br />   default => 'ntp',<br />}<...
カスタムFact<br />Facter.add(:serverid) do<br />setcodedo<br />      /d+$/.match(Facter.hostname)<br />end<br />end<br />
カスタムFactを利用したテンプレート<br />/etc/my.cnfのテンプレ<br />[mysqld]<br />server-id=<%= serverid %> <br />
0.25.xの利用推奨<br />いろいろなところで正規表現使えるようになってるので、0.25.xの利用がお勧めです<br />
Puppetの微妙なところ<br />
変数のスコープとオーバーライド<br />この関係がわかりづらく、仕様がいまいち<br />意図通りのオーバーライドができない<br />柔軟なオーバーライドができない<br />
想定通りに動かない例<br />classbase_class {<br />$myvar = 'bob'<br />file {"/tmp/testvar":<br />         content => "$myvar",<br /> ...
想定通りにするには<br />$myvar= ‘bob‘<br />classbase_class {<br />    file {"/tmp/testvar":<br />         content => "$myvar",<br /...
想定通りにするには(別パターン)<br />classbase_class {<br />$myvar = 'bob'<br />file {"/tmp/testvar":<br />         content => "$myvar",<...
といった感じで…<br />変数がグローバルになる、記述が冗長になるなど、いずれにしてもいまいち<br />
理想的な例<br />classfile {<br />$var= ‘hoge’<br />file {<br />       ‘/tmp/file’: content => $var<br />}<br />}<br />classfile...
もうひとつの理想的な例<br />継承ではなく委譲<br />classfile {<br />$var= ‘hoge’<br />file { ‘/tmp/file’: content => $var}<br />}<br />classfi...
理想的な例(ノードの場合)<br />ノード定義でもこんな風にできればいいのに<br />node‘www.example.com’ {<br />file.new( var => ‘fuga’ ).apply<br />}<br />
変数オーバーライドとモジュール<br />モジュールも結局はクラスなので、同じ問題が起こる<br />汎用的なモジュールつくるのが難しい一因<br />無理やり実現する方法はあるけど、ちょっと面倒<br />
モジュールでの変数オーバーライド<br />詳しくはPuppetBestPractices? at Cookpadの資料参照<br />node"sample1.example.com"{<br />classapache_config<br ...
External/LDAPNodeと変数オーバーライド<br />前ページのモジュール変数オーバーライド手法は、LDAPNodeやExternalNodeでは使えない<br />External/LDAPNodeではクラスのincludeとパラ...
柔軟性とメンテナンス性のバランス<br />以上のような感じで、マニフェスト言語については柔軟性不足な感がある<br />そもそも、クラスはリソースのコレクションでしかない<br />柔軟性が低いのは、誰が書いても同じになりやすく、メンテしやす...
内部DSL実装<br />マニフェストは外部DSL<br />内部DSL実装も実はある<br />Ruby DSL<br />http://reductivelabs.com/trac/puppet/wiki/RubyDSL<br />あまり使...
ShadowPuppet<br />class ManifestExample< ShadowShadow::Manifest<br />  recipe :sample<br />  recipe :mysql, {<br />:root_p...
変数オーバーライド以外のモジュールに関する問題<br />CPAN的な仕組みがない。PRM(Puppet Recipe Manager)というのがあったけど、現在はウェブサイトは残ってるが、ソースが見当たらない<br />PRMのウェブサイトか...
クラス設計が難しい<br />これも言語の柔軟性が低いゆえ?<br />特に、リソースの重複が悩ましい<br />複数クラスにまたがるリソースの定義が難しい<br />仮想リソースという仕組みはあるが、これはこれで面倒ではある<br />でも、...
ドキュメントが読みづらくなった<br />例えば TypeReference<br />現行ページ http://docs.reductivelabs.com/references/stable/type.html<br />旧ページ http...
現行ページ<br />
旧ページ<br />
リソースタイプに微妙なものが<br />リソースタイプには、file, user, group, package, service, cron といったものがある<br />上の例は、割りとOSに普遍的なものだけど、中にはnagios_comm...
パッケージ利用がほぼ必須<br />Puppetを利用する場合は、RPMなどパッケージ利用がほぼ必須<br />execでmakeは各サーバにコンパイラとかいれないといけないし、時間もかかる<br />Puppetでファイル配布できるけど、大量...
--noopのdiffが読みづらい<br />puppetdに—noopオプションをつけると、ファイルリの内容が変更された場合、実際にファイルは書き変えないけど、diff出力してくれる<br />だけど、ノーマルな形式のdiffで、ユニファイド...
ロールバックできない<br />「トランザクショナルレイヤー」というのがドキュメントを見るとあるんだけど、ロールバックはできない<br />
puppetrunの微妙なところ<br />LDAPNodeつかわないと、--allや--classが使えない<br />
サーバ間の依存関係が記述できない<br />リソース間の依存関係は記述できる<br />このサービスデーモンはこの設定ファイルに依存する、など<br />サーバ間の依存関係は記述できない<br />このサーバは、データベースサーバがセットアップ...
パッケージ削除が微妙<br />パッケージの追加は、依存関係勝手に解決してくれる(これはPuppetではなく、利用しているパッケージプロバイダ依存)<br />パッケージ削除は解決してくれない<br />RedHat系の場合、追加はyumコマン...
とはいうものの<br />色々微妙な点を挙げてみたけど、Puppet以上にシンプルで使いやすいものはなさそう<br />というわけで、当分はPuppet使い続けることになりそう<br />だけどChefの今後の動きにも要注目<br />内部DS...
結論<br />微妙なところもあるけど、現存するこの手のツールの中ではベストだと思う<br />なのでみんなPuppet使ってみよう<br />
ご清聴ありがとうございました<br />
Upcoming SlideShare
Loading in...5
×

Puppetのススメ

20,004

Published on

Published in: Technology
1 Comment
33 Likes
Statistics
Notes
No Downloads
Views
Total Views
20,004
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
197
Comments
1
Likes
33
Embeds 0
No embeds

No notes for slide

Transcript of "Puppetのススメ"

  1. 1. Puppetのススメ<br />hbstudy#8<br />(株)paperboy&co. 宮下 剛輔<br />2010/02/23<br />
  2. 2. 自己紹介<br />宮下 剛輔<br />mizzy, id:MIZZY<br />gosukenator(twitter, gmail)<br />http://mizzy.org/<br />ペパボで技術責任者というのをやってます<br />インフラからウェブ開発まで広く見てます<br />子だくさん<br />2009/11/24に4人目が生まれました<br />
  3. 3. 自己紹介<br />最近はまってること<br />WiiFitPlusで筋トレ<br />ホームベーカリーでパンを焼く<br />アサシンクリード2 シーケンス13プレイ中<br />ホットドクターペッパー牛乳<br />
  4. 4. Puppetのススメ<br />
  5. 5. アジェンダ<br />Puppetの概要<br />Puppetの動作概要<br />マニフェストの基礎<br />Puppetを動かしてみる<br />Puppetの使いどころ<br />Puppetを利用する上で知っておくべきこと<br />Puppetの微妙なところ<br />
  6. 6. Puppetの概要<br />
  7. 7. Puppet情報リソース<br />http://reductivelabs.com/products/puppet/<br />http://gihyo.jp/admin/serial/01/puppet<br />http://trac.mizzy.org/puppet<br />Software Design 2007年12月号<br />Software Design 総集編 【2000~2009】<br />
  8. 8. Puppetとは?<br />Ruby製のシステム管理ツール<br />でも、使う上ではRubyかどうかはあまり関係ない<br />Facter(後述)の拡張時にはRubyの知識必要<br />
  9. 9. システム管理ツール?<br />Puppetはサーバの状態を定義し、維持するためのツール<br />以下はPuppetの対象外<br />ハードウェアの設置<br />ネットワーク接続<br />OSインストール/初期設定<br />ネットワークの設定<br />Puppet自身のインストール<br />
  10. 10. Puppetの対象範囲<br />OSインストール/ネットワーク設定/Puppetインストール後のフェーズがPuppetの対象範囲<br />パッケージインストール/設定<br />ユーザ追加<br />cron設定<br />パッケージアップデート<br />などなど<br />
  11. 11. なぜPuppetが必要か?<br />手動作業に伴う問題<br />手作業は時間がかかる<br />手を動かしてる時間はもちろん<br />待ち時間も大幅に効率下げる要因<br />並行して別作業するのも大変<br />あるべき状態との乖離<br />正しい手順書があっても、作業漏れ、ミスなどが出る<br />手順書自体が間違ってたり、古かったりすることもある<br />
  12. 12. なぜPuppetが必要か?<br />他の自動化手法に伴う問題<br />カスタムスクリプトでの自動化<br />解読、メンテが大変<br />自由度が高すぎて、書く人のスキルの差によるばらつきが大きい<br />HDDイメージ複製、PXEブート+NFS、rsyncといった手法<br />複数OS、複数の役割を持つサーバが混在した環境では、一括管理が難しい<br />サーバによって異なる部分をどう吸収するか?<br />Apache の ServerName、MySQLの server-id など<br />
  13. 13. Puppet導入のメリット<br />システム構築/アップデートの自動化<br />システムの状態を目に見える形で記録できる<br />マニフェストと呼ばれる独自言語による記述<br />システムのあるべき状態と実際の状態の乖離を防ぐ<br />マニフェストで状態を定義し、システムへ適用する<br />マニフェストの独自言語は、スクリプト言語より自由度が低いが、その分属人的なスキルに依存しにくい<br />OS、役割、設定の異なるサーバ群の集中管理ができる<br />マニフェストはテキストファイルなので、バージョン管理ツールによるトラッキングが可能<br />
  14. 14.
  15. 15.
  16. 16. Puppetの動作概要<br />
  17. 17. Puppetのネットワーク構成<br />puppetサーバ<br />(puppetmasterd)<br />実行結果レポート<br />マニフェストの取得と実行<br />puppetクライアント<br />(puppetd)<br />puppetクライアント<br />(puppetd)<br />puppetクライアント<br />(puppetd)<br />プロトコルは XMLRPC over HTTPS<br />
  18. 18. Puppet用語<br />マニフェスト<br />システムのあるべき状態が記述されたファイル<br />Puppetサーバで一括して維持管理する<br />Puppetクライアントで取得し、システムに適用<br />リソース<br />Puppetマニフェスト内で扱うオブジェクト<br />ユーザ、ファイル、パッケージなど<br />
  19. 19. Puppetの動作概要パターン1<br />puppetサーバ<br />(puppetmasterd)<br />③ 適用結果をレポート<br />① マニフェストを取りに行く(デフォルトは30分に1回)<br />puppetクライアント<br />(puppetd)<br />② 取得したマニフェストを適用する<br />
  20. 20. Puppetの動作概要パターン2<br />puppetサーバ<br />(puppetmasterd)<br />④ 適用結果をレポート<br />② マニフェストを取りに行く<br />① サーバ上でpuppetrunを実行してpuppetdをキックする<br />puppetクライアント<br />(puppetd)<br />③ 取得したマニフェストを適用<br />
  21. 21. マニフェストの基礎<br />
  22. 22. リソースの定義<br />リソースタイプ<br />リソースのタイトル<br />リソースの属性<br />file { '/etc/hosts':<br /> owner => $default_owner,<br /> group => $default_group,<br /> mode => 644,<br /> source => 'puppet://server/module/hosts',<br />}<br />/etc/hosts を puppetサーバから取得し、オーナー、グループ、モードを適切に設定するためのリソース定義<br />これ全体が「リソース」<br />
  23. 23. クラスでリソースをまとめる<br />「sudo」クラスを定義<br />class sudo{<br />package { ‘sudo’:<br /> ensure => latest,<br /> alias => sudo<br /> }<br /> file { ‘/etc/sudoers’:<br /> source => 'puppet://server/module/sudoers',<br /> mode => 440,<br /> owner => $default_owner,<br /> group => $default_group,<br /> alias => sudoers<br /> }<br />}<br />node ‘mail.hoge.com’ { include sudo }<br />package リソース<br />file リソース<br />クラスをノードに適用<br />
  24. 24. クラスを継承する<br />base クラスを定義<br />class base { <br /> file { "/my/file":<br /> content => template("base.erb")<br /> }<br />}<br />class sub inherits base { # override the content <br /> File["/my/file"] {<br />content => template("other.erb")<br /> }<br />} <br />base クラスを継承した sub クラスを定義<br />base クラスの /my/file リソースの属性を上書き<br />
  25. 25. リソースの依存関係<br />file { '/etc/ssh':<br /> source => puppet://server/module/ssh,<br />recurse => true,<br />notify => Service[ssh]<br />}<br />service { 'ssh':<br /> name => sshd,<br /> ensure => running,<br />subscribe => File[‘/etc/ssh’]<br />}<br />/etc/ssh以下のファイルに変更があれば、sshサービスリソースに再起動を促す<br />/etc/sshリソースに変更があれば、サービスを再起動する<br />notifyかsubscribeのどちらか一方だけ定義すればOK<br />
  26. 26. Puppetを動かしてみる<br />
  27. 27. インストール<br />詳細は略。gihyo.jp 見てください。(といっても、古いのでそのまま利用できないかもですが。)<br />ちなみに、CentOSだとEPELリポジトリに割と新しめのパッケージがあります。<br />依存するパッケージもそれほど多くありません。(augeas-libs, facter, ruby, ruby-augeas, ruby-libs, ruby-shadow)<br />
  28. 28. デフォルトの設定ファイルを削除<br />基本的に、設定は最低限必要なところだけすれば良いので、デフォルトの設定ファイル群は消してしまうのが吉<br />自分がタッチしてない余分なファイルがあると、その挙動に悩むこともあるし<br />というわけで、インストールしたらおもむろに rm –rf /etc/puppet/* してしまう<br />
  29. 29. マニフェストを書く<br />簡単なマニフェストを書いてみる<br />まずはディレクトリ作成<br /># mkdir /etc/puppet/manifets<br />
  30. 30. マニフェストを書く<br />/etc/puppet/manifests/site.pp<br />file{ '/etc/passwd':<br /> owner => 'root',<br /> group => 'root',<br /> mode => 644,<br />}<br />
  31. 31. マニフェストを適用(スタンドアロン版)<br /># puppet /etc/puppet/manifests/site.pp<br />notice: //File[/etc/passwd]/mode: mode changed '777' to '644'<br />
  32. 32. マニフェスト適用(クライアント/サーバ版)<br />サーバ起動<br /># /usr/sbin/puppetmasterd --verbose <br /> --no-daemonize --nonodes<br />info: Starting server for Puppet version 0.24.8<br />info: Listening on port 8140<br />notice: Starting Puppet server version 0.24.8<br />
  33. 33. マニフェストを適用(クライアント/サーバ版)<br />クライアントで適用<br /># /usr/sbin/puppetd --server puppet.hoge.com <br />--no-daemonize --verbose --onetime<br />info: No classes to store<br />info: Caching catalog at /var/puppet/state/localconfig.yaml<br />notice: Starting catalog run<br />notice: //File[/etc/passwd]/mode: mode changed '777' to '644'<br />notice: Finished catalog run in 0.03 seconds<br />
  34. 34. 以上<br />簡単ですよね?<br />サーバとクライアントが別の場合は、証明書の署名が手順に入ります<br />/etc/puppet/autosign.confを設定すれば、署名手順は自動化できます<br />実運用では、デーモンとして常駐させたり、puppetrunでクライアントをキックしたりします<br />
  35. 35. Puppetの使いどころ<br />
  36. 36. Puppetの使いどころ<br />大量にサーバがある<br />異なるOSや環境のサーバが混在<br />台数少なくても、同じような手順を何度も実行する可能性がある<br />開発環境、検証環境等の、ベースになる部分<br />自分以外の人も同じ手順を実行するかもしれない<br />システムの状態を何らかの形で記録しておきたい、バージョン管理したい<br />インクリメンタル/テスト駆動サーバ構築<br />
  37. 37. バージョン管理ツールによるトラッキング<br />なぜこんな設定してるんだろう?という瞬間ありませんか?<br />こんな時でも、バージョン管理ツールで誰がどんな意図で設定、あるいは修正したのかが記録されていると安心です<br />デプロイツールと組み合わせて、サーバのアップデートもできます(ペパボではArcherつかってます)<br />ただし、適切なバージョン管理ツールの利用が必要です。特にコメントをしっかり残す、という習慣が大事<br />システム管理者にバージョン管理ツールを根付かせるのは難しい?<br />
  38. 38. インクリメンタル/テスト駆動サーバ構築<br />テスト環境では、Puppetマニフェストを少しづつ書き足し、修正、テストしながら、構築すべき内容を詰めていく<br />Puppet化しておくと、一からつくりなおすのも簡単<br />マニフェストは、テスト環境、本番環境どちらでも使えるように作成。環境の違いはFacter変数などで吸収<br />本番環境では、テスト環境で作り上げたマニフェストを適用するだけ<br />テスト環境できっちりテストしておけば、本番でも大丈夫と自信が持てる<br />
  39. 39. Puppetを利用する上で知っておくべきこと<br />
  40. 40. Puppetのコンセプトに馴染む<br />マニフェストでは、リソースとリソース間の関係を記述する<br />静的な状態を記述する<br />Puppetでどうシステムを管理するか、を考える場合、リソースとリソースの関係にブレイクダウンすること<br />システム上で何を実行するのか、ではなく、どういう状態にするのか、を考える<br />
  41. 41. リソースとその関係へのブレイクダウン<br />例えばApacheの場合、以下のようなリソースへとブレイクダウンし、各リソースとその関係を記述する<br />パッケージ<br />サービス<br />設定ファイル群<br />バーチャルホスト<br />Apacheモジュール<br />
  42. 42. Apacheマニフェスト<br />package { ‘httpd’: ensure => installed }<br />service { ‘httpd’:<br /> enable => true,<br /> ensure => running,<br /> require => Package[‘httpd’],<br />}<br />
  43. 43. Apacheマニフェスト(つづき)<br />file {<br /> ‘/etc/httpd/conf.d/hoge.conf’:<br /> source => “puppet://$server/hoge.conf”,<br /> notify => Service[‘httpd’];<br />‘/etc/httpd/conf.d/fuga.conf’:<br /> source => “puppet://$server/fuga.conf”,<br /> notify => Service[‘httpd’];<br />}<br />
  44. 44. Apacheマニフェスト(つづき)<br />defineapache_module() {<br /> ....<br />}<br />apache_module { ‘rewrite’:<br />config => “puppet://$server/rewrite.conf”,<br />}<br />
  45. 45. Apacheマニフェスト(つづき)<br />definevirtual_host() {<br /> ...<br />}<br />virtual_host { ‘www.example.jp’:<br />docroot => ‘/var/www/html’ ,<br />}<br />
  46. 46. マニフェストは宣言型言語<br />マニフェストは設定ではなく、言語である<br />手続型言語ではなく宣言型言語<br />「何を実行するか」ではなく最終的な「状態」を定義する<br />通常のシステム管理タスクは手続型なので、発想の転換が必要<br />
  47. 47. 手続型と宣言型<br />手続型<br />OpenSSHをインストールする<br />設定ファイルを修正する<br />サービスを起動する<br />宣言型<br />OpenSSHがインストールされた状態にする<br />設定ファイルの内容を決められた通りにする<br />サービスが起動した状態とする<br />
  48. 48. 手続型と宣言型<br />同じことをしているように見えるが、実は異なる<br />手続型はプロセスを記述する<br />同じことを何度も繰り返すと、違った状態になることがあり得る<br />宣言型は最終的な状態を記述する<br />マニフェストを何度適用しても、最終的な状態は同じ<br />
  49. 49. defined type<br />defineは関数/機能を定義しているように見えるけど、実際はリソースタイプを定義しているので注意<br />definevirtual_host() {<br /> ...<br />}<br />virtual_host { ‘www.example.jp’:<br />docroot => ‘/var/www/html’ ,<br />}<br />
  50. 50. クラスと継承<br />マニフェストにはクラスと継承があるけど、オブジェクト指向言語として十分な機能を備えてるわけではない<br />クラスはあくまでもリソースのコレクションにすぎない<br />
  51. 51. 以上はPuppetBest Practices 3.0から<br />http://plathrop.tertiusfamily.net/puppet/best-practice-draft.html<br />
  52. 52. モジュールの活用<br />モジュールは、よく利用するマニフェストを汎用的に利用できるようにまとめたもの<br />よくある処理や、複雑な処理はモジュールとしてまとめるとすっきり<br />でも、本当に汎用的なモジュールを作成するのは難しい…コピペになりがち<br />モジュールをうまく共有する仕組みがないのもイマイチ<br />でも、できるだけ早い段階から活用した方がいい<br />汎用的とか共有とか考慮しなくても、メンテナンス性は向上する<br />
  53. 53. iptablesモジュールの利用例<br />include'iptables'<br />file {<br />'/etc/iptables.d/filter':<br /> content => template('filter'),<br /> notify => Exec["rebuild_iptables"];<br />'/etc/iptables.d/nat':<br /> content => template('nat'),<br /> notify => Exec["rebuild_iptables"];<br />}<br />
  54. 54. iptablesモジュールでやってること<br />iptablesパッケージのインストール<br />必要なファイルの配布<br />全サーバ共通ルールファイル<br />rebuild用スクリプト<br />ルールファイルをがっちゃんこして /etc/sysconfig/iptables に書き込む<br />サーバ個別ルールファイルの配布<br />ルールファイルが変更された場合にrebuildスクリプト実行<br />
  55. 55. モジュール公開してるところ<br />http://reductivelabs.com/trac/puppet/wiki/PuppetModules<br />外部へのリンクもあり<br />http://github.com/n0ts/puppet<br />
  56. 56. エラー通知<br />Puppetにはエラーだけ通知する仕組みがない?<br />tagmailは特定のクラスに関するログの通知先アドレスを指定できるが、エラーのみ通知、ということができない<br />という話をクックパッドテックライフLTで話したけど、実は0.24.6からは、tagでログレベルも指定できるようになってたことに気づいた<br />/etc/puppet/tagmail.conf<br />err: error@example.jp<br />
  57. 57. syslogでエラー通知を分離<br />puppet.conf<br />[puppetd]<br />syslogfacility = local0<br />syslog.conf<br />local0.err <br />/var/log/puppet/error.log<br />
  58. 58. ノード情報の管理<br />シンプルなやりかたは、ノード情報をマニフェストに記述する<br />node‘www.hoge.com’ {<br />include‘base’<br />include‘www’<br />}<br />
  59. 59. ノード情報の管理<br />ExternalNode機能を使えば、既存で持ってるノード情報を使いまわせる<br />具体的には、ノード名を与えると、既存のノード情報を変換してYAML形式で出力するようなスクリプトを用意して、puppetに設定する<br />
  60. 60. External Nodeの設定例<br />/etc/puppet/puppet.confでの設定<br />[puppetmasterd]<br />external_nodes = <br /> /usr/bin/cobbler-ext-nodes<br />node_terminus = exec<br />
  61. 61. cobbler-ext-nodesの実行結果<br />$ cobbler-ext-nodes web-proxy.example.jp<br />classes: [base, web-proxy]<br />parameters: {from_cobbler: 1}<br />
  62. 62. Cobblerでノード情報管理<br />最近はCobblerを利用しているので、こいつのノード情報をマスターとしてます<br />cobbler-ext-nodesコマンドが付属してるので、Puppetと即連携可<br />Cobblerはdnsmasqと連携できるので、DNS/DHCPのノード情報としても利用できる<br />
  63. 63. LDAPによるノード情報管理<br />puppetrun –all とか –class オプションの利用には、LDAPでノード情報を管理する必要がある<br />でも、あまりお勧めしない。めんどうだけどあまりメリットない。<br />puppetrun –all や –class 相当のことがしたければ、スクリプト組むのがよい<br />
  64. 64. execは最小限に<br />Puppetマニフェストは基本的に、最終的な「状態」を定義するもの<br />なので、何度適用しても、最終的な状態は同じになる<br />ただしexecリソースは例外で、何を実行するかを定義する<br />副作用のあるコマンドを実行すると、何度実行しても同じ結果になるという保証がないので危険<br />execを濫用するとマニフェストのメンテもしづらくなる<br />Puppetの考え方に馴染んでない人は、何でもexecで実行してしまおうとするので注意<br />
  65. 65. execを濫用したマニフェスト<br />exec { 'sysctl add':<br />command => 'echo "net.ipv4.netfilter.ip_conntrack_max = 131072" >> /etc/sysctl.conf <br /> && /sbin/sysctl -p',<br />onlyif => "test -f /etc/sysctl.conf",<br />unless => "grep 'net.ipv4.netfilter.ip_conntrack_max' /etc/sysctl.conf 2>/dev/null"<br />}<br />
  66. 66. execを適切に利用したマニフェスト<br />file {'/etc/sysctl.conf':<br />ensure => present,<br />source => "puppet://$server/sysctl.conf",<br />}<br />exec { '/sbin/sysctl -p':<br />subscribe => File['/etc/sysctl.conf'],<br />refreshonly=> true,<br />}<br />
  67. 67. Facterの活用<br />FacterというライブラリをPuppetは利用している<br />システムに関する情報(プロセッサアーキテクチャ,利用OSとそのバージョン,ドメイン名,FQDN,IPアドレスなど)を収集するための,クロスプラットフォームなRubyライブラリ<br />FacterによってFacter変数が定義される<br />
  68. 68. Facter変数<br />$ facter<br />architecture => x86_64<br />domain => hoge.com<br />facterversion => 1.5.7<br />fqdn => puppet.hoge.com<br />hardwareisa => x86_64<br />hardwaremodel => x86_64<br />hostname => h026<br />id => miya<br />interfaces => eth0,eth1,sit0<br />ipaddress => 192.168.10.26<br />ipaddress_eth0 => 192.168.10.26<br />ipaddress_eth1 => 192.168.122.106<br />is_virtual => false<br />...<br />
  69. 69. Facter変数を利用したマニフェスト例<br />$ntp_package= $operatingsystem? { <br />freebsd => 'openntpd',<br /> default => 'ntp',<br />}<br />package { $ntp_package: ensure => present } <br />
  70. 70. カスタムFact<br />Facter.add(:serverid) do<br />setcodedo<br /> /d+$/.match(Facter.hostname)<br />end<br />end<br />
  71. 71. カスタムFactを利用したテンプレート<br />/etc/my.cnfのテンプレ<br />[mysqld]<br />server-id=<%= serverid %> <br />
  72. 72. 0.25.xの利用推奨<br />いろいろなところで正規表現使えるようになってるので、0.25.xの利用がお勧めです<br />
  73. 73. Puppetの微妙なところ<br />
  74. 74. 変数のスコープとオーバーライド<br />この関係がわかりづらく、仕様がいまいち<br />意図通りのオーバーライドができない<br />柔軟なオーバーライドができない<br />
  75. 75. 想定通りに動かない例<br />classbase_class {<br />$myvar = 'bob'<br />file {"/tmp/testvar":<br /> content => "$myvar",<br /> }<br />}<br />classchild_classinheritsbase_class {<br />$myvar= 'fred'<br />}<br />
  76. 76. 想定通りにするには<br />$myvar= ‘bob‘<br />classbase_class {<br /> file {"/tmp/testvar":<br /> content => "$myvar",<br /> }<br />}<br />classchild_class {<br />$myvar= 'fred‘<br />includebase_class<br />}<br />ただし、$myvarがグローバルになる<br />
  77. 77. 想定通りにするには(別パターン)<br />classbase_class {<br />$myvar = 'bob'<br />file {"/tmp/testvar":<br /> content => "$myvar",<br /> }<br />}<br />classchild_classinheritsbase_class {<br />$myvar= 'fred‘<br />File[‘/tmp/testvar’]{<br /> content => "$myvar“<br /> }<br />}<br />ただし、記述が冗長<br />
  78. 78. といった感じで…<br />変数がグローバルになる、記述が冗長になるなど、いずれにしてもいまいち<br />
  79. 79. 理想的な例<br />classfile {<br />$var= ‘hoge’<br />file {<br /> ‘/tmp/file’: content => $var<br />}<br />}<br />classfile_fugainherits file {<br />$var= ‘fuga’<br />}<br />
  80. 80. もうひとつの理想的な例<br />継承ではなく委譲<br />classfile {<br />$var= ‘hoge’<br />file { ‘/tmp/file’: content => $var}<br />}<br />classfile_fuga {<br />file.new( var => ‘fuga’ ).apply<br />}<br />
  81. 81. 理想的な例(ノードの場合)<br />ノード定義でもこんな風にできればいいのに<br />node‘www.example.com’ {<br />file.new( var => ‘fuga’ ).apply<br />}<br />
  82. 82. 変数オーバーライドとモジュール<br />モジュールも結局はクラスなので、同じ問題が起こる<br />汎用的なモジュールつくるのが難しい一因<br />無理やり実現する方法はあるけど、ちょっと面倒<br />
  83. 83. モジュールでの変数オーバーライド<br />詳しくはPuppetBestPractices? at Cookpadの資料参照<br />node"sample1.example.com"{<br />classapache_config<br />inheritsapache_defaults {<br />$ssl = false<br /> }<br />includeapache<br />}<br />
  84. 84. External/LDAPNodeと変数オーバーライド<br />前ページのモジュール変数オーバーライド手法は、LDAPNodeやExternalNodeでは使えない<br />External/LDAPNodeではクラスのincludeとパラメータ設定ぐらいしかできない<br />
  85. 85. 柔軟性とメンテナンス性のバランス<br />以上のような感じで、マニフェスト言語については柔軟性不足な感がある<br />そもそも、クラスはリソースのコレクションでしかない<br />柔軟性が低いのは、誰が書いても同じになりやすく、メンテしやすい、というメリットはある<br />バランスが難しい<br />
  86. 86. 内部DSL実装<br />マニフェストは外部DSL<br />内部DSL実装も実はある<br />Ruby DSL<br />http://reductivelabs.com/trac/puppet/wiki/RubyDSL<br />あまり使われてないって書いてある<br />ShadowPuppet<br />http://reductivelabs.com/trac/puppet/wiki/ShadowPuppet<br />
  87. 87. ShadowPuppet<br />class ManifestExample< ShadowShadow::Manifest<br /> recipe :sample<br /> recipe :mysql, {<br />:root_password=> 'OMGSEKRET'<br />}<br />defsample<br /> exec :foo, :command => '/bin/echo "foo" > /tmp/foo.txt'<br /> package :foo, :ensure => :installed<br /> file '/tmp/example.txt', :ensure => :present, :contents => Facter.to_hash_inspect<br />end<br />def mysql(options)<br /> ...<br />end<br />end<br />
  88. 88. 変数オーバーライド以外のモジュールに関する問題<br />CPAN的な仕組みがない。PRM(Puppet Recipe Manager)というのがあったけど、現在はウェブサイトは残ってるが、ソースが見当たらない<br />PRMのウェブサイトから辿れなかったけど、 http://people.redhat.com/~alikins/prm/にはあった<br />1年ほど更新されてない<br />
  89. 89. クラス設計が難しい<br />これも言語の柔軟性が低いゆえ?<br />特に、リソースの重複が悩ましい<br />複数クラスにまたがるリソースの定義が難しい<br />仮想リソースという仕組みはあるが、これはこれで面倒ではある<br />でも、柔軟性が増すと別の悩みが出てきそう<br />
  90. 90. ドキュメントが読みづらくなった<br />例えば TypeReference<br />現行ページ http://docs.reductivelabs.com/references/stable/type.html<br />旧ページ http://reductivelabs.com/trac/puppet/wiki/TypeReference.<br />
  91. 91. 現行ページ<br />
  92. 92. 旧ページ<br />
  93. 93. リソースタイプに微妙なものが<br />リソースタイプには、file, user, group, package, service, cron といったものがある<br />上の例は、割りとOSに普遍的なものだけど、中にはnagios_command, nagios_contact, nagios_hostといった、Nagios固有のものがある。(Nagios固有のタイプで14もあり、リファレンスの中でも目立ってる)<br />アプリケーション固有のものは、コアに入れないでモジュールにした方がいいのでは?<br />
  94. 94. パッケージ利用がほぼ必須<br />Puppetを利用する場合は、RPMなどパッケージ利用がほぼ必須<br />execでmakeは各サーバにコンパイラとかいれないといけないし、時間もかかる<br />Puppetでファイル配布できるけど、大量にファイルがあるとかなり遅い<br />rsyncをPuppetで実行するのも、微妙な感じ<br />でもパッケージングめんどくさい<br />とは言っても、パッケージングのメリットもある<br />ソースRPMつかってれば、異なるディストリビューション/アーキテクチャでもパッケージリビルドするだけでOK<br />
  95. 95. --noopのdiffが読みづらい<br />puppetdに—noopオプションをつけると、ファイルリの内容が変更された場合、実際にファイルは書き変えないけど、diff出力してくれる<br />だけど、ノーマルな形式のdiffで、ユニファイド形式じゃないので、読みづらい<br />
  96. 96. ロールバックできない<br />「トランザクショナルレイヤー」というのがドキュメントを見るとあるんだけど、ロールバックはできない<br />
  97. 97. puppetrunの微妙なところ<br />LDAPNodeつかわないと、--allや--classが使えない<br />
  98. 98. サーバ間の依存関係が記述できない<br />リソース間の依存関係は記述できる<br />このサービスデーモンはこの設定ファイルに依存する、など<br />サーバ間の依存関係は記述できない<br />このサーバは、データベースサーバがセットアップされてからマニフェストを適用する、といったことができない<br />
  99. 99. パッケージ削除が微妙<br />パッケージの追加は、依存関係勝手に解決してくれる(これはPuppetではなく、利用しているパッケージプロバイダ依存)<br />パッケージ削除は解決してくれない<br />RedHat系の場合、追加はyumコマンドでやるけど、削除はrpmコマンドでやってるっぽい<br />他のパッケージシステムは不明<br />余計なパッケージを最初から入れないのが吉<br />
  100. 100. とはいうものの<br />色々微妙な点を挙げてみたけど、Puppet以上にシンプルで使いやすいものはなさそう<br />というわけで、当分はPuppet使い続けることになりそう<br />だけどChefの今後の動きにも要注目<br />内部DSLなので言語の自由度は高そう<br />
  101. 101. 結論<br />微妙なところもあるけど、現存するこの手のツールの中ではベストだと思う<br />なのでみんなPuppet使ってみよう<br />
  102. 102. ご清聴ありがとうございました<br />
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×