ラベル ec2 の投稿を表示しています。 すべての投稿を表示
ラベル ec2 の投稿を表示しています。 すべての投稿を表示

2013年4月1日月曜日

EC2ってなんじゃ?(CentOSでSSDインスタンス)

USリージョンにはSSDインスタンスというものがあって、「ハイ I/O クワドラプル エクストラ ラージ」というすごい名前で、hi1.4xlargeというタイプのようです。

QuickStartのAMI一覧でこのインスタンスタイプを使用できるのは、Cluster系のAMIのみのようです。


AMIによって選択できるできないの違いを調べてみると、通常のAMIはXenにおける、Para-Virtualization(準仮想化)という形式、hi1.4xlargeやその他のクラスタコンピューティング用のAMIはHVM(完全仮想化)という形式で、この2つはゲストOSの扱いが異なり、それにともなってAMIの作りも違うようです。

AMIの仮想化方式はインスタンス一覧に表示されている、この部分です。



通常のparavirtualのAMIを起動しようとすると、、


hi1.4xlargeは見つかりません。

なので、たとえばhi1.4xlargeのCentOSを立ち上げようと思ったら、通常のparavirtualのAMIではなくHVMのAMIを使う必要があります。

現在使用できるHVMのCentOSのAMIは以下が使用可能です。
https://aws.amazon.com/amis/centos-6-3-x86-64-hvm


このAMIを起動すると、



選択肢にhi1.4xlargeが出てきます。
これを選択していくと、SSDがエフェメラルディスクとして追加されるのがわかります。



このようにHVMのAMIを使用するとSSDインスタンスを作れるようです。

今回は以上です。



2013年3月9日土曜日

Cassandraってなんじゃ?(CQL)

CassandraにはCQLというSQLライクに問い合わせるインターフェースが用意されています。
いままでのスクリプト風の問い合わせよりも多くの人に馴染みやすいと思うので、ちょっと触ってみます。



CQLコンソール


CQLのインターフェースはいままでのcassandra-cliとは別に、binディレクトリにあるcqlshコマンドを使用します。
まずhelpを見てみます。

# /usr/local/cassandra/bin/cqlsh --help
Usage: cqlsh [options] [host [port]]

CQL Shell for Apache Cassandra

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -C, --color           Always use color output
  --no-color            Never use color output
  -u USERNAME, --username=USERNAME
                        Authenticate as user.
  -p PASSWORD, --password=PASSWORD
                        Authenticate using password.
  -k KEYSPACE, --keyspace=KEYSPACE
                        Authenticate to the given keyspace.
  -f FILE, --file=FILE  Execute commands from FILE, then exit
  -t TRANSPORT_FACTORY, --transport-factory=TRANSPORT_FACTORY
                        Use the provided Thrift transport factory function.
  --debug               Show additional debugging information
  --cqlversion=CQLVERSION
                        Specify a particular CQL version (default: 3).
                        Examples: "2", "3.0.0-beta1"
  -2, --cql2            Shortcut notation for --cqlversion=2
  -3, --cql3            Shortcut notation for --cqlversion=3

Connects to localhost:9160 by default. These defaults can be changed by
setting $CQLSH_HOST and/or $CQLSH_PORT. When a host (and optional port number)
are given on the command line, they take precedence over any defaults.


-2や-3とオプションを渡すと指定されたバージョンのCQLを使用します。
ここではバージョン2を指定してみます。
# /usr/local/cassandra/bin/cqlsh -2

Connected to Memorycraft Cluster at localhost:9160.
[cqlsh 2.3.0 | Cassandra 0.0.0 | CQL spec 2.0.0 | Thrift protocol 19.35.0]
Use HELP for help.
cqlsh>


このようにSQLクライアント風のコンソールが開始されます。
コンソール上でもう一度helpを打ってみます。
cqlsh:Hogebook> help

Documented shell commands:
===========================
ASSUME   CONSISTENCY  DESC      EXIT  SHOW    TRACING
CAPTURE  COPY         DESCRIBE  HELP  SOURCE

CQL help topics:
================
ALTER                        CREATE_KEYSPACE       SELECT_EXPR    
ALTER_ADD                    CREATE_TABLE          SELECT_LIMIT   
ALTER_ALTER                  CREATE_TABLE_OPTIONS  SELECT_TABLE   
ALTER_DROP                   CREATE_TABLE_TYPES    SELECT_WHERE   
ALTER_WITH                   DELETE                TEXT_OUTPUT    
APPLY                        DELETE_COLUMNS        TIMESTAMP_INPUT
ASCII_OUTPUT                 DELETE_USING          TIMESTAMP_OUTPUT
BEGIN                        DELETE_WHERE          TRUNCATE       
BLOB_INPUT                   DROP                  TYPES          
BOOLEAN_INPUT                DROP_COLUMNFAMILY     UPDATE         
CONSISTENCYLEVEL             DROP_INDEX            UPDATE_COUNTERS
CREATE                       DROP_KEYSPACE         UPDATE_SET     
CREATE_COLUMNFAMILY          DROP_TABLE            UPDATE_USING   
CREATE_COLUMNFAMILY_OPTIONS  INSERT                UPDATE_WHERE   
CREATE_COLUMNFAMILY_TYPES    SELECT                USE            
CREATE_INDEX                 SELECT_COLUMNFAMILY   UUID_INPUT     


さらに各コマンドでhelpを打つと詳細が分かります。
cqlsh:Hogebook> help SELECT

        SELECT [FIRST n] [REVERSED] <selectExpr>
          FROM [<keyspace>.]<table>
            [USING CONSISTENCY <consistencylevel>]
            [WHERE <clause>]
            [ORDER BY <colname> [DESC]]
            [LIMIT m];

        SELECT is used to read one or more records from a CQL table. It returns
        a set of rows matching the selection criteria specified.


        Note that FIRST and REVERSED are only supported in CQL 2, and ORDER BY
        is only supported in CQL 3 and higher.

        For more information, see one of the following:

          HELP SELECT_EXPR
          HELP SELECT_TABLE
          HELP SELECT_WHERE
          HELP SELECT_LIMIT
          HELP CONSISTENCYLEVEL

かなりSQLっぽく使えるようです。
いくつかコマンドを打ってみたいと思います。



DESC TABLE
cqlsh:Hogebook> desc table User;

CREATE TABLE User (
  KEY text PRIMARY KEY,
  email text,
  gender text
) WITH
  comment='' AND
  comparator=text AND
  read_repair_chance=0.100000 AND
  gc_grace_seconds=864000 AND
  default_validation=text AND
  min_compaction_threshold=4 AND
  max_compaction_threshold=32 AND
  replicate_on_write='true' AND
  compaction_strategy_class='SizeTieredCompactionStrategy' AND
  compression_parameters:sstable_compression='SnappyCompressor';

CREATE INDEX User_gender_idx ON User (gender);



SELECT
cqlsh:Hogebook> select * from User;

 KEY             | email                      | gender
-----------------+----------------------------+--------
     memorycraft |      memorycraft@gmail.com |   male
 memorycraftgirl | memorycraft+girl@gmail.com | female



INSERT
cqlsh:Hogebook> insert into User(KEY, email, gender) VALUES('hellocql', 'memorycraft+cql@gmail.com', 'male');
cqlsh:Hogebook>
cqlsh:Hogebook> select * from User;

 KEY             | email                      | gender
-----------------+----------------------------+--------
     memorycraft |      memorycraft@gmail.com |   male
        hellocql |  memorycraft+cql@gmail.com |   male
 memorycraftgirl | memorycraft+girl@gmail.com | female

これなら違和感なくデータの操作や参照ができそうです。



APIアクセス



これらのCQLコマンドはコンソール上でも使用しますが、アプリケーションコードからも発行できます。
以前の記事で使用したphpcasaからも使うことができます。

例えば以下はテーブルの全データを取得して出力するスクリプトになります。


このスクリプトを実行してみます。

$ php ./cql.php 
cassandra\CqlResult Object
(
    [type] => 1
    [rows] => Array
        (
            [0] => cassandra\CqlRow Object
                (
                    [key] => memorycraft
                    [columns] => Array
                        (
                            [0] => cassandra\Column Object
                                (
                                    [name] => KEY
                                    [value] => memorycraft
                                    [timestamp] => -1
                                    [ttl] => 
                                )

                            [1] => cassandra\Column Object
                                (
                                    [name] => email
                                    [value] => memorycraft@gmail.com
                                    [timestamp] => 1589299048
                                    [ttl] => 
                                )

                            [2] => cassandra\Column Object
                                (
                                    [name] => gender
                                    [value] => male
                                    [timestamp] => 1596347048
                                    [ttl] => 
                                )

                        )

                )

            [1] => cassandra\CqlRow Object
                (
                    [key] => hellocql
                    [columns] => Array
                        (
                            [0] => cassandra\Column Object
                                (
                                    [name] => KEY
                                    [value] => hellocql
                                    [timestamp] => -1
                                    [ttl] => 
                                )

                            [1] => cassandra\Column Object
                                (
                                    [name] => email
                                    [value] => memorycraft+cql@gmail.com
                                    [timestamp] => 1562593385
                                    [ttl] => 
                                )

                            [2] => cassandra\Column Object
                                (
                                    [name] => gender
                                    [value] => male
                                    [timestamp] => 1562593384
                                    [ttl] => 
                                )

                        )

                )

            [2] => cassandra\CqlRow Object
                (
                    [key] => memorycraftgirl
                    [columns] => Array
                        (
                            [0] => cassandra\Column Object
                                (
                                    [name] => KEY
                                    [value] => memorycraftgirl
                                    [timestamp] => -1
                                    [ttl] => 
                                )

                            [1] => cassandra\Column Object
                                (
                                    [name] => email
                                    [value] => memorycraft+girl@gmail.com
                                    [timestamp] => 1611666048
                                    [ttl] => 
                                )

                            [2] => cassandra\Column Object
                                (
                                    [name] => gender
                                    [value] => female
                                    [timestamp] => 1602906048
                                    [ttl] => 
                                )

                        )

                )

        )

    [num] => 
    [schema] => cassandra\CqlMetadata Object
        (
            [name_types] => Array
                (
                    [KEY] => AsciiType
                )

            [value_types] => Array
                (
                    [KEY] => UTF8Type
                    [email] => UTF8Type
                    [gender] => UTF8Type
                )

            [default_name_type] => UTF8Type
            [default_value_type] => UTF8Type
        )

)


出力をみると、オブジェクト形式で結果が帰ってくるようです。 これなら普段のSQLと近い感覚でコードがかけるので、移行もしやすいと思います。

以上です。


Cassandraってなんじゃ?(EC2で起動時自動ノード追加とノードの削除)

Cassandraを使っているときに、容量が足らない、負荷が高いなどの理由でノードを増やしたい場合があります。また、負荷が長期的に落ち着き、予算を抑えるためにノードを減らすこともあります。

今回はノードの追加と削除をやってみます。



トークンの算出



ノードを追加するケースはリングの負荷状態によって、大きく分けて
  1. 保存するデータのハッシュやアクセスに偏りが大きく、特定ノードの容量または処理の負荷が高いので負荷集中を分散したい。
  2. リング全体の容量、または処理の負荷が高いので、全体的に数を増やして均一に分散したい。

の2通りかと思います。

1の場合、負荷の高いノードの近くにノードを追加し、ノードの均一化はせずに特定のトークンの範囲にノードを集中させたほうがよさそうです。
2の場合、ノードを追加したら、全ノードが均等にリング上に再配置したほうが全体としての負荷は抑えられそうです。

今回は1の場合を例にとってみます。


まず、トークンを計算するためのツールをつくっておくと便利です。
引数にノードの数を与えるとそれがリング上に均等に配置されるようなトークンのリストを返すツールです。

計算式はPartitionerによってことなり、
#RandomPartitionerの場合
 
def tokens(nodes):
  for x in xrange(nodes):
    print 2 ** 127 / nodes * x
 
#Murmur3Partitionerの場合
 
def tokens(num_nodes):
  for i in range(num_nodes):
    print ((2**64 / num_nodes) * i) - 2**63

のようになります。

今回はMurmur3Partitionerを使用しているので、
以下のようなpythonスクリプトを作ります。


引数にノード数を入れて実行すると、ノードリングに均等に配置された場合のハッシュトークンのリストが出力されます。
$ ./tokens.py 4
-9223372036854775808
-4611686018427387904
0
4611686018427387904
 
$ ./tokens.py 8
-9223372036854775808
-6917529027641081856
-4611686018427387904
-2305843009213693952
0
2305843009213693952
4611686018427387904
6917529027641081856


既存のノードが4つだったとして、トークンが以下のように配置されているとします。
  • A:0
  • B:4611686018427387904
  • C:-9223372036854775808
  • D:-4611686018427387904




この場合Aの両脇にノードを2つ追加しておくとよさそうです。
また、追加ノードのトークンは、
  • B、DもCに比べて負荷が高めであればA-B, A-Cのそれぞれ中間
  • BDの負荷はそれほどでもなければもっとAより

に配置する形になります。
前者であれば、./tokens 8、後者であれば./tokens 12 などでAの位置の両脇のトークンを使用します。
たとえば後者のパターンで追加してみます。

$ ./tokens 12
-9223372036854775808
-7686143364045646507
-6148914691236517206
-4611686018427387905
-3074457345618258604
-1537228672809129303
-2
1537228672809129299
3074457345618258600
4611686018427387901
6148914691236517202
7686143364045646503

-2の部分がAのノード位置です。
その両脇の
  • -1537228672809129303
  • 1537228672809129299

が今回の追加ノードとなります。




以前の記事でちょっと触れましたが、自動でリングに追加されるようなAMIを作ります。



AMIの作成



AMIの作成をします。cassandraをインストールしただけでまだ一度も起動していないインスタンスをベースに作業を行うとスムーズです。

以下の設定ファイルにはIPなどノード固有の情報(赤字の部分)が含まれます。

/usr/local/cassandra/conf/cassandra.yaml
cluster_name: 'クラスタ名'
initial_token: トークン
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: "シードIP"

listen_address: 自分のIP
endpoint_snitch: Ec2Snitch
auto_bootstrap: シードならfalse,非シードならtrue

/etc/hosts
127.0.0.1       localhost.localdomain localhost  ip-10-0-1-10

この固有の項目を書き換えるようなシェルスクリプトを書きます。

このスクリプトは後でUserDataから呼び出され、第1引数にトークン、第2引数にauto_bootstrapのブーリアン文字列、第3引数にシードIPが渡されます。

/etc/cloud/cassandra.sh


ここまで設定したらno rebootでAMIを作成します。




ノードの自動追加



このAMIをつかって新規ノードを追加します。
クラスタも何もない状態で、一番最初のノードを立ち上げる場合は以下のようにUserDataを指定します。

#!/bin/sh
/etc/cloud/cassandra.sh "0" false 10.0.1.10


そして、プライベートIPアドレスを10.0.1.10に固定して起動します。



また、2個め以降(ここでは例として6個目)の追加ノードは以下のようにUserDataを指定します。
ここで、第1引数のトークンは冒頭で記した計算ツールで算出しておきます。

#!/bin/sh
/etc/cloud/cassandra.sh "1537228672809129299" true 10.0.1.10,10.0.1.146,10.0.1.176,10.0.1.232,10.0.1.134


特にプライベートIPを指定する必要はありません。



これにより、立ち上がったインスタンスでは、hostsファイルとcassandra.yamlが自動的に設定され、cassandraが起動し、リングに自動的に追加されます。

起動前は、

# /usr/local/cassandra/bin/nodetool ring

Datacenter: ap-northeast
==========
Replicas: 3

Address         Rack        Status State   Load            Owns                Token                                     
                                                                               -4611686018427387905                       
10.0.1.146      1a          Up     Normal  75.43 KB        66.67%              -1537228672809129303                       
10.0.1.10       1a          Up     Normal  61.65 KB        50.00%              0                                         
10.0.1.176      1a          Up     Normal  58.33 KB        58.33%              -9223372036854775808                       
10.0.1.232      1a          Up     Normal  58.45 KB        50.00%              4611686018427387901                       
10.0.1.134      1a          Up     Normal  58.48 KB        75.00%              -4611686018427387905

だったのが、起動後


# /usr/local/cassandra/bin/nodetool ring

Datacenter: ap-northeast
==========
Replicas: 3

Address         Rack        Status State   Load            Owns                Token                                       
                                                                               -4611686018427387905                        
10.0.1.213      1a          Up     Normal  49.55 KB        33.33%              1537228672809129299                         
10.0.1.146      1a          Up     Normal  63.7 KB         66.67%              -1537228672809129303                        
10.0.1.10       1a          Up     Normal  66.59 KB        50.00%              0                                           
10.0.1.176      1a          Up     Normal  63.28 KB        50.00%              -9223372036854775808                        
10.0.1.232      1a          Up     Normal  63.4 KB         33.33%              4611686018427387901                         
10.0.1.134      1a          Up     Normal  63.43 KB        66.67%              -4611686018427387905 

↑のようにノード追加されていることが分かります。



ノードの取り外し



逆に問題があるノードを取り外すときは、そのノードに入って、

# /usr/local/cassandra/bin/nodetool decommission

とすれば外れます。
再び接続させるには、cassandraを追加します。

#/etc/init.d/cassandra stop
#/etc/init.d/cassandra start



接続できない場合


たまに、リングに接続できなかったりした場合は、まず7000(ノード間), 9160(Thrift), 7199(JMX)などのポートを準備できているかセキュリティグループやnsetstatで確認します。netstatでlistenできていない場合は、cassandraを再起動させたりログを調べたりして原因を探していく流れになります。




# netstat -tupln | grep -i listen | grep java
tcp        0      0 0.0.0.0:9160                0.0.0.0:*                   LISTEN      3967/java         
tcp        0      0 0.0.0.0:38250               0.0.0.0:*                   LISTEN      3967/java         
tcp        0      0 0.0.0.0:53170               0.0.0.0:*                   LISTEN      3967/java         
tcp        0      0 10.0.1.213:7000             0.0.0.0:*                   LISTEN      3967/java         
tcp        0      0 0.0.0.0:7199                0.0.0.0:*                   LISTEN      3967/java



これで、ノードを簡単に増やせるようになりました。
以上です。

2013年3月2日土曜日

StorageGatewayってなんじゃ?(GlusterFSで復旧編)

前回GlusterFSを使ってStorageGatewayインスタンスを冗長化しました。
今回は、インスタンスが落ちた場合の復旧方法を見てみます。

Gatewayインスタンスが落ちた場合





gatewayインスタンスを落とします。



ブリックである/mnt/sgwをみてみると


# ls -l /mnt/sgw
ls: reading directory /mnt/sgw: 入力/出力エラーです
合計 16
-rw-r--r-- 2 root root 27  3月  1 13:24 2013 1.txt
-rw-r--r-- 2 root root 27  3月  1 13:24 2013 4.txt


IOエラーがでます。


Glusterボリュームのマウントポイントをみてみると


# ls -lrt /mnt/gv
合計 24
-rw-r--r-- 1 root root 27  3月  1 13:51 2013 1.txt
-rw-r--r-- 1 root root 27  3月  1 13:51 2013 2.txt
-rw-r--r-- 1 root root 27  3月  1 13:51 2013 3.txt
-rw-r--r-- 1 root root 27  3月  1 13:51 2013 4.txt
-rw-r--r-- 1 root root 27  3月  1 13:51 2013 5.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 6.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 7.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 8.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 9.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 10.txt
-rw-r--r-- 1 root root 27  3月  1 13:52 2013 11.txt
-rw-r--r-- 1 root root 27  3月  1 13:53 2013 12.txt
-rw-r--r-- 1 root root 27  3月  1 13:53 2013 13.txt
-rw-r--r-- 1 root root 27  3月  1 13:53 2013 14.txt
-rw-r--r-- 1 root root 27  3月  1 13:53 2013 15.txt

# cat /mnt/gv/*
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZ


正しくレプリケーションされています。


gatewayインスタンスを復帰させます。




インスタンスが立ち上がったら、一度10.0.1.8のglusterfsを解除して、iSCSIボリュームを再マウントします。

# ps -ax | grep gluster
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
24350 ?        Ssl    0:00 /usr/sbin/glusterd -p /var/run/glusterd.pid
24371 ?        Ssl    0:00 /usr/sbin/glusterfsd -s localhost --volfile-id gv0.10.0.1.8.mnt-sgw -p /var/lib/glusterd/vols/gv0/run/10.0.1.8-mnt-sgw.pid -S /tmp/6f580d4f3eab1dcb22c5aef9d7fb2275.socket --brick-name /mnt/sgw -l /var/log/glusterfs/bricks/mnt-sgw.log --xlator-option *-posix.glusterd-uuid=4f2e8dff-1b51-423e-8ac0-b0e892bd2e0d --brick-port 24013 --xlator-option gv0-server.listen-port=24013
24377 ?        Ssl    0:00 /usr/sbin/glusterfs -s localhost --volfile-id gluster/nfs -p /var/lib/glusterd/nfs/run/nfs.pid -l /var/log/glusterfs/nfs.log -S /tmp/f34a5ad241dbfecb7dcb5f2c14aab1f4.socket
24383 ?        Ssl    0:00 /usr/sbin/glusterfs -s localhost --volfile-id gluster/glustershd -p /var/lib/glusterd/glustershd/run/glustershd.pid -l /var/log/glusterfs/glustershd.log -S /tmp/c019293c2e261dcab94469694dc5674e.socket --xlator-option *replicate*.node-uuid=4f2e8dff-1b51-423e-8ac0-b0e892bd2e0d
24393 pts/1    S+     0:00 grep gluster
# kill -9 24350 24371 24377 24383

# umount /mnt/sgw
# umount /mnt/gv
# iscsiadm --mode discovery --type sendtargets --portal 10.0.1.5:3260
# iscsiadm --mode node --targetname iqn.1997-05.com.amazon:memorycraft-sgw1 --portal 10.0.1.5:3260,1 --logout
# iscsiadm --mode node --targetname iqn.1997-05.com.amazon:memorycraft-sgw1 --portal 10.0.1.5:3260,1 --login
# mount /dev/sda /mnt/sgw
# /etc/init.d/glusterd start
# mount -t glusterfs 10.0.1.8:/gv0 /mnt/gv



ここでブリック(GlusterFSを構成するディレクトリ)である/mnt/sgwをみてみると、

# ls -l /mnt/sgw
合計 112
-rw-r--r-- 2 root root  0  3月  1 13:51 2013 1.txt
-rw-r--r-- 2 root root  0  3月  1 13:52 2013 10.txt
-rw-r--r-- 2 root root  0  3月  1 13:52 2013 11.txt
-rw-r--r-- 2 root root 27  3月  1 14:07 2013 12.txt
-rw-r--r-- 2 root root  0  3月  1 13:53 2013 13.txt
-rw-r--r-- 2 root root 27  3月  1 14:07 2013 14.txt
....略....
-rw-r--r-- 2 root root  0  3月  1 14:00 2013 58.txt
-rw-r--r-- 2 root root  0  3月  1 13:52 2013 6.txt
-rw-r--r-- 2 root root 27  3月  1 14:07 2013 7.txt
-rw-r--r-- 2 root root  0  3月  1 13:52 2013 8.txt
-rw-r--r-- 2 root root  0  3月  1 13:52 2013 9.txt



ファイルの内容は同期されましたが、ファイルサイズが0のままです。
これをマウントポイントから読み出しを行うと即座に完全同期できます。

# find /mnt/gv -type f -exec dd if='{}' of=/dev/null bs=1M \; > /dev/null 2>&1

# ls -l /mnt/sgw
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 1.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 10.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 11.txt
-rw-r--r-- 2 root root 27  3月  1 14:07 2013 12.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 13.txt
-rw-r--r-- 2 root root 27  3月  1 14:07 2013 14.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 15.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 16.txt
...略.....
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 56.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 57.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 58.txt
-rw-r--r-- 2 root root 27  3月  1 14:14 2013 59.txt
-rw-r--r-- 2 root root 27  3月  1 14:12 2013 6.txt
-rw-r--r-- 2 root root 27  3月  1 14:14 2013 60.txt

これで同期が復旧しました。
その後も投入されつづけたファイルが同期されているのがわかります。




イニシエータインスタンスが落ちた場合




10.0.1.8をstopしてみます。




10.0.1.9では投入が反映され続けられています。
# ls -lrt /mnt/gv
.....略......
-rw-r--r-- 1 root root 27  3月  1 17:37 2013 562.txt
-rw-r--r-- 1 root root 27  3月  1 17:37 2013 563.txt
-rw-r--r-- 1 root root 27  3月  1 17:37 2013 564.txt
-rw-r--r-- 1 root root 27  3月  1 17:37 2013 565.txt
-rw-r--r-- 1 root root 27  3月  1 17:38 2013 566.txt
-rw-r--r-- 1 root root 27  3月  1 17:38 2013 567.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 568.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 569.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 570.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 571.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 572.txt
-rw-r--r-- 1 root root 27  3月  1 17:39 2013 573.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 574.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 575.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 576.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 577.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 578.txt
-rw-r--r-- 1 root root 27  3月  1 17:40 2013 579.txt
-rw-r--r-- 1 root root 27  3月  1 17:41 2013 580.txt
-rw-r--r-- 1 root root 27  3月  1 17:41 2013 581.txt


10.0.1.8をstartします。



SSHで入り、ブリックと、Glusterボリュームをマウントしなおします。

# df -h
Filesystem            Size  Used Avail Use% マウント位置
/dev/xvde1            6.0G  2.6G  3.1G  46% /
none                  3.7G     0  3.7G   0% /dev/shm

# mount /dev/sda /mnt/sgw
# mount -t glusterfs 10.0.1.8:/gv0 /mnt/gv
# ls -lrt /mnt/gv
.....略......
-rw-r--r-- 1 root root 27  3月  1 20:34 2013 1602.txt
-rw-r--r-- 1 root root 27  3月  1 20:34 2013 1603.txt
-rw-r--r-- 1 root root 27  3月  1 20:34 2013 1604.txt
-rw-r--r-- 1 root root 27  3月  1 20:34 2013 1605.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1606.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1607.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1608.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1609.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1610.txt
-rw-r--r-- 1 root root 27  3月  1 20:35 2013 1611.txt
-rw-r--r-- 1 root root 27  3月  1 20:36 2013 1612.txt


# ls -lrt /mnt/sgw
.....略.....
rw-r--r-- 2 root root 27  3月  1 20:34 2013 1602.txt
-rw-r--r-- 2 root root 27  3月  1 20:34 2013 1603.txt
-rw-r--r-- 2 root root 27  3月  1 20:34 2013 1604.txt
-rw-r--r-- 2 root root 27  3月  1 20:34 2013 1605.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1606.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1607.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1608.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1609.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1610.txt
-rw-r--r-- 2 root root 27  3月  1 20:35 2013 1611.txt
-rw-r--r-- 2 root root 27  3月  1 20:36 2013 1612.txt

マウントポイントに復帰され、投入が反映されています。
起動時に自動でマウントするにはfstabに以下のように設定します。

# cat /etc/fstab
/dev/sda         /mnt/sgw  ext4    _netdev         0 0
10.0.1.8:/gv0 /mnt/gv glusterfs defaults,_netdev 0 0


以上です。

2013年2月25日月曜日

StorageGatewayってなんじゃ?(Gatewayインスタンスの冗長化:GlusterFS編)

StorageGatewayのiSCSIボリュームをEC2にマウントし、アプリケーションシステムの中で使おうとする場合、冗長化という課題が持ち上がってきます。


ここで、いくつか冗長化の可能性を考えてみました。


マルチパス(


その場合、iSCSIとしての冗長化に合わせると、マルチパスという方法があるようです。
イメージとしては、以下のような感じでiSCSIターゲットであるgatewayインスタンスに複数のIPを付与し、それぞれの接続先の複数のデバイスを1つのデバイスとして認識させ、1つの接続が切れても他のNICで接続ができる方法です。



これはそもそもGatewayインスタンスの冗長化ではなく、ネットワーク・インターフェースの冗長化になりますが、ちょっと試してみます。
2番目のENIIを10.0.1.6として追加し、gatewayインスタンスにアタッチします。





そして、マウント用のEC2から10.0.1.6のiSCSIを調べてみますが、接続できないようです。
(既存のENIのセカンダリIPに付与しても同じでした。)
# iscsiadm --mode discovery --type sendtargets --portal 10.0.1.6:3260
iscsiadm: cannot make connection to 10.0.1.6: Connection refused
iscsiadm: cannot make connection to 10.0.1.6: Connection refused
iscsiadm: cannot make connection to 10.0.1.6: Connection refused


その後、ググってみると、いろいろなことがわかりました。

また、EC2インスタンスのゲートウェイには通常のログインができないようです。
替わりにAWSのサポートにトラブルシュートをしてもらうために以下のsshコマンドだけ受け付けているそうです。
ssh -i IDENTITY_FILE sguser@INSTANCE_IP_ADDRESS grant-aws-support-access
ssh -i IDENTITY_FILE sguser@INSTANCE_IP_ADDRESS revoke-aws-support-access
(試したところ、理由はわかりませんが、上記のコマンドもPermission denied (publickey).がでてアクセス出来ませんでした。。)



ソフトウェアRAID(


2つのGatewayインスタンスを複数のイニシエータにマウントしそれぞれでソフトウェアRAID1を試してみましたが、
一方の変更が他方のイニシエータ上に反映されませんでした。クラスタファイルシステムなどを利用する必要があるようです。





DRBD


DRBD + iSCSIはiSCSIターゲット側でDRBDを行うことが通常のようですが、Gateway on EC2ではGatewayインスタンスにはログインできないようなので、マウント側のEC2でDRBDを行うことになります。
このケースも試してみたいのですが、今回は見送ります。


GlusterFS


今回はGlusterFSという分散ファイルシステムを使用してみます。



前回の記事までは、Gatewayインスタンスが1つでしたがこれを2つにして、冗長化を図ります。
また、これらのGatewayインスタンスにさらに複数のイニシエータが接続し、それぞれが担当するGatewayのiSCSIをマウントし、もう一方をGlusterFSで互いをレプリカとしてミラーリングしあいます。

まず、前回と同じ手順でStorageGatewayをもう一つ登録し、Gatewayインスタンスを2つの状態にしておきます。
2つのGatewayインスタンスの内部IPは 10.0.1.5, 10.0.1.6とします。
また、マウント用のインスタンスを2つ用意し、10.0.1.8, 10.0.1.9とします。

そして、10.0.1.8は10.0.1.5の、10.0.1.9は10.0.1.6のGatewayインスタンスのiSCSIボリュームをそれぞれマウントします。


10.0.1.8
# mkdir /mnt/sgw
# iscsiadm  --mode node --targetname iqn.1997-05.com.amazon:memorycraft-sgw --portal 10.0.1.5:3260,1 --login

# ls -l /dev/disk/by-path/
合計 0
lrwxrwxrwx 1 root root  9  2月 25 00:08 2013 ip-10.0.1.5:3260-iscsi-iqn.1997-05.com.amazon:memorycraft-sgw-lun-0 -> ../../sda
lrwxrwxrwx 1 root root  9  2月 25 00:48 2013 ip-10.0.1.6:3260-iscsi-iqn.1997-05.com.amazon:memorycraft-sgw2-lun-0 -> ../../sdb
lrwxrwxrwx 1 root root 11  2月 23 17:54 2013 xen-vbd-2049 -> ../../xvde1

# mkfs.ext4 /dev/sda
# mount /dev/sda /mnt/sgw


10.0.1.9
# mkdir /mnt/sgw2
# iscsiadm  --mode node --targetname iqn.1997-05.com.amazon:memorycraft-sgw2 --portal 10.0.1.6:3260,1 --login


# ls -l /dev/disk/by-path/
合計 0
lrwxrwxrwx 1 root root  9  2月 25 00:08 2013 ip-10.0.1.5:3260-iscsi-iqn.1997-05.com.amazon:memorycraft-sgw-lun-0 -> ../../sda
lrwxrwxrwx 1 root root  9  2月 25 00:48 2013 ip-10.0.1.6:3260-iscsi-iqn.1997-05.com.amazon:memorycraft-sgw2-lun-0 -> ../../sdb
lrwxrwxrwx 1 root root 11  2月 23 17:54 2013 xen-vbd-2049 -> ../../xvde1


# mkfs.ext4 /dev/sdb
# mount /dev/sdb /mnt/sgw2


次に、10.0.1.8で10.0.1.9をGlusterのピアとして登録し、互いをレプリカとしてGlusterボリュームを作成します。

10.0.1.8
# gluster peer probe 10.0.1.9
# gluster volume create gv0 replica 2 10.0.1.8:/mnt/sgw 10.0.1.9:/mnt/sgw2

すると、双方にgv0というデバイスが接続されるので、これをglusterfsとしてマウントします。


10.0.1.8, 10.0.1.9
# mount -t glusterfs 10.0.1.8:/gv0 /mnt/gv
# ls -l /mnt/gv
drwx------  2 root root     16384  2月 25 00:47 2013 lost+found


一方でファイルを作成すると、

10.0.1.8
# echo "hoge" > /mnt/gv/hoge.txt


10.0.1.9
# ls -l /mnt/gv
-rw-r--r--  1 root root         5  2月 25 01:26 2013 hoge.txt
drwx------  2 root root     16384  2月 25 00:47 2013 lost+found


もう一方にも更新が反映されています。
また、一方のゲートウェイインスタンス(10.0.1.6)を落としても、、、


それぞれのイニシエータでは問題なくファイル操作できるようです。


10.0.1.8
# echo "111" > /mnt/gv/111.txt

# ls -l /mnt/gv/
-rw-r--r--  1 root root         5  2月 25 03:42 2013 111.txt
-rw-r--r--  1 root root         5  2月 25 01:26 2013 hoge.txt
drwx------  2 root root     16384  2月 25 00:47 2013 lost+found


10.0.1.9
# echo "222" > /mnt/gv/222.txt
# ls -l /mnt/gv/
-rw-r--r--  1 root root         5  2月 25 03:42 2013 111.txt
-rw-r--r--  1 root root         4  2月 25 03:42 2013 222.txt
-rw-r--r--  1 root root         5  2月 25 01:26 2013 hoge.txt
drwx------  2 root root     16384  2月 25 00:47 2013 lost+found


とりあえず、これで冗長化はできました。
GlusterFSはFUSEを使うこともあり少しパフォーマンスが落ちますが、
GlusterFSに関わらず、以下のような対策でパフォーマンスは上がるかもしれません。

  • fuseのバージョンを変えてみる
  • ファイルシステムをxfsにしてみる、
  • EBS-Optimizedインスタンスにしてみる
  • PIOPS-EBSにしてみる
  • GlusterFSを4台構成でstriped + replicaにしてみる
などなどです。

また、他のクラスタソリューションを試してみても良いかもしれません。

  • GFS
  • OCFS
  • Lustre
  • ....

また、lsyncd+rsyncdなど二重化をするほうほうなど方法はまだまだありますので、要件にあわせていろいろ探ってみるのも良いと思います。

以上です。

2013年2月19日火曜日

RDSってなんじゃ?(MySQL on EBS-PIOPS vs RDS-PIOPS)

最近、Provisioned IOPS(以下PIOPS)という機能がEBSとRDSで使用できるようになりました。
そこで、EBS with PIOPS上のMySQLと、RDS with PIOPSでベンチマークを取ってみました。


RDSの準備


  • db.m1.large
  • 100GB/1000 IOPS 

MySQLインスタンスの起動設定をします。
インスタンスタイプはdb.m1.largeにして、ストレージは100GB、use Provisioned IOPSにチェックをいれて、IOPSを1000に設定します。



あとは手順にしたがって進みます。





EBSの準備


  • EC2はm1.largeのEBS Optimized
  • EBSは(100GB/1000 IOPS)をマウント
  • MySQLのデータディレクトリをEBS上に配置
  • なるべく設定をDBパラメータグループに合わせる


準備


 以下のようにm1.largeを選び、EBS-Optimized instanceにチェックを入れます。



EBS VolumesでVolume Sizeを100GiBにして、Volume TypeをProvisioned IOPSにして、IOPSを1000に設定します。



立ち上がったら、SSHで入ります。
まずEBSをマウントします。
# yum install -y xfsprogs
# mount /dev/xvdf /mnt/data

次に、RDSと同じバージョンのmysqlをインストールします。
# cd /usr/local/src
# curl -OL http://downloads.mysql.com/archives/mysql-5.5/mysql-5.5.27.tar.gz
# tar xzvf mysql-5.5.27.tar.gz
# cd mysql-5.5.27/
# yum install -y cmake ncurses-devel
# cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DENABLED_LOCAL_INFILE=true -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_EXTRA_CHARSETS=all -DWITH_READLINE=OFF
# make
# make install

# cat /etc/my.cnf

[mysqld]
user=mysql

datadir=/mnt/data/mysql
socket=/var/lib/mysql/mysql.sock

binlog_cache_size = 32768
binlog_format = MIXED
innodb_additional_mem_pool_size = 2097152
innodb_buffer_pool_size = 4509715660
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
innodb_log_buffer_size = 8388608
innodb_log_file_size = 134217728
key_buffer_size = 16777216
local_infile = 1
log_output = TABLE
log-error = /var/log/mysql/error.log
max_binlog_size = 134217728
max_connections = 477
read_buffer_size = 262144
read_only = false
read_rnd_buffer_size = 524288
thread_stack = 262144
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql

mysqlを立ち上げます。
/etc/init.d/mysql start


ベンチマーク用インスタンスの準備


新しくインスタンスを立ち上げ、mysql-benchをインストールします。
mysql-benchの使い方は、以下のサイトに詳しく書かれています。
suz-lab: "mysql-bench"でMySQLのベンチマークの比較
# yum -y install mysql-bench

ベンチマークの実行


# cd /usr/share/sql-bench/
# chmod 755 run-all-tests
# chmod 755 compare-results

RDS
# ./run-all-tests --host=rds-iops.cwnvl1ncuiwq.ap-northeast-1.rds.amazonaws.com --server=mysql --cmp=mysql --machine=rds --database=hoge --user=memorycraft --password=xxxxxxxxxx --log

EBS
# ./run-all-tests --host=ec2-46-51-237-207.ap-northeast-1.compute.amazonaws.com --server=mysql --cmp=mysql --machine=ebs --database=hoge --user=memorycraft --password= xxxxxxxxxx --log


比較


# ./compare-results --cmp=mysql

The test was run with limits from: mysql

The result logs which where found and the options:
 1 mysql-ebs                               : MySQL 5.5.27 
 2 mysql-rds                               : MySQL 5.5.27 

=====================================================
Operation                           |      1|      2|
                                    |mysql-e|mysql-r|
-----------------------------------------------------
Results per test in seconds:                        |
-----------------------------------------------------
ATIS                                |  31.00|  20.00|
alter-table                         |  28.00|  29.00|
big-tables                          |  16.00|  16.00|
connect                             | 339.00| 345.00|
create                              | 707.00|1003.00|
insert                              |2929.00|2092.00|
select                              | 331.00| 301.00|
wisconsin                           |  65.00|  35.00|
-----------------------------------------------------
The results per operation:                          |
-----------------------------------------------------
alter_table_add (100)               |  13.00|  14.00|
alter_table_drop (91)               |  12.00|  14.00|
connect (10000)                     |  26.00|  24.00|
connect+select_1_row (10000)        |  25.00|  26.00|
connect+select_simple (10000)       |  24.00|  25.00|
count (100)                         |   9.00|   8.00|
count_distinct (1000)               |   6.00|   5.00|
count_distinct_2 (1000)             |  13.00|  13.00|
count_distinct_big (120)            |  23.00|  14.00|
count_distinct_group (1000)         |  13.00|   9.00|
count_distinct_group_on_key (1000)  |  11.00|   9.00|
count_distinct_group_on_key_parts (1|  12.00|   9.00|
count_distinct_key_prefix (1000)    |   5.00|   4.00|
count_group_on_key_parts (1000)     |   6.00|   6.00|
count_on_key (50100)                |  78.00|  77.00|
create+drop (10000)                 | 124.00| 160.00|
create_MANY_tables (10000)          | 117.00| 187.00|
create_index (8)                    |   0.00|   0.00|
create_key+drop (10000)             | 424.00| 631.00|
create_table (31)                   |   0.00|   0.00|
delete_all_many_keys (1)            |  25.00|  26.00|
delete_big (1)                      |   0.00|   0.00|
delete_big_many_keys (128)          |  25.00|  26.00|
delete_key (10000)                  |  12.00|   8.00|
delete_range (12)                   |   3.00|   3.00|
drop_index (8)                      |   1.00|   0.00|
drop_table (28)                     |   0.00|   0.00|
drop_table_when_MANY_tables (10000) |  38.00|  20.00|
insert (350768)                     | 695.00| 357.00|
insert_duplicates (100000)          |  39.00|  39.00|
insert_key (100000)                 | 224.00| 141.00|
insert_many_fields (2000)           |   6.00|   6.00|
insert_select_1_key (1)             |   3.00|   3.00|
insert_select_2_keys (1)            |   4.00|   5.00|
min_max (60)                        |   5.00|   5.00|
min_max_on_key (85000)              |  39.00|  38.00|
multiple_value_insert (100000)      |   2.00|   2.00|
once_prepared_select (100000)       |  45.00|  44.00|
order_by_big (10)                   |  18.00|  18.00|
order_by_big_key (10)               |  17.00|  17.00|
order_by_big_key2 (10)              |  16.00|  17.00|
order_by_big_key_desc (10)          |  17.00|  17.00|
order_by_big_key_diff (10)          |  17.00|  16.00|
order_by_big_key_prefix (10)        |  17.00|  17.00|
order_by_key2_diff (500)            |   1.00|   2.00|
order_by_key_prefix (500)           |   1.00|   1.00|
order_by_range (500)                |   1.00|   1.00|
outer_join (10)                     |  11.00|  11.00|
outer_join_found (10)               |  11.00|  11.00|
outer_join_not_found (500)          |   9.00|   8.00|
outer_join_on_key (10)              |   8.00|   7.00|
prepared_select (100000)            |  52.00|  48.00|
select_1_row (100000)               |  38.00|  38.00|
select_1_row_cache (100000)         |  38.00|  38.00|
select_2_rows (100000)              |  40.00|  48.00|
select_big (80)                     |  17.00|  17.00|
select_big_str (10000)              |  43.00|  42.00|
select_cache (10000)                |  49.00|  46.00|
select_cache2 (10000)               |  55.00|  47.00|
select_column+column (100000)       |  39.00|  38.00|
select_diff_key (500)               |   1.00|   0.00|
select_distinct (800)               |   3.00|   2.00|
select_group (2911)                 |  12.00|  11.00|
select_group_when_MANY_tables (10000|   4.00|   5.00|
select_join (100)                   |   0.00|   0.00|
select_key (200000)                 |  99.00|  95.00|
select_key2 (200000)                | 119.00| 113.00|
select_key2_return_key (200000)     | 117.00| 116.00|
select_key2_return_prim (200000)    | 115.00| 110.00|
select_key_prefix (200000)          | 108.00| 103.00|
select_key_prefix_join (100)        |   4.00|   4.00|
select_key_return_key (200000)      |  96.00|  93.00|
select_many_fields (2000)           |  10.00|  10.00|
select_range (410)                  |  30.00|  33.00|
select_range_key2 (25010)           |   9.00|  10.00|
select_range_prefix (25010)         |   9.00|  10.00|
select_simple (100000)              |  33.00|  34.00|
select_simple_cache (100000)        |  33.00|  32.00|
select_simple_join (500)            |   1.00|   1.00|
update_big (10)                     |  29.00|  37.00|
update_of_key (50000)               |  99.00|  56.00|
update_of_key_big (501)             |  28.00|  19.00|
update_of_primary_key_many_keys (256|  74.00|  86.00|
update_with_key (300000)            | 596.00| 307.00|
update_with_key_prefix (100000)     | 198.00|  99.00|
wisc_benchmark (114)                |   3.00|   3.00|
-----------------------------------------------------
TOTALS                              |4452.00|3852.00|
=====================================================


 RDSの方が良い数値のようです。やはり最適化されているみたいですね。

ちなみに、ベンチマーク中のCloudWatchでも性能差が出ていました。
どちらもディスク操作/秒の値です。


RDS


1000 IOPSを上回る数値が出ています。
その後、落ち着くと1000で頭打ちになりました。




EBS


最初から1000で頭打ちで、ベンチマーク自体もRDSより時間がかかっています。




EBSの方は、設定やチューニングなどでもっとRDSの値に近づけられるのかもしれませんが、RDSならその手間も必要なく簡単に使うことができるということでしょうか。


以上です。

2013年2月14日木曜日

Cassandraってなんじゃ?(EC2でDataStaxOpsCenterを動かす)

前回の記事で、Cassandraでクラスタリングをした場合、クラスタの情報をみるためのnodetoolの紹介をしました。
ただ、nodetoolやcassandra-cliでは、ノードの構成や配置が複雑だったりデータの分布を直感的に確認することは大変です。

そんな場合、DataStax社が提供しているOpsCenterという管理画面ツールを使うと便利なようです。DataStaxはApache Cassandraのプロジェクトリーダーが起こした会社でcassandraのコミッタの多くが在籍しているそうです。

DataStax OpsCenterに関しては、以下のサイトで紹介されています。
Cassandraクラスタと、DataStax OpsCenterの構築

また、DataStaxの公式サイトに詳細なガイドがあります。
DataStax OpsCenter Documentation

これらのサイトを参考に、OpsCenterをEC2にインストールしてみました。いくつかEC2ならではの部分やはまった点に触れながら手順を紹介しようと思います。


OpsCenterのインストール


前回の記事でAPIアクセスをしたpublicサブネットのappサーバーにインストールします。

# cd /usr/local/src/
# rpm -Uvh http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
# cat /etc/yum.repos.d/datastax.repo
[datastax]
name= DataStax Repository
baseurl=http://rpm.datastax.com/community
enabled=1
gpgcheck=0
# yum install opscenter-free -y

接続先の設定をします。
opscenterd.confで設定します。
ここで、seed_hostsには、前回設定したseedインスタンスのIPを指定します。
また、ここではuse_sslをfalseにしてHTTPアクセスにしておきます。

# vi /etc/opscenter/opscenterd.conf
---

[jmx]
port = 7199
[webserver]
port = 8888
interface = 0.0.0.0
[cassandra]
seed_hosts = 10.0.1.10

[agents]
ssh_port = 22
use_ssl = false
https_port = 61621
incoming_port = 61620

---


セキュリティグループの設定


OpsCenterでは、以下のサイトに説明があるように接続に複数のポートを使用するようです。
OpsCenter and OpsCenter agent ports

ここでは以下のようにポートを設定します。

app(OpsCenter)インスタンス
  • 22  10.0.0.0/16 →ssh(natから入る想定)
  • 80  0.0.0.0/0  →通常のWEB接続
  • 8888  0.0.0.0/0  →OpsCenterコンソールのUI画面
  • 61620  10.0.0.0/16 →cassandraの各ノードからOpsCenterへ情報を送るポート

cassandraインスタンス
  • 22  10.0.0.0/16 →ssh(natから入る想定)、agentのインストールに必要
  • 7000  10.0.0.0/16 →cassandraノード同士の通信
  • 7199  10.0.0.0/16 →JMXポート
  • 9160  10.0.0.0/16 →Thrift API
  • 61621  10.0.0.0/16 →OpsCenterから各ノードへの情報取得用ポート


赤字が前回から新たに付与する設定です。


ここまでできたらOpsCenterを起動します。
# /etc/init.d/opscenterd start



ブラウザで確認


それでは、ブラウザでOpsCenterでUIを確認してみます。
app(OpsCenter)インスタンスにEIPをつけて、
http://インスタンスのEIP:8888/
を確認してみます。


おお!表示されました。
seedインスタンスのIPしか設定しませんでしたが、ノードが3つあることは理解されているようです。

しかし現時点では、情報が空のようです。
これは、cassandra側にOpsCenterのエージェントツールがないためです。


エージェントのインストール


次にエージェントをインストールします。
適切な設定がしてあると、OpsCenter側からcassandraにインストールすることが出来るようです。

タイトル部分の「Fix」というリンクをクリックします。



すると、以下のようなダイアログが開き、3つのノードのIPが表示されます。



ここで、「Edit Credentials」というリンクをクリックします。
すると、別のダイアログが更に開き、これらのインスタンスに入るためのユーザーとパスワードなどを聞かれます。


ここでは、rootユーザーか、もしくはsudoersに登録されているユーザーとパスワードを指定します。
sshがパスワードログインを許可していない場合は、「Private Key」に鍵ファイルのテキストをペーストします。
また、ここで登録された情報は永続化されることはない旨の説明が表示されています。
入力を終えたら「Done」ボタンをクリックします。

元のダイアログに戻るので、「Install on all nodes」ボタンをクリックします。
すると、SSHのフィンガープリントを確認されるので、「Accept Fingerprint」ボタンをクリックします。



エラー


しばらくすると、エラーダイアログが表示されてしまいました。



そこで、cassandra側を見てみます。
# ls -l /etc/init.d/ | grep ops
なにもインストールされていないようです。

インストールログがあるようなので、確認します。
# tail -1000f /var/log/opscenter-agent/installer.log
2013-02-13 23:12:09 +0900  Started: Wed Feb 13 23:10:26 2013 - 04:15 ago
2013-02-13 23:12:09 +0900  State  : Sleeping, pid: 25343
2013-02-13 23:10:27 +0900  Could not retrieve mirrorlist http://www.atomicorp.com/mirrorlist/atomic/centos-6-x86_64 error was
2013-02-13 23:10:27 +0900  12: Timeout on http://www.atomicorp.com/mirrorlist/atomic/centos-6-x86_64: (28, 'connect() timed out!')
2013-02-13 23:10:27 +0900  Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os error was
2013-02-13 23:10:27 +0900  12: Timeout on http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os: (28, 'connect() timed out!')
2013-02-13 23:10:27 +0900  Could not get metalink https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=x86_64 error was
2013-02-13 23:10:27 +0900  12: Timeout on https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=x86_64: (28, 'connect() timed out!')
これは、VPCでEIPをつけずにyumインストールをするときによく見るログです。
OpsCenterはSSHでcassandraノードに入ってyumでエージェントをインストールしようとしているようです。


なので、エージェントをインストールするときだけ、各ノードにEIPを付与してあげます。



では同じ手順でリトライしてみます。
OpsCenterの画面で再度「Install on all nodes」をクリックします。



。。。。やはりエラーになります。


くわしい原因が書かれていないので、OpsCenterのログを見てみます。
# tail -1000f /var/log/opscenter/opscenterd.log
2013-02-13 23:30:41+0900 [Test_Cluster]  INFO: Beginning install of OpsCenter agent to 10.0.1.176
2013-02-13 23:30:42+0900 [Test_Cluster]  INFO: Installing rpm package on 10.0.1.176
2013-02-13 23:31:12+0900 [Test_Cluster]  WARN: HTTP request http://10.0.1.227:61621/cluster/datacenter?node_ip=10.0.1.176 failed: Connection was refused by other side: 111: Connection refused.
2013-02-13 23:31:12+0900 [Test_Cluster]  WARN: Unable to collect datacenter, rack information: Failed query to http://10.0.1.227:61621/cluster/datacenter?node_ip=10.0.1.176 : Connection was refused by other side: 111: Connection refused.
2013-02-13 23:31:12+0900 [Test_Cluster]  WARN: HTTP request http://10.0.1.227:61621/cluster/datacenter?node_ip=10.0.1.10 failed: Connection was refused by other side: 111: Connection refused.
2013-02-13 23:31:12+0900 [Test_Cluster]  WARN: Unable to collect datacenter, rack information: Failed query to http://10.0.1.227:61621/cluster/datacenter?node_ip=10.0.1.10 : Connection was refused by other side: 111: Connection refused.
2013-02-13 23:31:12+0900 [Test_Cluster]  WARN: HTTP request http://10.0.1.10:61621/cluster/datacenter?node_ip=10.0.1.227 failed: Connection was refused by other side: 111: Connection refused.


どうやら61621ポートでHTTPリクエストが拒否されているようです。
再度cassandra側を見てみます。
# ls -l /etc/init.d/ | grep ops
-rwxr-xr-x 1 opscenter-agent opscenter-agent  3197  7月  3 05:39 2012 opscenter-agent


今度はインストール自体はできているようです。
このファイルの中を見てみます。
# cat /etc/init.d/opscenter-agent
...
OPSC_ADDR_DIR="/var/lib/opscenter-agent/conf"
...


/var/lib/opscenter-agent/confがcassandra側のエージェント設定ディレクトリのようです。
confディレクトリにはaddress.yamlしかないので、中身を見てみます。
# cat /var/lib/opscenter-agent/conf/address.yaml
stomp_interface: "10.0.0.39"


ググってみたところ、OpsCenter側でSSLをOFFにしてある場合エージェント側でもHTTPSをHTTPに切り替える必要があるようで、use_sslを0に設定するといいようです。
そこで3つのcassandraノードに以下のように設定しました。
# cat /var/lib/opscenter-agent/conf/address.yaml
stomp_interface: "10.0.0.39"
use_ssl: 0



そして、再びOpsCenterの画面をみると、以下の状態になっているので同じ手順で再度「Install on all nodes」をクリックします。





すると、うまくいったようで、OpsCenterの画面が更新されて、情報が表示されるようになりました!





左ペインのメニューを適当にクリックしてみると、、、

CLUSTER:RING VIEW」:ハッシュの分散状態を確認できます。




CLUSTER:PHYSICAL VIEW」:ap-north-eastにまとまっていることがわかります。(Ec2Snitchの場合)




CLUSTER:LIST VIEW」:リスト状にノードが表示されます。




PERFORMANCE」:各ノードや全体平均のパフォーマンス統計情報が表示されます。




Data Modeling」:KeySpaceやColumnFamilyなど、データモデルを追加編集できたりします。




Data Explorer」:登録されているデータも見ることができます。




EVENT LOG」:クラスタに起こったイベントのログを確認できます。



EDIT CLUSTER...」:クラスタの簡単な編集もできるようです。



CLUSTER」の各ビューでは各ノードのアクション(CLEAR、DISCOMMISION、REPAIRなど)もできるようです。一部は有償のEnterprise版にしかできない機能もあるようです。


まとめ



cassandraクラスタの状態がかなり直感的にわかりとても便利そうです。
そして、ここまでできて無料というのはすごいです。

これから勉強しながらちょっとずつ利用してみたいと思います。