2013年3月28日木曜日

VPCの(Amazon)DNSサーバ

スズキです。

何となく知ってたことがドキュメントに明記されているか確認したときのメモです。

まあ、下記のドキュメントがすべてって感じでしょうか?
Amazon DNS Server
適当に和訳もしてみました。
When you create a VPC, we automatically create a set of DHCP options
and associate them with the VPC.

VPCを作成するとき、自動的に"DHCP Options"が作成され、
そのVPCに関連づけられます。
This set includes only a single option: domain-name-servers=AmazonProvidedDNS.

この"DHCP Options"には"domain-name-servers=AmazonProvidedDNS"の設定のみが
含まれます。
This is an Amazon DNS server, and this option enables DNS for instances
that need to communicate over the VPC's Internet gateway.

これはAmazonの提供するDNSサーバで、このオプションはVPC上の
"Internet Gateway"を経由して通信(名前解決)する必要のあるEC2が利用する
DNSとして有効にできます。
The string AmazonProvidedDNS maps to a DNS server running on a reserved IP address
at the base of the VPC network range "plus two".

この"AmazonProvidedDNS"という文字はVPCのネットワークアドレスに2を足した 予約されたIPアドレスで起動しているDNSサーバにマッピングされます。
For example, the DNS Server on a 10.0.0.0/16 network is located at 10.0.0.2.

例えば、VPCのネットワークが" 10.0.0.0/16"のDNSサーバのIPアドレスは"10.0.0.2"となります。
You can also use the Amazon DNS server IP address 169.254.169.253,
though some servers don't allow its use.

Amazonが提供するDNSサーバのIPアドレスは利用できないサーバもありますが
"169.254.169.253"を利用することも可能です。
Windows Server 2008, for example, disallows the use of a DNS server located
in the 169.254.x.x network range.

例えば"Windows Server 2008"はネットワークレンジ"169.254.x.x"の範囲に
配置されるDNSサーバを利用することはできません。

要は下記といったところでしょうか?
  • DNSサーバのIPアドレスはVPCのネットワークアドレスに"2"を足したもの
    • VPCのCIDRが"10.0.0.0/16"なら"10.0.0.2"
  • "169.254.169.253"もDNSサーバとして利用可能

実際に"10.0.0.2"は下記のように確認でき、
# cat /etc/resolv.conf 
; generated by /sbin/dhclient-script
nameserver 10.0.0.2
"169.254.169.253"は次のように確認できます。
# nslookup www.suz-lab.com 169.254.169.253
...
Address: 27.0.1.214

"169.254.169.253"は知らなかった...
--------
http://www.suz-lab.com

2013年3月27日水曜日

NagiosのCloudWatchプラグイン(Python版AWSコマンドラインツール版)

スズキです。

以前、下記のようにNagiosでCloudWatchのメトリックスを監視するプラグインを
作りましたが、
NagiosのCloudWatchプラグイン(PHP版)
次で紹介したようにPython版AWSコマンドラインツールが利用できるように
なったので、そちらを利用する形で作り直してみました。
Python版AWSコマンドラインツールでCloudWatchのメトリックス情報を取得

プラグインは下記のような感じです。
# cat check_cloudwatch 
#!/bin/sh

. `dirname $0`/utils.sh

set -e
trap 'echo "UNKNOWN: $?"; exit $STATE_UNKNOWN' ERR

WARN=0
CRIT=0
REVERSE=false

while getopts c:w:n:m:d:s:r OPTNAME; do
    case $OPTNAME in
    w)
        WARN=$OPTARG
        ;;
    c)
        CRIT=$OPTARG
        ;;
    n)
        NAMESPACE=$OPTARG
        ;;
    m)
        METRIC_NAME=$OPTARG
        ;;
    d)
        DIMENSIONS=$OPTARG
        ;;
    s)
        STATISTICS=$OPTARG
        ;;
    r)
        REVERSE=true
        ;;
    *)
        echo "UNKNOWN: Usage"
        exit $STATE_UNKNOWN
        ;;
    esac
done

START_TIME=`date -u -d '10 minutes ago' +%Y-%m-%dT%TZ`
END_TIME=`date -u +%Y-%m-%dT%TZ`

METRIC_DATA=`aws cloudwatch get-metric-statistics \
--namespace   $NAMESPACE   \
--metric-name $METRIC_NAME \
--dimensions  $DIMENSIONS  \
--statistics  $STATISTICS  \
--period      60           \
--start-time  $START_TIME  \
--end-time    $END_TIME    \
| jq ".Datapoints[0] | .$STATISTICS" \
| cut -d\" -f2`

if [ $REVERSE = "true" ]; then
    CRIT_STATUS=`echo "$METRIC_DATA < $CRIT" | bc`
    WARN_STATUS=`echo "$METRIC_DATA < $WARN" | bc`
else
    CRIT_STATUS=`echo "$METRIC_DATA > $CRIT" | bc`
    WARN_STATUS=`echo "$METRIC_DATA > $WARN" | bc`
fi

if   [ $CRIT_STATUS -eq 1 ]; then
    echo "CRITICAL $NAMESPACE $METRIC_NAME $DIMENSIONS $STATISTICS: $METRIC_DATA"
    exit $STATE_CRITICAL
elif [ $WARN_STATUS -eq 1 ]; then
    echo "WARNING $NAMESPACE $METRIC_NAME $DIMENSIONS $STATISTICS: $METRIC_DATA"
    exit $STATE_WARNING
elif [ $CRIT_STATUS -eq 0 -a $WARN_STATUS -eq 0 ]; then
    echo "OK $NAMESPACE $METRIC_NAME $DIMENSIONS $STATISTICS: $METRIC_DATA"
    exit $STATE_OK
fi

echo "UNKNOWN: End"; exit $STATE_UNKNOWN
※同一フォルダに"utils.sh"(/usr/lib64/nagios/plugins/utils.sh)が必要になります。

取得した値と閾値との比較は"bc"コマンドで行っているので下記のように
インストールしておく必要もあります。
# yum -y install bc
...

実行すると下記のようになります。(閾値を上に超えたらCritical/Warningになります)
# ./check_cloudwatch -c 2 -w 0 -n AWS/EC2 -m CPUUtilization -d '{"name":"InstanceId","value":"i-xxxxxxxx"}' -s Average
CRITICAL AWS/EC2 CPUUtilization {"name":"InstanceId","value":"i-f2f016f0"} Average: 2.3440000000000003

閾値を下に超えたらCritical/Warningになるようにするには"-r"オプションを付けます
# ./check_cloudwatch -c 2 -w 0 -n AWS/EC2 -m CPUUtilization -d '{"name":"InstanceId","value":"i-xxxxxxxx"}' -s Average -r
OK AWS/EC2 CPUUtilization {"name":"InstanceId","value":"i-f2f016f0"} Average: 2.3440000000000003

もう少し手を入れたらGitHubに上げてRPMにして...
--------
http://www.suz-lab.com

2013年3月26日火曜日

Python版AWSコマンドラインツールでCloudWatchのメトリックス情報を取得

スズキです。

どちらかというと、下記のメモとして...
  • "--dimensions"の指定方法
  • "date"コマンドのフォーマットと時刻(相対的)の指定方法
  • "jq"の出力のダブルクウォートを削除("10"→10)

Python版AWSコマンドラインツールでCloudWatchのメトリックス情報を取得は
下記の通りです。
# aws cloudwatch get-metric-statistics \
> --namespace   AWS/EC2 \
> --metric-name CPUUtilization \
> --dimensions  '{"name":"InstanceId","value":"i-xxxxxxxx"}' \
> --statistics  Average \
> --period      60 \
> --start-time  `date -u -d '10 minutes ago' +%Y-%m-%dT%TZ` \
> --end-time    `date -u +%Y-%m-%dT%TZ`
{
    "Label": "CPUUtilization", 
    "ResponseMetadata": {
        "RequestId": "e54a59ca-95f4-11e2-8103-6f7ec19b50ca"
    }, 
    "Datapoints": [
        {
            "Timestamp": "2013-03-26T09:04:00Z", 
            "Average": "12.662", 
            "Unit": "Percent"
        }, 
        {
            "Timestamp": "2013-03-26T08:59:00Z", 
            "Average": "1.334", 
            "Unit": "Percent"
        }
    ]
}

"jq"を使って最初のデータの値のみダブルクウォートを削除した形で出力する場合は、
下記となります。
# aws cloudwatch get-metric-statistics \
> --namespace   AWS/EC2 \
> --metric-name CPUUtilization \
> --dimensions  '{"name":"InstanceId","value":"i-xxxxxxxx"}' \
> --statistics  Average \
> --period      60 \
> --start-time  `date -u -d '10 minutes ago' +%Y-%m-%dT%TZ` \
> --end-time    `date -u +%Y-%m-%dT%TZ` \
> | jq '.Datapoints[0] | .Average' \
> | cut -d\" -f2
3.338

そして、Nagiosの新CloudWatchプラグインへ...
--------
http://www.suz-lab.com

"Route 53"への移行前の確認用DNSサーバ(Unbound)

スズキです。

DNSサーバを"Route 53"に移行することはよくあると思いますが、当然、
移行(切り替え)前の確認は行いたいわけです。
ということでUnboundを使って確認用DNSサーバを作ってみました。

"cloudpack.jp"のDNSサーバを下記のRoute53に移行することを想定しています。


上記のRoute53をDNSサーバとして指定すると、下記のように登録されているレコードは
名前解決できますが、
# nslookup blog.cloudpack.jp ns-1053.awsdns-03.org
...
blog.cloudpack.jp canonical name = blog.suz-lab.com.
登録されてないレコードは次のように名前解決できません。
# nslookup www.suz-lab.com. ns-1053.awsdns-03.org
...
** server can't find www.suz-lab.com: REFUSED

なので、独自にDNSサーバ(Unbound)を立ち上げ、"cloudpack.jp"は上記のRoute53で
名前解決し、それ以外は、OSで設定してあるDNSサーバで名前解決するようにしてみました。

Unboundのインストールは下記の通りです。
# yum -y install unbound
...

「"cloudpack.jp"は上記のRoute53で名前解決」の部分は下記のように設定しています。

# cat /etc/unbound/conf.d/cloudpack.jp.conf 
forward-zone:
    name: "cloudpack.jp."
    forward-host: ns-1053.awsdns-03.org

次のようにUnboundを起動すれば、利用できるようになります。
# service unbound start
unbound の制御キーと証明証を生成中:
unbound を起動中: [  OK  ]

OSに設定してあるDNSサーバで名前解決した場合は、当然、下記のように本来の設定の
結果となります。
# nslookup blog.cloudpack.jp
...
Non-authoritative answer:
Name: blog.cloudpack.jp
Address: 216.239.34.21
Name: blog.cloudpack.jp
Address: 216.239.36.21
Name: blog.cloudpack.jp
Address: 216.239.38.21
Name: blog.cloudpack.jp
Address: 216.239.32.21

そしてUnboundを指定して名前解決すると次のようにRoute53に登録した内容が
結果として表示されます。
# nslookup blog.cloudpack.jp localhost
...
Non-authoritative answer:
blog.cloudpack.jp canonical name = blog.suz-lab.com.
blog.suz-lab.com canonical name= ghs.google.com.
ghs.google.com canonical name = ghs.l.google.com.
Name: ghs.l.google.com
Address: 74.125.31.121

Unboundを指定していても、"cloudpack.jp"以外の名前解決は、OSに設定されている
DNSサーバを利用して結果を返していることも確認できます。
# nslookup www.suz-lab.com localhost
...
Non-authoritative answer:
www.suz-lab.com canonical name = www.suz-lab.com.s3-website-ap-northeast-1.amazonaws.com.
www.suz-lab.com.s3-website-ap-northeast-1.amazonaws.com canonical name = s3-website-ap-northeast-1.amazonaws.com.
Name: s3-website-ap-northeast-1.amazonaws.com
Address: 27.0.1.84

この後、このDNSサーバ'(Unbound)をセキュリティグループなどを調整して、
インターネット越しに参照できるようにし、テストPCのDNSサーバに設定することで
テストを行う形になると思います。

Unbound、久しぶりに使った...
--------
http://www.suz-lab.com

2013年3月25日月曜日

すべての送受信メールをPostfixで取得してみる

スズキです。

"always_bcc"の設定で可能です。(BCCを設定し受信する形となります)
下記のように、すべての送受信メールを受信するメールアドレスを指定し、Postfixをリスタートします。
# cat /etc/postfix/main.cf
...
always_bcc = zzz@suz-lab.com

まずは送信のテストです。
次のようにメールを送ってみると、
# mail yyy@cloudpack.jp
Subject: Send Test
Send Test
.
EOT
下記のようにログが出力され、
... postfix/pickup[3674]: ...: uid=500 from=<xxx>
... postfix/cleanup[3697]: ...: message-id=<...@...>
... postfix/qmgr[2379]: ...: from=<xxx@...>, size=553, nrcpt=2 (queue active)
... postfix/smtp[3703]: ...: to=<yyy@cloudpack.jp>, relay=..., delay=1.1, delays=0.04/0.02/0.33/0.72, dsn=2.0.0, status=sent (...)
... postfix/smtp[3706]: ...: to=<zzz@suz-lab.com>, relay=..., delay=1.1, delays=0.04/0.03/0.39/0.66, dsn=2.0.0, status=sent (...)
... postfix/qmgr[2379]: ...: removed
"always_bcc"で設定したメールアドレスにも送信されていることが確認できます。

次に受信のテストです。
下記のように送信して(受信させて)みると、
# cat smtp.txt
HELO localhost
MAIL FROM: yyy@cloudpack.jp
RCPT TO: xxx@xxx.xxx.xxx
DATA
SUBJECT: Recieve Test

Recieve Test
.
QUIT
# nc xxx.xxx.xxx.xxx 25 < smtp.txt
下記のようにログが出力され、
... postfix/smtpd[3717]: connect from unknown[...]
... postfix/smtpd[3717]: improper command pipelining after HELO from unknown[...]
... postfix/smtpd[3717]: ...: client=unknown[...]
... postfix/cleanup[3782]: ...: message-id=<...>
... postfix/qmgr[2379]: ...: from=<yyy@cloudpack.jp>, size=492, nrcpt=2 (queue active)
... postfix/smtpd[3717]: disconnect from unknown[...]
... postfix/local[3785]: ...: to=<xxx@...>, relay=local, delay=0.08, delays=0.04/0.03/0/0.01, dsn=2.0.0, status=sent (...)
... postfix/smtp[3786]: ...: to=<zzz@suz-lab.com>, relay=..., delay=1.3, delays=0.04/0.03/0.47/0.76, dsn=2.0.0, status=sent (...)
... postfix/qmgr[2379]: ...: removed
"always_bcc"で設定したメールアドレスにも送信されていることが確認できます。

ということで、送受信でメールが取得できていることが確認できました。

あっさりできた!
--------
http://www.suz-lab.com

2013年3月13日水曜日

FluentdでJSON形式のログを読み込んで整形する

スズキです。

下記のようなJSON形式のログをFluentd(と、そのプラグイン)で処理したくて、
いろいろと調べてみました。
{ "a": "test", "b": "1", "c": 2, "d": true, "e": "true", "f": [ { "g": "test1" }, { "h": "test2" } ] }

そのそのJSON形式のログもTailプラグインで下記のように"format json"で簡単に
読み込むことができます。
<source>
    type     tail
    format   json
    path     /tmp/test.log
    tag      tail.json
    pos_file /tmp/tail.syslog.pos
</source>
<match tail.json>
    type     file
    path     /tmp/tail
</match>
読み込んだデータは下記のように出力されます。
2013-03-13T16:31:23+09:00       tail.json       {"a":"test","b":"1","c":2,"d":true,"e":"true","f":[{"g":"test1"},{"h":"test2"}]}

しかしFluentdのプラグインは、ネスト構造を考慮してないものが多いような気がします。
なので、下記のようなプラグインを作成してネスト構造のJSONをフラットなJSONに
変更して、他のプラグインで処理できるようにしてみました。
module Fluent
    require "jsonpath"
    class ConvertOutput < Output
        Fluent::Plugin.register_output("convert", self)
        config_param :format, :string, :default => nil
        config_param :tag   , :string, :default => nil

        def configure(conf)
            super
            @formatter = create_formatter(JSON.parse(@format))
        end

        def create_formatter(formatter)
            case formatter
            when Array
                formatter.map{|e| create_formatter(e)}
            when Hash
                formatter.inject({}) do |hash, (k, v)|
                    hash[k] = create_formatter(v)
                    hash
                end
            when String
                if formatter.start_with?("$")
                    JsonPath.new(formatter)
                else
                    formatter
                end
            else
                formatter
            end
        end

        def emit(tag, es, chain)
            es.each do |time, record|
                converted = convert_record(@formatter, record)
                Engine.emit(@tag, time, converted)
            end
            chain.next
        end

        def convert_record(formatter, record)
            case formatter
            when Array
                formatter.map{|e| convert_record(e, record)}
            when Hash
                formatter.inject({}) do |hash, (k, v)|
                    hash[k] = convert_record(v, record)
                    hash
                end
            when JsonPath
                formatter.first(record)
            else
                formatter
            end
        end

    end
end
※上記は"/etc/td-agent/plugin/out_convert.rb"として配置しています。
※下記のように"jsonpath"のGemパッケージをインストールする必要があります。
# /usr/lib64/fluent/ruby/bin/gem install jsonpath
Fetching: jsonpath-0.5.0.gem (100%)
Successfully installed jsonpath-0.5.0
1 gem installed
Installing ri documentation for jsonpath-0.5.0...
Installing RDoc documentation for jsonpath-0.5.0...

Fluentdの設定ファイル(/etc/td-agent/td-agent.conf)は下記のような感じになります。
<source>
    type     tail
    format   json
    path     /tmp/test.log
    tag      tail.json
    pos_file /tmp/tail.syslog.pos
</source>
<match tail.json>
    type     convert
    format   { "a": "$['b']", "b": 10, "c": { "d": "$['a']" }, "e": [ {"f": "$['f'][0]" }, {"g": "$['f'][1]['h']" } ] }
    tag      convert.json
</match>
<match convert.json>
    type     file
    path     /tmp/convert
</match>
※"format"の部分に整形後のログのテンプレート(データの指定はJSONPathを利用)を
記載します。

すると、最初のJSON形式のログが、下記のように整形されて出力されるようになります。
2013-03-13T15:27:10+09:00       convert.json    {"a":"1","b":10,"c":{"d":"test"},"e":[{"f":{"g":"test1"}},{"g":"test2"}]}

これで、いつも使ってるプラグインにつなげれるはず...
--------
http://www.suz-lab.com

2013年3月12日火曜日

Postfixでリレー設定(冗長構成)

スズキです。

下記のようにパブリックセグメントのSMTPサーバ(Postfix)経由で、
プライベートセグメントのEC2からメールを送る方法です。(よく目にする方法です)



パブリックセグメント側のPostfixは下記のように設定しています。
# cat /etc/postfix/main.cf
...
inet_interfaces = all
mynetworks      = 10.0.0.0/16, 127.0.0.0/8

デフォルトでは"inet_interfaces = localhost"となっていますが、
上記のように"all"に変更する必要があります。

"mynetworks"の10.0.0.0/16はリレーが許可できるCIDR(VPC全体など)を
指定する必要があります。

プライベートセグメントのPostfixは下記のように設定しています。
# cat /etc/postfix/main.cf
...
relayhost       = [10.0.8.4]
fallback_relay  = [10.0.9.4]

"relayhost"にはリレー先のSMTPサーバを指定し、"fallback_relay"は"relayhost"が
利用できなかったときに利用するSMTPサーバを指定することになります。

※IPアドレスでの指定は[]で囲むべきという指摘を受け、確かにその通りだったので、
修正しました。([]無しでも動くのは正しい挙動なのか?)

ELBを間に入れる方法とどっちがいいんだろう?
--------
http://www.suz-lab.com

CentOS6に"RVM & Passenger & Nginx"

スズキです。

以前、"Passenger & Apache"を試しましたが、
CentOS(6.3)にRuby(1.9)、Rails、Passengerをインストール
今回は、RubyもRVMでインストールし、PassengerもNginxで利用する形を試して
みました。

RVMのインストール

# curl -L https://get.rvm.io | bash -s stable
...

Rubyのインストール

# /usr/local/rvm/bin/rvm install 1.9.3
...

デフォルトのRubyの設定

# rvm use ruby-1.9.3 --default
Using /usr/local/rvm/gems/ruby-1.9.3-p392

デフォルトのRubyのバージョン確認

# ruby -v
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-linux]

Passengerのインストール

# gem install passenger
...

依存パッケージのインストール

# yum -y install gcc gcc-c++ make curl-devel openssl-devel zlib-devel 
...

OpenSSL関係のビルド

# cd /usr/local/rvm/src/ruby-1.9.3-p392
# cd ext/openssl/
# ruby extconf.rb
...
# make
...
# make install
/usr/bin/install -c -m 0755 openssl.so /usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/x86_64-linux
installing default openssl libraries

Passenger対応Nginxのインストール

# passenger-install-nginx-module 
...
 * GNU C++ compiler... found at /usr/bin/g++
 * The 'make' tool... found at /usr/bin/make
 * A download tool like 'wget' or 'curl'... found at /usr/bin/curl
 * Ruby development headers... found
 * OpenSSL support for Ruby... found
 * RubyGems... found
 * Rake... found at /usr/local/rvm/wrappers/ruby-1.9.3-p392/rake
 * rack... found
 * Curl development headers with SSL support... found
 * OpenSSL development headers... found
 * Zlib development headers... found
...
下記でNginxのダウンロードからインストールも行います。
...
Automatically download and install Nginx?

Nginx doesn't support loadable modules such as some other web servers do,
so in order to install Nginx with Passenger support, it must be recompiled.

Do you want this installer to download, compile and install Nginx for you?

 1. Yes: download, compile and install Nginx for me. (recommended)
    The easiest way to get started. A stock Nginx 1.2.6 with Passenger
    support, but with no other additional third party modules, will be
    installed for you to a directory of your choice.

 2. No: I want to customize my Nginx installation. (for advanced users)
    Choose this if you want to compile Nginx with more third party modules
    besides Passenger, or if you need to pass additional options to Nginx's
    'configure' script. This installer will  1) ask you for the location of
    the Nginx source code,  2) run the 'configure' script according to your
    instructions, and  3) run 'make install'.

Whichever you choose, if you already have an existing Nginx configuration file,
then it will be preserved.

Enter your choice (1 or 2) or press Ctrl-C to abort: 1
...

以上で"/opt/nginx"以下にPassengerに対応したNginxがインストールされます。

設定ファイルは、すでに下記のようになっており、
# cat /opt/nginx/conf/nginx.conf
...
http {
    ...
    passenger_root /usr/local/rvm/gems/ruby-1.9.3-p392/gems/passenger-3.0.19;
    passenger_ruby /usr/local/rvm/wrappers/ruby-1.9.3-p392/ruby;
    ...
}
....
"Ruby on Rails"を利用する場合は、次のように設定すればOKなようです。
server {
    listen 80;
    server_name www.yourhost.com;
    root /somewhere/public;
    passenger_enabled on;
}
Nginxの起動スクリプトは用意しないといけないのか...
--------
http://www.suz-lab.com

2013年3月11日月曜日

HAProxyでBasic認証のユーザー別にバックエンドサーバを振り分ける

スズキです。

あまり使うことは無いような気がしますが...

まずは二種類のユーザー(suzuki/suzuki2)を用意します。
# cat /etc/httpd/conf/suz-lab.htpasswd
suzuki:xxxxxxxx
suzuki2:yyyyyyyy

次に二つのバーチャルホストに対して同じユーザーでのBasic認証をかけておきます。
# cat /etc/httpd/conf/httpd.conf
...
Listen 81
Listen 82
...
<VirtualHost *:81>
    DocumentRoot /var/www/81
    <Directory "/var/www/81">
        AuthUserFile /etc/httpd/conf/suz-lab.htpasswd
        AuthName     suz-lab
        AuthType     Basic
        Require      valid-user
    </Directory>
</VirtualHost>
<VirtualHost *:82>
    DocumentRoot /var/www/82
    <Directory "/var/www/82">
        AuthUserFile /etc/httpd/conf/suz-lab.htpasswd
        AuthName     suz-lab
        AuthType     Basic
        Require      valid-user
    </Directory>
</VirtualHost>

そして、HAProxyを下記のように設定します。
# cat /etc/haproxy/haproxy.cfg
...
userlist suz-lab
    user suzuki insecure-password suzuki!23

frontend proxy
    bind 0.0.0.0:80
    acl auth_ok http_auth(suz-lab)
    use_backend     local81  if auth_ok
    default_backend local82

backend local81
    balance leastconn
    server  local81 localhost:81 check port 81

backend local82
    balance leastconn
    server  local82 localhost:82 check port 82
これはユーザーが"suzuki"の場合、81番ポートのバーチャルホストに振り分けられ、
それ以外(suzuki2)の場合、82番ポートのバーチャルホストに振り分けられます。

いつか、どこかで、使えるか?
--------
http://www.suz-lab.com

Pacemakerの"crm"コマンドが無くなっていたので"pcs"で代用してみた

スズキです。

久しぶりに"yum"でPacemakerをインストールしたら"crm"コマンドが無くて、
下記のような設定ができなくなってしまったので、
# crm configure property no-quorum-policy="ignore" stonith-enabled="false"
# crm configure rsc_defaults resource-stickiness="INFINITY" migration-threshold="1"
# crm configure primitive iptables lsb:iptables op monitor interval="5s"
代替ツールとして"pcs"なるものをインストールして、同様の設定をしてみました。

インストールは下記のように"yum"で簡単に実施できます。
# yum -y install pcs
...
上記と同様の設定は、"pcs"の場合、下記となります。
# pcs property set no-quorum-policy=ignore
# pcs property set stonith-enabled=false
# pcs resource rsc defaults resource-stickiness=INFINITY migration-threshold=1
# pcs resource create iptables lsb:iptables op monitor interval="5s"

そのうち"crm"コマンドも復活するのかなー?
--------
http://www.suz-lab..com

HAProxyのログをSyslog(rsyslog)に出力

スズキです。

CentOS6上でHAProxyのログをSyslog(rsyslog)に出力する方法です。

HAProxyはSyslogにログ出力するとき、UDPの514番(Syslogの待受ポート)を
利用するので下記のように、"rsyslog"の設定を変更する必要があります。
# cat /etc/rsyslog.conf
...
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
...
再起動すると有効になります。
# service rsyslog restart
...

HAProxyは下記のようにデフォルトのままでOKです。

"yum"で簡単にインストールできます。
# yum -y install haproxy
...
ログまわりの設定は下記のようになっておりSyslog(local2)に出力されます。
# cat /etc/haproxy/haproxy.cfg
...
global
    log         127.0.0.1 local2
...
HAProxyを起動すると、
# service haproxy start
...
Syslogに下記のように出力されるはずです。
...
Mar 11 09:30:47 localhost.localdomain haproxy[31610]: Proxy main started.
Mar 11 09:30:47 localhost.localdomain haproxy[31610]: Proxy static started.
Mar 11 09:30:47 localhost.localdomain haproxy[31610]: Proxy app started.
...

Syslogに出力できれば、あとはFluentdで自由自在ですね。
--------
http://www.suz-lab.com

2013年3月1日金曜日

最新バージョン以外のGemを削除する(Fluentd)

スズキです。

よく、下記でFluentdで利用しているGemのアップデートをしているのですが、
/usr/lib64/fluent/ruby/bin/gem update
よく見たら、下記のように古いバージョンが、ずっと残っていました。
# ls -1 /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/
aws-sdk-1.7.1
aws-sdk-1.8.1.1
aws-sdk-1.8.2
aws-sdk-1.8.3.1
...
当然、古いバージョンは必要無い(はず?)なので、最新のバージョンのみ残して、
他は削除したいところです。

というのを下記で実現できます。
# yes | /usr/lib64/fluent/ruby/bin/gem cleanup
...
Attempting to uninstall aws-sdk-1.7.1
Successfully uninstalled aws-sdk-1.7.1
Attempting to uninstall aws-sdk-1.8.1.1
Successfully uninstalled aws-sdk-1.8.1.1
Attempting to uninstall aws-sdk-1.8.2
Successfully uninstalled aws-sdk-1.8.2
...

実行すると、次のように最新のバージョンのみ残ります。
# ls -1 /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/
aws-sdk-1.8.3.1
...

ということで、アップデートスクリプトも下記のように修正しました。

suz-lab-centos-ami / bin / update-fluent
#!/bin/sh
set -e
trap 'echo "NG: $?"' ERR
service td-agent stop
/usr/lib64/fluent/ruby/bin/gem update 2>&1 | logger -s -t ${0##*/}
yes | /usr/lib64/fluent/ruby/bin/gem cleanup 2>&1 | logger -s -t ${0##*/}
service td-agent start
exit 0

ちょっとスッキリした...
--------
http://www.suz-lab.com