連載
» 2015年01月23日 18時00分 公開

新人インフラ技術者のためのサーバー構築/運用自動化入門(4):作業手順書はもういらない! Puppetにおける自動化の定義書「マニフェスト」の書き方と基礎文法まとめ (2/5)

[菅原亮, 岡本隆史,NTT OSSセンタ]

Puppetでは作業を「リソース」で管理

 先ほど書きました、HTTPサーバーをインストールする手順を、もう一度思い出してみましょう。

  1. HTTPサーバーのパッケージをインストール
  2. httpd.confの設定
  3. HTTPDサービスの自動起動設定
  4. HTTPDサービスの起動確認

 Puppetでは「パッケージのインストール」「設定ファイルの作成」「サービスの設定」といった作業を「リソース」という概念で管理しています。パッケージの管理はpackageリソース、ファイルの管理はfileリソース、サービスの管理はserviceリソースという具合です。マニフェストではリソースに“属性”の情報を与えてシステムの“あるべき姿”を指示します。以下にリソースの中でも特に重要な「Core Types」と呼ばれる8種類のリソースを紹介します。

Puppetの「Core Types」リソース
file ローカルファイルシステム上のファイルを管理
package ソフトウェアパッケージを管理。CentOSなどRed Hat系のOSではyumコマンドを呼び出す形で動作するため、パッケージのインストールにはインストールDVDなど必要なパッケージに対して連載第2回で紹介したようなYumリポジトリとしてアクセスできる準備が必要になる
service サービスの起動/停止/再起動や、自動起動の設定を行う
notify ログにメッセージを出力
exec 指定のコマンドを実行
cron cronのジョブを管理
user ユーザーアカウントを管理
group グループを管理
使い方などの詳細は『Core Types Cheat Sheet』(PDF)を参照してください

Puppetのマニフェストの書き方の基本

 それでは先ほどの作業手順を実行するマニフェストを作ってみましょう。基本形は以下のようになります。

マニフェストの基本形

[リソース名] { 'インスタンス名称':

  属性名 => 属性値,

   : (繰り返し)

}


packageリソースを使ってみよう

 作業手順のうち「1. HTTPサーバーのパッケージをインストール」をマニフェストで表現してみます。packageリソースは先ほど紹介した『Core Types Cheat Sheet』を参照すると、『パッケージをインストールするには「ensure」属性で「present」を指定』とあります。パッケージ名は「name」属性で指定しますが、デフォルトでインスタンス名称が使われますので、ここではCentOSでのパッケージ名である「httpd」を指定します。では実際に記述してみましょう。入力が終わりましたら「test.pp」などのファイル名で保存してください。

package { 'httpd':
  ensure => present,
}

 これだけでHTTPサーバーのパッケージをインストールできます。

「ドライラン」で動かしてみよう

 実際に試してみたいところですが、いきなり本当にインストールしてしまうのではなく、マニフェストを実行はしますがシステムへの変更はしない「ドライラン」で動かしてみましょう。

 前回少し紹介しましたが、ドライランの場合は「--noop」オプションを付けて実行します。また、ローカルのファイルに保存されたマニフェストを実行するので「puppet apply」コマンドで実行します。このコマンドは構築対象のサーバー上で実行してください。それでは試してみましょう。以下のようにコマンドを実行してください(本連載で筆者はCentOS 6.5とPuppet 3.7.3を用いています)。

#  puppet apply --noop test.pp
 
Notice: Compiled catalog for dock01 in environment production in 0.58 seconds
Notice: /Stage[main]/Main/Package[httpd]/ensure: current_value absent, should be present (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Finished catalog run in 0.26 seconds

 このような結果になりましたか?環境によっては「Warning: Could not retrieve fact fqdn」という警告が出るかもしれません。この警告はFQDN名が取得できなかった場合に出ますが、実行には影響ありませんので無視して構いません。エラーが出た場合はマニフェストを見直してください。

各リソースと属性の書き方の例

 動作が確認できたら、作業手順の残りもマニフェスト化しましょう。設定ファイルはfileリソース、サービス設定はserviceリソースを使います。結果、以下のようなマニフェストになります。

package { 'httpd':
  ensure => present,
}
 
file { '/etc/httpd/conf/httpd.conf':
  ensure  => present,
  content => template('/root/httpd.conf.erb'),
}
 
service { 'httpd':
  ensure => running,
  enable => true,
}

 ここで属性について簡単に説明します。詳細は先ほど紹介した『Core Types Cheat Sheet』を参照してください。

 fileリソースではensure属性とcontent属性を指定しています。fileリソースでのensure属性は、作成するもの(ファイル、ディレクトリ、シンボリックリンクなど)を指定します。

 content属性は作成するファイルの中身を記述できます。ここでは「テンプレート」を指定していますが、テンプレートについては詳細は後述します。“インスタンス名称”では対象をフルパスで指定します。

 serviceリソースではensure属性とenable属性を指定しています。serviceリソースでのensure属性はサービスのあるべき状態(実行中、停止中)を指定します。enable属性ではサービスの自動実行設定を指定します。インスタンス名称では対象サービスを指定します。

依存関係は各リソースで属性として指定する

 さて、このマニフェスト、一見問題なさそうに見えますが、このままだと不具合があります。先ほど手順には“依存関係”があるというお話をしましたが、このマニフェストには“依存関係”が記述されていません。マニフェスト上は順番通りになっているのにと思われたかもしれませんが、Puppet言語での記述順と実際に実行される順番は一致しません。依存関係は各リソースで属性として、以下を指定します。

依存関係を指定する属性
require 指定したリソースが適用された後に実行
before 指定したリソースが適用される前に実行

 ここで特定のリソースを指定する必要がありますが、Puppet言語ではある特定のリソースを指定(「リソース参照」と言います)するにはリソース名の先頭を大文字にします。

リソース参照の例

 これでは分かりにくいので具体的に書いてみます。先ほどのpackageリソース、fileリソース、serviceリソースは以下のように記述します。

Package['httpd']
File['/etc/httpd/conf/httpd.conf']
Service['httpd']

 リソース名の先頭が大文字になる以外に、括弧の記号が波括弧{}ではなく角括弧[]になっていることに注意してください。またインスタンス名の後にあったコロン:は不要です。では先ほどのマニフェストに依存関係を追加してみましょう。

package { 'httpd':
  ensure => present,
}
 
file { '/etc/httpd/conf/httpd.conf':
  ensure  => present,
  content => template('/root/httpd.conf.erb'),
  require => Package['httpd'],
}
 
service { 'httpd':
  ensure  => running,
  enable  => true,
  require => File['/etc/httpd/conf/httpd.conf'],
}

 これで各作業の依存関係を記述できました。

リフレッシュイベントも各リソースで属性として指定する

 このままでも動作しますが、より良くするため運用に入ってからのことを考えてみましょう。K男さんからの指示でも「設定変更はマニフェストの変更で対応とすること」とありましたので、マニフェスト側の変更だけで対応できなくてはなりませんので。

 運用に入ってからメンテナンスする際に、設定ファイルを変更するのはよくあることですが、設定ファイルを変更するとサービスの再起動が必要ですね。今のマニフェストを見ると、serviceリソースでは単に“サービスが起動しており、自動起動設定になっていること”だけ定義しています。運用中だと、すでに定義されている“あるべき状態”になっているので、fileリソースで何か変更があってもserviceリソースでは何もしません。

 それだと運用などのシーンでは困ってしまいますので、そのような用途にPuppet言語ではリソースに変更があったときにイベントを送出して、再起動などのリフレッシュ動作をさせる機能があります。依存関係の記述に以下を指定します。

リフレッシュイベントに関する属性
subscribe 指定したリソースからリフレッシュイベントを受け取る。それ以外の動作はrequireと同様
notify 指定したリソースにリフレッシュイベントを送出する。それ以外の動作はbeforeと同様

 ちなみに先ほどリソース名としてのnotifyを紹介していますが、ここで紹介したのは属性のnotifyです。名称は同じですが別物です。ちょっと混同しやすいので注意してください。

 それではserviceリソースがfileリソースからイベントを受け取るので、マニフェストを修正しましょう。

package { 'httpd':
  ensure => present,
}
 
file { '/etc/httpd/conf/httpd.conf':
  ensure  => present,
  content => template('/root/httpd.conf.erb'),
  require => Package['httpd'],
}
 
service { 'httpd':
  ensure    => running,
  enable    => true,
  subscribe => File['/etc/httpd/conf/httpd.conf'],
}

 こうすると、運用に入ってからメンテナンスなどで設定ファイルを修正した場合でも、サービスが自動的に再起動するようになります。

コラム「deprecated警告について」

 デフォルトの設定でPuppetを動かすと、以下のようなdeprecated警告が表示されることがあります。

Warning: Setting modulepath is deprecated in puppet.conf.
 See http://links.puppetlabs.com/env-settings-deprecations
   (at /usr/lib/ruby/site_ruby/1.8/puppet/settings.rb:1119:in `issue_deprecation_warning')
package {'httpd': ensure => present, }

 これは将来のリリースで廃止される予定の機能を使った場合に出ます。現行バージョンを使っている分には特に問題ないので、deprecated警告を表示させないようにするには、「/etc/puppet/puppt.conf」の[main]に以下の設定を追加してください。

disable_warnings = deprecations

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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