hatenob

プログラムって分からないことだらけ

一人Web開発~第4夜 Apache導入

今回、Webサーバ兼ロードバランサとしてApacheを選択しました。後段にWildflyを使うので、それとの連携を考えた時に尤もらしい選択肢と言えると思います。
パラメータ関連のチューニングはとりあえず後回しにして、インストールを進めます。

httpdのインストール

どうやらCentOS6.5でインストールされるhttpdは2.2.15のようで、2.2系の最新でもなければ、2.4でもありませんでした。何でだろうか?

# Install package

package "httpd" do
  action :install
end

service "httpd" do
  action [:disable, :stop]
end

# Setup httpd.conf

cookbook_file "/etc/sysconfig/httpd" do
  mode 00644
end

template "/etc/httpd/conf/httpd.conf" do
  source "httpd.conf.erb"
  mode 00644
  variables({
    :listen => node[:httpd][:listen],
    :server_name => node[:httpd][:server_name],
    :max_clients => node[:httpd][:max_clients],
    :threads_per_child => node[:httpd][:threads_per_child]
  })
end

/etc/sysconfig/httpdで、環境変数HTTPDhttpd.workerを指定して、これでMPMをworkerに固定しています。デフォルトだとprefork。workerのほうがスレッドで処理をするのでリソースを効率的に利用できたりするんだと思います。
httpd.confのうち、いくつかは変数化してあります。今のところはお試し程度なので、もっとずっと後で余裕があればもう少しそれらしくしたいと思います。

mod_clusterの導入

ロードバランサ用のモジュールとしてmod_clusterを使うことにしました。mod_jkやらmod_proxyもあるんですが、使ったことがないのでこれを選びました。

# Clear conf.d directory

Dir::glob("/etc/httpd/conf.d/*").each do |f|
  file f do
    action :delete
    not_if { File.basename(f) == "cluster.conf" }
  end
end

# Setup mod_cluster

remote_file node[:httpd][:mod_cluster][:file] do
  source node[:httpd][:mod_cluster][:url]
  action :create_if_missing
end

["tar", "gzip"].each do |pkg|
  package pkg do
    action :install
  end
end

bash "install_mod_cluster" do
  user "root"
  cwd "/etc/httpd/modules"
  code <<-EOH
    tar --no-same-owner -xzf #{node[:httpd][:mod_cluster][:file]}
  EOH
  not_if { File.exist?("/etc/httpd/modules/mod_advertise.so") \
    && File.exist?("/etc/httpd/modules/mod_manager.so") \
    && File.exist?("/etc/httpd/modules/mod_proxy_cluster.so") \
    && File.exist?("/etc/httpd/modules/mod_slotmem.so") }
end

template "/etc/httpd/conf.d/cluster.conf" do
  source "cluster.conf.erb"
  mode 00644
  variables({
    :listen => node[:httpd][:listen],
    :cluster_name => node[:httpd][:mod_cluster][:cluster_name]
  })
end

最初に、使わない余計なconfファイルを削除しています。あとでcluster.confを配置するのですが、実行するたびにこいつが消されると差分とかが見た目に分かりにくいので、これは残しておくことにします。
mod_clusterをダウンロードして展開しますが、展開にはtarとgunzipが必要なのでパッケージをインストールしておきます。まぁ普通は入ってますよね。
インストールは、すでに展開済みでなければ展開するということにしました。
cluster.confを作成してますが、こちらもいくつか回った参考サイトに書かれているままなので、今後、もっとずっと後でカリカリにしたいと思います。

configtestの実行

最後に、configtestを実行するようにしました。

# Config check

bash "configtest" do
  user "root"
  code <<-EOH
    service httpd configtest
  EOH
end

設定ファイルにシンタクスエラーがあった場合、configtestはエラーを返してくれるので、レシピの実行がエラーになります。ここでエラーを拾っておくことで、導入後に起動してserverspecでテストをできるというわけです。

serverspecでテスト

テストを書きます。
ひとまず最低限という感じです。
なお、このテストではポートのリスン状態をテストしているので、サービス起動状態でないといけません。

require 'spec_helper'
describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should_not be_enabled }
  it { should     be_running }
end

describe port(80) do
  it { should be_listening }
end

describe file('/etc/sysconfig/httpd') do
  it { should be_file }
  it { should contain "^HTTPD=/usr/sbin/httpd.worker" }
end

describe file('/etc/httpd/conf/httpd.conf') do
  it { should be_file }
  it { should contain "ServerName node1" }
  it { should contain "MaxClients \\+300" }
  it { should contain "User apache" }
end

describe file('/etc/httpd/conf.d/cluster.conf') do
  it { should be_file }
  it { should contain "<VirtualHost *:80>" }
  it { should contain "EnableMCPMReceive true" }
  it { should contain "ServerAdvertise On" }
  it { should contain "AdvertiseFrequency 5" }
  it { should contain "ManagerBalancerName cluster1" }
end

describe file('/etc/httpd/modules/mod_advertise.so') do
  it { should be_file }
end

describe file('/etc/httpd/modules/mod_manager.so') do
  it { should be_file }
end

describe file('/etc/httpd/modules/mod_proxy_cluster.so') do
  it { should be_file }
end

describe file('/etc/httpd/modules/mod_slotmem.so') do
  it { should be_file }
end

describe group('apache') do
  it { should exist }
end

describe user('apache') do
  it { should exist }
  it { should belong_to_group 'apache' }
  it { should have_login_shell '/sbin/nologin' }
end

最後に、ユーザとグループのテストをしていますが、これはhttpdパッケージ導入時に勝手に作られるものなので、Chef側には作成するコードが入っていません。Chefで明示的に作ってもいいんですが、作られることが分かっているので省いています。仮に仕様が変わってもここでテストしているので大丈夫!なはず。

雑感

serverspecでの設定ファイルのテストは、やっぱり全項目書くべきなのかなぁ。悩ましいところだわ。

次はWildfly
実はここまでは書き溜めた分があったけど、次からはないので多分更新まではもう少しかかる。