連載
» 2016年06月24日 05時00分 公開

実際に検証済み!OSS徹底比較(4)サーバ構築自動化【後編】:OSSのサーバ構築自動化ツール、4製品徹底検証 2016年版 (4/8)

[森元敏雄,TIS]

Puppet manifestのTIPS

1.manifestへのパラメータ受け渡し

 3ページの「2.manifestを作成」のセクションでも述べたが、manifest内で使用するパラメータ変数の引き渡しは、manifestのclass呼び出し時の引数で設定される。

$ sudo cat /etc/puppetlabs/code/environments/production/manifests/site.pp
node 'tissvv096' {
  #include wordpress_sample module
  class { 'wordpress_sample':
    mysql_root_pass   => "FM11AD2+",
    wp_db_name        => "WordPress",
    wp_db_user        => "wp_admin",
    wp_db_pass        => "HB-F1XDJ",
    wordpress_latest  => "https://ja.wordpress.org/latest-ja.tar.gz",
    wp_unique_phrase  => "FX702PFX801PPB100FX860PPB700PB500PB750PAI1000",
}

 パラメータのデフォルト値はparams.ppファイルに定義しておく。

$ cd /etc/puppetlabs/code/environments/production/modules/wordpress_sample
$ sudo cat ./manifests/params.pp
# Class: wordpress_sample::params
#
# Actions: WordPress,mariadb,apache and php install manifest paramaters
#
class wordpress_sample::params (
  # default paramaters
  $mysql_root_pass   = 'password',
  $wordpress_latest  = 'https://wordpress.org/latest.tar.gz',
  $wp_os_user        = 'root',
  $wp_os_group       = 'root',
  $wp_db_name        = 'wordpress',
  $wp_db_user        = 'wordpress',
  $wp_db_pass        = 'password',
  $wp_unique_phrase  = 'bMvc7W2eLuhKFewafVyirWJaXDhbSf',
  $wp_unarchive_path = '/var/www',
  $wp_install_path   = '/var/www/wordpress',
) {
}

 manifest実行時に最初に処理されるinit.ppで、まず変数にparams.ppのデフォルト値が設定される。クラス呼び出し時に設定された引数が存在した場合、その値で上書きする。これにより、引数に設定されなかった変数はデフォルト値が使用されることとなる。その設定されたパラメータ値を、実際にインストール・設定を行う各クラスに継承する。

$ sudo cat ./manifests/init.pp
# Class: wordpress_sample
#
# Actions: WordPress,mariadb,apache and php install manifest
#
class wordpress_sample (
  # default paramaters
  $mysql_root_pass   = $wordpress_sample::params::mysql_root_pass,
  $wordpress_latest  = $wordpress_sample::params::wordpress_latest,
  $wp_os_user        = $wordpress_sample::params::wp_os_user,
  $wp_os_group       = $wordpress_sample::params::wp_os_group,
  $wp_db_name        = $wordpress_sample::params::wp_db_name,
  $wp_db_user        = $wordpress_sample::params::wp_db_user,
  $wp_db_pass        = $wordpress_sample::params::wp_db_pass,
  $wp_unique_phrase  = $wordpress_sample::params::wp_unique_phrase,
  $wp_unarchive_path = $wordpress_sample::params::wp_unarchive_path,
  $wp_install_path   = $wordpress_sample::params::wp_install_path
) inherits wordpress_sample::params {
  class { 'wordpress_sample::install':
    mysql_root_pass   => $mysql_root_pass,
    wordpress_latest  => $wordpress_latest,
    wp_os_user        => $wp_os_user,
    wp_os_group       => $wp_os_group,
    wp_db_name        => $wp_db_name,
    wp_db_user        => $wp_db_user,
    wp_db_pass        => $wp_db_pass,
    wp_unique_phrase  => $wp_unique_phrase,
    wp_unarchive_path => $wp_unarchive_path,
    wp_install_path   => $wp_install_path
  }
}

2.manifestの記述方法

 Puppetのmanifestの記述方法は、公式サイトのPuppet Documentationに記載されているので、こちらも参照いただきたい。

(1)yumコマンドでのパッケージの制御

 yumコマンドでのパッケージのインストールはpackageリソースを使用する。複数のパッケージをインストールする場合は、パッケージ名を[]内に記載することで再帰的に処理が実行される。パッケージが1個の場合は[]は不要である。

 # install packages
  package { [ "httpd", "php", "php-mysql" ]:
    provider => "yum",
    ensure   => "installed",
  }

(2)serviceの起動制御

 serviceの起動(CentOS 7.2の場合、systemctlコマンド)の実行はserviceリソースで行う。下記の例ではサービスの起動とenableを設定している。

 # start/enable httpd
  -> service { "httpd":
    provider => systemd,
    ensure   => running,
    enable   => true,
  }

(3)node上でのコマンドを実行

 manifest内で任意のコマンドを実行する方法として、execリソースが提供されている。「Exec {}」で、execコマンドで共通に使用できるパラメータを定義できる。実行するコマンドは「command =>」の後ろの”〜”,内に記載する。行末に";"を付与することで複数行に記載することもできる。

   # defaults execute environment
  Exec {
    path      => ['/usr/bin','/usr/sbin','/opt/puppetlabs/bin'],
    cwd       => '/tmp',
    user      => 'root',
    group     => 'root',
    logoutput => on_failure,
  }
  # install wordpress
  exec { 'install wordpress':
    command => "curl ${wordpress_latest} | tar zx -C ${wp_unarchive_path}",
    creates => "${wp_install_path}/wp-config.php",
  }
  # httpd firewall setting
  exec { "firewall-cmd httpd open":
    command => "firewall-cmd --add-service=http --zone=public --permanent;
                firewall-cmd --reload",
    require => Package['httpd'],
    onlyif  => "test `firewall-cmd --zone=public --list-all | grep -c http` == 0",
  }

(4)templateを使用したファイルの作成

 設定ファイルなどを新規に作成する場合、fileリソースのtemplateパラメータを使用する。

 以下のようなtemplateファイルを作成する。上位のmanifestから変数を受け取る場合、<%= @[変数名] %>と記載しておくと、ファイル生成時にその部分が呼び出し元のmanifestの変数の値で置換される。

$ cd /etc/puppetlabs/code/environments/production/modules/wordpress_sample
$ sudo cat ./templates/wordpress.conf.erb
 <VirtualHost *:80>
  ServerName <%= @hostname %>
  DocumentRoot /var/www/wordpress
  <Directory "/var/www/wordpress">
    AllowOverride All
    Options -Indexes
  </Directory>
  <Files wp-config.php>
    order allow,deny
    deny from all
  </Files>
</VirtualHost>

 templateファイルはmanifest内から以下のように呼び出される。contentの記述ルールが、通常はパスではなく、「template( '[moduleフォルダ名]/[moduleフォルダ以下のtemplateフォルダ以下のパス+ファイル名]' )」である点は注意が必要だ。moduleフォルダ外を参照する場合は、フルパスを指定することでも対応できる。

   # create httpd/wordpress.conf
  file { '/etc/httpd/conf.d/wordpress.conf':
    ensure  => file,
    content => template( 'wordpress_sample/wordpress.conf.erb' ),
    require => Package['httpd'],
  }

(5)設定処理の実行要否の判定

 再実行時の設定処理の実行要否の判定のために、onlyifのパラメータが提供されている。使用例は以下の通り。onlyifの条件式は、[]を使用することで複数条件も指定できる。ただ複数条件の場合、条件間はand条件で処理され、全ての条件がtureの場合のみ、処理が実行されることになる。

  # httpd firewall setting
  exec { "firewall-cmd httpd open":
    command => "firewall-cmd --add-service=http --zone=public --permanent;
                firewall-cmd --reload",
    require => Package['httpd'],
    onlyif  => "test `firewall-cmd --zone=public --list-all | grep -c http` == 0",
  }
 # chown wordpress files
 exec { "chown wordpress":
    command => "chown -R ${wp_os_user}:${wp_os_group} ${wp_install_path}",
    user    => "${wp_os_user}",
    group   => "${wp_os_group}",
    onlyif  => [ "test `find ${wp_install_path} -not -user ${wp_os_user} | wc -l` != 0",
                 "test `find ${wp_install_path} -not -group ${wp_os_group} | wc -l` != 0" ],
  }

 onlyifパラメータはexecコマンド以外では使用できない。その他のコマンドでは、設定条件やファイルの日付、サイズ、チェックサムなどの値をpuppetのフォルダ内に保持しており、実行時に処理要否を判定している。そのため、manifest内には実行要否の判定処理を記述する必要があまりなくなっている。

 だが、ファイルをバックアップし、編集を行う処理を行っていると、バックアップ元のファイルが更新されるため、バックアップの処理が再実行される(=編集済みファイルで上書きされる)状態になってしまう。それを回避する手段が以下である。

    # modify httpd config
  file { '/etc/httpd/conf/httpd.conf.bak':
    ensure  => file,
    source  => '/etc/httpd/conf/httpd.conf',
    replace => 'no',
  }

 replace => 'no'を設定することで、初回に生成されたファイルが存在すれば上書きされなくなる。

(6)ファイルの文字列置換

 ファイル内の文字列の置換の機能として、file_lineリソースが提供されている。対象ファイルの行単位の追加、削除、置換に対応している。文字列の部分的な置換に対応していないため、使える場所は若干限定される。ただ前述の通り、ファイル書き換え要否の判定がpuppetで詳細に行われるため、使える場所であれば積極的に使っていきたい。

  file_line { 'modify httpd config':
    path    => '/etc/httpd/conf/httpd.conf',
    line    => "ServerName ${hostname}",
    match   => "^#ServerName.*$"
  }

(7)MySQL設定用のモジュール

 puppetは各プロダクトのmanifestをモジュールとしてダウンロードして使用する機能を提供している。puppetserverをインストールしたサーバで、以下のコマンドを実行すると検索条件に一致したモジュールを参照できる。

$ sudo /opt/puppetlabs/bin/puppet module search mysql
Notice: Searching https://forgeapi.puppetlabs.com ...
NAME		DESCRIPTION				AUTHOR 
puppetlabs-mysql	Installs, configures, and manages the MySQL service.	@puppetlabs

 今回はPuppet Labs公式のモジュールを使用している。公式なサンプルであり、かつMariaDBにも対応していることからこのモジュールを選定した。モジュールを使用することで、非常に簡単にMariaDBの設定を行える。

 以下のクラスを呼び出すだけで、使用しているOSのディストリビューション、バージョンを判定し、MariaDB(もしくはMySQL)のインストール、設定、起動、/root/.my.cnfファイルの作成まで行ってくれる。

  # mariadb install, start, enable,
  # setting root password and create /root/.my.cnf
  class { 'mysql::server':
    root_password => "${mysql_root_pass}",
  }

(8)処理の順序、依存関係の定義

 Puppetでは、manifest中の処理を解析して処理順序を制御している。そのため、記述した順番通りには処理されないことから、依存関係のある処理では問題が発生する可能性がある。これを受けて、処理順序や依存関係を制御する機能が提供されている。

 順序の依存関係の定義の例は以下の通り。tarファイルが解凍されないと、編集対象のファイルが存在しないため、エラーになってしまう。順序の依存関係はモジュール名の前に "->" を付与することで設定できる。

  # install wordpress
  exec { 'install wordpress':
    command => "curl ${wordpress_latest} | tar zx -C ${wp_unarchive_path}",
    creates => "${wp_install_path}/wp-config.php",
  }
  # modify wordpress config
  -> exec { "modify wordpress config":
    command => "sed -e 's/\\(.*\\)database_name_here\\(.*\\)/\\1${wp_db_name}\\2/' \
                    -e 's/\\(.*\\)username_here\\(.*\\)/\\1${wp_db_user}\\2/' \
                    -e 's/\\(.*\\)password_here\\(.*\\)/\\1${wp_db_pass}\\2/' \
                    -e 's/\\(.*\\)put your unique phrase here\\(.*\\)/\\1${wp_unique_phrase}\\2/' \
                    ${wp_install_path}/wp-config-sample.php  > ${wp_install_path}/wp-config.php",
    creates => "${wp_install_path}/wp-config.php",
  }

 パッケージのインストールの有無の依存関係の定義の例は以下の通り。Apache2(httpd)がインストールされていないと、"/etc/httpd/conf.d/"フォルダが存在しないため、ファイルを作成できない。fileリソースのパラメータに "require => Package['httpd']" を設定することで、Apache2のインストール後に処理が行われるようになる。

  # create httpd/wordpress.conf
  file { '/etc/httpd/conf.d/wordpress.conf':
    ensure  => file,
    content => template( 'wordpress_sample/wordpress.conf.erb' ),
    require => Package['httpd'],
  }

 他にも、mysql_database/mysql_user/mysql_grantなどの機能が提供されている。詳細な使用方法は、GitHub - puppetlabs-mysql上のREADMEに記載されている。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。