cloudpack の 脳筋の (岸上) です。

はじめに

chef-zeroのC/S wrapper knife-zero使ってますか?
とても便利です。重宝しています。

higanworks/knife-zero · GitHub

個人的にchefの真髄である search が利用できるため、chef-soloと違って関連nodeの情報をattributeに記述すること無くrecipeを記述でき、管理の幅を広げてくれるツールなので是非使いましょうと思っている次第です(がまだ横展開しきれず)

今回はHAproxyを用いてGalera Cluster MariaDBへの接続を行うための定義を簡単に書くためのtipsを残したいと思います。

EnvironmentとRoleを使い、HAProxyのロードバランス対象となるノードをnode情報から自動判別してHAProxyの設定を生成します。

chef repositoryで利用するEnvironmentとRole

Environment

chef_environment 意味
production 本番環境

Role

role 意味
galera_master Galera Cluster初期ノード
galera_member Galera Clusterメンバーノード

DBサーバとなるノードには role[galera_master] または role{galera_member] を割り当ててknife zeroを実行しておきます。(実行しておかないとnode.jsonに対象ノードの情報が集約されない)

recipe

haproxy/recipes/default.rb

Galera Clusterを構成するノードの情報を search で取得して template variables に渡します。

if node.chef_environment.include?("production")
  cookbook_file "/root/haproxy-1.5.9-2.amzn1.x86_64.rpm" do
    source "haproxy-1.5.9-2.amzn1.x86_64.rpm"
    owner "root"
    group "root"
    mode 0644
  end

  package "haproxy" do
    action :install
    provider Chef::Provider::Package::Rpm
    source "/root/haproxy-1.5.9-2.amzn1.x86_64.rpm"
  end

  template "/etc/haproxy/haproxy.cfg" do
    source "haproxy.cfg.erb"
    owner "root"
    group "root"
    mode 0644
    notifies :restart, "service[haproxy]"
    variables(
      :galerahosts => search(:node,"roles:galera* AND chef_environment:#{node.chef_environment}")
    )
  end

  service "haproxy" do
    action :nothing
  end
end

haproxy/template/haproxy.cfg.erb(一部抜粋)

template variables から渡された情報をeachでぶん回します。

listen  haproxy-galera
        bind *:33306
        mode tcp
        timeout client  28800s
        timeout server  28800s
        balance roundrobin
        option httpchk
        option allbackups
        <% @galerahosts.each do |host|  %>
        server <%= host.ipaddress %> <%= host.ipaddress %>:3306 check
        <% end %>

apply後

このようにHAProxyを導入するサーバにrecipeを適用します(chef-repo毎にbundler使ってるのでbundle exec かいてます)

bundle exec knife zero chef_client search "role:app AND chef_environment production" -x ec2-user --sudo --attribute name

実行後は対象ノードに以下のようなhaproxy.cfgが作成されます。

..省略..
listen  haproxy-galera
        bind *:33306
        mode tcp
        timeout client  28800s
        timeout server  28800s
        balance roundrobin
        option httpchk
        option allbackups
        server 192.168.1.100 192.168.1.100:3306 check
        server 192.168.1.101 192.168.1.101:3306 check
        server 192.168.1.102 192.168.1.102:3306 check

attributeを使用せず rolechef_environment の検索でロードバランス対象ノードのIPアドレスを設定することが出来ました。

search最高。

ちなみに自分はknife zeroのコマンドラインを実行するのが面倒なので 簡単なRakefileを作成して、search条件だけ渡してknife zeroを実行しています。

適用する roleenvironment 毎にtaskを作成したらもっと簡単にかつsearchのミス無く適用することができると思います。

Rakefile例

require 'rake'

desc "run, bundle exec knife  list"
task :list, [:type] do |t,args|
  command = %(bundle exec knife #{args[:type]} #{t} )
  puts command
  Bundler.clean_system command
end

desc "run, bundle exec knife search "
task :search, [:hint] do |t, args|
  command = %(bundle exec knife #{t} "#{args[:hint]}")
  puts command
  Bundler.clean_system command
end

knife_args = "-x ec2-user --sudo --attribute name"

desc "run, bundle exec knife zero chef_client --why-run"
task "dry-run", [:hint] do |t,args|
  command = %(bundle exec berks vendor cookbooks;bundle exec knife zero chef_client "#{args[:hint]}" #{knife_args} --why-run)
  puts command
  Bundler.clean_system command
end

desc "run, bundle exec knife zero chef_client."
task :apply, [:hint] do |t,args|
  command = %(bundle exec berks vendor cookbooks;bundle exec knife zero chef_client "#{args[:hint]}" #{knife_args})
  puts command
  Bundler.clean_system command
end

Rake実行例

why-run
bundle exec rake "dry-run[(roles:galera* AND chef_environment:production)]"
apply
bundle exec rake "apply[(roles:galera* AND chef_environment:production)]"

Rake saikou.

元記事はこちらです。
Infrastructure as 脳筋のためのchef recipe tips. HAProxyの例