shnagaiの日記

主にエンジニアリング関連のトピックについて雑多に書いています

mysql ibdata1を小さくする。テーブル全て作り直したというお話

fluentd経由でmysqlにログつっこんで、レンジパーティション切ってパーティション毎にdropで楽な運用にと思ってたのに、デフォルトだとinnodbのデータはibdata1にすべて格納されると知らず、それが肥大化しすぎて圧縮不可と知ったので、物理ファイルをテーブル毎に分けるため作り直した話

やった作業の備忘録(自分の為に)


$ sudo vim /etc/my.cnf

innodbのテーブル毎ファイル保管をオンにする
※新規にテーブル作成時に適用され圧縮等できるようになる
innodb_file_per_table = 1
innodb_data_file_path = ibdata1:1G:autoextend

自作スクリプトにて対象全テーブルのdump取得
$ sudo sh winevt_dump.sh

各テーブルの件数を確認しとく

対象テーブルを削除
mysql> drop database **db;
mysql> drop database **db;
mysql> drop database **db;

サービス停止
$sudo service mysqld stop

$sudo mv /var/lib/mysql/ibdata1 /tmp/
$sudo mv /var/lib/mysql/ib_logfile0 /tmp/
$sudo mv /var/lib/mysql/ib_logfile1 /tmp/

DB作成
mysql> create database **db;
mysql> create database **db;
mysql> create database **db;

dump取得時に一番小さいテーブルをまずリストアしてみる
解凍
$ gunzip tbl_**_db.sql.2014-05-13.gz

$ mysql -uroot -p -d **db --default-character-set=utf8
<tbl_**_db.sql.2014-05-13.gz

リストアして*.idbが作成されたことを確認する

ll /var/lib/mysql

drwx------ 2 mysql mysql       4096  5月 13 10:40 2014 **db

DB毎にディレクトリが切られてその下に.idbが出来てる

# ll **db
合計 135188
-rw-rw---- 1 mysql mysql        61  5月 13 10:40 2014 db.opt
-rw-rw---- 1 mysql mysql      8722  5月 13 10:40 2014 tbl_**.frm
-rw-rw---- 1 mysql mysql 138412032  5月 13 10:40 2014 tbl_**.ibd

ここで直近のデータ引いてデータ入っていることと件数を確認

ここまでくれば後は、同じ手順を繰り返す

退避したibdata1とログを消すの忘れずに。


一番感動したのは、パーティショニングしているテーブルはこんな感じでパーティション毎に物理ファイル分かれる。
これぞ求めていた形。

合計 506649600
-rw-rw---- 1 mysql mysql           61  5月 13 11:17 2014 db.opt
-rw-rw---- 1 mysql mysql 209660674048  5月 14 01:11 2014 tbl_**#P#p201403.ibd
-rw-rw---- 1 mysql mysql 202505191424  5月 14 09:23 2014 tbl_**#P#p201404.ibd
-rw-rw---- 1 mysql mysql 106640179200  5月 14 17:15 2014 tbl_**#P#p201405.ibd
-rw-rw---- 1 mysql mysql        98304  5月 13 16:44 2014 tbl_**#P#p201406.ibd
-rw-rw---- 1 mysql mysql        98304  5月 13 16:44 2014 tbl_**#P#p201407.ibd
-rw-rw---- 1 mysql mysql        98304  5月 13 16:44 2014 tbl_**#P#p201408.ibd
-rw-rw---- 1 mysql mysql        98304  5月 13 16:44 2014 tbl_**#P#p201409.ibd

自分の無知さでリカバリにだいぶ時間かかったがいい経験になったかな。。

ElasticSearch テンプレートでインデックスの型を指定する

ElasticSearchにデータを突っ込んで、文字列の完全一致の件数を集計したいことがあった。

ElasticSearchは、自動で型変換する全文検索エンジンなので特に型指定をしないと、下記のようにトークナイザによって要素分割されて格納される。

今回のケースでは、下記2つの文字列が格納されたレコードがある場合に、warnと完全一致するレコードの件数をカウントする為の方法を書こうと思う。

例)

①warn 123

②warn

ElasticSearchのクエリで、warnの文字列マッチングでLuceneクエリを書くと、

①+②が両方がカウントされて件数が出てきてしまう。

これは、ElasticSearch上で要素分解されて、②は[warn]+[123]のように格納される為、warnでの部分一致で上記検索にマッチしてしまう為である。

 

では、どうするか。

ElasticSearchにはテンプレートという機能があり、これを使えば要素分解せずに値を素のままで格納するような型指定[not_analyzed]を出来るのでこれを使う。

 

下記Qiitaの記事とjohtaniさんのElasticSearch入門を非常に参考にさせていただきました。ありがとうございます。

http://qiita.com/harukasan/items/4ec517d8d96f557367e1

http://blog.johtani.info/images/entries/20130830/IntroductionES20130829.pdf

 

任意の場所に下記のようなJSONを配置

※下記のテンプレートの意味は、

1.messageを要素分析された形とされない形で格納("type":"multi_field"

2.tagを要素分析されない形のみにするようなテンプレート

<syslog_template.json>

{
  "template":"syslog-*", //対象となるINDEX
  "mappings":{
    "_default_":{
      "_source":{"compress":true},
      "properties":{
        "message":{
          "type":"multi_field", //1の部分 multi_fieldの指定で一つのpropertiesに対して、複数のfieldを持たすこと可能
          "fields":{
            "message":{ //要素解析あり
              "type":"string",
              "index":"analyzed"
             },
            "full":{ //要素解析なし
              "type":"string",
              "index":"not_analyzed"
             }
          }
        },
        "tag":{
          "type":"string",
          "index":"not_analyzed"
        }
       }
      }
    }
  }
}

 

上記テンプレートを作ったら、下記リクエストをESに投げてテンプレートを設置

curl -XPUT localhost:9200/_template/syslog_template -d "`cat syslog_template.json`"

INDEX作成時しかテンプレートは読まれないようなので、既に出来ているインデックスに対しては、有効にならない。

今回の例で言うと、syslog-??というインデックスを新規作成するとテンプレートが読み込まれ意図した型のインデックスが出来ているはず。

 

新規に作成し、ElasticSearchのheadでmetadata確認したところ下記のように意図した型に。

message: {

    type: multi_field
    fields: {
        message: {
            type: string
        }
        full: {
            include_in_all: false
            index: not_analyzed
            omit_norms: true
            index_options: docs
            type: string
        }
    }
}
tag: {
    index: not_analyzed
    omit_norms: true
    index_options: docs
    type: string

}

 

後はLuceneのクエリで、message.fullに対してwarnを検索するとノイズなく完全一致のもののみ抽出出来る。

ちなみに、messageに対して同じクエリを投げると、部分一致も含んだセットが返される。これを使いわければElasticSearch+kibanaでのグラフ化の幅も広がりそうな気がした。

ElasticSearchは、文献少なくチューニングどころもまだまだわからないので引き続き研究していこうと思う。

Vagrant Chef 環境準備

chef soloのrecipeのテスト環境として、Vagrantを使うのがいいらしいと聞いたので、CentOS6.4の上に、Vagrantをインストールし、Vagrant上のマシンにローカルからIP指定でssh接続するまでの証跡を残しておこうと思う。

通常、 vagrant sshというコマンドを打てばVagrant上のマシンにはつなげるか、後々にknife-solo+chef soloでのテストを行う為、IPベースのsshでつなげるところまでやる。

今回の作業は、vagrantであげたインスタンスssh IPアドレスって形ログイン出来る事をゴールとします。

 

プラットホーム:Cent0S6.4

 

作業するにあたり、下記を非常に参考させていただきました。

■参照
参考URL:http://hirofukami.com/2013/10/11/install-chef-solve-way/
書籍:入門chefsolo

 

■概要

・VirutalBoxインストール

Vagrant+Saharaインストール

Vagrantでイメージの立ち上げからssh接続まで。

 

Web上では、すんなり出来たという情報が結構あったがそこそこハマったので同じエラーで困ってる人の役には立つかもしれません。

 

・VirutalBoxインストール
..VirtualBoxの準備
$ cd /etc/yum.repos.d/
$ wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
$ sudo yum install -y VirtualBox-4.2

Vagrant+Saharaインストール

$ sudo wget http://files.vagrantup.com/packages/a40522f5fabccb9ddabad03d836e120ff5d14093/vagrant_1.3.5_x86_64.rpm
$ sudo rpm -i vagrant_1.3.5_x86_64.rpm
$ vagrant -v
Vagrant 1.3.5
$ vagrant plugin install sahara
$ vagrant -h
Usage: vagrant [-v] [-h] command [<args>]

    -v, --version                    Print the version and exit.
    -h, --help                       Print this help.

Available subcommands:
     box
     destroy
     halt
     help
     init
     package
     plugin
     provision
     reload
     resume
     sandbox #これが追加されていればOK
     ssh
     ssh-config
     status
     suspend
     up

 

Vagrantでイメージの立ち上げからssh接続まで


#vagrantbox vagrant用のVirtualboximageをダウンロードする
$ vagrant box add cent64 http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130731.box

#任意のディレクトリを作成
$sudo mkdir /opt/vagrantbox/dev1
$cd /opt/vagrantbox/dev1
#vagrant初期化
$ sudo vagrant init
#networkの構成をいじる
$ vim Vagrantfile
  config.vm.box = "cent64"
  #config.vm.network :hostonly, "192.168.50.12" #これは古いバージョンのvagrantの指定方法らしい。。。
  config.vm.network :private_network, ip: "192.168.50.12"

#こけたー
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'cent64'...
Progress: 90%/opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/machine.rb:204:in`initialize': Permission denied -
/opt/vagrantbox/dev1/.vagrant/machines/default/virtualbox/id(Errno::EACCES)
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/machine.rb:204:in`open'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/machine.rb:204:in`open'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/machine.rb:204:in`id='
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/plugins/providers/virtualbox/action/import.rb:15:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/plugins/providers/virtualbox/action/customize.rb:38:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/plugins/providers/virtualbox/action/check_accessible.rb:18:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/runner.rb:61:in`block inrun'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/util/busy.rb:19:in`busy'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/runner.rb:61:in`run'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/builtin/call.rb:51:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/builtin/config_validate.rb:25:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/builtin/call.rb:57:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/plugins/providers/virtualbox/action/check_virtualbox.rb:17:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/warden.rb:34:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/builder.rb:116:in`call'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/runner.rb:61:in`block in run'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/util/busy.rb:19:in`busy'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/action/runner.rb:61:in`run'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/machine.rb:147:in`action'
        from /opt/vagrant/embedded/gems/gems/vagrant-1.3.5/lib/vagrant/batch_action.rb:63:in`block (2 levels) in run'

#エラーが出ているディレクトリのパーミッションを確認
$ find /opt/vagrantbox/dev1/.vagrant/machines/ -exec ls -al {} \;
#下記ディレクトリがrootのパーミッションになっていたのでファイル作成が出来ずパーミッションでこけていたよう。。
#vagrant initをsudoで行った事で、rootのパーミッションがついてしまったのかもしれない。。
drwxr-xr-x. 2 UserName UserName 4096  2月  5 21:48 2014 virtualbox
drwxr-xr-x. 3 UserName UserName 4096  2月  5 21:17 2014 default

#下記ディレクトリのパーミッションを自分に変える事でOK
$ sudo chown UserName:UserName /opt/vagrantbox/dev1/.vagrant/machines/default
$ sudo chown UserName:UserName
/opt/vagrantbox/dev1/.vagrant/machines/default/virtualbox/

#再度起動 出来たー
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'cent64'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
[default] Machine booted and ready!
[default] Configuring and enabling network interfaces...
[default] Mounting shared folders...
[default] -- /vagrant

#入れたー
$ vagrant ssh
Welcome to your Vagrant-built virtual machine.
$ pwd
/home/vagrant

#ローカルからIP指定のssh接続をする為の設定 knife-soloでchef-soloをつつく試験環境としたいので、
#ssh 192.168.50.12でつつけるようにする
#ローカル環境に戻り実行
$ vim ~/.ssh/config

#中身
# ~/.ssh/config
 Host 192.168.50.*
   IdentityFile ~/.vagrant.d/insecure_private_key
   User vagrant

#さぁ、つなげるか。。またエラー。。
$ ssh 192.168.50.12
Bad owner or permissions on /home/UserName/.ssh/config

#/home/UserName/.ssh/config このファイルのパーミッションが644であるのが原因なのでhomeユーザのみにする
$ chmod 600 /home/UserName/.ssh/config

#再チャレンジ 行けたー
$ ssh 192.168.50.12
Last login: Wed Feb  5 13:10:31 2014 from 192.168.50.1
Welcome to your Vagrant-built virtual machine.

参考までに今回実行したruby環境
$ which ruby
/usr/bin/ruby
$ gem -v
1.3.7
$ /opt/chef/embedded/bin/ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-linux]
$ /opt/chef/embedded/bin/gem -v
1.8.24

Fluentd メール通知 フィルタリングする

SYSLOG(warn以上)を、NW機器からFluentdに収集してエラー検知に役立てようと

思っているが、全てメール通知したのではノイズが多く運用に耐えない。

条件は、環境によりまちまちだが特定の条件を除外(出来る限りノイズを減らしたいという思い)し、

メール通知する事は出来ないかと考え、Fluentdのプラグインを使い比較的簡単に出来たのでメモ


収集の仕組みは、ここでは触れないがざっくり書くと
rsyslogで一度集めてセパレートして、/var/log/messageからwarn以上のログを別ファイルに保存

その別ファイルをFluentdのin_tailで読込む

※インプットプラグインにsyslogがあるようなので、近いうちにそちらに乗り換えればシンプルになるはず。地味に複雑なのは、1年前くらいに作った時にsyslogインプットが有ることを知らなかったから。。


■やりたい事

・ログレベルinfo,notice,warningは緊急性はないと考え通知対象から除外

・通知不要なものは、message部の文字列マッチングで随時除外出来る構成にする


■使用するプラグイン
・fluent-plugin-rewrite ※タグつけと正規表現による文字列除外や変換

  https://github.com/kentaro/fluent-plugin-rewrite

・fluent-plugin-mail ※マッチしたタグをメール送信する機能
  https://github.com/u-ichi/fluent-plugin-mail

 

■設定
手元の環境で、fluent-plugin-mailはインストールしているが、fluent-plugin-rewriteはなかったのでインストールから。


①リライトプラグインのインストール
# /usr/lib64/fluent/ruby/bin/gem install fluent-plugin-rewrite

Fetching: fluent-plugin-rewrite-0.0.12.

gem (100%)
Fetching: cool.io-1.1.1.gem (100%)
Building native extensions.  This could take a while...
Successfully installed fluent-plugin-rewrite-0.0.12
Successfully installed cool.io-1.1.1
2 gems installed
Installing ri documentation for fluent-plugin-rewrite-0.0.12...

Installing ri documentation for cool.io-1.1.1...
Installing RDoc documentation for fluent-plugin-rewrite-0.0.12...

Installing RDoc documentation for cool.io-1.1.1...

②アウトプットプラグインの設定

処理的には、in_tailでaaa.zタグが付けられたレコードに対して、

rewriteフィルタで除外条件をつける。

除外条件にマッチしないものは、mailというプレフィックスがつき、

次のマッチ条件でメール送信とファイル出力を行う。


<match aaa.z>

  type rewrite
  add_prefix mail #条件にマッチしたレコードにフィルタを追加

    <rule> #message部の除外文字列指定
      key message
      #ここに除外文字列を記載
      pattern ^.*(aaa).* #messageにaaaが含まれていたら除外
      ignore true
    </rule>

    <rule> #ログレベルがwarn以下の場合は除外
      key level
      pattern (info|notice|warning|warn)
      ignore true
    </rule>

</match>

<match mail.aaa.z>

  type copy

  <store>
    #mail送信部分
    type mail
    host #SMTPサーバIP
    port #接続ポート
    domain #送信元ドメイン
    from #送信元アドレス
    to #受信アドレス
    subject #タイトル なんでもいい
    message SYSLOG Alerts\n\n[Time]:%s\n\n[Host]:%s\n\n[Log_Level]:%s\n\n[Message]:%s\n \n\n #メッセージBODY

    message_out_keys time,host,level,message #メッセージに使うキー
  </store>

#動作確認で、ファイルでも見たいので。。
#運用にのったらいらなくなる。
  <store>
    type file
    path #出力パス Fluentdの起動ユーザに書込み権限ないとパーミッションエラーでこけるので注意。
  </store>
</match>

 

■簡単なテスト

お試しでログを吐いてみる
logger -s local0.err 'logtest'
logger -s local0.warn 'logtest'

実際のメールの本文
--------------------------------------
SYSLOG Alerts

[Time]:2014-01-29T19:41:06+09:00

[Host]:ホスト名

[Log_Level]:err

[Message]:logtest

--------------------------------------


ちゃんとwarnのレコードは除外されメール来ず、errのものだけ来ました。
ひとまずやりたい処理は出来ました。

tmuxインストール ~centos 6.4

tmuxを入れると、マルチターミナル環境を手に入れられると聞いたので、早速インストール。

centOS6.3からだと、yumでは入らないようなので、ソースから。

 

簡単だが、ちょっとだけつまずいたのでメモ程度に。

 

まずは、tmuxに必要なライブラリをインストール

 

# cd /usr/local/src

# wget https://github.com/downloads/libevent/libevent/libevent-2.0.20-stable.tar.gz

# tar zxvf libevent-2.0.20-stable.tar.gz

# cd libevent-2.0.20-stable

# ./configure

# make

# make install

 

 

# cd /usr/local/src

# wget downloads.sourceforge.net/tmux/tmux-1.7.tar.gz

# tar xzf tmux-1.7.tar.gz

# cd tmux-1.7

# ./configure

 

ncursesないと怒られるので

 

# yum -y install ncurses-devel

 

# make

# make install

 

# tmux

ライブラリが見つからないよ的なエラーが。。。

tmux: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory

 

#vi /etc/ld.so.conf.d/libevent.conf

中身

/usr/local/lib

 

これでライブラリの再読み込み

# ldconfig

 

# tmux

入れた。・

 

Linuxからwindows共有へ接続する

LinuxからWindowsの共有にアクセスしたいシチューエーションがあり、設定してみたのでメモ書き

 

.mountのインストール
# yum -y install mount

.samba-clientのインストール
# yum -y install samba-client

.マウントポイントの作成
# mkdir /win

.cifs関連のモジュールのインストール
※cifsは、smbの拡張でWindowsのファイル共有サービスに使うプロトコル
# yum install -y cifs*

.共有可能フォルダの表示
# smbclient -L '接続先IP' -U 'ユーザ名'

共有一覧表示

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        D$              Disk      Default share
        IPC$            IPC       Remote IPC
        share           Disk     

.共有フォルダのマウント
#mount -t cifs -o user='ユーザ名' '//マウント先IP/フォルダ' 'マウント元(今回の例で言うと/win)'
パスワード聞かれるので入力

.マウント確認
#ls -l /win

共有先のディレクトリ一覧が表示されれば成功

WindowsPE ブータブルUSB作成

Windwosがうまくブートしない場合の緊急復旧方法を検討すべくWindowsPEを使ってUSBブートに挑戦。

今回は、WindowsPEを使いブートしないPCをUSBブート出来るようにブータブルUSBを作成してみる
WAIKからWindowsPEをローカルに展開するまでの作業は下記のサイトを参考にさせていただいた
http://pnpk.net/cms/archives/293/all/1

USBメモリをブータブルディスクとしてフォーマット
#diskpart

#DISKPART> list disk
  ディスク      状態           サイズ   空き   ダイナ GPT
  ###                                          ミック
  ------------  -------------  -------  -------  ---  ---
  ディスク 0    オンライン           298 GB      0 B
  ディスク 1    オンライン          7648 MB      0 B
※ここでUSBのボリュームを確認(今回は1)

#select disk 1(list diskで確認したUSBのボリューム番号を指定)

#DISKPART> clean
DiskPart はディスクを正常にクリーンな状態にしました。

#DISKPART> create partition primary
DiskPart は指定したパーティションの作成に成功しました。

#DISKPART> active
DiskPart は現在のパーティションをアクティブとしてマークしました。

#DISKPART> list partition
※*がアクティブパーティションのマークなので一応確認
  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
* Partition 1    プライマリ             7647 MB  1024 KB

#DISKPART> format fs=fat32 quick
※FAT32でクイックフォーマット
  100% 完了しました
DiskPart は、ボリュームのフォーマットを完了しました。

#DISKPART> assign
DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。

②WindowsPEのイメージをUSBへコピー

xcopy <windowsPEのイメージ展開フォルダ>\ISO /s /e I:\

コピー完了したら、起動しないWindowsをこのUSBでブートしてみよう!!