既に動いているサーバーの運用をしていて
- 検証環境と本番環境で設定ファイルが意図せず違うことがある(DB接続先が違うというものではなく)
- 運用でよく使う設定(cron,logrotate)の設定方針がサーバーで違う
など辛かったので、状況を改善するためにまずはJenkinsとServerspecを使って設定ファイルの定期監視をするようにしました。(本来はそのような状況になっていないべきですが、既にその状況になっている場合にはまず現状把握が大事かと個人的には思いました)
具体的には
- Serverspecで指定された場所にファイルがあるか確認する(cronであればanacronなのか/etc/cron.dなのか/var/spool/なのか)
- 設定ファイルをGitlabに登録し、実サーバーのファイルと同一であるか確認する(md5sum)
ということをJenkinsのデイリーで実行するジョブを設定するようにしてみました。
実際に行うと
- SSHしなくても設定ファイルがどのようになっているかをGitlab(ブラウザ)から見れるように可視化
- cronなどの設定がサーバーごとにどこにされているか分かるようにする
- Gitlabに登録されたファイルと違う場合にはエラーとしてすぐに検出し、誰が何のために変えたかを確認し、Gitlabに登録することで履歴を追えるようにする
というメリットが得られました。
本サンプルではJenkinsを動かすサーバーとServerspecで検証するサーバーを同じにしていますが、実際はServerspecで検証したいサーバーは別ホストになると思うので適宜置き換えてください。
サンプル
とりあえず構成みたい、最終的にどんな感じになるか確認する場合にはどうぞ。
準備
各サーバーから設定ファイルを取得してGitlabに登録しておきます。検証、本番でファイルが違う場合にはフォルダを分けるなどして管理とします。
例えばnginxの設定ファイルが各環境で違う場合
nginx/ ├── development ├── production └── verification
という風にします。トップディレクトリをverificationなどの環境にしてその下にサービスごとにディレクトリを切ってもいいでしょうし、状況に応じて構成を変更すれば良いと思います。
差分が少ないファイル(DB接続先が違うだけなど)であれば管理するファイルは一つにしてServerspecのテスト内でファイル内の文字列を置き換える方式でも良いかもしれません。
Jenkinsのインストール
Jenkinsをインストールします。
- インストール方法はJenkinsの公式サイト参照
- JenkinsのGit Pluginをインストールしておくこと
また、Jenkinsユーザーになり、以下のコマンドでbundleは入れておきます。
$gem install bundle
Serverspecのテストを書く
設定ファイルが登録してあるリポジトリでServerspecのテストを書きます。書くテストコードですが、ServerspecはRubyなので以下のようにすることで設定ファイルが同一か確認出来きます。
require 'spec_helper' require 'digest/md5' describe file('/etc/nginx/nginx.conf') do its(:md5sum) { should eq Digest::MD5.file('nginx/nginx.conf').to_s } end
パスの設定部分(nginx/nginx.conf)は適宜環境に合わせて変更してください。
Jenkinsで実行する
ジョブを作って以下のようなスクリプトを実行することでServerspecを実行できます。
bundle install bundle exec rake
ただ、この状態だとJenkinsの出力結果で色がつかず見ずらいので、設定変更およびJenkinsプラグインを使って見やすくします。
まず、以下2つのJenkinsプラグインをインストールします。
次にJenkinsの設定でURL of theme CSSと記載されている場所にhttp://jazzzz.github.io/jenkins-black-console/black-console.cssというコンソールの背景を黒くするCSSを指定します。
また、対象のジョブの設定のColor ANSI Console Outputで任意のAnsiColorMapを指定します。
Jenkins側の設定はこれで終わりなのですが、Serverspec側でも.rspecファイルに–ttyを追加してRspec実行時にttyオプションを有効化します。
--color --format documentation --tty
これでジョブを実行すればいい感じに色付きで見えるようになります。
XMLでのテスト結果の出力を行う
通常出力されるメッセージでもわかりやすいのですが、せっかくJenkinsを使っているのでより見やすいようにXML出力して、グラフ形式などで見れるようにしようと思います。
RSpec(Servespec)ではXML出力は出来ないのでrspec_junit_formatterを利用します。
$echo "gem 'rspec_junit_formatter'" >> Gemfile $bundle install
これでbundle exec rake –format RspecJunitFormatter –out reports/result.xmlとするとXML出力は可能です。ただし、CLIから実行するとホストが複数ある時に後で実行した結果をresultx.xmlで上書きするので、一つのホストの結果しか見えません。なので、Rakefileでホスト名ごとに結果のxmlを出力するようにします。また、ローカルで確認する場合にはXML出力でなく、documentフォーマットで見たいのでRakefileでは環境変数JENKINSが設定されている場合のみ、XML出力するようにします。
require 'rake' require 'rspec/core/rake_task' task :spec => 'spec:all' task :default => :spec namespace :spec do targets = [] Dir.glob('./spec/*').each do |dir| next unless File.directory?(dir) target = File.basename(dir) target = "_#{target}" if target == "default" targets << target end task :all => targets task :default => :all targets.each do |target| original_target = target == "_default" ? target[1..-1] : target desc "Run serverspec tests to #{original_target}" RSpec::Core::RakeTask.new(target.to_sym) do |t| ENV['TARGET_HOST'] = original_target t.pattern = "spec/#{original_target}/*_spec.rb" t.rspec_opts = "--format RspecJunitFormatter --out reports/#{target}.xml" if ENV['JENKINS'] end end end
上記変更後、Jenkinsのジョブで以下のように指定することでreports配下にホストごとの結果が出力され、以下のような形で確認できるようになります。
export JENKINS=True bundle install bundle exec rake
あとはJenkinsのジョブ設定のPublish JUnit test result reportのTest reports XMLsで「reports/*.xml」と指定すればOKです
終わりに
とりあえずこの対応を行っていくことで現状のサーバーの状況を確認、監視できるようになります。また、現状はChefやAnsibleなどのコードのインフラ化は進んでいないのですが、これをもっと細かく作成できれば安心してコードによるインフラ構成管理に進めるような気がします。