ぶていのログでぶログ

思い出したが吉日

よく使うpuppetモジュールの紹介

これは pepabo Advent Calendar 2016 - Qiita の12日目の記事です。 昨日は id:kumak1 さんの 好きなキーボードを使い続けるためにキーボード作り始めたでした!


こんにちはこんにちは。 ペパボではサーバの構成管理にpuppetを使用しています。 日々の業務でpuppetを使用していて、最近はマニフェストをゴリゴリ書くより公開されているモジュールを使用することが多くなりました。 そこで、今日は私がよく使うpuppetモジュールを紹介したいと思います!

Puppetモジュールの選び方

puppetモジュールの紹介の前に、私がモジュールを選ぶときのポイントを書いておきます。

Puppetモジュールは、Puppet Forgeで公開されています。 数多くの人がモジュールを公開していますが玉石混交ですので、選ぶのも一苦労です? そこで、私は以下のようなポイントをチェックしています。 1. puppetlabsが公開しているもの 2. スターが多くついていて定期的に更新されているもの

1に関しては公式モジュールなので定期的にメンテされており、今後puppetがバージョンアップしてもそれに追随してくれる安心感があります! また、puppetモジュールを作る上で参考になる作りになっているので、これを真似て作ると良いと思います*1 2のスターが多いということは、それほど使用者が多くハマってしまって情報が見つかることが多いですし、定期的に更新されていないと、puppetのバージョンアップなどに追随できない可能性があります。 これは、puppetモジュールに限らない話ですね。

クラス名のバッティング

すでに使用しているpuppetマニフェストに、公開されているpuppetモジュールを追加するとクラス名がバッティングする場合があります。 例えば、 ::apache とか ::nginx とか…。 バッティングした場合どうなるかというと、先に定義されているものが使用されます*2。 そのため、公開されているpuppetモジュールを使うつもりでマニフェストに定義すると、エラーになります。。 しかも、パラメータを指定していた場合、 そのようなパラメータはない みたいなエラーになりかなり混乱します…。

バッティングしてしまった場合の対処は、対象をリネームするか利用しているモジュールのサブクラスにするのが良いと思います。 サブクラスにするとは例えば ::apache というクラス名を some_module::apache のように変更することを指します。

モジュールの紹介

puppetlabs-stdlib

puppetlabs/stdlib · Puppet Forge

puppetに様々な関数を追加するライブラリ群です。 validation系の関数も追加されるので、他のモジュールからincludeされていることが多いです。 個人的によく使うのは file_lineensure_resource です。

puppetlabs-puppet_agent

puppetlabs/puppet_agent · Puppet Forge

puppet-agentをよしなに管理してくれるモジュールです。 pupept-agentを3系から4系にアップグレードするときに、このモジュールをincludeするだけでめんどくさいあれやこれをよしなに処理してくれます!

puppetlabs-inifile

puppetlabs/inifile · Puppet Forge

inifileを扱うモジュールです。 iniファイルをfileリソースで、変更後のファイルを用意して適用するスタイルで今までマニフェストを書いていました。 それでは、本当に必要な設定部分がわからなくなってしまいます。 このモジュールを使って、設定部分のみを明示することで後からマニフェストを見た時に、どの部分を変更したのかわかりやすくなります。

以下使用例です。 コミュニティ版のmysql-5.5を使いたい時に、公式で用意されているRPMからインストールすると、デフォルトではmysql56-communityリポジトリが有効化されているので、mysql56-communityを無効化して、mysql55-communityを有効化する必要があります。 以下のように記述すると目的が達成できます*3

package { 'mysql-community-release':
  ensure   => installed,
  source   => 'http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm',
  provider => 'rpm',
} ->
ini_setting {
  'enable mysql55-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql55-community',
    setting => 'enabled',
    value   => 1;

  'disable mysql56-community repo':
    path    => '/etc/yum.repos.d/mysql-community.repo',
    section => 'mysql56-community',
    setting => 'enabled',
    value   => 0;
}

puppetlabs-mysql

puppetlabs/mysql · Puppet Forge

mysqlを扱うのに便利なモジュールです。 my.cnfの定義から、DBやユーザの作成までできます。 (私が携わっているサービスでは、ユーザの管理はGratanを使用しているのでmy.cnfやパッケージ、サービスの管理にのみ使っています)

puppetlabs-apache

puppetlabs/apache · Puppet Forge

Apacheを扱うモジュールです。 httpd.confは設定する内容が多いので、templatesファイルで用意してそのままファイルを配置することが多いですが、このモジュールを使うことで変更点が宣言的になってとても読みやすくなります。 例えば、以下の様な定義を書いて使用しています。

class { '::apache':
  apache_version   => '2.2.3',
  user             => 'apache',
  group            => 'apache',
  manage_user      => false,
  manage_group     => false,
  server_signature => false,
  serveradmin      => 'admin@example.com',
  default_vhost    => false,
  trace_enable     => false,
  # MPMのパラメータをカスタマイズしたいので別途定義している
  mpm_module       => false,
  default_mods     => [
    'alias',
    'auth_basic',
    'authn_core',
    'authn_file',
    'authz_user',
    'dir',
    'deflate',
    'mime',
    'negotiation',
    'rewrite',
    'setenvif',
    'status',
  ],
}

class { '::apache::mod::prefork':
  startservers        => '8',
  minspareservers     => '5',
  maxspareservers     => '20',
  serverlimit         => '256',
  maxclients          => '256',
  maxrequestsperchild => '4000',
}

apache::vhost { 'example.com':
  vhost_name      => '*',
  port            => '80',
  servername      => 'example.com',
  error_log       => false,
  docroot         => '/var/www/html',
  manage_docroot  => false,
  custom_fragment => template('sample/apache_custom_fragment.conf'),
}

Class[::apache] では /etc/httpd/conf/httpd.conf の定義が作成されます*4。 また、default_modsに定義されたモジュールが読み込まれるように /etc/httpd/conf.d 配下にconfファイルが作成されます。 apache::vhost でvhostの定義が作成されます。 作成されるファイル名は、上記の例でいくと /etc/httpd/conf.d/50-example.com.conf になります。 ほぼ、この関数に渡すパラメータでカバーできますが、足りない場合は custom_fragment を使って定義を追加できます。

puppet-nginx

puppet/nginx · Puppet Forge

puppetlabs社が公開しているnginxモジュールもあったのですが、開発が停止してこちらのモジュールにリンクが貼られています。 Apache同様に宣言的にパラメータを定義できます。 以下は定義例です。

$ltsv_log_format = join([
  'vhost:$host', 'time:$time_local', 'remote_addr:$remote_addr', 'method:$request_method',
  'path:$request_uri', 'protocol:$server_protocol', 'status:$status', 'size:$body_bytes_sent',
  'referer:$http_referer', 'user_agent:$http_user_agent', 'request_time:$request_time',
  'upstream_time:$upstream_response_time',
], '\t')

class { '::nginx::config':
  confd_purge              => true,
  worker_processes         => 'auto',
  worker_rlimit_nofile     => 4096,
  http_access_log          => '/var/log/nginx/access.log',
  http_format_log          => 'ltsv',
  nginx_error_log_severity => 'warn',
  log_format               => {
    'ltsv' => $ltsv_log_format
  },
  http_cfg_append          => {
    mruby_init_worker => '/etc/nginx/mruby/init_worker.rb',
    mruby_exit_worker => '/etc/nginx/mruby/exit_worker.rb',
  },
}

class { '::nginx':
  # mruby入りの自前ビルド
  package_ensure => '1.11.6-1.el7.centos.ngx',
  manage_repo    => false,
}

nginx::resource::vhost { 'sample':
  server_name          => ['example.com'],
  listen_port          => 80,
  # vhost毎にアクセスログ/エラーログを作られてしまうのを回避
  access_log           => absent,
  error_log            => absent,
  use_default_location => false,
}

nginx::resource::location { 'sample-default':
  location             => '/',
  vhost                => 'example.com',
  www_root             => undef,
  index_files          => undef,
  proxy                => 'http://$backend',
  location_cfg_prepend => {
    mruby_set => '$backend /etc/nginx/mruby/get_backend.rb cache',
  },
}

LTSVなログフォーマットを定義するために少し煩雑になっています…。 また、ngx_mrubyなパラメータはサポートされていないので http_cfg_append / location_cfg_prepend を用いて定義しています。

stahnma-epel

stahnma/epel · Puppet Forge

RedHat系のディストリを使用する場合EPELは必須だと思います。 このモジュールをincludeするだけで、DRY的になるしモジュールにGPGキーも含まれていて、毎回 yum install が走らなくてよいです。

hfm-stns

hfm/stns · Puppet Forge

弊社若手インフラエンジニア @hfm が作ったSTNS を使うためのモジュールです! includeするだけでSTNSに対応できてとても便利です! STNSとは、弊社 id:pyamax が作ったTOMLで管理するシンプルなユーザ管理システムです。 詳しくは以下の記事を参考にしてください。

tomohiro-mackerel_agent

tomohiro/mackerel_agent · Puppet Forge

mackerel を扱うモジュールです。 check-pluginに notification_intervalmax_check_attempts を設定する場合は /etc/mackerel-agent/conf.d に設定ファイルを配置するのが良いと思います。

まとめ

puppetforgeで公開されているpuppetモジュールを利用すると、DRY的になったり設定が宣言的になり、マニフェストがすっきりします。 モジュールの使い方を覚える必要があったり、既存の環境に適用するにはモジュールが定義するコンフィグファイルに合わせて変更しないといけなかったり、デメリットはありますが一度使い方を憶えてしまえばすぐにマニフェストを掛けるメリットがあります! また、バージョンアップしてもモジュール側で吸収できるので、アップデートに伴ってモジュールを作ったり、派生物を作る必要がなくなります。

今回紹介した内容ではclassのパラメータで設定を定義していますが、各モジュール共にhieraが利用できます。 すべてサーバの定義をpuppetモジュールに集約できれば、究極的にはhieraとpuppetモジュールの管理だけでサーバが定義できるようになります。

puppetモジュールをうまく活用し、サーバの構成管理の負担を下げ生産性を上げていきましょう?

おわりに

個人ブログじゃなくてペパボテックブログに書けばよかったと後悔…

*1:といいつつpuppetモジュールを作ったことないですが ?

*2:puppetのmodulepathで指定された順にマニフェストが読み込まれます

*3:yumrepoリソースで定義するとうまく適用できません

*4:RedHat系の場合