Infrastructure as 脳筋のためのchef recipe tips. HAProxyの例
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を使用せずroleとchef_environmentの検索でロードバランス対象ノードのIPアドレスを設定することが出来ました。
search最高。
ちなみに自分はknife zeroのコマンドラインを実行するのが面倒なので 簡単なRakefileを作成して、search条件だけ渡してknife zeroを実行しています。
適用するroleやenvironment毎にtaskを作成したらもっと簡単にかつsearchのミス無く適用することができると思います。
require 'rake' desc "run, bundle exec knife <type> 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 <hint>" 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.