Dnsruby試した
RubyでDynamicDNSサーバに対してNsupdateするのに、pNet-DNSというライブラリを使ってきたのですが
Rubyforgeのページを見ると、A direct port of the perl Net::DNS project - this project has been discontinued. PLEASE USE DNSRUBY INSTEAD!って記述があったので、
dnsrubyをインストールして試して見ました。
インストール
rubygemでインストール(fastthreadが使える場合内部で呼び出しているので一緒にインストールした方がいいです)
$ sudo gem install dnsruby $ sudo gem install fastthread
※最初仕事用のPCにインストールしたとき、なぜか同一バージョンのfastthreadが重複して入ってしまっておりrequire 'dnsruby'したときにエラーが発生しましたが、
その場合は、fastthreadの全削除、再インストールで直りました。
AXFR
とりあえずゾーン転送で全内容表示
サーバの設定としては、
- Bindのポートはデフォルトではない
- TSIG鍵による認証
#!/usr/bin/env ruby # coding: utf-8 # zt.rb require 'pp' require 'rubygems' require 'dnsruby' # Model find zt = Dnsruby::ZoneTransfer.new.tap do |ins| ins.server = "10.1.1.1" ins.port = "10053" ins.tsig = "nsupdate.example.com.", "WImSObCU+ClK7Ol8wWSDo6AkeR6kBtGp8CUPSBpKBSc1yA2ODpcye7vryKzIMqBjELzRsHjWJACyfgs+b7qUnA==" end %w[nsupdate.example.com int.nsupdate.example.com].each do |zone| puts "#{zone} -------------------------------------------------------------" result = zt.transfer(zone) puts "Record Total: #{result.size}" result.each do |r| rrset = "#{r.name} #{r.ttl} #{r.klass} #{r.type}" rrset = [rrset, r.type != "SOA" ? "#{r.rdata}": r.rdata.map {|x| "#{x}" }.join(' ')].join(' ') puts rrset end end
digコマンド風に表示
$ ruby zt.rb -------- nsupdate.example.com --------------------------------------------------- Record Total: 9 nsupdate.example.com 10 IN SOA dns.nsupdate.example.com root.nsupdate.example.com 1970010102 20 2 86400 60 nsupdate.example.com 10 IN NS dns.nsupdate.example.com nsupdate.example.com 10 IN NS dns-001.nsupdate.example.com nsupdate.example.com 10 IN NS dns-002.nsupdate.example.com nsupdate.example.com 10 IN NS dns-003.nsupdate.example.com nsupdate.example.com 10 IN NS dns-004.nsupdate.example.com nsupdate.example.com 10 IN NS dns-005.nsupdate.example.com nsupdate.example.com 10 IN NS dns-006.nsupdate.example.com foo.nsupdate.example.com 3600 IN A 1.2.3.4 -------- int.nsupdate.example.com --------------------------------------------------- Record Total: 8 int.nsupdate.example.com 10 IN SOA dns.nsupdate.example.com root.int.nsupdate.example.com 1970010100 20 2 86400 60 int.nsupdate.example.com 10 IN NS dns.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-001.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-002.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-003.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-004.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-005.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-006.nsupdate.example.com
Nsupdate
なにかレコードを更新してみます。
#!/usr/bin/env ruby # coding: utf-8 # nsupdate.rb require 'pp' require 'rubygems' require 'dnsruby' res = Dnsruby::Resolver.new(:nameservers => ["10.1.1.1"], :port => "10053") res.tsig = "nsupdate.example.com.", "WImSObCU+ClK7Ol8wWSDo6AkeR6kBtGp8CUPSBpKBSc1yA2ODpcye7vryKzIMqBjELzRsHjWJACyfgs+b7qUnA==" update = Dnsruby::Update.new("nsupdate.example.com") update.add("bar.nsupdate.example.com", "A", 3600, "1.2.3.4") update.delete("foo.nsupdate.example.com") begin reply = res.send_message(update) rescue => e pp e end
bar.nsupdate.example.comを追加して、foo.nsupdate.example.comを削除しました。
シリアル番号も更新されてますね。
$ ruby nsupdate.rb $ ruby zt.rb -------- nsupdate.example.com --------------------------------------------------- Record Total: 9 nsupdate.example.com 10 IN SOA dns.nsupdate.example.com root.nsupdate.example.com 1970010103 20 2 86400 60 nsupdate.example.com 10 IN NS dns.nsupdate.example.com nsupdate.example.com 10 IN NS dns-001.nsupdate.example.com nsupdate.example.com 10 IN NS dns-002.nsupdate.example.com nsupdate.example.com 10 IN NS dns-003.nsupdate.example.com nsupdate.example.com 10 IN NS dns-004.nsupdate.example.com nsupdate.example.com 10 IN NS dns-005.nsupdate.example.com nsupdate.example.com 10 IN NS dns-006.nsupdate.example.com bar.nsupdate.example.com 3600 IN A 1.2.3.4 -------- int.nsupdate.example.com --------------------------------------------------- Record Total: 8 int.nsupdate.example.com 10 IN SOA dns.nsupdate.example.com root.int.nsupdate.example.com 1970010100 20 2 86400 60 int.nsupdate.example.com 10 IN NS dns.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-001.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-002.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-003.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-004.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-005.nsupdate.example.com int.nsupdate.example.com 10 IN NS dns-006.nsupdate.example.com
Symfony1.4をgithubから取得し、プロジェクトにサブモジュールで取り込む
イメージ的には、svn externals
svnじゃなくてgitの方がうざい隠しディレクトリがなくていいですね
手順
Symfonyプロジェクトのトップディレクトリで下記のコマンドを実行するだけ
$ cd <sfproject> $ mkdir -p lib/vendor $ git submodule add git://github.com/vjousse/symfony-1.4.git lib/vendor/symfony Cloning into lib/vendor/symfony... remote: Counting objects: 5247, done. remote: Compressing objects: 100% (2611/2611), done. remote: Total 5247 (delta 2383), reused 5037 (delta 2226) Receiving objects: 100% (5247/5247), 4.12 MiB | 308 KiB/s, done. Resolving deltas: 100% (2383/2383), done. $ git ci -m 'import symfony' [master (root-commit) 688aee2] import symfony 2 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 .gitmodules create mode 160000 lib/vendor/symfony $ git st # On branch master nothing to commit (working directory clean) # 確認 $ php lib/vendor/symfony/data/bin/symfony -V symfony version 1.4.12-DEV (<sfproject>/lib/vendor/symfony/lib) # タスク一覧 $ php lib/vendor/symfony/data/bin/symfony -vT Usage: symfony [options] task_name [arguments] Options: --help -H Display this help message. --quiet -q Do not log messages to standard output. --trace -t Turn on invoke/execute tracing, enable full backtrace. --version -V Display the program version. --color Forces ANSI color output. --xml To output help as XML [...]
memo storeconfigs
設定
Using Stored Configuration - Puppet - Puppet Labs
Exported Resourceを使うのであれば必須
Exporting and Collecting Resources — Documentation — Puppet Labs
とりあえず、Rails必須、DB必須、Queuing任意(ActiveMQ)
記述があっても動かない
ただ、Exported Resources Overrideは使えるっぽい
入れたもの
rpm
設定
#<my.cnf>innodb-4G-heavy.cnfをコピー $ sudo /usr/bin/mysqladmin -u root password 'rootpassword' $ mysql -u root -p mysql> create database puppet; mysql> grant all privileges on puppet.* to puppet@localhost identified by 'password';
[puppetmasterd] storeconfigs = true dbadapter = mysql dbuser = puppet dbpassword = password dbserver = localhost dbsocket = /var/lib/mysql/mysql.sock
PuppetをPassengerで動かして大規模サイトに対応させる
大規模サイトでPuppetを運用する場合、複数のノードに同時にmanifestを適用すると思います。しかし、同時接続数5台を超えたあたりからクライアントのリクエストを捌けなくなり適用時にエラーが発生することがよくあります。その場合、同時接続数を減らしたり接続時間をずらしたりして対応していると思います。ただ、そんなのやってられねーって人に、Passengerを使ったパフォーマンスの改善を紹介します。
前提
Passengerってなに?
上記で説明されている通りApache等でRubyアプリケーションを動かすための動作環境です。インストールと設定が楽で、RailsにおいてはほとんどApacheの設定だけで動作環境の設定が済んでしまいます。
注意事項
- puppet v0.25系環境で、rack,passengerの最新版をインストールしても動作しません。
上記でも書かれているように、何も考えずrackとpassengerの最新版をインストールしても動作しません。
Ruby v1.8.5(CentOS5系のデフォルトバージョン)では、
Remove rack 1.2.1 first and then install rack 1.1.0. It seems that rack
1.1.0 and passenger 2.2.9 have been the magic combination (at least for me).
- Gary
って、言ってるのでおとなしくrack v1.1.0とpassenger v2.2.9をインストールしましょう。
Railsアプリケーションを既に動かしている場合は、別のサーバを用意するかした方がいいです。
Ruby v1.8.7系では最新版でも問題なく動作するかもしれません。(未検証)
手順
必要なソフトウエアのインストール
$ sudo yum install httpd httpd-devel ruby-devel rubygems mod_ssl $ sudo gem rack -v 1.1.0 $ sudo gem Passenger -v 2.2.9
Passenger-Apacheモジュールのビルドとインストール
対話形式なので、指示に従って進めます。
$ sudo passenger-install-apache2-module
途中で必要なパッケージがインストールされていなければ、下記のように親切に指示されますので指示に従ってインストールした後、再実行しましょう。
Installation instructions for required software * To install Curl development headers with SSL support: Please run yum install curl-devel as root. * To install OpenSSL development headers: Please run yum install openssl-devel as root.
Rackの設定
Rack用のディレクトリと設定ファイルを作成します。Puppet v0.25系からはconfig.ruのテンプレートが用意されているのでそれをコピーして使うだけでいいです。
$ mkdir -p /usr/share/puppet/rack/puppetmasterd
$ mkdir /usr/share/puppet/rack/puppetmasterd/public /usr/share/puppet/rack/puppetmasterd/tmp
$ cp /usr/share/puppet/ext/rack/files/config.ru /usr/share/puppet/rack/puppetmasterd/
$ chown puppet /usr/share/puppet/rack/puppetmasterd/config.ru
Apacheの設定
インストール時に指示されたように、passenger-Apacheモジュールの設定を組み込みます。
$ sudo vim /etc/httpd/conf.d/passenger.conf
# passenger.conf LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9/ext/apache2/mod_passenger.so PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9 PassengerRuby /usr/bin/ruby
puppetmasterを動かすためのVirtualHostの設定を行います。
SSL証明書ファイルの名前はssl配下のディレクトリに作成されているサーバ用証明書のファイル名に置き換えてください。
$ sudo vim /etc/httpd/conf.d/puppetmaster.conf
# puppetmaster.conf # Performance #PassengerPoolIdleTime 300 # default: 300 PassengerUseGlobalQueue on PassengerMaxPoolSize 60 Listen 8140 <VirtualHost *:8140> SSLEngine on SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA SSLCertificateFile /var/lib/puppet/ssl/certs/puppet-001.example.com.pem SSLCertificateKeyFile /var/lib/puppet/ssl/private_keys/puppet-001.example.com.pem SSLCertificateChainFile /var/lib/puppet/ssl/certs/ca.pem SSLCACertificateFile /var/lib/puppet/ssl/certs/ca.pem # CRL checking should be enabled; if you have problems with Apache complaining about the CRL, disable the next line SSLCARevocationFile /var/lib/puppet/ssl/ca/ca_crl.pem SSLVerifyClient optional SSLVerifyDepth 1 SSLOptions +StdEnvVars # The following client headers allow the same configuration to work with Pound. RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e PassengerHighPerformance on # DO NOT USE Global config!!(disable mod_rewrite) RackAutoDetect On RackBaseURI / DocumentRoot /usr/share/puppet/rack/puppetmasterd/public/ CustomLog /puppet/logs/puppet_access_log combined ErrorLog /puppet/logs/puppet_error_log <Directory /usr/share/puppet/rack/puppetmasterd/> Options None AllowOverride None Order Allow,Deny Allow from all </Directory> </VirtualHost>
後はApacheを起動するだけです。
動作確認
クライアントから、puppetd等でアクセスするとpassengerはpuppetmasterのインスタンスを起動し通常通りpuppetmasterにアクセスできるようになります。
$ sudo /usr/sbin/puppetd --verbose --no-daemonize --onetime --noop
サーバで下記のコマンドを実行すると、passengerがpuppetmasterを起動していることを確認できます。
$ sudo passenger-status ----------- General information ----------- max = 15 count = 1 active = 1 inactive = 0 Waiting on global queue: 0 ----------- Domains ----------- /usr/share/puppet/rack/puppetmasterd: PID: 8897 Sessions: 1 Processed: 1 Uptime: 12s
Tips
通常の/etc/init.d/puppetmasterdスクリプトを使用した方法では、/etc/sysconfig/puppetmasterの内容をデーモン実行時のコマンドライン引数として読み込めたのですが、この方法でも同じことが可能です。
config.ruに記述することで実現できます。
# config.ru # a config.ru, for use with every rack-compatible webserver. # SSL needs to be handled outside this, though. # if puppet is not in your RUBYLIB: # $:.unshift('/opt/puppet/lib') $0 = "puppetmasterd" require 'puppet' # if you want debugging: # ARGV << "--debug" ARGV << "--rack" ARGV << "--confdir=/puppet/etc" ARGV << "--logdest=/var/log/puppet/puppetmaster.log" require 'puppet/application/puppetmasterd' # we're usually running inside a Rack::Builder.new {} block, # therefore we need to call run *here*. run Puppet::Application[:puppetmasterd].run
上記の通り、ARGV変数に追加したいオプションを記述するだけです。
終わりに
Passengerを使用することにより、悩みどころだった大規模サイトでのpuppet運用がこれで可能になります。
''passenger-status''や''sudo passenger-memory-stats''を使うことによりモニタリングが可能ですし、
Passengerのチューニング可能でApacheの設定に記述するだけなので、手軽に運用できると思います。
Puppetサーバを集約する(複数環境対応)
はじめに
サーバ管理にpuppetを使うと、設定の管理等の点において楽できます。
一台のpuppetで複数のサービス環境に対応させる方法がわかったのでその設定方法
前提
下記についてはわかっているものとして説明
- 既に基本的なpuppetの概念や設定がわかっていること
- 特にpuppet.conf等の設定ファイルの記述
複数環境に対応できるのは、manifestとmodulepathのみのようです。そのためpuppet.conf等の設定ファイルはサーバに一つしか配置できません。またこの機能、本来は(production, development, test)環境に応じたmanifestを運用することを想定しているらしいです。
この機能は、個々のサービスごとのmanifestを一つのサーバで運用する方法に使うのに有効に活用できるので、下記では、そのような構成で運用する設定を載せます。
ソフトウェア
- puppet v0.25.x
- CentOS v5.4
手順
サーバ(puppetmasterd)の設定
- 複数環境に対応するためのpuppet.confを用意する
# puppet.conf [main] # This is the default environment for all clients environment=infra # 1.) Defaultのenvironmentを定義(何も定義しないとproductionが割り当てられる) server = puppet pluginsync = true pluginsource = puppet://$server/plugins diff_args = -u [puppetmasterd] # specify allowed environments environments=infra,blog,iphone,board # 2.)個々のmanifest,moduleに環境名を定義 # 3.) 個々の環境ごとに使用するmanifestとmoduleを設定 # configure environments [infra] modulepath = /puppet/infra/current/idc/modules:/puppet/infra/current/ec2/modules manifest = /puppet/infra/current/manifests/site.pp [blog] modulepath = /puppet/blog/current/modules:/puppet/infra/current/idc/modules:/puppet/infra/current/ec2/modules manifest = /puppet/blog/current/manifests/site.pp [iphone] modulepath = /puppet/iphone/current/modules:/puppet/infra/current/idc/modules:/puppet/infra/current/ec2/modules manifest = /puppet/iphone/current/manifests/site.pp [board] modulepath = /puppet/board/current/modules:/puppet/infra/current/idc/modules:/puppet/infra/current/ec2/modules manifest = /puppet/board/current/manifests/site.pp
上記の通りなんですが、2.)のようにまず、puppetmasterdセクションに個々のmanifest,moduleに対して何でもいいので環境名を定義します。
3.)でその名前を付けた個々の環境で使用するmanifestとmoduleのmodulepathを定義します。
1.)は、オプションで、後で説明するClient側のpuppet.confに適用する環境が未設定の場合に適用するdefaultを定義します。これはmainセクションに定義します。
クライアント(puppetd)の設定
- puppet.confにサーバで定義した環境名を定義する
サーバのpuppet.confで定義した環境名のうち、適用したいmanifestが配置されている環境を一つ記述します
ちなみに、サーバでdefaultの環境(mainセクションのenvironmentで定義した環境)が設定されている場合、クライアントに適用されるDefaultのmanifestはその環境のmanifestとなります。逆にサーバでdefaultの環境が定義されていない場合、エラーが発生します。
# puppet.conf
[puppetd]
environment = blog
おわりに
複数のmanifestを管理していて別々のサーバと立てている場合、これで一つのサーバに集約することができると思います。しかし、puppetで管理するノードが多い場合、パフォーマンスの悪化という別の問題が発生するため、その場合passengerを併用して動かすといいでしょう。
カッとなってUbuntu/DebianでRubygems実行コマンドのパスを通した
はじめに
MacOSXやCentOSを普段使用している場合、Rubygemsの実行コマンドのパスを意識することはないですが、Ubuntu/Debianの場合そこにパスがとおっていないため、コマンドを実行するのが少々面倒です。
毎回rubygemsの実行コマンドがどこにあるか確認しなくて済むように、シェル実行時にパスを通してしまいます。
.bash_profileや.profileに追加します
手順
1. Linux DistributionとGem environmentを調べる
まずLinux Distributionは、下記のコマンドで調査できます。(例は、Ubuntuで実行した場合)
$ lsb_release -si => Ubuntu
これで、特定のディストリビューションの場合のみRubygemsの実行コマンドのパスを設定することができるようになりました
次にGem environmentを調べます。下記のコマンドで確認できます。
$ gem environment RubyGems Environment: - RUBYGEMS VERSION: 1.3.7 - RUBY VERSION: 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux] - INSTALLATION DIRECTORY: /var/lib/gems/1.8 - RUBY EXECUTABLE: /usr/bin/ruby1.8 - EXECUTABLE DIRECTORY: /var/lib/gems/1.8/bin - RUBYGEMS PLATFORMS: - ruby - x86_64-linux - GEM PATHS: - /var/lib/gems/1.8 - /home/satsv/.gem/ruby/1.8 - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :benchmark => false - :backtrace => false - :bulk_threshold => 1000 - REMOTE SOURCES: - http://rubygems.org/
上記のEXECUTABLE DIRECTORY変数が取得したいパスです。あとはgrepなりsedコマンドなりを駆使して実行コマンドのパスを取得できるのですが、もっと簡単に取得する方法があります。
$ ruby -e 'require "rubygems"; puts Gem::bindir' => /var/lib/gems/1.8/bin
Rubyのスクリプトとして実行すれば余計な文字列もないのでそのまま使用することができます。
2. .bash_profileまたは、.profileに追記
最終的に下記のように記述すれば、シェルにログインした時にRubygemsの実行コマンドのパスが環境変数PATHに追加されると思います。
最初にwhichコマンドを実行しているのは、MacOSXではlsb_releaseがないを利用して判定から除外します。
[...] # Gem executable directory which lsb_release >/dev/null 2>&1 && lsb_release -si | grep -E 'Ubuntu|Debian' >/dev/null 2>/dev/null && { export GEM_BIN=$(ruby -e 'require "rubygems"; puts Gem::bindir') export PATH=$GEM_BIN:$PATH }
Ubuntuで、毎回cap shellを実行してcapがないよって言われてたので、かっとなって調べてみました。
これで、安心して''cap shell''とか実行できますね。