2013年2月28日木曜日

"Deep Security Manage"にELB経由でアクセス

スズキです。

下記でデータベース側の冗長化ができたので、次は"Deep Security Manager"を冗長化
(Multi-Node)です。
"Deep Security Manager 9.0"のデータベースをRDS(Oracle)にしてみた
しかし現状、"Deep Security Manager"のノード追加に難航しており、先にELBでの
分散を試してみました。


ELBは下記のように作成しています。


"Deep Security Manager"側でELBの情報を入力する必要もあります。

System Settings > Advanced

これでELB経由でも管理画面にアクセスできるようになります。

ちなみに上記の画像から、管理画面だけでなくAgentとHeartbeat通信したり
Relayサーバに接続するポートもロードバランサー経由にすることができそうです。
(その場合は"Internal ELB"を利用する形になると思いますが)

Multi-Node化がよくわからん...
--------
http://www.suz-lab.com

"Deep Security Manager 9.0"のデータベースをRDS(Oracle)にしてみた

スズキです。

下記で"Deep Security Manager 9.0"をインストールしたのですが、
このときはデータベースに組み込みのものを使っていました。
"Deep Security Manager 9.0"をCentOS6にインストールしてみた
"Deep Security Manager"はデータベースにOracleを利用することもでき、
ということなら、RDS(Oracle)でもできるのでは?と試してみました。

といっても実際にやってみると、インストール時に利用するプロパティファイルを、
下記のように変更するだけでした。
# cat dsm.properties
CredentialsScreen.Administrator.Username=testuser
CredentialsScreen.Administrator.Password=TestPass!23
DatabaseScreen.DatabaseType=Oracle
DatabaseScreen.Hostname=dsm.xxx.ap-northeast-1.rds.amazonaws.com
DatabaseScreen.DatabaseName=dsm
DatabaseScreen.Transport=TCP
DatabaseScreen.Username=testuser
DatabaseScreen.Password=TestPass!23
※当然RDS(Oracle)は作成済みです。

"Deep Security Manager"にログインして確認すると、下記のようにデータベースが
RDS(Oracle)になっていることが確認できます。



でも、なぜかMulti-Nodeがうまくいかない...
--------
http://www.suz-lab.com

2013年2月27日水曜日

"Deep Security Manager 9.0"をCentOS6にインストールしてみた

スズキです。

今までWindows環境でしかインストールできなかった"Deep Security Manager"ですが、
下記のように9.0からはLinux(RHEL6)にもインストールできるようになりました。


ということなら、CentOS6でも動きそうなので、インストールしてみました。

"Deep Security Manager"のダウンロードと展開

# curl -OL http://www.trendmicro.com/ftp/products/deepsecurity/Manager-Linux-9.0.4017.x64.zip
...
# unzip Manager-Linux-9.0.4017.x64.zip 
Archive:  Manager-Linux-9.0.4017.x64.zip
  inflating: Manager-Linux-9.0.4017.x64.sh  
  inflating: Relay-RedHat_EL5-9.0.0-883.x86_64.rpm  
  inflating: Relay-RedHat_EL6-9.0.0-883.x86_64.rpm  
# chmod 755 Manager-Linux-9.0.4017.x64.sh

プロパティファイルの用意(インストール時に利用)

# cat dsm.properties 
CredentialsScreen.Administrator.Username=testuser
CredentialsScreen.Administrator.Password=TestPass!23
今回は組み込みデータベースを利用するので、上記程度のプロパティでOKです。

"Deep Security Manager"のインストール

# ./Manager-Linux-9.0.4017.x64.sh -q -console -varfile ./dsm.properties
Unpacking JRE ...
Preparing JRE ...
Starting Installer ...
Stopping Trend Micro Deep Security Manager Service...
Feb 27, 2013 8:00:59 PM java.util.prefs.FileSystemPreferences$2 run
INFO: Created user preferences directory.
Feb 27, 2013 8:00:59 PM java.util.prefs.FileSystemPreferences$3 run
INFO: Created system preferences directory in java.home.
Detecting previous versions of Trend Micro Deep Security Manager...
Upgrade Verification Screen settings accepted...
[WARNING] Deep Security Manager's embedded database is intended for trial and demonstration purposes only.  It is NOT supported for use in production environments.
Database Screen settings accepted...
License Screen settings accepted...
Address And Ports Screen settings accepted...
Credentials Screen settings accepted...
Security Update Screen settings accepted...
Smart Protection Network Screen settings accepted...
All settings accepted, ready to execute...
Extracting files...
Downloading ...
Extracting files...
Setting Up...
Connecting to the Database...
Creating the Database Schema...
Creating testuser Account...
Recording Settings...
Creating Temporary Directory...
Installing Reports...
Installing Modules and Plug-ins...
Creating Help System...
Validating and Applying Activation Codes...
Configure Localizable Settings...
Setting Default Password Policy...
Creating Scheduled Tasks...
Creating Asset Importance Entries...
Creating Auditor Role...
Optimizing...
Importing Software Packages...
Importing Software Package: Relay-RedHat_EL5-9.0.0-883.x86_64.rpm
Importing Software Package: Relay-RedHat_EL6-9.0.0-883.x86_64.rpm
Configuring Relay For Install...
Importing Performance Profiles...
Recording Installation...
Clearing Sessions...
Creating Properties File...
Creating Shortcut...
Configuring SSL...
Configuring Service...
Configuring Java Security...
Configuring Java Logging...
Cleaning Up...
Starting Deep Security Manager...
Finishing installation...

Webインターフェースにログイン




"https://xxx.xxx.xxx.xxx:4119/"にアクセスすれば上記のようにログインできます。

次はデータベースをRDS(Oracle)にしてみます。
--------
http://www.suz-lab.com

"MySQL Proxy"でRDSを中継したときの(RDSの)フェイルオーバー対策

スズキです。

以前、ELBのDNS名に関連づけられているIPアドレスが変更されたときに、HAProxyを
リロードする仕組みを紹介しましたが、
HAProxyをDNS名で指定したバックエンドのIPアドレスが変わったらリロードする
今回は、ほぼ同じことを下記のようなRDS(MySQL)と"MySQL Proxy"で試してみました。
(VPC外からRDSにアクセスする場合に"MySQL Proxy"を中継するケースです)


RDS(MySQL)はDNS名が"suzuki.xxx.ap-northeast-1.rds.amazonaws.com"で
作成済みとします。

"MySQL Proxy"の準備

# yum -y install mysql-proxy
...

# cat /etc/sysconfig/mysql-proxy 
# Options for mysql-proxy 
PROXY_USER="mysql-proxy"
PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog --keepalive --defaults-file=/etc/my.cnf"

# cat /etc/my.cnf 
[mysql-proxy]
proxy-address=:3306
proxy-backend-addresses=suzuki.xxx.ap-northeast-1.rds.amazonaws.com:3306

# diff /etc/init.d/mysql-proxy.bak /etc/init.d/mysql-proxy
23,25d22
< ADMIN_USER="admin"
< ADMIN_PASSWD=""
< ADMIN_LUA_SCRIPT="/usr/lib64/mysql-proxy/lua/admin.lua"
39c36
<     daemon $prog $PROXY_OPTIONS --pid-file=$PROXY_PID --user=$PROXY_USER --admin-username="$ADMIN_USER" --admin-lua-script="$ADMIN_LUA_SCRIPT" --admin-password="$ADMIN_PASSWORD"
---
>     daemon $prog $PROXY_OPTIONS --pid-file=$PROXY_PID --user=$PROXY_USER
何故かADMIN関係の設定が利用できなかったので、デフォルトの
"/etc/sysconfig/mysql-proxy"と"/etc/init.d/mysql-proxy"から
ADMIN関係の記載を外しました。

RDS(MySQL)への接続

# mysql -u suzuki -p -h 127.0.0.1
...
mysql> show databases;
...
5 rows in set (0.01 sec)
127.0.0.1(MySQL Proxy)に接続すると、自動的にRDS(MySQL)に接続されます。

RDSがフェイルオーバーした場合の挙動



上記のようにRDSを手動でフェイルオーバーさせると、"MySQL Proxy"は
下記のように接続できなくなります。
mysql> show databases;
ERROR 2013 (HY000): Lost connection to MySQL server during query

RDSがフェイルオーバーした場合に"MySQL Proxy"をリスタート


基本的には最初に紹介した下記ブログの通りです。
HAProxyをDNS名で指定したバックエンドのIPアドレスが変わったらリロードする
下記のファイル(スクリプト)でMonitによるチェックと再起動を実現しています。
# cat /etc/monit.d/check_dns_ip_rds.conf 
check program check_dns_ip_rds with path "/opt/suz-lab/etc/monit/check_dns_ip_rds.sh"
    if status != 0 then exec "/etc/init.d/mysql-proxy restart"

# cat /opt/suz-lab/etc/monit/check_dns_ip_rds.sh
#!/bin/sh
DNS_NAME=suzuki.xxx.ap-northeast-1.rds.amazonaws.com
set -e
trap 'echo "NG: $?"' ERR
/opt/suz-lab/lib/nagios/check_dns_ip -n $DNS_NAME
exit $?

"MySQL Proxy"の自動リスタート

# cat /var/log/messages
... monit[9138]: 'check_dns_ip_rds' status failed (2) for /opt/suz-lab/etc/monit/check_dns_ip_rds.sh. Error: no output to stderr..
... monit[9138]: 'check_dns_ip_rds' exec: /etc/init.d/mysql-proxy
... mysql-proxy: 2013-02-27 15:12:44: (message) Initiating shutdown, requested from signal handler
... mysql-proxy: 2013-02-27 15:12:44: (message) shutting down normally, exit code is: 0
... mysql-proxy: 2013-02-27 15:12:44: (message) chassis-unix-daemon.c:176: [angel] PID=9206 exited normally with exit-code = 0 (it used 1 kBytes max)
... mysql-proxy: 2013-02-27 15:12:44: (message) Initiating shutdown, requested from mysql-proxy-cli.c:604
... mysql-proxy: 2013-02-27 15:12:44: (message) shutting down normally, exit code is: 0
... mysql-proxy: 2013-02-27 15:12:45: (message) chassis-unix-daemon.c:136: [angel] we try to keep PID=9345 alive
... mysql-proxy: 2013-02-27 15:12:45: (message) mysql-proxy 0.8.2 started
... mysql-proxy: 2013-02-27 15:12:45: (message) proxy listening on port :3306
... mysql-proxy: 2013-02-27 15:12:45: (message) added read/write backend: suzuki.xxx.ap-northeast-1.rds.amazonaws.com:3306
上記よりRDSをフェイルオーバーするとMonitがDNS名に関連づけられたIPアドレスが
変更されたことを検知して、"MySQL Proxy"がリスタートされていることがわかり、
下記のように今まで同様RDS(MySQL)にに接続できることが確認できます。
# mysql -u suzuki -p -h 127.0.0.1
...
mysql> show databases;
...
5 rows in set (0.01 sec)

RDSのフェイルオーバーは要注意です...
--------
http://www.suz-lab.com

2013年2月26日火曜日

1つEC2の2つのENIの4つのEIPと通信できるようにしてみた

スズキです。

今までENIを複数アタッチした場合のルーティングがよくわからず、複数のIPが必要な場合は、
下記のようにENIを複数アタッチするのではなく、同じENIの"Secondary IP"などを利用するようにしていました。
ENIに"Secondary IP"をつけてCentOS(6)で利用
しかし、このまま、よくわからない状態ではだめだなー、思っていたところ、
@j3tm0t0さんが、下記の素晴らしいブログを記事を書いてくれました!
もう一度ENIについて考えてみた(Linux編)
このブログを読むことで、複数ENIのルーティングの問題、それを解決するための
"Policy Based Routing"がわかると思います。

上記のブログでは、各ENIが別々のサブネットに接続されていましたが、今回は、
一つのサブネットに二つのENI、そして各ENIに二つのIP(EIPも)を付けて、
下記のように4つすべてのEIPに対して、通信できるようにしてみます。


実際のENIやIPの設定は下記のような感じです。(セキュリティグループの設定も忘れずに!)




CentOS6上のネットワーク設定は下記の通りです。
# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=on

# cat /etc/sysconfig/network-scripts/ifcfg-eth0:0
DEVICE=eth0:0
ONBOOT=yes
BOOTPROTO=static
NETADDR=10.0.0.0
NETMASK=255.255.255.0
IPADDR=10.0.0.22

# cat /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=on
DEFROUTE=no

# cat /etc/sysconfig/network-scripts/ifcfg-eth1:0
DEVICE=eth1:0
ONBOOT=yes
BOOTPROTO=static
NETADDR=10.0.0.0
NETMASK=255.255.255.0
IPADDR=10.0.0.24
この状態で、上記の4つのEIPにPingを打つと下記のような結果になりました。
$ ping 54.aaa.aaa.aaa
PING 54.aaa.aaa.aaa (54.aaa.aaa.aaa): 56 data bytes
64 bytes from 54.249.41.77: icmp_seq=0 ttl=53 time=22.453 ms

$ ping 54.bbb.bbb.bbb
PING 54.bbb.bbb.bbb (54.bbb.bbb.bbb): 56 data bytes
64 bytes from 54.249.41.71: icmp_seq=0 ttl=52 time=5.440 ms

$ ping 54.ccc.ccc.ccc
PING 54.ccc.ccc.ccc (54.ccc.ccc.ccc): 56 data bytes
Request timeout for icmp_seq 0

$ ping 54.ddd.ddd.ddd
PING 54.ddd.ddd.ddd (54.ddd.ddd.ddd): 56 data bytes
Request timeout for icmp_seq 0
"eth1"の設定に"DEFROUTE=no"をいれているため、デフォルトルートが"eth0"のままで、
"eth1"への通信が返れず、"eth1"に付けた2つのEIPへのPingも返っていない状態です。
(ちなみにルーティングは下記のようになっています)
# netstat -nr
Kernel IP routing table
Destination   Gateway       Genmask       Flags MSS Window irtt Iface
10.0.0.0      0.0.0.0       255.255.255.0 U       0 0         0 eth0
10.0.0.0      0.0.0.0       255.255.255.0 U       0 0         0 eth1
169.254.0.0   0.0.0.0       255.255.0.0   U       0 0         0 eth0
169.254.0.0   0.0.0.0       255.255.0.0   U       0 0         0 eth1
0.0.0.0       10.0.0.1      0.0.0.0       UG      0 0         0 eth0

ここで"Policy Based Routing"です!

現状のルールは、こんな感じです。
# ip rule show
0: from all lookup local 
32766: from all lookup main 
32767: from all lookup default 

下記のように設定します。
# ip rule add from 10.0.0.21 table 1021 prio 1021
# ip route add table 1021 default via 10.0.0.1 dev eth0

# ip rule add from 10.0.0.22 table 1022 prio 1022
# ip route add table 1022 default via 10.0.0.1 dev eth0

# ip rule add from 10.0.0.23 table 1023 prio 1023
# ip route add table 1023 default via 10.0.0.1 dev eth1

# ip rule add from 10.0.0.24 table 1024 prio 1024
# ip route add table 1024 default via 10.0.0.1 dev eth1
上記は例えば、10.0.0.24からの通信は"eth1"を使ってデフォルトルートが
10.0.0.1に行くようにしています、それが、他の10.0.0.21,10.0.0.22,10.0.0.23
に対しても同様に行っています。

するとルールは、こんな感じになります。
# ip rule show
0: from all lookup local 
1021: from 10.0.0.21 lookup 1021 
1022: from 10.0.0.22 lookup 1022 
1023: from 10.0.0.23 lookup 1023 
1024: from 10.0.0.24 lookup 1024 
32766: from all lookup main 
32767: from all lookup default 

この状態で実際に最初と同じようにPingを打ってみると、下記のように、今度はすべての
EIPに対して通信することができました。
$ ping 54.aaa.aaa.aaa
PING 54.aaa.aaa.aaa (54.aaa.aaa.aaa): 56 data bytes
64 bytes from 54.aaa.aaa.aaa: icmp_seq=0 ttl=53 time=5.869 ms

$ ping 54.bbb.bbb.bbb
PING 54.bbb.bbb.bbb (54.bbb.bbb.bbb): 56 data bytes
64 bytes from 54.bbb.bbb.bbb: icmp_seq=0 ttl=52 time=5.997 ms

$ ping 54.ccc.ccc.ccc
PING 54.ccc.ccc.ccc (54.ccc.ccc.ccc): 56 data bytes
64 bytes from 54.249.45.44: icmp_seq=0 ttl=53 time=5.857 ms

$ ping 54.ddd.ddd.ddd
PING 54.ddd.ddd.ddd (54.ddd.ddd.ddd): 56 data bytes
64 bytes from 54.ddd.ddd.ddd: icmp_seq=0 ttl=52 time=5.799 ms

これをENIを勝手に認識して、自動で設定できるようにしたい...
--------
http://www.suz-lab.com

ElastiCacheの"Configuration Endpoint"の実体

スズキです。

ElastiCacheの"Cache Cluster"を作成すると、下記のように"Configuration Endpoint"が
利用できます。


この"Configuration Endpoint"を名前解決してみたら下記のようになりました。
# dig +noall +answer test.xxxxxx.cfg.apne1.cache.amazonaws.com
test.xxxxxx.cfg.apne1.cache.amazonaws.com. 60 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-54-249-151-184.ap-northeast-1.compute.amazonaws.com. 60 IN A yyy.yyy.15.105

実はこのIPアドレスは、下記のような"Cache Node"のIPアドレスでした。

# dig +noall +answer test.xxxxxx.0001.apne1.cache.amazonaws.com
test.xxxxxx.0001.apne1.cache.amazonaws.com. 60 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 60 IN A yyy.yyy.15.105

ただ"Cache Node"は複数あるので、どのノードが割り当てられているのか、いろいろと
確認してみたところ、下記のようにDNSのTTLが切れたら、他のノードに変わるような
挙動をしていました。
# dig +noall +answer test.xxxxxx.cfg.apne1.cache.amazonaws.com
test.xxxxxx.cfg.apne1.cache.amazonaws.com. 2 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 2  IN A yyy.yyy.16.246
# dig +noall +answer test.xxxxxx.cfg.apne1.cache.amazonaws.com
test.xxxxxx.cfg.apne1.cache.amazonaws.com. 1 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 1  IN A yyy.yyy.16.246
# dig +noall +answer test.xxxxxx.cfg.apne1.cache.amazonaws.com
test.xxxxxx.cfg.apne1.cache.amazonaws.com. 60 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 60 IN A yyy.yyy.15.105
# dig +noall +answer test.xxxxxx.cfg.apne1.cache.amazonaws.com
test.xxxxxx.cfg.apne1.cache.amazonaws.com. 59 IN CNAME ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com.
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com. 59 IN A yyy.yyy.15.105

というのが下記のドキュメントに、なんとなく書かれていました。
Connecting to Cache Nodes

The application resolves the configuration endpoint's DNS name.
Because the configuration endpoint maintains CNAME entries
for all of the cache nodes, the DNS name resolves to one of the nodes;
the client can then connect to that node.

なので"Configuration Endpoint"に向かってデータのGET/PUTはできちゃうのですが...
--------
http://www.suz-lab.com

2013年2月22日金曜日

スナップショットのリージョン間コピー機能を使ってWindowsのEC2インスタンスを他リージョンに移行

スズキです。

実は今までスナップショットのリージョン間コピー機能を利用したことが
なかったのですが、この機能を使って東京リージョンのEC2インスタンス
(Windows)を、シンガポールリージョンに移行してみました。

シンガポールリージョンのEC2(Windows)は、スナップショットからAMIを
作成するのではなく、下記のようにCドライブの差し替えで実現しています。
WindowsのEC2でCドライブのサイズを増やす

東京リージョンでの作業


下記のAMIでEC2を起動します。


起動したEC2を確認します。


EBSからスナップショットを作成。


スナップショットをコピーします。


別リージョン(シンガポール)にコピーします。


シンガポールリージョンでの作業


下記のAMIでEC2を起動します。


起動したEC2を停止します。


EBSをEC2からデタッチします。


デタッチしたEBSを確認します。


東京リージョンからコピーされたスナップショットを確認します。


スナップショットからEBSを作成します。


作成されたEBSをEC2にアタッチします。


デバイスは"/dev/sda1"にします。


アタッチされたEBSを確認します。


EC2をStopがらStartします。


これでスナップショットのリージョン間コピーの機能を使って、東京リージョンの
EC2(Windows)をシンガポールリージョンに移行することができました。
(リモートデスクトップで同じアカウントでログインできるはずです)

昔はもっと大変だったんだけど...
--------
http://www.suz-lab.com

2013年2月20日水曜日

Moxi起動時に"Auto Discovery"でElastiCacheのクラスタ内のノードを自動的に登録してみた

スズキです。

下記でMoxiでElastiCacheのノードをまとめるところまでできたので、
MoxiでElastiCacheのノードをまとめてみた
下記の"Auto Discovery"と組み合わせて、
ElastiCacheのクラスタ情報を取得してみた(Auto Discovery)
Moxi起動時にクラスタ内のすべてのノードが対象になるような起動スクリプトを
作ってみました。

実際のスクリプトは少し長いので最後に掲載することとして、まずは挙動の確認です。

Moxiを起動して登録してあるElastiCacheノードを確認
# service moxi-elasticache start
Starting moxi server                                       [  OK  ]
# echo stats proxy config | nc localhost 11211
STAT 11211:default:config test.xxxxxx.0001.apne1.cache.amazonaws.com:11211,test.xxxxxx.0002.apne1.cache.amazonaws.com:11211,test.xxxxxx.0003.apne1.cache.amazonaws.com:11211
END
いくつか登録されています。

ElastiCacheのノードを追加してMoxiをリスタートして登録ノードの確認
# service moxi-elasticache restart
Stopping moxi server                                       [  OK  ]
Starting moxi server                                       [  OK  ]
# echo stats proxy config | nc localhost 11211
STAT 11211:default:config test.xxxxxx.0001.apne1.cache.amazonaws.com:11211,test.xxxxxx.0002.apne1.cache.amazonaws.com:11211,test.xxxxxx.0003.apne1.cache.amazonaws.com:11211,test.xxxxxx.0004.apne1.cache.amazonaws.com:11211
END
ちゃんと増えてます。

ElastiCacheのノードを削除してMoxiをリスタートして登録ノードの確認
# service moxi-elasticache restart
Stopping moxi server                                       [  OK  ]
Starting moxi server                                       [  OK  ]
# echo stats proxy config | nc localhost 11211
STAT 11211:default:config test.xxxxxx.0001.apne1.cache.amazonaws.com:11211
END
ちゃんと減ってます。

ということで実際のスクリプトです。
# cat /etc/sysconfig/moxi-elasticache 
MOXI_PORT=11211
ELASTICACHE_CONFIG_NODE=test.xxxxxx.cfg.apne1.cache.amazonaws.com
ELASTICACHE_CONFIG_PORT=11211
# cat /etc/init.d/moxi-elasticache 
#!/bin/sh

# Source Function Library
. /etc/init.d/functions

# System Variable
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DAEMON=/opt/moxi/bin/moxi
PIDFILE=/var/run/moxi-server.pid

# User Variavle
MOXI_PORT=11211
ELASTICACHE_CONFIG_NODE=localhost
ELASTICACHE_CONFIG_PORT=11211

# Source Config
if [ -f /etc/sysconfig/${0##*/} ] ; then
    . /etc/sysconfig/${0##*/}
fi

MOXI_CLUSTER_CFG=$MOXI_PORT=

test -f $DAEMON || exit 0

discover() {
    LINE=`echo config get cluster | nc $ELASTICACHE_CONFIG_NODE $ELASTICACHE_CONFIG_PORT | head -3 | tail -1`
    COUNT=`echo $LINE | tr -dc ' ' | wc -c`
    COUNT=`expr $COUNT + 1`
    for INDEX in `seq 1 $COUNT`; do
        NODE=`echo $LINE | cut -d ' ' -f $INDEX`
        HOST=`echo $NODE | cut -d '|' -f 1`
        PORT=`echo $NODE | cut -d '|' -f 3`
        if [ $INDEX -ne 1 ]; then
            MOXI_CLUSTER_CFG=$MOXI_CLUSTER_CFG,
        fi
        MOXI_CLUSTER_CFG=$MOXI_CLUSTER_CFG$HOST:$PORT
    done
}

start() {
    touch $PIDFILE
    chown moxi $PIDFILE
    cd /var/run
    ulimit -n 10240
    ulimit -c unlimited
    discover
    daemon "/bin/su -c \"$DAEMON -d -P $PIDFILE -z $MOXI_CLUSTER_CFG\" moxi"
    errcode=$?
    return $errcode
}

stop() {
    killproc -p $PIDFILE $DAEMON
    errcode=$?
    rm -f $PIDFILE
    return $errcode
}

running() {
    pidofproc -p $PIDFILE $DAEMON >/dev/null
    errcode=$?
    return $errcode
}

case $1 in
    start)
        if running ; then
            warning && echo "moxi server is already started"
            exit 0
        fi
        echo -n $"Starting moxi server"
        start
        echo
        ;;
    stop)
        echo -n $"Stopping moxi server"
        stop
        echo
        ;;
    restart)
        echo -n $"Stopping moxi server"
        stop
        echo
        echo -n $"Starting moxi server"
        start
        echo
        ;;
    status)
        if running ; then
            echo "moxi server is running"
            exit 0
        else
            echo "moxi server is not running"
            exit 3
        fi
        ;;
    *)
        echo "Usage: /etc/init.d/moxi-server {start|stop|restart|status}" >&2
        exit 3
esac

複数クラスタにも対応したい...
--------
http://www.suz-lab.com

MoxiでElastiCacheのノードをまとめてみた

スズキです。

以前、TwemproxyでElastiCacheのノードをまとめてみたのですが、
TwemproxyからElastiCacheに分散(同じキーは同じElastiCacheへ)してみる

今回はmoxiでまとめて見ました。
Moxi Server 1.8

インストール

# rpm -Uvh http://packages.couchbase.com/releases/1.8.1/moxi-server_x86_64_1.8.1.rpm

初期起動(/etc/init.d/moxi-server)スクリプトの調整

# diff /etc/init.d/moxi-server /etc/init.d/moxi-server.bak 
30,35c30
< MOXI_CLUSTER_CFG="11211=localhost:11211"
< 
< # Source Config
< if [ -f /etc/sysconfig/${0##*/} ] ; then
<     . /etc/sysconfig/${0##*/}
< fi
---
> MOXI_CLUSTER_CFG=/opt/moxi/etc/moxi-cluster.cfg
37a33,34
> test -f $MOXI_CFG || exit 0
> test -f $MOXI_CLUSTER_CFG || exit 0
45c42
<     daemon "/bin/su -c \"$DAEMON -d -P $PIDFILE -z $MOXI_CLUSTER_CFG\" moxi"
---
>     daemon "/bin/su -c \"$DAEMON -d -P $PIDFILE -Z $MOXI_CFG -z $MOXI_CLUSTER_CFG\" moxi"

対象ノード(ElastiCache)の設定

# cat /etc/sysconfig/moxi-server
MOXI_CLUSTER_CFG="11211=test.xxxxxx.0001.apne1.cache.amazonaws.com:11211,test.xxxxxx.0002.apne1.cache.amazonaws.com:11211"

Moxiの起動

# service moxi-server start
Starting moxi server                                       [  OK  ]

設定内容の確認

# echo stats proxy config | nc localhost 11211
STAT 11211:default:config test.bia10i.0001.apne1.cache.amazonaws.com:11211,test.bia10i.0002.apne1.cache.amazonaws.com:11211
END
確かTwenproxyではIPアドレスでの登録になってしまい、DNS名でエンドポイントが
提供されるElastiCacheでは、相性はよくないかなーと思っていたのですが、Moxiだと
上記の通りDNS名での登録もOKなので、そうなるとMoxiの方がいいかも知れません。
(あまり検証はしていませんが...)

データの登録

# echo -e 'set mykey 0 60 5\r\nhello\r' | nc localhost 11211
STORED

データの取得

# echo -e 'get mykey\r' | nc localhost 11211
VALUE mykey 0 5
hello
END
# echo -e 'get mykey\r' | nc localhost 11211
VALUE mykey 0 5
hello
END
# echo -e 'get mykey\r' | nc localhost 11211
VALUE mykey 0 5
hello
END
# echo -e 'get mykey\r' | nc localhost 11211
VALUE mykey 0 5
hello
END
# echo -e 'get mykey\r' | nc localhost 11211
VALUE mykey 0 5
hello
END
上記より、同じキーなら同じノードから取得していることがわかります。
下記にも「"ketama"ですよ」って書いてありました。
Chapter 4. Moxi with Memcached

When used with standard, classic memcached, Moxi should be
started with different command-line parameters that will make
Moxi use libmemcached (ketama) hashing.

"Auto Discovery"関係で、もう少し、いろいろやってみよう。
--------
http://www.suz-lab.com

2013年2月19日火曜日

ElastiCacheのクラスタ情報を取得してみた(Auto Discovery)

スズキです。

ElastiCacheを作成すると、"Configuration Endpoint"というものが利用でき、
"Auto Discovery"で利用するElastiCacheのクラスタ情報を取得することができます。


情報は下記のように"config get cluster"で取得することができます。
# telnet test.xxxxxx.cfg.apne1.cache.amazonaws.com 11211
Trying xxx.xxx.xxx.xxx...
Connected to test.xxxxxx.cfg.apne1.cache.amazonaws.com.
Escape character is '^]'.
config get cluster
CONFIG cluster 0 191
2
test.xxxxxx.0001.apne1.cache.amazonaws.com|10.156.25.174|11211 test.xxxxxx.0002.apne1.cache.amazonaws.com|10.158.181.191|11211

END
quit
Connection closed by foreign host.

上記の情報からノードやポートの情報を切り出すシェルスクリプトを作ってみました。
#!/bin/sh
CONFIG_NODE=test.xxxxxx.cfg.apne1.cache.amazonaws.com
CONFIG_PORT=11211
LINE=`echo config get cluster | nc $CONFIG_NODE $CONFIG_PORT | head -3 | tail -1`
COUNT=`echo $LINE | tr -dc ' ' | wc -c`
COUNT=`expr $COUNT + 1`
for INDEX in `seq 1 $COUNT`; do
    NODE=`echo $LINE | cut -d ' ' -f $INDEX`
    HOST=`echo $NODE | cut -d '|' -f 1`
    PORT=`echo $NODE | cut -d '|' -f 3`
    echo $HOST $PORT
done
※下記でインストールした"netcat(nc)"を利用しています。
# yum -y install nc
...

実行すると下記のようにノード情報を切り出すことができます。
# ./test.sh 
test.xxxxxx.0001.apne1.cache.amazonaws.com 11211
test.xxxxxx.0002.apne1.cache.amazonaws.com 11211

ElastiCacheのノードを追加して、もう一回実行すると、ちゃんと増えています。
# ./test.sh 
test.xxxxxx.0001.apne1.cache.amazonaws.com 11211
test.xxxxxx.0002.apne1.cache.amazonaws.com 11211
test.xxxxxx.0003.apne1.cache.amazonaws.com 11211

シェルスクリプトは深い...
--------
http://www.suz-lab.com

2013年2月18日月曜日

CentOS6でのPython版AWSコマンドラインツールの環境設定(/etc/profile.d/awscli.sh)

スズキです。

以前、下記で環境設定(/etc/profile.d/awscli.sh)まで紹介していたのですが、
Python版AWSコマンドラインツールをCentOS6で使ってみた
そのときは、なぜか環境変数AWS_DEFAULT_REGIONがきかず、設定から
外していたのですが、適当にPython版コマンドラインツールをアップデートしてたら、
知らないうちにきくようになっていたので、アップデートとして紹介(メモ)しておきます。
# cat /etc/profile.d/awscli.sh
# awscli initialization script (sh)
if [ -x /usr/bin/aws ]; then
    AZ=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
    export AWS_DEFAULT_REGION=`echo $AZ | cut -c 1-$((${#AZ} - 1))`
    complete -C aws_completer aws
fi
今までは補完の部分(complete ...)だけでしたが、今回からリージョンも勝手に
設定(export ...)してくれます。

この辺を反映したAMIを早くリリースしなくては...
--------
http://www.suz-lab.com

シェルスクリプトでリトライ処理

スズキです。

下記のように作ってみました。("sub.sh"がリトライ対象です)
# cat test.sh 
#/bin/sh
trap 'echo "NG: $?"' ERR
set -e
# ...

RETRY_COUNT=5
RETRY_INTERVAL=1
set +e
COUNT=0
while true; do
    /root/sub.sh
    if [ $? -eq 0 ]; then
        break
    fi
    if [ $COUNT -eq $RETRY_COUNT ]; then
        echo "Timeout!" >&2
        exit 1
    fi
    COUNT=`expr $COUNT + 1`
    sleep $RETRY_INTERVAL
done

set -e
# ...
exit 0

呼び出しているスクリプトを下記のよう(正常終了)にすると、
# cat sub.sh 
#!/bin/sh
echo test
exit 0
すぐに(正常)終了します。
# ./test.sh 
test

逆に下記のように(異常終了)にすると、
# cat sub.sh 
#!/bin/sh
echo test
exit 1
指定時間(RETRY_INTERVAL:1秒)のインターバルをおいて、
指定回数(RETRY_COUNT:5回)のリトライ後、タイムアウトで(異常)終了します。
# ./test.sh 
test
NG: 1
test
NG: 1
test
NG: 1
test
NG: 1
test
NG: 1
test
NG: 1
Timeout!

これで、毎回ググらなくてもいいかも。
--------
http://www.suz-lab.com

2013年2月15日金曜日

"phpLDAPadmin"でユーザーを作ったユーザーでCentOSにログイン

スズキです。

下記で"phpLDAPadmin"をインストールできたので、次は、実際にアカウントを作成して、
CentOS6に"phpLDAPadmin"をインストール
SSHなどで、そのアカウントでログインしてみます。

グループの作成







ユーザーの作成








SUやSSHでの確認


LDAP認証を利用してCentOSにSUやSSHを行う方法は下記で紹介しています。
CentOS6.2のログインユーザー(認証)をOpenLDAPで管理(SSH編)
実際に下記のように"phpLDAPadmin"で作成したユーザーでログインすることができました。
$ su - suzuki
パスワード:
# ssh -l suzuki localhost
suzuki@localhost's password: 
Last login: Fri Feb 15 16:05:23 2013 from 127.0.0.1

"phpLDAPadmin"はもう少し、いろいろといじってみよう。
--------
http://www.suz-lab.com

2013年2月14日木曜日

CentOS6に"phpLDAPadmin"をインストール

スズキです。

OpenLDAPでログインアカウントを管理するときに、その追加/変更/削除は、
やはり"コマンドライン"ではなく、"Web UI"でやってもらいたいので、
下記の"phpLDAPadmin"を試してみました。


OpenLDAPに関しては下記の"schema.ldif"の登録まで実施していることとします。
CentOS6.2のログインユーザー(認証)をOpenLDAPで管理(OpenLDAP編)

インストールは下記のように"yum"で簡単にできます。
# yum -y install httpd phpldapadmin
...

Apacheの設定ファイルは下記のようにしておきます。(セキュリティはしっかりと...)
# cat /etc/httpd/conf.d/phpldapadmin.conf 
Alias /phpldapadmin /usr/share/phpldapadmin/htdocs
Alias /ldapadmin /usr/share/phpldapadmin/htdocs
<Directory /usr/share/phpldapadmin/htdocs>
    Order Deny,Allow
    Deny  from all
    Allow from all
</Directory>

"phpLDAPadmin"の設定は下記のように調整しておきます。
# cat /usr/share/phpldapadmin/config/config.php
...
$servers->setValue('login','fallback_dn',true);
...

この状態でApacheを再起動すると、下記のようにWebでアクセスでき、
ログインも可能です。


次は実際にグループやユーザーを作成し、CentOSにログインできるようにしてみます。

"Web UI"なら、誰でもできるだろう...
--------
http://www.suz-lab.com

"iptables, ntpd, postfix, openldap, phpldapadmin"をインストールした冗長化されたNATインスタンスを作るメモ

スズキです。

NATインスタンスに、いろいろ(iptables, ntpd, postfix, openldap, phpldapadmin)
を入れて、万能共通管理サーバ(?)っぽいものを作る必要があったので、構築方法を、
今までのブログ記事を参照する形で、まとめてみました。


"High Availability NAT"の構築


NATインスタンスの構築は下記参照。
CloutInitでNATインスタンス(iptables)を構築
"High Availability NAT"化は下記参照。
"High Availability NAT"の作成(CentOS6)

"ntpd"の設定


"ntpd"の設定と参照EC2に対する"DHCP Options"の設定は下記参照。
VPCの"DHCP Options Set"でNTPサーバを指定する

"postfix"の設定


他のサーバからのリレー設定は下記参照。(オープンリレーにならないように注意!)
Postfixをlocalhost以外からも利用できるように

OpenLDAPの構築


OpenLDAPを利用してSSHログインできる設定は下記参照。
CentOS6.2のログインユーザー(認証)をOpenLDAPで管理(SSH編)

冗長化に関しては下記参照。
ログインユーザー(認証)をOpenLDAPで管理(冗長化編)

"phpldapadmin"は、これからやります...
--------
http://www.suz-lab.com

2013年2月12日火曜日

Fluentdの既存のプラグインを継承してメソッドをオーバーライドして使ってみた

スズキです。

Fluentdで既存の(Gemでインストールした)プラグインを少し改造して使う(簡単な)方法です。
(Fluentdは下記の方法でインストールされているとします)
CentOS6にFluentdをインストール
ポイントは以下に示した感じでしょうか?
  • 継承したクラス(ファイル)は"/etc/td-agent/plugin"に配置
    • ファイル名はプラグインのファイル名のルール通り
  • 継承するプラグイン(クラス)のファイルを"require"する
ということで、"fluent-plugin-datacounter"の挙動を、キリのいい時刻
(1分間隔の出力なら"hh::mm::00"でログ出力)でログ出力
("watch"メソッドをオーバーライド)するようにしてみました。
# cat /etc/td-agent/plugin/out_datacounter_ex.rb
module Fluent
    require 'fluent/plugin/out_datacounter'

    class DataCounterExOutput < DataCounterOutput
        Plugin.register_output('datacounter_ex', self)

        def watch
            @last_checked = Fluent::Engine.now
            while true
                sleep 0.5
                if Engine.now != @last_checked && Engine.now % @tick == 0
                    now = Engine.now
                    flush_emit(now - @last_checked)
                    @last_checked = now
                end
            end
        end

    end

end
オーバーライドした親のメソッドは下記の通りです。
def watch
    # instance variable, and public accessable, for test
    @last_checked = Fluent::Engine.now
    while true
        sleep 0.5
        if Fluent::Engine.now - @last_checked >= @tick
            now = Fluent::Engine.now
            flush_emit(now - @last_checked)
            @last_checked = now
        end
    end
end
当然、設定ファイルの修正(特に"type")も必要です。
cat /etc/td-agent/td-agent.conf
...
type      datacounter_ex
unit      minute
aggregate all
count_key ident
pattern1  history ^-bash$
pattern2  audit   ^audispd$
tag       datacounter.syslog
...
Fluentd(td-agent)を再起動すると、下記のように変更した挙動
(キリのいい時刻"hh:mm:00"でログ出力)で動作することが確認できます。
# tail /tmp/datacounter.syslog.20130212.b4d585c76d5883b21
...
2013-02-12T22:46:00+09:00 datacounter.syslog {"unmatched_count":3,"unmatched_rate":0.05,"unmatched_percentage":37.5,"history_count":0,"history_rate":0.0,"history_percentage":0.0,"audit_count":5,"audit_rate":0.08,"audit_percentage":62.5}
2013-02-12T22:47:00+09:00 datacounter.syslog {"unmatched_count":3,"unmatched_rate":0.05,"unmatched_percentage":37.5,"history_count":0,"history_rate":0.0,"history_percentage":0.0,"audit_count":5,"audit_rate":0.08,"audit_percentage":62.5}
2013-02-12T22:48:00+09:00 datacounter.syslog {"unmatched_count":3,"unmatched_rate":0.05,"unmatched_percentage":37.5,"history_count":0,"history_rate":0.0,"history_percentage":0.0,"audit_count":5,"audit_rate":0.08,"audit_percentage":62.5}
といっても1分間隔でしかテストしてないので、他の間隔だとおかしな挙動になってしまう
可能性は十分にあります...とりあえず、やり方としてのメモです。

だいぶRuby覚えてきた...
--------
http://www.suz-lab.com

CentOS6(EC2)で"MySQL Cluster"を試してみる(複数サーバ編)

スズキです。

下記で単一のサーバでの稼働が確認できたので、
CentOS6で"MySQL Cluster"を試してみる(単一サーバ編)
いよいよ、下記のような複数サーバ(EC2 x 2)での確認です。


各種プロセス(mysqld, ndbd, ndb_mgmd)の停止(両EC2で)

# /etc/init.d/mysql stop
Shutting down MySQL... SUCCESS! 
# killall ndbd 
# killall ndb_mgmd 

Hostsファイルに各ノードを登録(両EC2で)

# cat /etc/hosts
...
10.160.102.121  mgmd-1 ndbd-1 mysqld-1
10.150.174.36   mgmd-2 ndbd-2 mysqld-2

設定ファイルの調整(両EC2で)

# /etc/my.cnf
...
[mysqld]
ndbcluster

[mysql_cluster]
ndb_connectstring=mgmd-1;mgmd-2

[ndb_mgmd]
config_file=/var/lib/ndb/config.ini
config_dir=/var/lib/ndb
initial

[ndbd]
initial
# cat /var/lib/ndb/config.ini 
[ndb_mgmd default]
datadir=/var/lib/ndb

[ndb_mgmd]
hostname=mgmd-1
NodeId=1

[ndb_mgmd]
hostname=mgmd-2
NodeId=2

[ndbd default]
noofreplicas=2
datadir=/var/lib/ndb

[ndbd]
hostname=ndbd-1
NodeId=11

[ndbd]
hostname=ndbd-2
NodeId=12


[mysqld]
hostname=mysqld-1
NodeId=21

[mysqld]
hostname=mysqld-2
NodeId=22

各プロセスの起動(両EC2で)

# ndb_mgmd
MySQL Cluster Management Server mysql-5.5.29 ndb-7.2.10
# ndbd 
2013-02-12 01:07:50 [ndbd] INFO     -- Angel connected to 'mgmd-1:1186;mgmd-2:1186'
2013-02-12 01:07:50 [ndbd] INFO     -- Angel allocated nodeid: 11
# service mysql start
Starting MySQL.... SUCCESS! 
※"allocated nodeid: 11"はもう一つのEC2では"12"となります。

各ノードの状態確認

# ndb_mgm -e show
Connected to Management Server at: mgmd-1:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=11 @10.160.102.121  (mysql-5.5.29 ndb-7.2.10, Nodegroup: 0)
id=12 @10.150.174.36  (mysql-5.5.29 ndb-7.2.10, Nodegroup: 0, Master)
[ndb_mgmd(MGM)] 2 node(s)
id=1 @10.160.102.121  (mysql-5.5.29 ndb-7.2.10)
id=2 @10.150.174.36  (mysql-5.5.29 ndb-7.2.10)
[mysqld(API)] 2 node(s)
id=21 @10.160.102.121  (mysql-5.5.29 ndb-7.2.10)
id=22 @10.150.174.36  (mysql-5.5.29 ndb-7.2.10)

最後に、適当にテーブル作ったり、データ登録したり抽出したりして、
ちゃんと動作してることも確認できると思います。

ということで、AWS上でもいけそうです。
--------
http://www.suz-lab.com