オープンソースなシステム自動管理ツール Puppet

第13回仮想リソース

仮想リソースとは?

仮想リソースは通常のリソースとは異なり、マニフェストで宣言しただけでは、システムに適用されません。⁠実体化」することによってはじめてシステムに適用されます。

仮想リソースの宣言は通常のリソースの宣言とほぼ同じですが、リソースタイプの前に@を付加します。

@user { luke: ensure => present }

この仮想リソースをシステムに適用するためには、realize関数によって実体化します。

realize(User['luke'])

これでシステム上にlukeというユーザが作成されます。

他にも実体化の方法はありますが、その解説の前に、まずは仮想リソースを具体的にどのような場面で利用するとうれしいのかを説明します。

仮想リソースの利用シナリオ

仮想リソースの利用シーンとして、以下のようなシナリオを想定します。

  • ウェブサービスのためのサーバを構築する。
  • このウェブサービスでは、前段にリバースプロキシを置いてブラウザからのリクエストを受ける。
  • リバースプロキシは背後のウェブアプリケーションサーバにリクエストを中継する。
  • スモールスタートでコストを抑えつつ、冗長性も確保するために、マシンは2台用意し、それぞれにリバースプロキシとウェブアプリケーションサーバを同居させる。
  • リバースプロキシ、ウェブアプリケーションのどちらでも負荷に応じて個別に台数を増やせるような柔軟性を確保する。
  • リバースプロキシで利用するPerlbalと、ウェブアプリケーションで利用するBackgrounDrbのプロセスは、daemontoolsで管理する。

このようなシナリオを想定した上で、まずは仮想リソースを使わずにマニフェストを記述してみます。

リバースプロキシとウェブアプリケーションサーバが同居しない場合には、マニフェストは以下のようになり、特に問題はありません。

class proxy {
  package {
    'daemontools':
      ensure => present; 
    'perl-Perlbal':
      ensure => present;
  }
}

class www {
  package {
    'daemontools':
      ensure => present;
    'rubygem-rails':
      ensure => present;
  }
}

node proxy {
  include proxy
}

node www {
  include www
}

リバースプロキシとウェブアプリケーションサーバを同居させようとした場合、以下のようなマニフェストになります。

class proxy {
  package {
    'daemontools':
      ensure => present; 
    'perl-Perlbal':
      ensure => present;
  }
}

class www {
  package {
    'daemontools':
      ensure => present;
    'rubygem-rails':
      ensure => present;
  }
}

node proxy_and_www {
  include proxy
  include www
}

これをシステムに適用しようとすると、daemontoolsパッケージリソース宣言が重複しているため、以下のようなエラーが発生します。

err: Could not retrieve configuration: Duplicate definition: Package[daemontools] is already defined in file manifests/site.pp at line 11; cannot redefine at manifests/site.pp:2

では、以下のようにdaemontoolsはどちらか一方のクラスに記述しておけばいい、と考えるかもしれません。

class proxy {
  package {
    'daemontools':
      ensure => present; 
    'perl-Perlbal':
      ensure => present;
  }
}

class www {
  package { 'rubygem-rails': ensure => present; }
}

node proxy_and_www {
  include proxy
  include www
}

このマニフェスト自体は問題ありませんが、負荷が高くなってきたため、ウェブアプリケーションサーバのみ新規に増やしたいということになり、以下のようなマニフェストを追加した場合にはどうなるでしょうか?

node www {
  include www
}

wwwクラスにはdaemontoolsパッケージリソースの宣言がないため、daemontoolsはインストールされず、BackgrounDrbのプロセスが起動しない、という事態が発生し、マニフェストの修正が必要となります。

これを解決するために、以下のようなマニフェストを記述し、daemontoolsパッケージリソースを仮想リソースとして宣言、proxyクラスとwwwクラスで実体化します。

@package { 'daemontools': ensure => present }

class proxy {
  realize(Package['daemontools'])
  package { 'perl-Perlbal': ensure => present; }
}

class www {
  realize(Package['daemontools'])
  package { 'rubygem-rails': ensure => present; }

}

node proxy_and_www {
  include proxy
  include www
}

node proxy {
  inclue proxy
}

node www {
  include www
}

こうすることで、リバースプロキシやウェブアプリケーションサーバを個別に増設する場合でも、単純にノードを追加するだけで済みます。

このように仮想リソースを利用することで、マニフェストが柔軟で拡張しやすいものとなります。

仮想リソースの実体化

relize関数での実体化

最初の方でも述べましたが、仮想リソースを実体化する方法のひとつは、realize関数を実行することです。実体化する仮想リソースがひとつの場合には、括弧はなくても構いません。

realize User[luke]

複数の仮想リソースを実体化する場合には、以下のように記述します。

realize(User[johnny], User[billy])

コレクションでの実体化

もうひとつの方法は、コレクションと呼ばれるシンタックスを利用することです。コレクションは実体化したい仮想リソースのタイプと条件を Type<| condition |> といった形で記述します。

たとえば、lukeユーザの仮想リソースを実体化するには、以下のように記述します。

User <| title == luke |>

条件には == 以外にも、!=, and, or が使えます。

Grpup <| title != sysadmin |>
File  <| owner == root and mode == 400 |>
User  <| title == luke or (group == dba or group == sysadmin) |>

コレクションを利用すると、複数の仮想リソースを短い記述で実体化することができます。

仮想リソースの解説は以上です。次回はFacterの拡張方法について解説予定です。

おすすめ記事

記事・ニュース一覧