Memo/Puppet

http://dexlab.net/pukiwiki/index.php?Memo%2FPuppet
 

Puppet(パペット)

  • http://projects.puppetlabs.com/projects/puppet
    • オープンソースなシステム自動管理ツール
    • Ruby製
    • DSLで設定ファイルを書く(手続き型言語ではなく、宣言型言語。最終状態を定義する)
    • APLライセンス
    • クライアント/サーバ型
    • puppetd:8140/tcp
    • puppetrun:8139/tcp
    • puppetdが定期的にpuppetmasterdに設定を取りに行く(デフォルトは30分)
  • メリット
    • 1台のmasterで多数(100台以上)のagentを管理できる
    • agentが常駐して定期実行もできるため、定期的に更新する用途に向いている
  • デメリット
    • DSLの上から下に実行されない(puppet v4未満)。リソースの依存関係を設定しないと、実行時に順序が決定されてしまい、1回目は失敗するが、2回目は成功するなど不安定な挙動になる。これがプログラマにとって理解しにくく、忘れがち
    • DSLの構文がRubyのようでRubyでないため、覚えにくい。Rubyの知識があってもそのまま書けない
    • 歴史があるため、古いバージョン向けの情報と新しいバージョン向けの情報が混在して理解しにくい。
    • 1箇所エラーがあると、一見関係が無い部分もエラーになるためエラー箇所を特定しにくい。
  • 洋書Amazon.co.jp
  • kindle版Amazon.co.jp

systemctl daemon-reload相当を行う

puppetの構文上は無い?
結局Execだが以下モジュールも使える。


Visual Studio Code用プラグイン

Geppetが新規インストールしたmacOS sierraから起動しなくなったため、代わりに使えるかもしれない。


puppet-agentの監視

  • puppet-agentがインストールされているホスト上で使えそうなファイル
    1. sudo ls -1 /var/lib/puppet/state/
    2. graphs
    3. last_run_report.yaml
    4. last_run_summary.yaml
    5. resources.txt
    6. state.yaml
  • /var/lib/puppet/state/last_run_summary.yaml
    1. --- 
    2.   events:
    3.     total: 10
    4.     success: 10
    5.     failure: 0
    6.   resources:
    7. ...
    8.   version:
    9. ...
    10.     puppet: "3.8.6"
    11.   time:
    12. ...
    13.   changes:
    14.     total: 10

変数が未定義の場合の時エラーを出す

デフォルトでは変数が未定義でもエラーが出ないため、typo等に気がつきにくい。


tag

  • httpdでSSLファイルが変わったら再起動させる
    1. file {  '/etc/pki/tls/private/example.com.key':
    2.   content => $ssl_key,
    3.   ensure  => file,
    4.   owner   => 'root',
    5.   group   => 'root',
    6.   mode    => '0600',
    7.   tag     => ['restart-httpd'];
    8. }
    9.  
    10. File <| tag == 'restart-httpd' |> ~> Service['httpd']

他classのdefine等を呼ぶ

  • puppet 3.8
  • NG: 他classから「apache::virtual_host{}」を呼ぶとエラー
    1. class apache($conf_d = "/etc/httpd/conf.d", $confs = ['default.conf']) {
    2.   define apache::virtual_host() {
    3.     file { "${apache::conf_d}/${title}":;}
    4.   }
    5.  
    6.   apache::virtual_host{ $confs:; }
    7. }
  • OK: 他classからでもincludeせずに呼べる。
    1. class apache($conf_d = "/etc/httpd/conf.d") {
    2.   apache::virtual_host{ $confs: conf_d => $conf_d; }
    3. }
    4.  
    5. define apache::virtual_host($conf_d = "/etc/httpd/conf.d") {
    6.   file { "${conf_d}/${title}":;}
    7. }

ベストプラクティス


Selectorsを使って インストール/アンインストール処理

三項演算子同じような処理がしたい時

  • Selectors 〜 セレクタ
    • boolを判定する場合、0にならない場合がある?
      1. $enabled = versioncmp($mysql_version, '5.5') == 0 ? {
      2.   true => 1,
      3.   default => 0
      4. }
  • /etc/puppet/modules/example/manifests/init.pp 例:enabledフラグによって、ファイル、ディレクトリの作成と削除を行う
    • ディレクトリ削除時に「force => true」にすると強制的に削除される
    • hieraで「true/false」が文字列として渡されるので「str2bool($enabled)」が必要
    • geppettoだと「default」が無いと警告が出る
      1. class example(
      2.   enabled = false
      3. ){
      4.   file {
      5.     '/opt/example':
      6.       mode    => 755,
      7.       force   => true,
      8.       ensure  => str2bool($enabled) ? { true => directory, default => absent };
      9.  
      10.     '/opt/example/start.sh':
      11.       mode    => 755,
      12.       ensure  => str2bool($enabled) ? { true => file, default => absent },
      13.       require => File['/opt/example'],
      14.       content => template('example/start.erb');
      15.   }
      16. }

undefined method ... for nil:NilClass?

  • 解決: hieraに誤りがある。YAML構文で区切り文字が「---」だが、「--」に間違えると発生。

provider: pipを使えるようにする

  • 環境
    • CentOS 6.x
    • puppet 3.8.6
  • pipをインストール。'pip-python'が存在しないと失敗するので作成。
    1.   package { ['python-setuptools', 'python-pip']: ensure => 'installed' } ->
    2.   file { '/usr/bin/pip-python':
    3.     ensure => 'link',
    4.     target => '/usr/bin/pip',
    5.     require => Package["python-pip"]
    6.   }
  • awscliをインストール
    1.   package { 'awscli':
    2.     provider => 'pip',
    3.     ensure   => 'installed',
    4.   }

プロキシを経由して実行する

  • /etc/puppet/puppet.conf の [main] セクションに以下を追加
    1. cat /etc/puppet/puppet.conf
    2.  
    3. [main]
    4. ...
    5.     http_proxy_host = <proxy-host or IP>
    6.     http_proxy_port = <8080>
  • squidをproxyとして使う場合
    1. sudo cat /etc/squid/squid.conf
    2. ...
    3. acl SSL_ports port 443  # https
    4. acl SSL_ports port 8140 # puppet
    5. acl Safe_ports port 80  # http
    6. acl Safe_ports port 443 # https
    7. acl CONNECT method CONNECT
    8. http_port 8080
  • proxyの設定を間違えている場合「403 Forbidden」が出た
    1. curl -x proxy-host:8080 https://puppetmaster:8140/
    2. curl: (56) Received HTTP code 403 from proxy after CONNECT
    3. ...
  • 正常な場合のレスポンス
    1. curl https://puppetmaster:8140/
    2. curl: (60) Peer certificate cannot be authenticated with known CA certificates
    3. ...

create_resources: 複数回のリソース呼び出し時にハッシュを渡す

ハッシュで複数項目を定義して、複数回のリソース(ファイル等)呼び出し時に利用できる。

hieraからhashを渡す時にも使える。

  • puppet v3.xの場合:create_resources 3番目の引数はデフォルト値を指定できる
    1. class test::main(
    2.   $files = {
    3.     '/var/log/messages' => {
    4.       'mode'  => '0640',
    5.       'group' => 'wheel',
    6.     },
    7.   }
    8. ){
    9.   $defaults = {
    10.     ensure => file,
    11.     notify => Service['td-agent'],
    12.   }
    13.   create_resources('file', $files) # 標準のfileリソースを使う場合
    14. #  create_resources('test::set_attr', $files, $defaults) # 独自のdefineを使う場合
    15. }
    16.  
    17. define test::set_attr(
    18.   $ensure = file,
    19.   $mode  = '0640',
    20.   $owner = 'root',
    21.   $group = 'wheel'
    22. ) {
    23.   file { "${title}":
    24.     ensure => $ensure,
    25.     mode   => $mode,
    26.     owner  => $owner,
    27.     group  => $group,
    28.   }
    29. }
  • puppet v4.xの場合:each

puppet実行時に色(エスケープシーケンス)を付けない

  • puppetの標準出力を取り込む時に、エスケープシーケンスが邪魔な時がある
  • 実行時に "--color=false" オプションを追加する
    1. puppet agent --color=false --no-daemonize --verbose --onetime --pluginsync --noop

hieraをローカルでテストする

  • 単純な"key: value"形式なら、"key"だけ指定すれば参照できる。
  • hiera中のハッシュや配列を参照する時は "class::func::var" のように指定する
  • hiera.yaml
    • 拡張子(.yaml)は自動的に補完されるので不要
    • "%{environment}" を使うとhieraコマンド引数でenvironment=valueとして参照できる。"%{::environment}" だとNG
      1. :backends:  - yaml :hierarchy:  - defaults  - "%{environment}" :yaml:  :datadir: ./
  • defaults.yaml
    1. foo: var
  • 実行
    1. hiera -d -c hiera.yaml foo
    2. var
    3.  
    4. # dev.yaml を指定するには
    5. hiera -d -c hiera.yaml foo environment=dev

hiera:設定値をyamlファイルで管理

  • https://docs.puppetlabs.com/hiera/1/
    • 設定値をyamlファイルに書ける
    • class::var1: のmanifestに対して、自動でhieraの値を使う。defineには使えない
    • puppet v3以降、標準で使える
  • yamlの機能として エイリアスマージ が使える
    • アンカーを先に、エイリアスを後に書かないとエラーが出る。puppet --noopではまったく関係の無いエラーに見える。
  • hiera内で任意のkey: valueを定義できる。manifest上に存在しない変数でもOK
    1. foo: "var123"
  • hiera内でfacter変数を参照
    1. foo::var: "%{::hostname}"

文字列の置換

  • perlを使って、正規表現で置換。シングルクオートとダブルクオートの場合で動作が異なったので注意。
    • defines.inc.php
      1. -define('ZBX_GRAPH_FONT_NAME',          'DejaVuSans'); // font file name
      2. +define('ZBX_GRAPH_FONT_NAME', 'ipagp'); // font file name
    • example.pp
      1. exec { "/usr/bin/perl -pi.bak -e \"s/ZBX_GRAPH_FONT_NAME\',\\s+\'DejaVuSans/ZBX_GRAPH_FONT_NAME\', \'ipagp/\" 'defines.inc.php'"
      2. : onlyif => "/usr/bin/perl -ne \"BEGIN { \\\$ret = 1; } \\\$ret = 0 if /ZBX_GRAPH_FONT_NAME\',\\s+\'DejaVuSans/ ; END { exit \\\$ret; }\" 'defines.inc.php'",
      3. }

テンプレート(Templates)

  • $varに文字が入っていれば、「var=$var」としてテンプレート出力
    1. # manifest側
    2. $var="hoge"
    3.  
    4. # template側
    5. <%= "var="+@var if var != "" %>
  • template側でundefによって分岐したい場合 template]]
    1. # manifest側
    2. $logfile=undef
    3.  
    4. # template側
    5. <%- unless @logfile.nil? -%>
    6. logfile <%= @logfile %>
    7. <%- end -%>

セキュリティアップデート


Error: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server session ticket A:...

  • 環境
    • CentOS 6.x x86_64
    • puppet 3.4.x
  • puppet agent側で以下エラーが発生
    1. Error: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server session ticket A: sslv3 alert certificate revoked
  • puppetmasterを再起動してみる
    1. service puppetmaster restart
  • master, agentでdate,timeがずれている場合。ntpや ntpdate ntp.nict.jp 等で時刻を合わせる。master,agentでTimeZone?が異なっていても問題は無い
  • master側で、certificate revoked になっていると出るので確認
    1. sudo puppet cert list --all | grep "certificate revoked" | awk '{gsub("\"","",$2);print $2}'
  • master側 node情報の削除
    1. puppet node clean [hostname]
  • master,agentのcertを消して再登録する方法(これで直ったケースあり)
    • puppet agent側: hostname=agent.example.com
      1. sudo rm -rf /var/lib/puppet/ssl
      2. sudo puppet agent --server master.example.com --no-daemonize --verbose --onetime --pluginsync --noop --test
    • puppet master側: hostname=master.example.com
      1. sudo puppet cert list
      2. sudo puppet cert sign agent.example.com
      3.  
      4. # certを削除する場合
      5. sudo puppet cert clean agent.example.com

facter: Illegal instruction

puppetでこのエラーが出て調べた所、facterのエラーメッセージだった。
なぜか、t1.microで発生し、m1.smallでは発生しなかった。

  • 問題が出た環境: AWS
    • Instance Type:
      • NG: t1.micro
      • OK: m1.small
    • Kernel ID: aki-40992841
    • OS:
      1. # error
      2. facter
      3. Illegal instruction
      4.  
      5. # env
      6. cat /etc/redhat-release
      7. CentOS release 6.2 (Final)
      8.  
      9. rpm -qa | grep ruby | sort
      10. ruby-1.8.7.352-13.el6.x86_64
      11. ruby-libs-1.8.7.352-13.el6.x86_64
      12.  
      13. rpm -qa | grep facter
      14. facter-2.1.0-1.el6.x86_64

既存ファイルの先頭に追加する

  • 例:/etc/resolv.conf の先頭に「nameserver 127.0.0.1」を追加する
    1. exec { "add_resolv_conf":
    2.   path    => "/usr/local/bin/:/bin:/usr/sbin",
    3.   command => "sed -i -e '1inameserver 127.0.0.1' /etc/resolv.conf",
    4.   unless => "grep -P '^nameserver\s+127.0.0.1' /etc/resolv.conf";
    5. }

古いpuppet reportsを削除する

puppet masterの/var/lib/puppet/reports/に古い*.yamlが貯まって、ディスクが溢れる場合がある。

  • 記事
    • Cleaning Old Reports Puppet Dashboardとうweb uiを提供するアプリに古いreportsを削除する機能があるが、別途インストールが必要
  • 7日以上古い *.yaml ファイルを削除
    1. sudo crontab -e
    2. ----
    3. 5 1 * * * /bin/find /var/lib/puppet/reports/ -type f -name "*.yaml" -mtime +7 -delete 2>&1 | logger -i -t delete-puppet-reports
    4. ----
  • そもそもpuppet agent apply時(--noopでも増える)にreportsを保存しないように変更
    • About reporting — Documentation — Puppet
    • puppet masterの設定変更: puppet 3.8.xで確認済み
      1. sudo vim /etc/puppet/puppet.conf
      2. ----
      3. [main]
      4. ...
      5. reports=none
      6. ----
      7. sudo service puppetmaster restart
    • puppet agentで「Could not send report:」を抑制したい場合は、agent側で同様の対処が必要。

r10k: 環境毎にmanifestとmoduleを分ける


fqdn_rand : ランダム

  • 例: cronの実行分をランダムで決定
    1.   cron { 'test':
    2.     ensure  => present,
    3.     user    => 'user01',
    4.     hour    => '*',
    5.     minute  => fqdn_rand(60),
    6.     command => "/tmp/test.sh > /dev/null 2>&1";
    7.   }

puppet v3.xのインストール

  • CentOS v6.xの場合
    1. wget http://yum.puppetlabs.com/el/6/products/$(uname -i)/puppetlabs-release-6-10.noarch.rpm
    2. rpm -ivh puppetlabs-release-6-10.noarch.rpm
    3.  
    4. # 新規インストール
    5. yum install puppet-server puppet
    6.  
    7. # アップデート
    8. yum update puppet-server puppet
  • CentOS v5.xの場合
    1. wget http://yum.puppetlabs.com/el/5/products/$(uname -i)/puppetlabs-release-5-10.noarch.rpm
  • Mac OS X
    • Installing Puppet: Mac OS X Puppet Labs
      1. curl -O http://downloads.puppetlabs.com/mac/facter-2.1.0.dmg
      2. curl -O http://downloads.puppetlabs.com/mac/hiera-1.3.4.dmg
      3. curl -O http://downloads.puppetlabs.com/mac/puppet-3.6.2.dmg
      4. hdiutil mount facter-2.1.0.dmg
      5. hdiutil mount hiera-1.3.4.dmg
      6. hdiutil mount puppet-3.6.2.dmg
    • Mac ports: 2.7.6と古い
      1. port search puppet
      2. puppet @2.7.6_1(sysutils)

geppetto:manifest編集用IDE

※新規インストールしたmacOS sierraから起動しなくなった

  • macOSで起動しない場合

tips

  • 自動フォーマット: ctrl + shift + F
  • 読みやすいように色等の変更
  1. ウィンドウ > 設定 > Puppet > 構文の色の指定
    • String - Double Quoted の色を String と同じに
    • Resource Title の斜体のチェックを外す

geppettoの日本語化

eclipseベースなので試しに Pleiades をインストールしたら日本語化できた。

  1. http://mergedoc.sourceforge.jp/ から 最新版(現在 1.4.x)をダウンロード
  2. pleiades.zip を展開。readme/readme_pleiades.txt に説明が書いてあるので読む
  3. 以下ディレクトリを \geppetto に上書き
    pleiades\features
    pleiades\plugins
  • geppetto.ini に 以下の行を追加
    -javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
  1. geppetto.exeを実行し、日本語になっているか確認
  • 「システムプロパティ pleiades.logger.class.name=jp.sourceforge.mergedoc.pleiades.log.PopupFileLogger?に設定されたロガークラスがロードできませんでした。」
    • 「geppetto.exe」のプロパティから管理者権限を与えて実行する

設定

  • puppet moduleが別パスにある場合に、検索対象に追加する
    • プロジェクト > 右クリック:プロパティ
    • Puppet Project Properties > Puppet Search Path に追加
    • D:\puppet\module にある場合は、「D/puppet/module/*」とする
  • プロジェクト > 自動的にビルド のチェックを外す
  • ウィンドウ > 設定 > 一般 > エディター > テキスト・エディター
    • 行番号の表示:チェック
    • 空白文字の表示:チェック
  • ウィンドウ > 設定 > 一般 > ワークスペース
    • テキストファイルのエンコード:UTF-8
    • 新規テキスト・ファイルの行区切り文字:Unix
  • ウィンドウ > 設定 > Puppet
    • Puppet target version: 3.2 (任意)
  • メモリ不足(GC overhead limit exceeded)等
    • geppetto.iniを開いて以下のように変更
      1. -Xmx512m

stdlib:sortやjoinといったよく使われる関数を追加


デバッグメッセージの表示

  • puppet master(/var/log/messages)に出力したい場合
    1. notice("message")
  • puppet agent側に出力したい場合
    1. notify {"message":}
    2.  
    3. # リソースフルパスも表示
    4. notify {"message": withpath => true}
  • 以下でテスト実行(--noop)とdiff(--test)が表示されるが、依存部分が失敗しているとdiffが表示されないため注意。一見関係なさそうな依存でもdiffが表示されなくなる。
    1. puppet agent --server server.localdomain --no-daemonize --verbose --onetime --pluginsync --noop --test

MySQL

  • puppetlabs/mysql
    1. cd /etc/puppet/modules
    2. puppet module install puppetlabs/mysql
    • 閲覧権限のユーザだけ作成したい場合
      1. vim /etc/puppet/manifests/example.pp
      2. ----
      3.    $mysql_root_password='YOUR ROOT PASSWORD'
      4.    file {
      5.      '/root/.my.cnf':
      6.        ensure => file,
      7.        content => "
      8. [client]
      9. user=root
      10. host=localhost
      11. password='$mysql_root_password'
      12. ";
      13.     }
      14.  
      15.     database_user {
      16.         'bob@%':
      17.             password_hash => mysql_password('foo');
      18.         'bob@localhost':
      19.             password_hash => mysql_password('foo');
      20.     }
      21.  
      22.     database_grant {
      23.         'bob@%':
      24.             privileges => ['Select_priv'];
      25.         'bob@localhost':
      26.             privileges => ['Select_priv'];
      27.     }
      28. ----

メール通知

  • manifestが更新された時だけ、1日1回メール送信
    • puppet master側
      1. vim /etc/puppet/puppet.conf
      2. ----
      3. [master]
      4.     reports = tagmail,daily,security
      5.     reportfrom = puppetmaster@example.com
      6. ----
      7.  
      8. vim /etc/puppet/tagmail.conf
      9. ----
      10. all: user01@example.com
      11. ----
      12.  
      13. service puppetmaster restart
    • puppet agent側
      1. vim /etc/puppet/puppet.conf
      2. ----
      3. [agent]
      4.     report=true
      5. ----

stage:実行の順序を指定できる


プロセス監視 monitのインストール

サーバに常駐して指定したプロセスを監視し、落ちたら自動的に再起動等を設定できる


ログ管理 td-agent(fluentd)のインストール

fluentdの安定版であるtd-agentをpuppetでインストール

  • puppet-module-tdagent の導入
    • そのままではyumでtd-agentがインストールできないのでパッチ filepuppet-module-td-agent.centos.patch yum, logrotate, /var/tmp/td-agent追加
      1. wget -O puppet-module-tdagent.zip https://github.com/ziguzagu/puppet-module-tdagent/archive/master.zip
      2. unzip puppet-module-tdagent.zip
      3. mv puppet-module-tdagent-master /etc/puppet/modules/td-agent
      4. rm puppet-module-tdagent.zip
      5. cd /etc/puppet/modules/
      6. patch -p0 < puppet-module-td-agent.centos.patch
      7.  
      8. # 対象ホストを許可
      9. vim /etc/puppet/fileserver.conf
      10. ----
      11. [plugins]
      12.  allow *.localdomain
      13. ----
  • manifest
    1. node default {
    2.     include 'td-agent'
    3.     package { [ 'fluent-plugin-datacounter', 'fluent-plugin-growthforecast' ]:
    4.         ensure   => 'installed',
    5.         provider => 'fluentgem',
    6.         require  => Package['td-agent'],
    7.     }
    8. }
  • puppet実行(--pluginsync 必須)
    1. puppet agent --server server.localdomain --no-daemonize --verbose --onetime --pluginsync
  • puppet実行後
    1. less /etc/yum.repos.d/td.repo
    2.  
    3. chkconfig --list td-agent
    4. td-agent        0:off   1:off   2:on    3:on    4:on    5:on    6:off
    5.  
    6. service td-agent status
    7. td-agent (pid  2923) を実行中...
    8.  
    9. tree -a /etc/td-agent/
    10. /etc/td-agent/
    11. ├── conf.d
    12. ├── plugin
    13. ├── prelink.conf.d
    14. │      └── td-agent.conf
    15. ├── td-agent.conf
    16. └── td-agent.conf.tmpl
    17.  
    18. 3 directories, 3 files
  • 導入済みプラグイン等
    1. /usr/lib64/fluent/ruby/bin/gem list | grep fluent
    2. fluent-logger (0.4.3)
    3. fluent-mixin-config-placeholders (0.1.0)
    4. fluent-mixin-plaintextformatter (0.1.0)
    5. fluent-plugin-datacounter (0.4.0)
    6. fluent-plugin-flume (0.1.1)
    7. fluent-plugin-growthforecast (0.1.5)
    8. fluent-plugin-mongo (0.6.11)
    9. fluent-plugin-s3 (0.2.5)
    10. fluent-plugin-scribe (0.10.9)
    11. fluent-plugin-td (0.10.13)
    12. fluent-plugin-webhdfs (0.1.0)
    13. fluentd (0.10.30)
  • td-agent(fluentd)の更新
    1. yum -y update td-agent
    2. yum -y install make gcc libxml2-devel libxslt-devel
    3. /usr/lib64/fluent/ruby/bin/gem update
  • アンインストール
    1. yum erase td-agent td-libyaml
    2. rm -rf /etc/td-agent
    3. rm -rf /usr/lib64/fluent

naveで異なるバージョンのnodejsをインストールするmodule

  • naveを使うpuppet moduleが公開されている。danheberden/puppet-nodejs GitHub。ただし、Ubuntu向けのようでCentOSでも動くようにパッチを作った filenodejs-init.pp.centos.patch
    1. wget -O master.zip https://github.com/danheberden/puppet-nodejs/archive/master.zip
    2. unzip master.zip
    3. sudo mv puppet-nodejs-master /etc/puppet/modules/nodejs
    4. sudo vi /etc/puppet/manifests/example/example.pp
    5.  
    6. # CentOS向けパッチ
    7. patch -p0 < nodejs-init.pp.centos.patch
    8.  
    9. # manifest
    10. ----
    11. node default {
    12.   class { 'nodejs':
    13.     version => '0.8.16';
    14.   }
    15. }
    16. ----
    17.  
    18. # インストール後のバージョンの確認
    19. node -v
    20. v0.8.16
    21. npm -v
    22. 1.1.69
  • アンインストール
    1. wget https://raw.github.com/isaacs/nave/master/nave.sh
    2. bash nave.sh uninstall 0.8.16

yaml中のssl key/crtのチェック


pp/erb/yamlファイルの構文チェック


エラー

  • Could not retrieve catalog from remote server: wrong header line format
    • テンプレートで「<%= %>」になっていない事が多い

エラー「Duplicate definition」

  • 共通部分をクラスに分割して、includeを使う。includeは重複してもエラーにならないため。
    1. include test::test_file
  • definedでリソースの2重定義を避ける例(if ! define() でも良い)
    1. node /^server\d+.localdomain/ {
    2. define test::define_test {
    3. if defined(File['/tmp/test.tmp']) == false {
    4. file {
    5. '/tmp/test.tmp':
    6. ensure  => file,
    7. content => "test file",
    8. ;
    9. }
    10. }
    11. }
    12.  
    13. test::define_test {
    14. "test1":;
    15. }
    16.  
    17. test::define_test {
    18. "test2":;
    19. }
    20. }

エラー「Host is missing hostname and/or domain」

  • /var/log/messages に以下のエラーメッセージが出る場合
    1. puppet-master[3904]: Host is missing hostname and/or domain: example
  • facterでfqdnが取得できないのが原因
    1. facter -p | grep fqdn
  • 対策としてhostnameにfqdnを設定するなどして、facterでfqdnを取得できるようにする
    1. HOST=test.example.com
    2.  
    3. hostname $HOST
    4. HOSTNAME=`hostname`
    5. perl -p -i -e "s#localhost.localdomain localhost4 localhost4.localdomain4#$HOSTNAME#" /etc/hosts
    6. perl -p -i -e "s#localhost.localdomain#$HOSTNAME#" /etc/sysconfig/network

終了ステータスの詳細を得る

0, 2の場合は成功と見なして良い

  • --detailed-exitcodes
    • 0: 正常終了(manifestにエラーがあってもコレ)
    • 2: 変更あり
    • 4: 変更なしで失敗
    • 6: 変更ありで失敗
  1. puppet agent --server server.localdomain --no-daemonize --verbose --onetime --detailed-exitcodes
  2. echo $?

カスタムfacter

facter変数や任意のリソースタイプを追加できる


Rubyスクリプトで拡張する

  • ローカルで試す場合: 例 /etc/resolv.conf から nameserver を取得する
    • fileresolver.rb
      1. mkdir -p ~/lib/ruby/facter/
      2. cp resolver.rb ~/lib/ruby/facter/
      3.  
      4. export RUBYLIB=~/lib/ruby
      5. facter nameservers
      6. 192.168.61.2
  • puppet moduleに入れる場合
    • <MODULE>/lib/facter/resolver.rb に配置する

環境変数 FACTER_varname として定義する場合

  1. export FACTER_my_key1=value1
  2. export FACTER_my_key2=value2
  3. export FACTER_my_key3=value3
  4.  
  5. facter | grep my
  6. my_key1 => value1
  7. my_key2 => value2
  8. my_key3 => value3

/etc/facter/facts.d/ 以下に固定ファイルを置いて定義する場合

  • /etc/facter/facts.d/ 以下にファイルを置く事でfacterから参照できる
  • *.yaml, *.json, *.txt 形式が使える
  1. sudo mkdir -p /etc/facter/facts.d/
  2. sudo vim /etc/facter/facts.d/my.txt
  3. ----
  4. my_key1=value1
  5. my_key2=value2
  6. my_key3=value3
  7. ----
  8.  
  9. facter | grep my
  10. my_key1 => value1
  11. my_key2 => value2
  12. my_key3 => value3

/etc/puppet/modules/MY_MODULE/lib/facter/ 以下にプログラムを配置する場合

  • puppetmaster, agent共に設定
    • puppetを実行するとagent側のpuppet.conf の "pluginsync = true"が消えてしまう。puppetmaster側でmy.rbを変更してもキャッシュされ反映されなくなる。再度"pluginsync = true"を付けるか、puppet実行時に"--pluginsync"を付けると再同期されるようだ
      1. vi /etc/puppet/puppet.conf
      2. ----
      3. [main]
      4. ...
      5.     pluginsync = true
      6. ----
      7. service puppetmaster restart
  • $my_x 変数を追加したい場合
    1. mkdir -p /etc/puppet/modules/{MODULE_NAME}/lib/facter
    2. vi /etc/puppet/modules/{MODULE_NAME}/lib/facter/my.rb
    3. ----
    4. Facter.add("my_var1") { setcode { "my_value1" } }
    5. Facter.add("my_var2") { setcode { "my_value2" } }
    6. ----
    7.  
    8. # puppetmaster側で確認
    9. FACTERLIB=/etc/puppet/modules/{MODULE_NAME}/lib/facter:$FACTERLIB facter -p my_var1
    10. my_value1
    11.  
    12. # agent側で確認
    13. facter -p my_var1
    14. my_value1
  • "--pluginsync"オプションを付けてプラグインを同期して実行
    1. puppet agent --server server.localdomain --no-daemonize --verbose --onetime --pluginsync

AmazonWebService?

  • 記事
  • aws関係のモジュールを探す
    1. puppet-module search aws

Puppet Dashboard


正規表現

  • Puppetはruby製。RubyではPerlとほぼ互換性のある正規表現が使える
  • puppet 0.25以降、正規表現が使える。

軽量化/スケーラビリティ

  • Passenger - Documentation - Puppet Labs Apache + Passenger + Puppetmaster
    • PuppetをPassengerで動かして大規模サイトに対応させる - rh7's blog
    • CentOS6.3 x86_64
    • ruby-1.8.7
    • rubygems-1.3.7
    • 元(WEBrick)のpuppetmasterは停止
      1. service puppetmaster stop
      2. chkconfig puppetmaster off
    • 必須ソフトのインストール
      1. sudo yum install httpd httpd-devel ruby-devel rubygems mod_ssl gcc-c++ curl-devel zlib-devel
      2. sudo gem install rack passenger
    • Passenger-Apacheモジュールのビルドとインストール
      1. sudo passenger-install-apache2-module
    • Rackの設定
      1. mkdir -p /usr/share/puppet/rack/puppetmasterd/{public,tmp}
      2. cp /usr/share/puppet/ext/rack/files/config.ru /usr/share/puppet/rack/puppetmasterd/
      3. chown puppet. /usr/share/puppet/rack/puppetmasterd/config.ru
    • Apacheの設定
      1. cat >> /etc/httpd/conf.d/passenger.conf << 'EOS'
      2. # passenger.conf
      3. LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.17/ext/apache2/mod_passenger.so
      4. PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.17
      5. PassengerRuby /usr/bin/ruby
      6. EOS
      7.  
      8. cat >> /etc/httpd/conf.d/puppetmaster.conf << 'EOS'
      9. # puppetmaster.conf
      10. # Performance
      11. #PassengerPoolIdleTime 300  # default: 300
      12. PassengerUseGlobalQueue on
      13. PassengerMaxPoolSize 60
      14.  
      15. Listen 8140
      16. <VirtualHost *:8140>
      17. SSLEngine on
      18. SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
      19. SSLCertificateFile    /var/lib/puppet/ssl/certs/puppet-001.example.com.pem
      20. SSLCertificateKeyFile   /var/lib/puppet/ssl/private_keys/puppet-001.example.com.pem
      21. SSLCertificateChainFile /var/lib/puppet/ssl/certs/ca.pem
      22. SSLCACertificateFile    /var/lib/puppet/ssl/certs/ca.pem
      23. # CRL checking should be enabled; if you have problems with Apache complaining about the CRL, disable the next line
      24. SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
      25. SSLVerifyClient optional
      26. SSLVerifyDepth  1
      27. SSLOptions +StdEnvVars
      28.  
      29. # The following client headers allow the same configuration to work with Pound.
      30. RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
      31. RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
      32. RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
      33.  
      34. PassengerHighPerformance on # DO NOT USE Global config!!(disable mod_rewrite)
      35. RackAutoDetect On
      36. RackBaseURI /
      37.  
      38. DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
      39. CustomLog /var/log/httpd//puppet_access_log combined
      40. ErrorLog /var/log/httpd//puppet_error_log
      41.  
      42. <Directory /usr/share/puppet/rack/puppetmasterd/>
      43. Options None
      44. AllowOverride None
      45. Order Allow,Deny
      46. Allow from all
      47. </Directory>
      48. </VirtualHost>
      49. EOS
      50.  
      51. service httpd restart
    • 動作確認
      1. sudo passenger-status
      2.  
      3. sudo passenger-memory-stats
    • /etc/rc.d/init.d/puppetmaster は /etc/sysconfig/puppetmaster のオプションを呼んでいる。同じようにオプションを変更したい場合、ARGVに追加するだけ
      1. vi /usr/share/puppet/rack/puppetmasterd/config.ru
      2. ----
      3. ARGV << "--masterport=8140"
      4. ----
  • WEBサーバWEBrick(標準)、の代わりにMongrelを使う。SSLを処理できないため、前段にリバースプロキシが必要
    1. yum -y install rubygems ruby-devel
    2. gem install mongrel --include-dependencies
    3.  
    4. vi /etc/rc.d/init.d/puppetmaster
    5. ----
    6. PUPPETMASTER_OPTS="--servertype mongrel"
    7. ----
    8.  
    9. service puppetmaster restart

puppetlabsで公開されているモジュールのインストール

  • puppet 3.x以上。puppet自体に機能が追加された
    1. puppet module search apache
    2.  
    3. puppet module install puppetlabs/apache
  • puppet 2.7.x以下
    1. # インストール
    2. sudo gem install puppet-module
    3.  
    4. # README確認
    5. puppet-module usage
    6.  
    7. # ヘルプ
    8. puppet-module help
    9.  
    10. # 検索
    11. puppet-module search apache
    12.  
    13. # インストール(カレントディレクトリにインストールされるので注意)
    14. cd /etc/puppet/modules/
    15. puppet-module install puppetlabs/apache

モジュール

マニフェスト,テンプレート,ファイルのセット

puppet-iptables

iptablesを設定してくれる


タグ

特定リソースだけ実行したいなどに使える。

  • 単純リソースの場合。
    1. file { '/etc/hosts':
    2.     owner => 'root',
    3.     group => 'root',
    4.     mode  => 644,
    5.     tag   => 'hosts',
    6. }
    7.  
    8. file { '/etc/sudoers':
    9.     owner => 'root',
    10.     group => 'root',
    11.     mode  => 440,
    12.     tag   => 'sudoers',
    13. }
  • 実行
    1. sudo puppetd --tags hosts,sudoers
  • classや定義済みタイプ内のリソースは,自動でタグが付く。
    1. class ssh {
    2.   # package { 'sshd': ensure => present, tag => 'ssh' } と同じ
    3.   package { 'sshd': ensure => present }
    4.   # service { 'sshd': ensure => running, tag => 'ssh' } と同じ
    5.   service { 'sshd': ensure => running }
    6. }

puppetrun

デフォルトでは30分でagentがpuppetmasterに取りに行くが、任意のタイミングで実行させたい時にpuppetrunが使える


ファイルサーバ

masterからagentへファイルを配布できる

Could not run: Invalid mount files

  • fileserver.confで[files]セクションだけの場合にエラーになる。[files]もコメントアウトするとか、pathのコメントアウトを外す
    1. sudo /usr/sbin/puppetmasterd --no-daemonize  --verbose
    2. notice: Starting Puppet master version 2.6.17
    3. Could not run: Invalid mount files
    4.  
    5. vi /etc/puppet/fileserver.conf
    6. ----
    7. [files]
    8. #  path /var/lib/puppet/files
    9. ----

プロバイダ

OSのコマンドの違いを吸収してくれる中間レイヤー

  • 対象ホストを許可する必要がある
    1. vim /etc/puppet/fileserver.conf
    2. ----
    3. [plugins]
    4.  allow *.localdomain
    5. ----
  • プロバイダの明示的指定。yumを指定
    1. package { 'ntp':
    2.     provider => 'yum',
    3.     ensure   => 'present',
    4. }
    5.  
    6. # packageリソースタイプのデフォルトプロバイダを指定
    7. Package { provider => 'yum' }

masterからagentへ向けての操作

masterからagentへ操作(puppet kick)したい時

  • puppetmaster, puppet共にデーモン停止している状態
  • agent側の設定
    1. vi /etc/puppet/namespaceauth.conf
    2. ----
    3. # puppetdからのマニフェスト取得アクセスのコントロール
    4. [puppetmaster]
    5.     allow *.example.org
    6.     deny  deny.example.org
    7.  
    8. # puppetdからのレポート通知アクセスのコントロール
    9. [puppetreports]
    10.     allow *.example.org
    11.     deny  deny.example.org
    12.  
    13. # puppetdからのファイルサーバ機能へのアクセスコントロール
    14. [fileserver]
    15.     allow *.example.org
    16.     deny  deny.example.org
    17. ----
    • puppetmasterサーバを許可する
      1. vi /etc/puppet/auth.conf
      2. ----
      3. path /run
      4. method save
      5. allow server.localdomain
      6. ----
    • agentを起動
      1. sudo puppet agent --no-daemonize -d -v -l console --no-client --listen
  • master側
    1. sudo puppet kick --host agent01.localdomain --debug

関数(Function)

  • 返り値あり(rval)、なし(statement)がある
  • 関数ならカッコあり、なしでも実行できる
    1. notice('Something weird is going on')
    2. notice 'Something weird is going on'
  • ipアドレスの最後の数字を取得。templates/example.conf.erb
    1. <%= ipaddress.split(".")[3] %>

条件文

  • セレクタ:$operatingsystem が freebsd,defaultの時に$sudoに値を入れる
    1. $sudo = $operatingsystem ? {
    2.     freebsd => 'security/sudo',
    3.     default => 'sudo',
    4. }
  • case:条件によって宣言するリソースを変える
    1. case $operatingsystem {
    2.     openbsd: {}
    3.     default: {
    4.         package { 'sudo':
    5.             ensure => present
    6.         }
    7.     }
    8. }
  • if/else:ブール変数のみで審議判定だけができる
    1. if $boolean {
    2.     file { '/some/file': ensure => present }
    3. } else {
    4.     file { '/some/other/file': ensure => present }
    5. }
  • 0.25以降、正規表現が使える
    1. # =~, !~
    2. if $host =~ /^www(\d+)\./ {
    3.     notice('Welcome web server #$1')
    4. }
  • 0.26以降、inが使える。文字列、配列、ハッシュから探索できる
    1. $eatme = 'eat'
    2. if $eatme in ['ate', 'eat'] {
    3. ...
    4. }

変数と配列

undef
未定義。if(undef)はfalse
  • 変数をブール値として扱うには $is_virtual == 'true', str2bool("$is_virtual") とする。if 'false' {} では常にtrueとして判定される。
  • 配列をCSVに変換。(他には、puppetlabs/stdlibにjoin()がある)
    1. # manifest側
    2. $vars=[ '1', '2', '3' ]
    3.  
    4. # template側
    5. csv='<% @vars.each_with_index do |var, i| -%><%= var %><%= "," if i < (vars.size - 1) %><% end -%>'
  • 変数の定義と参照はできるが、同一スコープ内での再定義はできない
    1. $default_owner = 'root'
    2. $default_group = 'root'
    3. #$default_owner = 'hoge'; # エラー
    4. #$default_owner => 'hoge'; # エラー
    5.  
    6. file { '/etc/hosts':
    7.    #$default_owner = 'hoge'; # エラー
    8.    #$default_owner => 'hoge'; # エラー
    9.     owner => $default_owner,
    10.     group => $default_group,
    11. }
  • define内(サブスコープ)での再定義は可能
    1. $owner = 'root'
    2.  
    3. define testing {
    4.     $owner = 'nobody'
    5. }
  • ファイルは以下にある
    1. /var/lib/puppet/yaml/facts/[NODENAME].yaml
  • nginxのworker_processesを自動調整。templates/nginx.conf.erb
    1. worker_processes <%= processorcount %>;
  • 配列。単純な文字列配列やFile, User等も配列として扱える
    1. $vars=[ '1', '2', '3' ]
    2.  
    3. service { 'ntpd':
    4.     ensure  => running,
    5.     require => [ File['ntpd.conf'], User['ntp'], Package['ntp'] ],
    6. }
    • my-ntp/manifests/init.pp
      1. $ntp_server=[ 'ntp.nict.jp', 'ntp.jst.mfeed.ad.jp', 'ntp.ring.gr.jp' ]
    • my-ntp/templates/ntp.conf.erb
      1. <% ntp_server.each do |val| -%>
      2. server <%= val %>
      3. <% end -%>
  • 連想配列
    • manifest
      1. $sites = {
      2.   'site01' => {
      3.     'title' => 'sample01',
      4.     'url' => 'http://www01.example.com/'.
      5.   },
      6.   'site02' => {
      7.     'title' => 'sample02',
      8.     'url' => 'http://www02.example.com/'.
      9.   }
      10. }
    • template (連想配列なのでソートしないと順序は保証されない)
      1. <% sites.keys.sort.each do |id| -%>
      2.   <%= id %>, <%= sites[id]['title'] %>, <%= sites[id]['url'] %>
      3. <% end -%>

Facter変数

  • Facterライブラリから取得できる変数。「$変数名」でアクセスできる
    1. facter -p
    2.  
    3. architecture => x86_64
    4. augeasversion => 0.10.0
    5. hostname => server
    6. fqdn => server.localdomain
    7. kernel => Linux
    8. ...
  • 実行時に環境変数 "FACTER_{key}=value" で一時的に指定可能
    1. export FACTER_system_role=`cat /etc/system_role`; facter
    2.  
    3. # puppet実行時でも可能
    4. FACTER_system_role=dev puppet agent --noop --test
  • uniqueid: ソースを追った所、hostidコマンドを実行していた。hostidはIPアドレスを16進数に変換した値

リソース

/etc/hosts

  • /etc/hostsに追加
    1. host { 'ntp.example.com':
    2.     ensure => 'present', # uninstall: absent
    3.     ip => '10.100.10.20',
    4.     host_aliases => 'timeserver'
    5. }

仮想リソース

  • Language: Virtual Resources Documentation Puppet Labs
    • 通常、同じリソース名を定義すると「Duplicate definition」エラーが発生する
    • 宣言(@リソース名)と実体化(realize(リソース名))に分ける事でエラーを回避できる
    • 分かりにくい
  • /tmp/test.tmp を共通ファイルと仮定。複数回実行してもエラーが出ないようにする場合
    1. node /^server\d+.localdomain/ {
    2. @file{
    3. '/tmp/test.tmp':
    4. ensure  => file,
    5. content => "test file",
    6. ;
    7. }
    8.  
    9. define test::realize_test {
    10. realize(File["/tmp/test.tmp"])
    11. }
    12.  
    13. test::realize_test {
    14. "test1":;
    15. }
    16.  
    17. test::realize_test {
    18. "test2":;
    19. }
    20. }
  • /tmp/test.tmp を共通ファイルと仮定。パラメータを渡しつつ、複数回実行してもエラーが出ないようにする場合
    1. node /^server\d+.localdomain/ {
    2. define test::mkfile(
    3. $body=""
    4. ){
    5. file {
    6. "$title":
    7. ensure  => file,
    8. content => $body,
    9. ;
    10. }
    11. }
    12.  
    13. @test::mkfile{
    14. '/tmp/test.tmp':
    15. body => "test file",
    16. ;
    17. }
    18.  
    19. define test::realize_test {
    20. realize(Test::Mkfile["/tmp/test.tmp"])
    21. }
    22.  
    23. test::realize_test {
    24. "test1":;
    25. }
    26.  
    27. test::realize_test {
    28. "test2":;
    29. }
    30. }

依存関係

  • ドキュメント
  • Chaining Arrows "->" 演算子で依存関係の順序を指定できる

マニフェストでリソースの依存関係を定義できる

  • before:Bリソースより前にAリソース適用など
  • require:beforeと逆。Aリソースの後にBリソース適用など
  • notify:リソースに変更があった場合に通知して、別リソースを適用
  • subscribe:notifyとは逆。
  • php-mysqlを先に削除してから、php-mysqlndをインストール
    1.   package {
    2.     'php-mysql':
    3.       ensure => 'absent',
    4.       provider => 'rpm',
    5.       before => Package['php-mysqlnd'],
    6.       uninstall_options => ['--nodeps'];
    7.  
    8.     'php-mysqlnd':
    9.       ensure => 'installed';
    10.   }

リソースタイプ

  • svnリポジトリの作成するリソースタイプの定義
    1. define svn_repo($path) {
    2.     exec { "/usr/bin/svnadmin create $path/$title":
    3.         creates => "$path/$title",
    4.     }
    5. }
    • 使う場合のマニフェスト。/var/svn/pupptが存在しなければ「svnadmin create /var/svn/puppt」を実行
      1. svn_repo { puppet: path => '/var/svn' }
  • execタイプ
    • コマンドを実行するタイプだが、puppetは状態を適用する考えのため、どうしてもという場合のみ使う。複数回の実行でエラーにならないように、冪等性を考慮する。
    • creates: ファイルやディレクトリが存在する場合、実行しない。
    • onlyif: 指定コマンドの終了コードが0の場合、実行する。
    • unless:指定コマンドの終了コードが0以外の場合、実行する。

リソースコマンド

  • =>:上書き
  • +>:リソースに対して追加。apacheは「httpd」が必要、apache-sslでは「apache.pem」も必要だと明示している
    1. class apache {
    2.     service { 'apache': require => Package['httpd'] }
    3. }
    4.  
    5. class apache-ssl inherits apache {
    6.     # host certificate is required for SSL to function
    7.     Service[apache] { require +> File['apache.pem'] }
    8. }

define

  • define
    • classとの違いは、1ホストで複数インスタンスを複数定義できる
    • example:backup { "hoge": } の"hoge"は $titleとしてmodule側で参照できる
    • $titleに配列も渡せる。 example:backup { ["var1", "var2", "var3"]: }
  • /etc/puppet/modules/example/manifests/init.pp
    1. class example
    2. (
    3. )
    4. {
    5. # backup
    6. define backup ( $user, $group, $path, $cron_hour=1, $cron_minute=5, $cron_ensure="absent" ) {
    7. # virtual resource
    8. @file {
    9. "${path}":
    10. ensure  => directory,
    11. ;
    12. }
    13. realize(File["${path}"])
    14. file {
    15. "${path}/backup.sh":
    16. owner => $user,
    17. group => $group,
    18. mode  => 755,
    19. source => "puppet:///modules/example/backup.sh";
    20. }
    21.  
    22. cron {
    23. "cron-backup.sh":
    24. require => File["${path}/backup.sh"],
    25. ensure  => $cron_ensure,
    26. command => "/bin/nice ${path}/backup.sh > ${path}/backup.log 2>&1",
    27. user    => $user,
    28. hour    => $cron_hour,
    29. minute  => $cron_minute,
    30. ;
    31. }
    32. }
    33. }
  • /etc/puppet/manifests/web01.example.com.pp
    1. node 'web01.example.com' {
    2. include 'example'
    3. example:backup {
    4. 'default':
    5. user => 'root',
    6. group => 'root',
    7. path => "/root/bin",
    8. cron_hour => 1,
    9. cron_minute => 5,
    10. cron_ensure => "present", # present, absent
    11. ;
    12. }
    13. }
  • 引数に未定義の変数名を指定するとエラーにならず、テンプレートではundefになる(puppet 2.6.x)
    1. define test_a($a="aaa", $b=$a) {
    2.   notice($a) # aaa
    3.   notice($b) # undef
    4. }
    5.  
    6. test_a {"hoge":;}
  • 関数から関数を呼ぶ時
    1. define print {
    2.   notice("The value is: '${name}'")
    3. }
    4.  
    5. define func_a {
    6.   print { $name:; }
    7. }
    8.  
    9. func_a {["a","b"]:;}

class

複数のリソースを一つにまとめ、名前を付けられる。
defineとの違いは、インスタンスの数。一つの場合はclass、複数の場合はdefine

  • unix.pp
    1. class unix {
    2.     file { '/etc/passwd':
    3.         owner => 'root',
    4.         group => 'root',
    5.         mode  => 644;
    6.     }
    7.  
    8.     file { '/etc/shadow':
    9.         owner => 'root',
    10.         group => 'root',
    11.         mode  => 440;
    12.     }
    13.  
    14.     exec { 'blah':
    15.         path => '/usr/bin',
    16.         cwd  => '/tmp',
    17.     }
    18. }
  • どのクライアントに適用させるかnodeを書く
    1. node 'client.example.com' {
    2.     include 'unix'
    3. }
  • クラスも継承可能。以下の例ではgroupを上書き
    1. class freebsd inherits unix {
    2.     File['/etc/passwd'] { group => 'wheel' }
    3.     File['/etc/shadow'] { group => 'wheel' }
    4. }

node

どのクライアントに適用させるかを記述する

  • ノード名に英数字とハイフン'-'以外が含まれる場合にはクオート('〜')する必要がある
  • 0.22.4では継承元(inherits 'base')をクオート('〜')するとSyntax errorが出るバグがある
  • 1ファイル:単一ノード
    1. node 'client.example.com' {
    2.     file {
    3.         '/etc/passwd':
    4.             owner => 'root',
    5.             group => 'root',
    6.             mode  => 644;
    7.     }
    8. }
  • 1ファイル:複数ノード。マッチしない場合には、defaultノードが適用
    1. node 'mail.example.com' {
    2.     file {
    3. ...省略
    4.     }
    5. }
    6.  
    7. node 'www.example.com' {
    8.     file {
    9. ...省略
    10.     }
    11. }
    12.  
    13. node default {
    14.     file {
    15. ...省略
    16.     }
    17. }
  • nodeの継承して、複数クライアントに設定
    1. node base {
    2.     file {
    3. ...省略
    4.     }
    5. }
    6.  
    7. node 'client1.example.com' inherits base {
    8.  
    9. }
    10.  
    11. node 'client2.example.com' inherits base {
    12.  
    13. }
  • 正規表現でも可能(0.25〜)
    1. # www01.example.com, www02.example.com 等にマッチ
    2. node /^www(\d+)\./ {
    3. ...
    4. }

ヘルパーモード

  • メリット
    • ソースコードの構文ハイライト
    • vim, emacs用が用意されている

エラー「Host is missing hostname and/or domain」

  • /var/log/messages に以下のエラーメッセージが出る場合
    1. puppet-master[3904]: Host is missing hostname and/or domain: example
  • facterでfqdnが取得できないのが原因
    1. facter -p | grep fqdn
  • 対策としてhostnameにfqdnを設定するなどして、facterでfqdnを取得できるようにする
    1. HOST=test.example.com
    2.  
    3. hostname $HOST
    4. HOSTNAME=`hostname`
    5. perl -p -i -e i(dos){{
    6. $HOME/.vim/
  • windowsの場合
    1. $HOME/vimfiles/
  • ヘルパーモードの有効化

自動署名

特定ドメインだけ自動承認させる事で、サーバ側で「puppetca sign」する手間が省ける

  • puppet master側
    • 特定のドメインだけ自動署名。先頭に「#」でコメントも有効
      1. cat >> /etc/puppet/autosign.conf << 'EOS'
      2. client.example.org
      3. *.example.com
      4. *.local
      5. *.localdomain
      6. #*.internal
      7. EOS
      8.  
      9. service puppetmaster restart
      10.  
      11.  
      12. # 確認
      13. service puppetmaster genconfig | grep autosign                                  
      14.  
      15.     autosign = /etc/puppet/autosign.conf
      16.  
      17. # 後は autosign.conf への変更は puppetmaster の再起動は不要
    • すべて自動署名
      1. vi /etc/puppet/puppet.conf
      2. ----
      3. [main]
      4. autosign = true
      5. ----
      6. service puppetmaster restart

エラー:クライアントが登録できない

  • デフォルトはhostnameを元に秘密鍵/公開鍵が作成されるため、明示的に指定し、証明書類を全て削除して再起動してやる。他にもサーバに登録できなくなった場合も有効
    1. vi /etc/puppet/puppet.conf
    2. ----
    3. [main]
    4. # [クライアントのFQDN or IPAddress]
    5. certname=agent01.localdomain
    6. ----
    7.  
    8. find /var/lib/puppet/ssl/ -name '*.pem' -delete
    9.  
    10. service puppet restart

マニフェスト(DSL)

  • Puppet_Best_Practice2のサンプル構成
    • filepuppet-example.zip
      +---mbc1=000000 ex
      +  # No route to host - connect(2)
      +  puts anifests
      |   |   nodes.pp
      |   |   site.pp
      |   |   templates.pp
      |   |   
      |   \---example
      |           example.pp
      |           
      \--
      [client]
      user=root
      host=localhost
      password='$mysql_root_password'
      -modules
          +---centos
          |   +---files
          |   +---manifests
          |   |       init.pp
          |   |       
          |   \---templates
          +---httpd-document-root
          |   +---files
          |   |       .htaccess
          |   |       robots.txt
          |   |       
          |   +---manifests
          |   |       init.pp
          |   |       
          |   \---templates
          |           index.html.erb
          |           
          \---puppetclient
              +---files
              +---manifests
              |       init.pp
              |       
              \---templates
                      puppet.conf.erb

基本

  • シングルクオートは変数展開されない。ダブルクオートは変数展開される
    1. # 展開されない
    2. $value = '$one'
    3.  
    4. # 展開される
    5. $value = "$one"
    6. $value = "${one}two"
  • 予約語
    true
    false
    define
    inherits
    class
  • コメント
    • sh風の先頭が「#」以後はコメント
  • 他のマニフェストをインポート
    1. import 'other.pp'
    2. import 'classes/*'
    3. import 'packages/[a-z]*'
  1. サーバ上で以下パスにファイルを追加する。例:site.pp
    1. /etc/puppet/manifests/site.pp
  2. 例:ファイルのパーミッションを変更
    1. file { '/etc/hosts':
    2.     owner => 'root',
    3.     group => 'root',
    4.     mode  => 644,
    5. }
  3. マニフェスト構文チェック
    1. # 2.7.x
    2. puppet parser validate manifests/site.pp
    3.  
    4. # 2.6.x
    5. puppet --parseonly manifests/site.pp
  4. dry-run & diff(実際には適用しない)
    1. # 2.7.x
    2. puppet agent --noop --test
    3.  
    4. # 2.6.x
    5. puppet agent --noop
  5. マニフェスト更新
    1. puppet apply manifests/site.pp
  6. デフォルトでは30分後にクライアントに適用されている

デフォルト

  • リソースタイプの先頭を大文字にし,リソース名は指定しない
    1. File {
    2.     owner => 'root',
    3.     group => 'root',
    4.     mode  => 644,
    5. }
    6.  
    7. file {
    8.     '/etc/hosts':  ;
    9.     '/etc/passwd': ;
    10.     '/etc/group' : ;
    11.     '/etc/sudoers':
    12.         mode => 440;
    13. }

yumrepo

/etc/yum.repos.d/REPONAME.repo を作成するリソース


package

  • ensure:
    • latest: 最新バージョンを指定
    • present: インストール
    • purged: アンインストール。設定ファイルも削除。依存関係にあるパッケージも消してくれる
    • absent: アンインストール。設定ファイルは残る
    • held: スーパーセットのインストール
      1. package {
      2.     "vim-enhanced":
      3.         ensure => present;
      4. }
  • sourceにはローカルファイル、URLが指定できるが、"/bin/rpm -i --oldpackage [URL]"で失敗する場合#8212; Puppet Labs
  1. package {
  2.     がある。手動でwgetならうまくいくケースがある
  3. #geshi(bash){{
  4. package { 'zabbix-jp-release':0
  5. ensure => installed,
  6. provider => rpm,
  7. source => 'http://www.zabbix.jp/binaries/relatedpkgs/rhel6/x86_64/zabbix-jp-release-6-5.noarch.rpm'
  8. }
  • sourceにURLでエラーになるケースはexecでインストール
    1. exec {
    2. 'wget-zabbix-jp-release':
    3. cwd      => "/tmp/",
    4. path     => ["/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"],
    5. user     => "root",
    6. timeout  => 600,
    7. command  => "wget -q 'http://www.zabbix.jp/binaries/relatedpkgs/rhel6/x86_64/zabbix-jp-release-6-5.noarch.rpm' && rpm -i --oldpackage zabbix-jp-release-6-5.noarch.rpm && rm -f zabbix-jp-release-6-5.noarch.rpm",
    8. creates  => "/usr/share/zabbix-jp-release";
    9. }
    10.  
    11. package { 'zabbix-jp-release':
    12. ensure => installed,
    13. require => Exec['wget-zabbix-jp-release'];
    14. }
  • install_options でyumのオプション等を指定できるようだ
    1. package {"epel-release":
    2.   provider=>rpm,
    3.   ensure=>installed,
    4.   install_options => ['--nodeps'],
    5.   source=>"http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm",
    6. }
  • パッケージ間に依存関係があり同時にインストールする必要がある場合。例:openssl
    1. package { "openssl":
    2.   provider => "rpm",
    3.   ensure => ["1.0.1e-30.el6.8", "1.0.1e-30.el6.8"],
    4.   source => ["rpms/openssl-devel-1.0.1e-30.el6.8.x86_64.rpm","rpms/openssl-1.0.1e-30.el6.8.x86_64.rpm"],
    5. }

exec

  • 削除ファイル復元ツール extundelete をインストールする例
    1. @package {
    2. "gcc":
    3. ensure => installed;
    4. "gcc-c++":
    5. ensure => installed;
    6. "make":
    7. ensure => installed;
    8. "e2fsprogs-devel":
    9. ensure => installed;
    10. }
    11.  
    12. realize(Package["make"], Package["gcc"], Package["gcc-c++"], Package["e2fsprogs-devel"])
    13. exec {
    14. 'install-extundelete':
    15. cwd   => "/tmp/",
    16. path => ["/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"],
    17. user => "root",
    18. timeout  => 600,
    19. command  => "wget -O extundelete-0.2.0.tar.bz2 'http://downloads.sourceforge.net/project/extundelete/extundelete/0.2.0/extundelete-0.2.0.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fextundelete%2F&ts=1347001409&use_mirror=jaist' && tar xvfj extundelete-0.2.0.tar.bz2 && cd extundelete-0.2.0 && ./configure && make && make install && cd .. && rm -rf extundelete-0.2.0.tar.bz2 extundelete-0.2.0",
    20. creates  => "/usr/local/bin/extundelete",
    21. require  => [Package["make"], Package["gcc"], Package["gcc-c++"], Package["e2fsprogs-devel"]];
    22. }

file

  • rpmに含まれるファイルを必ず"置換|削除"したい場合、requireを指定する。指定しないと順序が保証されないので、rpm更新時に、 1.削除, 2. rpm update される場合があり不具合が起きる
    1. file { '/etc/httpd/conf.d/welcome.conf':
    2.     ensure  => absent,
    3.     require => Package['httpd'],
    4.     ;
    5. }
  • ダミーファイルを作成
    1. file { '/tmp/dummy':
    2.     ensure  => file,
    3.     mode  => 644,
    4.     content => "dummy file",
    5.     ;
    6. }
  • オーナー、グループ、パーミッションを変更
    1. file { '/etc/hosts':
    2.     owner => 'root',
    3.     group => 'root',
    4.     mode  => 644,
    5.     ;
    6. }
  • ディレクトリを再帰的に作成できないので列挙する(recurse=>trueではダメ) Create a directory tree
    1. file { [ "/tmp/var/", "/tmp/var/foo" ]:
    2. ensure => directory;
    3. }
  • 時刻を日本に変更
    1. file { '/etc/localtime':
    2.     ensure => link,
    3.     target => "/usr/share/zoneinfo/Asia/Tokyo",
    4. }
  • staticファイルを配信
    • module_name/files/example.conf
    • module_name/manifests/init.pp
      1. file { '/tmp/example.conf':
      2. path => "/tmp/example.conf",
      3. ensure => file,
      4. mode => 644,
      5. source => "puppet:///modules/module_name/example.conf";
      6. }
    • sourceに特定の拡張子のファイルを指定すると"Permission denied"で配信されない。しかし、pathで元のファイル名に戻す事はできる。また、数百MBの大きなファイルも無理なのでwget等を使う
      1. # puppet-server-2.6.17-2.el6.noarch
      2. OK: なし
      3. OK: .tar
      4. OK: .conf
      5. OK: .gz
      6. OK: .hoge.gz
      7. OK: .tar.bz2
      8. NG: .tar.gz
  • 内容が変わるdynamicファイルを配信
    • module_name/templates/example.conf.erb
      1. # facter変数
      2. hostname=<%= hostname %>
    • module_name/manifests/init.pp
      1. file { '/tmp/example.conf':
      2. path => "/tmp/example.conf",
      3. ensure => file,
      4. mode => 644,
      5. content => template("module_name/example.conf.erb");
      6. }
  • templateに配列を使う
    • my-ntp/templates/ntp.conf.erb
      1. <% ntp_server.each do |val| -%>
      2. server <%= val %>
      3. <% end -%>
    • my-ntp/manifests/init.pp
      1. class my-ntp
      2. (
      3. $package_version='latest',
      4. $ntp_server=[ 'ntp.nict.jp', 'ntp.jst.mfeed.ad.jp', 'ntp.ring.gr.jp' ]
      5. )
      6. {
      7. package { "ntp": ensure => $package_version }
      8.  
      9. service { "ntpd":
      10. enable => true,
      11. ensure => running,
      12. require => Package["ntp"];
      13. }
      14.  
      15. exec { "/sbin/chkconfig --add ntpd":
      16. cwd => "/etc",
      17. unless => "/bin/ls /etc/rc3.d | grep ntp"
      18. }
      19.  
      20. exec { "/bin/mv localtime localtime.org;/bin/ln -s /usr/share/zoneinfo/Japan /etc/localtime":
      21. cwd => "/etc",
      22. onlyif => "/usr/bin/test ! -h /etc/localtime.org"
      23. }
      24.  
      25. file { "/etc/ntp.conf":
      26. path => "/etc/ntp.conf",
      27. ensure => file,
      28. require => Package[ntp],
      29. content => template('my-ntp/ntp.conf.erb'),
      30.                 notify  => Service["ntpd"];
      31. }
      32. }

user

  • ユーザ追加
    1. user { 'testuser':
    2.     name       => 'testuser',
    3.     password   => 'test123',
    4.     managehome => true,
    5.     groups     => 'wheel',
    6. }

コマンド


puppetサーバコマンド

  • サーバ設定の表示
    1. service puppetmaster genconfig
    2.  
    3. # モジュールパス
    4. service puppetmaster genconfig | grep -i modulepath
    5.  
    6.     modulepath = /etc/puppet/modules:/usr/share/puppet/modules
    7.  
    8.  
    9. # Factパス
    10. service puppetmaster genconfig | grep -i factpath
    11.  
    12.     factpath = /var/lib/puppet/lib/facter:/var/lib/puppet/facts
  • 証明書の作成。hostnameからCNを生成しているため変わったら再作成
    1. puppetca generate hostname
    2.  
    3. # 以下に作成される
    4. /var/lib/puppet/ssl/
  • 認証待ちpuppetクライアント一覧。先頭が「+」なら認証済み
    1. puppetca list
    2.  
    3. # 認証済みも表示
    4. puppetca --all list
  • puppetクライアント認証(autosignやってない時)
    1. puppetca sign hostname
  • 認証済みクライアントの拒否
    1. puppetca revoke hostname
  • 認証リクエストの削除
    1. puppetca clean hostname
    2.  
    3. #全ての認証リクエストの削除
    4. puppetca clean --all
  • 証明書の表示
    1. puppetca print hostname
  • クライアントへ手動適用
    1. puppet kick --host hostname
  • クライアントへtag付きで手動適用
    1. puppet kick --host hostname --tag newsetting
  • マニフェスト構文チェック
    1. # 2.7.x
    2. puppet parser validate manifests/site.pp
    3.  
    4. # 2.6.x
    5. puppet --parseonly manifests/site.pp
  • dry-run & diff(実際には適用しない)
    1. # 2.7.x
    2. puppet agent --noop --test
    3.  
    4. # 2.6.x
    5. puppet agent --noop
  • マニフェストファイル更新
    1. puppet apply manifestでなくs/site.pp

puppetクライアントコマンド

  • よく使うコマンドをaliasとして登録。(引数 $1等を使いたい場合は関数にする)
    1. cat >> ~/.bashrc << 'EOS'
    2. alias puppet-agent='puppet agent --server server.localdomain --no-daemonize --verbose --onetime --pluginsync'
    3. EOS
    4.  
    5. # dry-run
    6. puppet-agent --noop
    7.  
    8. # exec
    9. puppet-agent
  • 1回だけマニフェストを実行して終了する。puppetdだと「--onetime」を付けてもプロセスが終了しない
    1. puppet agent --server=server.localdomain --no-daemonize --verbose --onetime --pluginsync
    2.  
    3. echo $?
    4. # 0: エラーがあっても0が返る
  • クライアント設定の表示
    1. service puppet genconfig
  • テストコマンド
    1. puppet agent --test --debug
  • クライアントの特定サービスの確認
    1. puppet resource service httpd
  • 各サービス状態をマニフェスト形式で出力
    1. puppet resource service
    2.  
    3. service { 'httpd':
    4.   ensure => 'stopped',
    5.   enable => 'false',
    6. }
    7. service { 'iptables':
    8.   ensure => 'running',
    9.   enable => 'true',
    10. }
    11. service { 'ntpd':
    12.   ensure => 'running',
    13.   enable => 'true',
    14. }
  • 各パッケージ状態をマニフェスト形式で出力
    1. puppet resource package
    2.  
    3. package { 'httpd':
    4.   ensure => '2.2.3-65.el5.centos',
    5. }
    6. package { 'iptables':
    7.   ensure => '1.3.5-9.1.el5',
    8. }
    9. package { 'iptables-ipv6':
    10.   ensure => '1.3.5-9.1.el5',
    11. }

puppetインストール

  • CentOS6.xにpuppetlabsのリポジトリを追加して 3.4.2 をインストールする場合
    1. sudo rpm -ivh https://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm
    2. sudo yum install puppet
  • エージェントであるpuppet
    • CentOS5.8 x86_64
    • rpmforgeリポジトリには2.7.9があるのでこれを使う
    • テスト用でDNS設定するのも面倒なので「agent01.localdomain」という名前にしておく
    • サーバIPは便宜上:192.168.1.100
      1. vi /etc/sysconfig/iptables
      2. ----
      3. # puppet-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8140 -j ACCEPT                        
      4. ----
      5. service iptables restart
      6.  
      7. hostname agent01.localdomain
      8. echo "127.0.0.1 agent01.localdomain" >> /etc/hosts
      9. echo "192.168.1.100 server.localdomain" >> /etc/hosts
      10.  
      11. yum install puppet --enablerepo=rpmforge
      12.  
      13. vi /etc/sysconfig/puppet
      14. ----
      15. PUPPET_SERVER=server.localdomain                                                            
      16. ----
      17.  
      18. vi /etc/puppet/puppet.conf
      19. ----
      20. [main]
      21. # [クライアントのFQDN or IPAddress]
      22. certname=agent01.localdomain
      23. ----
      24.  
      25. service puppet restart
      26. chkconfig puppet on
  • puppetサーバ側で認証する(autosign=falseの場合)
    1. puppetca list
    2. agent01.localdomain
    3.  
    4. puppetca sign agent01.localdomain
  • ログの確認
    1. tail -f /var/log/puppet/puppet.log

puppet-serverインストール

  • CentOS6.xにpuppetlabsのリポジトリを追加して 3.4.2 をインストールする場合
    1. sudo rpm -ivh https://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm
    2. sudo yum install puppet-server
  • サーバであるpuppet-server
    • CentOS5.8 x86_64
    • rpmforgeリポジトリには2.7.9があるのでこれを使う。epelリポジトリは2.6.xだった
    • テスト用でDNS設定するのも面倒なので「server.localdomain」という名前にしておく
    • テスト用なので全て認証「autosign = true」
    • サーバIPは便宜上:192.168.1.100
      1. vi /etc/sysconfig/iptables
      2. ----
      3. # puppet-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8140 -j ACCEPT                        
      4. ----
      5. service iptables restart
      6.  
      7. hostname server.localdomain
      8. echo "127.0.0.1 server.localdomain" >> /etc/hosts
      9.  
      10. yum install puppet-server --enablerepo=rpmforge
      11.  
      12. vi /etc/puppet/puppet.conf
      13. ----
      14. [main]
      15. # [サーバのFQDN or IPAddress]
      16. certname=server.localdomain
      17. ----
      18.  
      19. service puppetmaster restart
      20. chkconfig puppetmaster on
      21.  
      22. # 証明書確認。勝手にサーバ用のものが作られているはず
      23. puppetca list --all
  • ログの確認
    1. tail -f /var/log/puppet/masterhttp.log
  • ディレクトリ構造
    /etc/puppet
    ├── auth.conf
    ├── fileserver.conf
    ├── manifests
    │   ├── example
    │   │   └── example.pp
    │   └── site.pp
    ├── modules
    │   ├── httpd-document-root
    │       ├── files
    │       │   └── robots.txt
    │       ├── manifests
    │       │   └── init.pp
    │       └── templates
    │           └── index.html.erb
    └── puppet.conf

添付ファイル: filevalidate-puppet.20180410.zip 3件 [詳細] filevalidate-ssl.20170907.zip 81件 [詳細] fileresolver.rb 275件 [詳細] filepuppet-module-td-agent.centos.patch 483件 [詳細] filenodejs-init.pp.centos.patch 334件 [詳細] filepuppet-module-rpmforge.zip 518件 [詳細] filepuppet-example.zip 656件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-04-13 (金) 13:41:51 (13d)