Memo/Puppet

https://dexlab.net:443/pukiwiki/index.php?Memo/Puppet
 

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の上から下に実行されない。リソースの依存関係を設定しないと、実行時に順序が決定されてしまい、1回目は失敗するが、2回目は成功するなど不安定な挙動になる。これがプログラマにとって理解しにくく、忘れがち
    • DSLの構文がRubyのようでRubyでないため、覚えにくい。Rubyの知識があってもそのまま書けない
    • 歴史があるため、古いバージョン向けの情報と新しいバージョン向けの情報が混在して理解しにくい。
  • 洋書Amazon.co.jp
  • kindle版Amazon.co.jp

octocatalog-diff: 2つのブランチ間の変更を表示


VM/dockerで試す時


ベストプラクティス


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

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

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

undefined method ... for nil:NilClass

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

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

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

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

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

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

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

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

  • puppet v3.xの場合:create_resources 3番目の引数はデフォルト値を指定できる
    class test::main(
      $files = {
        '/var/log/messages' => {
          'mode'  => '0640',
          'group' => 'wheel',
        },
      }
    ){
      $defaults = {
        ensure => file,
        notify => Service['td-agent'],
      }
      create_resources('file', $files) # 標準のfileリソースを使う場合
    #  create_resources('test::set_attr', $files, $defaults) # 独自のdefineを使う場合
    }
    
    define test::set_attr(
      $ensure = file,
      $mode  = '0640',
      $owner = 'root',
      $group = 'wheel'
    ) {
      file { "${title}":
        ensure => $ensure,
        mode   => $mode,
        owner  => $owner,
        group  => $group,
      }
    }
  • puppet v4.xの場合:each

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

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

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

  • 単純な"key: value"形式なら、"key"だけ指定すれば参照できる。
  • hiera中のハッシュや配列を参照する方法が分からない
  • hiera.yaml
    • 拡張子(.yaml)は自動的に補完されるので不要
      :backends:
        - yaml
      :hierarchy:
        - defaults
        - "%{environment}"
      
      :yaml:
        :datadir: ./
  • defaults.yaml
    foo: var
  • 実行
    hiera -d -c hiera.yaml foo
    var
    
    # dev.yaml を指定するには
    hiera -d -c hiera.yaml foo environment=dev

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

  • https://docs.puppetlabs.com/hiera/1/
    • 設定値をyamlファイルに書ける
    • class::var1: のmanifestに対して、自動でhieraの値を使う。defineには使えない
    • puppet v3以降、標準で使える
  • hiera内で任意のkey: valueを定義できる。manifest上に存在しない変数でもOK
    foo: "var123"
  • hiera内でfacter変数を参照
    foo::var: "%{::hostname}"

文字列の置換

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

テンプレート(Templates)

  • $varに文字が入っていれば、「var=$var」としてテンプレート出力
    # manifest側
    $var="hoge"
    
    # template側
    <%= "var="+@var if var != "" %>
  • template側でundefによって分岐したい場合 template]]
    # manifest側
    $logfile=undef
    
    # template側
    <%- unless @logfile.nil? -%>
    logfile <%= @logfile %>
    <%- 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側で以下エラーが発生
    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を再起動してみる
    service puppetmaster restart
  • master, agentでdate,timeがずれている場合。ntpや ntpdate ntp.nict.jp 等で時刻を合わせる。master,agentでTimeZoneが異なっていても問題は無い
  • master側で、certificate revoked になっていると出るので確認
    sudo puppet cert list --all | grep "certificate revoked" | awk '{gsub("\"","",$2);print $2}'
  • master側 node情報の削除
    puppet node clean [hostname]
  • master,agentのcertを消して再登録する方法(これで直ったケースあり)
    • puppet agent側: hostname=agent.example.com
      sudo rm -rf /var/lib/puppet/ssl
      sudo puppet agent --server master.example.com --no-daemonize --verbose --onetime --pluginsync --noop --test
    • puppet master側: hostname=master.example.com
      sudo puppet cert list
      sudo puppet cert sign agent.example.com
      
      # certを削除する場合
      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:
      # error
      facter
      Illegal instruction
      
      # env
      cat /etc/redhat-release
      CentOS release 6.2 (Final)
      
      rpm -qa | grep ruby | sort
      ruby-1.8.7.352-13.el6.x86_64
      ruby-libs-1.8.7.352-13.el6.x86_64
      
      rpm -qa | grep facter
      facter-2.1.0-1.el6.x86_64

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

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

古いpuppet reportsを削除する

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

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

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


fqdn_rand : ランダム

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

puppet v3.xのインストール

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

geppetto:manifest編集用IDE

  • 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を開いて以下のように変更
      -Xmx512m

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


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

  • puppet master(/var/log/messages)に出力したい場合
    notice("message")
  • puppet agent側に出力したい場合
    notify {"message":}
    
    # リソースフルパスも表示
    notify {"message": withpath => true}

MySQL

  • puppetlabs/mysql
    cd /etc/puppet/modules
    puppet module install puppetlabs/mysql
    • 閲覧権限のユーザだけ作成したい場合
      vim /etc/puppet/manifests/example.pp
      ----
         $mysql_root_password='YOUR ROOT PASSWORD'
         file {
           '/root/.my.cnf':
             ensure => file,
             content => "
      [client]
      user=root
      host=localhost
      password='$mysql_root_password'
      ";
          }
      
          database_user {
              'bob@%':
                  password_hash => mysql_password('foo');
              'bob@localhost':
                  password_hash => mysql_password('foo');
          }
      
          database_grant {
              'bob@%':
                  privileges => ['Select_priv'];
              'bob@localhost':
                  privileges => ['Select_priv'];
          }
      ----

メール通知

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

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

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

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

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

  • /.bashrc に追加

    function puppet-validate() {
        local ext=${1##*.}
        case $ext in
        [pP][pP])
            puppet parser validate "$1"
            ;;
        [eE][rR][bB])
            erb -P -x -T '-' "$1" | ruby -c
            ;;
        [yY][aA][mM][lL]|[yY][mM][lL])
            ruby -e "require 'yaml'; YAML.parse(File.open('$1'))"
            # find duplicate key
            egrep -v "^( |-|$|#)" $1 | cut -d' ' -f1 | sort | uniq -d -c
            ;;
        *)
            echo "ERROR: $1 is not supported" 1>&2
            ;;
        esac
    }
  • 実行
    source ~/.bashrc
    puppet-validate example.pp
    puppet-validate example.erb
    puppet-validate example.yaml

エラー

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

エラー「Duplicate definition」

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

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

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

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

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

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

カスタムfacter

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


Rubyスクリプトで拡張する

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

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

export FACTER_my_key1=value1
export FACTER_my_key2=value2
export FACTER_my_key3=value3

facter | grep my
my_key1 => value1
my_key2 => value2
my_key3 => value3

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

  • /etc/facter/facts.d/ 以下にファイルを置く事でfacterから参照できる
  • *.yaml, *.json, *.txt 形式が使える
sudo mkdir -p /etc/facter/facts.d/
sudo vim /etc/facter/facts.d/my.txt
----
my_key1=value1
my_key2=value2
my_key3=value3
----

facter | grep my
my_key1 => value1
my_key2 => value2
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"を付けると再同期されるようだ
      vi /etc/puppet/puppet.conf
      ----
      [main]
      ...
          pluginsync = true
      ----
      service puppetmaster restart
  • $my_x 変数を追加したい場合
    mkdir -p /etc/puppet/modules/{MODULE_NAME}/lib/facter
    vi /etc/puppet/modules/{MODULE_NAME}/lib/facter/my.rb
    ----
    Facter.add("my_var1") { setcode { "my_value1" } }
    Facter.add("my_var2") { setcode { "my_value2" } }
    ----
    
    # puppetmaster側で確認
    FACTERLIB=/etc/puppet/modules/{MODULE_NAME}/lib/facter:$FACTERLIB facter -p my_var1
    my_value1
    
    # agent側で確認
    facter -p my_var1
    my_value1
  • "--pluginsync"オプションを付けてプラグインを同期して実行
    puppet agent --server server.localdomain --no-daemonize --verbose --onetime --pluginsync

AmazonWebService

  • 記事
  • aws関係のモジュールを探す
    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は停止
      service puppetmaster stop
      chkconfig puppetmaster off
    • 必須ソフトのインストール
      sudo yum install httpd httpd-devel ruby-devel rubygems mod_ssl gcc-c++ curl-devel zlib-devel
      sudo gem install rack passenger
    • Passenger-Apacheモジュールのビルドとインストール
      sudo passenger-install-apache2-module
    • Rackの設定
      mkdir -p /usr/share/puppet/rack/puppetmasterd/{public,tmp}
      cp /usr/share/puppet/ext/rack/files/config.ru /usr/share/puppet/rack/puppetmasterd/
      chown puppet. /usr/share/puppet/rack/puppetmasterd/config.ru
    • Apacheの設定
      cat >> /etc/httpd/conf.d/passenger.conf << 'EOS'
      # passenger.conf
      LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.17/ext/apache2/mod_passenger.so
      PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.17
      PassengerRuby /usr/bin/ruby
      EOS
      
      cat >> /etc/httpd/conf.d/puppetmaster.conf << 'EOS'
      # puppetmaster.conf
      # Performance
      #PassengerPoolIdleTime 300  # default: 300
      PassengerUseGlobalQueue on
      PassengerMaxPoolSize 60
      
      Listen 8140
      <VirtualHost *:8140>
      	SSLEngine on
      	SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
      	SSLCertificateFile	    /var/lib/puppet/ssl/certs/puppet-001.example.com.pem
      	SSLCertificateKeyFile   /var/lib/puppet/ssl/private_keys/puppet-001.example.com.pem
      	SSLCertificateChainFile /var/lib/puppet/ssl/certs/ca.pem
      	SSLCACertificateFile    /var/lib/puppet/ssl/certs/ca.pem
      	# CRL checking should be enabled; if you have problems with Apache complaining about the CRL, disable the next line
      	SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
      	SSLVerifyClient optional
      	SSLVerifyDepth  1
      	SSLOptions +StdEnvVars
      
      	# The following client headers allow the same configuration to work with Pound.
      	RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
      	RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
      	RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
      
      	PassengerHighPerformance on # DO NOT USE Global config!!(disable mod_rewrite)
      	RackAutoDetect On
      	RackBaseURI /
      
      	DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/
      	CustomLog /var/log/httpd//puppet_access_log combined
      	ErrorLog /var/log/httpd//puppet_error_log
      
      	<Directory /usr/share/puppet/rack/puppetmasterd/>
      		Options None
      		AllowOverride None
      		Order Allow,Deny
      		Allow from all
      	</Directory>
      </VirtualHost>
      EOS
      
      service httpd restart
    • 動作確認
      sudo passenger-status
      
      sudo passenger-memory-stats
    • /etc/rc.d/init.d/puppetmaster は /etc/sysconfig/puppetmaster のオプションを呼んでいる。同じようにオプションを変更したい場合、ARGVに追加するだけ
      vi /usr/share/puppet/rack/puppetmasterd/config.ru
      ----
      ARGV << "--masterport=8140"
      ----
  • WEBサーバWEBrick(標準)、の代わりにMongrelを使う。SSLを処理できないため、前段にリバースプロキシが必要
    yum -y install rubygems ruby-devel
    gem install mongrel --include-dependencies
    
    vi /etc/rc.d/init.d/puppetmaster
    ----
    PUPPETMASTER_OPTS="--servertype mongrel"
    ----
    
    service puppetmaster restart

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

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

モジュール

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

puppet-iptables

iptablesを設定してくれる


タグ

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

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

puppetrun

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


ファイルサーバ

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

Could not run: Invalid mount files

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

プロバイダ

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

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

masterからagentへ向けての操作

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

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

関数(Function)

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

条件文

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

変数と配列

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

Facter変数

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

リソース

/etc/hosts

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

仮想リソース

  • Language: Virtual Resources Documentation Puppet Labs
    • 通常、同じリソース名を定義すると「Duplicate definition」エラーが発生する
    • 宣言(@リソース名)と実体化(realize(リソース名))に分ける事でエラーを回避できる
    • 分かりにくい
  • /tmp/test.tmp を共通ファイルと仮定。複数回実行してもエラーが出ないようにする場合
    node /^server\d+.localdomain/ {
    	@file{
    		'/tmp/test.tmp':
    			ensure  => file,
    			content => "test file",
    			;
    	}
    
    	define test::realize_test {
    		realize(File["/tmp/test.tmp"])
    	}
    
    	test::realize_test {
    		"test1":;
    	}
    
    	test::realize_test {
    		"test2":;
    	}
    }
  • /tmp/test.tmp を共通ファイルと仮定。パラメータを渡しつつ、複数回実行してもエラーが出ないようにする場合
    node /^server\d+.localdomain/ {
    	define test::mkfile(
    		$body=""
    	){
    		file {
    			"$title":
    				ensure  => file,
    				content => $body,
    				;
    		}
    	}
    
    	@test::mkfile{
    		'/tmp/test.tmp':
    			body => "test file",
    			;
    	}
    
    	define test::realize_test {
    		realize(Test::Mkfile["/tmp/test.tmp"])
    	}
    
    	test::realize_test {
    		"test1":;
    	}
    
    	test::realize_test {
    		"test2":;
    	}
    }

依存関係

  • Chaining Arrows
    • "A -> B" 演算子でA -> Bの順に実行
    • "A ~> B" 演算子でA -> B(refresh)の順に実行

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

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

リソースタイプ

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

リソースコマンド

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

define

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

class

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

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

node

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

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

ヘルパーモード

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

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

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

自動署名

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

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

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

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

基本

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

デフォルト

  • リソースタイプの先頭を大文字にし,リソース名は指定しない
    File {
        owner => 'root',
        group => 'root',
        mode  => 644,
    }
    
    file {
        '/etc/hosts':  ;
        '/etc/passwd': ;
        '/etc/group' : ;
        '/etc/sudoers':
            mode => 440;
    }

yumrepo

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


package

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

exec

  • 削除ファイル復元ツール extundelete をインストールする例
    @package {
    	"gcc":
    		ensure => installed;
    	"gcc-c++":
    		ensure => installed;
    	"make":
    		ensure => installed;
    	"e2fsprogs-devel":
    		ensure => installed;
    }
    
    realize(Package["make"], Package["gcc"], Package["gcc-c++"], Package["e2fsprogs-devel"])
    exec {
    	'install-extundelete':
    	cwd   => "/tmp/",
    	path	 => ["/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"],
    	user	 => "root",
    	timeout  => 600,
    	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",
    	creates  => "/usr/local/bin/extundelete",
    	require  => [Package["make"], Package["gcc"], Package["gcc-c++"], Package["e2fsprogs-devel"]];
    }

file

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

user

  • ユーザ追加
    user { 'testuser':
        name       => 'testuser',
        password   => 'test123',
        managehome => true,
        groups     => 'wheel',
    }

コマンド


puppetサーバコマンド

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

puppetクライアントコマンド

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

puppetインストール

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

puppet-serverインストール

  • CentOS6.xにpuppetlabsのリポジトリを追加して 3.4.2 をインストールする場合
    sudo rpm -ivh https://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm
    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
      vi /etc/sysconfig/iptables
      ----
      # puppet-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8140 -j ACCEPT                        
      ----
      service iptables restart
      
      hostname server.localdomain
      echo "127.0.0.1 server.localdomain" >> /etc/hosts
      
      yum install puppet-server --enablerepo=rpmforge
      
      vi /etc/puppet/puppet.conf
      ----
      [main]
      # [サーバのFQDN or IPAddress]
      certname=server.localdomain
      ----
      
      service puppetmaster restart
      chkconfig puppetmaster on
      
      # 証明書確認。勝手にサーバ用のものが作られているはず
      puppetca list --all
  • ログの確認
    tail -f /var/log/puppet/masterhttp.log
  • ディレクトリ構造

添付ファイル: fileresolver.rb 300件 [詳細] filepuppet-module-td-agent.centos.patch 501件 [詳細] filenodejs-init.pp.centos.patch 357件 [詳細] filepuppet-module-rpmforge.zip 493件 [詳細] filepuppet-example.zip 627件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-12-10 (月) 15:19:53 (5d)