2017年6月23日金曜日

Windows Defenderの定義ファイルを手動で適用するスクリプトを作った

自宅の検証環境にWindows Server 2016を評価版としてインストールして使っているのだが、Windows Defenderの定義ファイルがうまく更新できないという事象が発生している(WSUS環境なので、WSUS側の問題かもしれない)。

そのため、不定期に定義ファイルをダウンロードして、手動で適用していたのだが、それすらも面倒にもなってきたし、セキュリティ的にも可能な限り定義ファイルは最新にしておきたいと考え、スクリプトを組んで自動化することにした。

手作業でやる場合

Windows Defenderの定義ファイルをダウンロード元は、以下URLとなる。

・Updating your Microsoft antimalware and antispyware software
https://www.microsoft.com/en-us/security/portal/definitions/adl.aspx

「Antimalware and antispyware updates」の項目に、Microsoftの各セキュリティ製品の定義ファイルの最新リンクが記載されているので、該当するものをクリックしてダウンロードする。Windows Server 2016であれば、「Windows Defender in Windows 10 and Windows 8.1 - 64bit」を選べばよい。


「mpam-fe.exe」というexeファイルがダウンロードされる(2017年6月時点で124MB)。このexeファイルをダブルクリックで実行するだけで、定義ファイルが更新される。

スクリプトでやる場合

手作業でやっていた作業を単純にPowerShellで実行するスクリプト「update_windefender.ps1」を作成し、タスクスケジューラで1日1回実行するようにした。動作はPowerShell 3.0で確認している。

------------------------------
#
# Windows Defender定義ファイル更新スクリプト
# update_windefender.ps1
#

# 定義ファイルのダウンロード先を指定
$url = "http://go.microsoft.com/fwlink/?LinkID=121721&arch=x64"

# 定義ファイルのダウンロードフォルダを指定
$workdir = "c:\work\"

# 実行コマンド
$cmd = $workdir + "mpam-fe.exe"

# 定義ファイルをダウンロード
Invoke-WebRequest -Uri $url -OutFile $cmd

# 適用チェック
if ( (Get-Item $cmd).VersionInfo.FileVersion -eq (Get-MpComputerStatus).AntivirusSignatureVersion ){
   echo "定義ファイルは最新です。"   
}else{
   echo "定義ファイルを更新します。"

   # 更新処理
   Start-Process $cmd -Wait
}
------------------------------

シンプルなスクリプトではあるが、Windows版wgetのようなInvoke-WebRequestコマンドの存在を知ることができたり、久しぶりにPowerShellに触れたこともあって、なかなか楽しく作ることができた。

参考

・Defender Cmdlets
https://technet.microsoft.com/ja-jp/library/dn433280.aspx



2017年6月17日土曜日

Zabbixを使ってWindowsとLinuxのログイン失敗を監視する

近年、セキュリティ上の問題から、不正アクセスへの対策は必要不可欠になっている。WindowsやLinuxであれば、ログイン失敗のログはOS標準機能にて出力されているので、そのログをZabbixにて監視させることで、予期しない不正ログインをリアルタイムに捉えることができる。

今回はWindowsとLinuxでログイン失敗した際に、Zabbixを使って検知する方法を記載する。動作確認は以下OSで実施した。

・Windows:Windows Server 2016 (他バージョンも同様に対応可能)
・Linux:CentOS 6、7 (RHELも同様に対応可能)

Windowsの場合

Windowsではログイン失敗時に、セキュリティイベントログに以下が記録される。

------------------------------
失敗の監査 2017/05/30 21:15:28 Microsoft Windows security auditing. 4625 ログオン
------------------------------

上記ログのイベントID 4625をZabbixで検知させる。アイテムとトリガーを以下のように設定すればよい。

◆アイテムを設定
・名前:Eventlog Security
・タイプ:Zabbixエージェント(アクティブ)
・キー:eventlog[Security,,,,4625,,skip]
・データ型:ログ
・更新間隔(秒):30
・ヒストリ保存期間(日):7
・アプリケーション:<任意>


◆トリガーを設定
・名前:Eventlog Security
・条件式:{Template OS Windows:eventlog[Security,,,,4625,,skip].strlen()}>0
・障害イベントを継続して生成:チェック
・深刻度:軽度の障害


Linuxの場合

Linuxではログイン失敗時に、/var/log/secureに以下が記録される。

------------------------------
May 30 21:53:28 t3023ce72 sshd[28426]: Failed password for root from 192.168.11.81 port 62145 ssh2
↑★sshログイン失敗

May 30 21:51:39 t3023ce72 login: FAILED LOGIN 1 FROM tty1 FOR root, Authentication failure
↑★コンソールログイン失敗
------------------------------

上記ログに出力される"Failed password"と"FAILED LOGIN"をZabbixで検知させる。アイテムとトリガーを以下のように設定すればよい。

◆アイテムを設定
・名前:secure
・タイプ:Zabbixエージェント(アクティブ)
・キー:log[/var/log/secure,"Failed password|FAILED LOGIN",,,skip]
・データ型:ログ
・更新間隔(秒):30
・ヒストリ保存期間(日):7
・アプリケーション:<任意>


◆トリガーを設定
・名前:secure
・条件式:{Template OS Linux:log[/var/log/secure,"Failed password|FAILED LOGIN",,,skip].strlen()}>0
・障害イベントを継続して生成:チェック
・深刻度:軽度の障害


実際に検知した結果

実際にログイン失敗をしてみると、Zabbixのダッシュボードに障害として上がることが確認できた。


2017年6月7日水曜日

WSFC / MSFC入門

Windows Serverを使う場合、WSFC (Windows Server Failover Clustering)、別名MSFC (Microsoft Failover Clustering)を使ってクラスターを組む場合が多いと思う。クラスターというと、とっつきにくいイメージがあるかもしれないが、今回、Windows Server 2012 R2を使って、サクッとクラスターサーバーを作ってみたいと思う。

WSFCの呼び方は複数ある

余談だが、WSFCはOSや時期によって名前が変わってきており、以下のようになっている。

 ・MSCS:Windows Server 2003 R2以前
 ・WSFC / MSFC:Windows Server 2008 以降

Windows Server 2012 R2のGUI上では、カタカナでフェールオーバークラスターと表記されていたりする。Microsoftのサイトを見る限りでは、WSFCが公式な略称として使用されているようだ。

・例:Windows Server フェールオーバー クラスタリング (WSFC) と SQL Server
https://msdn.microsoft.com/ja-jp/library/hh270278.aspx

本記事では、WSFCで記載を統一することにする。

WSFCの前提条件と今回の構成

WSFCを構成する上での前提条件を以下に記載する。

・同一ドメインに所属することが必要 (すなわちドメインコントローラーが必要)
・クラスター用にIPが1つ、アプリケーション用にIPが1つ必要
・クラスター通信用のネットワークは2つ用意することが推奨 (必須ではないが可用性の観点から推奨)
・アプリケーション用に共有ディスクが必要 (今回はiSCSIで構築)
・クォーラムディスク用に1GB程度の共有ディスクの用意を推奨 (今回はiSCSIで構築)

条件をふまえて、今回のサーバー構成は以下の通りとした。


それでは、上記を構成する手順を順に追っていこう。

WSFC構成手順

1. 共有ディスクをマウント

今回はiSCSIにて2台のノードで共有するディスクをマウントする。マウントする方法は別記事を参照。マウント後は以下のようになる。Eドライブをクラスター用の共有ディスクとし、Qドライブはクォーラム監視用に使用する。


2. 機能を追加

「サーバーマネージャー」の「役割と機能の追加」から「フェールオーバークラスタリング」の機能を両方のノードに追加する。ここは特に難しい設定はなく、ひたすら次へを押していけばよい。


3. フェールオーバークラスターマネージャーの起動

「サーバーマネージャー」の「ツール」から「フェールオーバークラスターマネージャー」を選択する。


4. クラスターの構成の検証

左ペインの「フェールオーバークラスターマネージャー」を右クリックし、「構成の検証」を選択すると、クラスターを組むにあたって、必要な前提条件の確認を自動で検証してくれる。なお、構成の検証は、クラスター作成が初回時の場合も実施を促されるため、一度は実施する必要がある。


構成の検証が終わると、最後にレポートの表示をすることができる。「カテゴリ別の結果」が、すべて「成功」となっていることを確認しておこう。


5. クラスターの作成

検証が終わったら、再度、左ペインの「フェールオーバークラスターマネージャー」を右クリックし、「クラスターの作成」を選択する。

この際にクラスター管理用のクラスター名とIPアドレスの入力を促されるため、適切に設定する。ここで設定したクラスター名とIPアドレスは、ホスト名としてADに登録される。

「使用可能な記憶域をすべてクラスターに追加する」について、今回は手動でディスクの追加を行うこととするため、チェックは外しておく。


クラスターの作成が完了すると、1点警告が表示されるが、クォーラム監視が設定されていないという内容であり、この後の作業で実施するため無視して問題ない。


6. ディスクの追加

左ペインの「フェールオーバークラスターマネージャー」→「クラスター名」→「記憶域」→「ディスク」を右クリックし、「ディスクの追加」を選択すると、「クラスターへのディスク追加」のポップアップが表示されるため、追加したいディスクを選択して「OK」をクリックする。


ディスクが追加されると、デフォルトではディスクの名前が「クラスター ディスク X」という名前となっており判別しづらいので、右クリック→「プロパティ」から名前を変更しておくと管理が楽になる。


最終的にディスクの状態は以下のようになる。EドライブとQドライブが「使用可能記憶域」という状態で追加されている。


7. クォーラムの設定

「フェールオーバークラスターマネージャー」→「クラスター名」を右クリックし、「他のアクション」→「クラスタークォーラム設定の構成」を選択する。


クォーラム監視にはいくつか方式があるようだが、「標準のクォーラム構成を使用する」を選択しておけば、自動的に最適なものが選択される模様。


クォーラム監視のオプションの説明はMicrosoftのサイトに記載があるため、詳細はそちらを参照すること。

・Windows Server 2012 フェールオーバー クラスターでクォーラムを構成および管理する
https://technet.microsoft.com/ja-jp/library/jj612870(v=ws.11).aspx

標準構成で選ばれた構成は以下の通りとなった。

 ------------------------------
 ・監視の種類     :ディスク監視
 ・監視リソース    :Qドライブ
 ・クラスターの管理投票:有効
 ------------------------------

8. 汎用アプリケーションの追加

以上でクラスターの準備は整ったので、実際にアプリケーションをクラスター化してみよう。

今回は簡易的なWebサーバとして、MiniWeb HTTP serverをクラスター化してみることにする。

まず、事前準備として、解凍したMiniWeb HTTP serverのフォルダをEドライブ直下に配置し、コマンドプロンプトで使い方を確認しておく。

E:\miniweb>miniweb.exe -h
------------------------------
MiniWeb (build 300, built on Feb 28 2013)
(C)2005-2013 Written by Stanley Huang <stanleyhuangyc@gmail.com>

Usage: miniweb -h | -u  : display this help screen
               -v       : log status/error info
               -p       : specifiy http port [default 8000]
               -r       : specify http document directory [default .]
               -l       : specify log file
               -m       : specifiy max clients [default 32]
               -M       : specifiy max clients per IP
               -n       : disallow multi-part download
               -d       : disallow directory listing [default ON]
------------------------------

ポート番号は80番にしたいので、実行コマンドは以下の通りとなる。

E:\miniweb\miniweb.exe -p 80

「フェールオーバークラスターマネージャー」→「クラスター名」→「役割」を右クリックし、「役割の構成」を選択する。「高可用性ウィザード」が表示されるので、以下のように設定する。

 ------------------------------
 ・役割の選択          :汎用アプリケーション
 ・汎用アプリケーションの設定
  ・コマンドライン       :E:\miniweb\miniweb.exe
  ・パラメーター        :-p 80
 ・クライアントアクセスポイント
  ・名前            :t1192wsfc
  ・アドレス          :192.168.11.192
 ・記憶域の選択         :Eドライブを割り当て
 ・レジストリ設定のレプリケート :設定なし
 ------------------------------


上記を設定し、構成を終えると最後にレポートが表示される。以下2つの警告が表示されるが、フェールオーバー可能であり、動作には影響なさそうだった。

 ・この役割をサポートしているリソースの種類があるノードは t1121w12r のみです。
 ・この役割をホストできないノードは t1122w12r です。


これでMiniWeb HTTP serverがクラスターに組み込まれた。試しに適当なHTMLファイル(タイトルとブラウザのUser-agentを表示するだけ)を配置して、ブラウザでクラスター用IPアドレス(192.168.11.192)にアクセスすると、正常にHTMLが表示された。


9. フェールオーバーの動作確認

動作確認のため、実際にフェールオーバーさせてみよう。タスクマネージャーから、miniweb.exeを終了させればよい。なお、1回は再起動を試みて復活するので、2回終了させるとフェールオーバーする。

以下は切り替わり後の状態となるが、所有者ノードがt1122w12rになっていることがわかる。当然、Webサーバにも問題なくアクセスできた。


以上でクラスターの構成は終了となる。実際は細かい設定(エラー時の再起動の試行回数や、各クラスターリソースの依存関係の設定)など、いろいろチューニングする要素はあるものの、比較的少ない手順でクラスターを組むことができた。

参考

・MiniWeb HTTP server
https://sourceforge.net/projects/miniweb/


2017年6月1日木曜日

ZabbixのMySQLのDBをバックアップして、リストアする方法

自宅の検証環境の監視用にZabbixを構築しており、DBはMySQLを選択しているが、たまにはDBのバックアップを取得したいと思い実施方法を調べてみた。

バックアップ方法

mysqldumpコマンドでバックアップは実行できるようだ。構文は以下の通り。

# mysqldump -u <ユーザー名> -p <DB名> > <出力ファイル名>.sql

試しに実行してみよう。

# mysqldump -u zabbix -p zabbix > mysqldump_zabbix_`date +"%Y%m%d"`.sql
------------------------------
Enter password:   ←★MySQLの"zabbix"ユーザーのパスワードを入力
------------------------------

ファイルを確認してみると、以下のようにファイルが出力されている。

# ls -l
------------------------------
-rw-r--r--  1 root root 1525531580  5月 28 21:33 2017 mysqldump_zabbix_20170528.sql
------------------------------

ちなみに、mysqldumpは、MySQLのDBの中身をひたすらSQL文としてテキスト出力するコマンドとなっており、出力ファイルの中身はテキストデータになっている。テキストデータなので、圧縮するとファイルサイズがだいぶ小さくなるので、容量効率の観点からは圧縮するのもおすすめとなる。

試しに私の環境のバックアップファイルをzipで圧縮したら、7割以上の容量が削減できた。

# zip mysqldump_zabbix_20170528.sql.zip mysqldump_zabbix_20170528.sql
------------------------------
  adding: mysqldump_zabbix_20170528.sql
 (deflated 73%)   ←★73%の容量が削減された、という意味
------------------------------

以上のように簡単に使えるmysqldumpであるが、1点問題があって、実行中はDBがロックされるため、バックアップ中はZabbixのGUI操作ができなくなり、監視にも影響がでるものと考えられる。

上記問題を回避するために、DBをロックさせないオプションとして、"--single-transaction"を付与することで、ロックを掛けずにバックアップを取得可能となる。

# mysqldump -u zabbix -p --single-transaction zabbix > mysqldump_zabbix_`date +"%Y%m%d"`.sql

上記コマンドであれば、バックアップ取得中であっても、ZabbixのGUI操作は継続して実施可能となる。

リストア方法

バックアップファイルからリストアを行う場合、mysqldumpはSQL文のテキストファイルなので、そのままSQL文としてMySQLに流してしまえばよい。

以下に簡単にリストアの手順を記載する。

1. zabbix-serverの停止

リストア中はDBが使えなくなるため、zabbix-serverを停止しておく。
# service zabbix-server stop
------------------------------
Shutting down zabbix server:                               [  OK  ]
------------------------------

2. ZabbixのDBを削除

MySQLにログインし、リストア対象のDBを削除する。

まずは、MySQLにログインする。

# mysql -u root -p

事前にDBの一覧を確認しておく。今回の削除対象は"zabbix"となる。

mysql> show databases ;
------------------------------
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
| zabbix             |   ←★削除対象
+--------------------+
4 rows in set (0.00 sec)
------------------------------

DBを削除する。

mysql> drop database zabbix ;
------------------------------
Query OK, 108 rows affected (0.07 sec)
------------------------------

削除後のDB一覧を確認し、問題なく削除されていることを確認する。

mysql> show databases ;
------------------------------
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test               |
+--------------------+
2 rows in set (0.00 sec)
------------------------------

MySQLからログオフする。

mysql> quit

3. MySQLを停止し不要ファイルを削除

DB削除後に不要なファイルの削除を行うため、一度MySQLを停止する。

# service mysqld stop
------------------------------
mysqld を停止中:                                           [  OK  ]
------------------------------

削除前にファイルを確認する。ib_logfile*とibdata1を削除する。これらはInnoDBの更新用のファイルらしいが、リストアしてMySQL起動時に再作成されるとのことなので、削除して問題ないようだ。

# ls -l /var/lib/mysql/
------------------------------
-rw-rw----  1 mysql mysql 268435456  5月 29 14:53 2017 ib_logfile0   ←★削除対象
-rw-rw----  1 mysql mysql 268435456  5月 28 21:33 2017 ib_logfile1   ←★削除対象
-rw-rw----  1 mysql mysql  35651584  5月 29 14:53 2017 ibdata1       ←★削除対象
drwx------. 2 mysql mysql      4096  3月 19 23:04 2016 mysql
drwx------. 2 mysql mysql      4096  3月 19 23:04 2016 test
------------------------------

以下コマンドで不要ファイルを削除する。

# rm -f /var/lib/mysql/ibdata1
# rm -f /var/lib/mysql/ib_logfile*

4. MySQLを起動

# service mysqld start
------------------------------
mysqld を起動中:                                           [  OK  ]
------------------------------

5. Zabbix用のDBを再作成

DBを作り直し、zabbixユーザーに権限を付与しておく。

mysql> create database zabbix ;
------------------------------
Query OK, 1 row affected (0.00 sec)
------------------------------

mysql> grant all privileges on zabbix.* to zabbix@localhost ;
------------------------------
Query OK, 0 rows affected (0.00 sec)
------------------------------

6. リストア実施

mysqldumpのバックアップファイルをSQL文として、DBに流し込む。

# mysql -u root -p zabbix < /root/mysqldump_zabbix_20170528.sql

7. zabbix-serverの起動

zabbix-serverを起動する。

# service zabbix-server start
------------------------------
Starting zabbix server:                                    [  OK  ]
------------------------------

以上でリストアは完了。問題なくZabbixのGUIにログインできるはず。

以下はリストア後のグラフの表示となる。当たり前だが、バックアップ取得からリストアまでのデータは失われてしまうが、グラフが描画が正常に再開していることがわかる。



2017年5月26日金曜日

GraylogのElasticsearchのデータを削除する ("Elasticsearch cluster unhealthy (RED)"のエラーを解消する②)

前回、Graylogのディスク拡張を実施したが、以下Elasticsearchのエラーは解消されない状態となっていた。

------------------------------
Elasticsearch cluster unhealthy (RED)
The Elasticsearch cluster state is RED which means shards are unassigned. This usually indicates a crashed and corrupt cluster and needs to be investigated.

~(以下略)~
------------------------------

この状態ではGraylogで受信したログの検索ができない状態となるため、どうにかして復旧する必要があった。復旧までの手順を本記事にて記載するが、先に言っておくと、Elasticsearchのデータを消すことによって対処をした(復旧というより初期化という表現が近いかもしれない)。

大活躍するcurlコマンド

Elasticsearchでは、各種URLにHTTPアクセスをすると、結果を返したり、設定をしたりすることができる。どうもこれがREST APIと呼ばれるものらしいが、とにかくまずは各種確認をしてみることにした。

この際に利用できるコマンドがcurlコマンドである。client for URLの略(?)で、カールと呼ぶようだ。このコマンドでHTTPリクエストを送るとHTTPレスポンスを受けることができる。

例えば、Elasticsearchの状態確認は以下コマンドで実行できる。

◆Elasticsearchの状態確認
# curl -XGET http://192.168.11.151:9200/_cluster/health?pretty=true
------------------------------
{
  "cluster_name" : "graylog",
  "status" : "red",
  "timed_out" : false,
  "number_of_nodes" : 2,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 2,
  "active_shards" : 2,
  "relocating_shards" : 0,
  "initializing_shards" : 2,
  "unassigned_shards" : 4,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 25.0
}
------------------------------

上記下線部にて、冒頭のエラーと同様に、statusが"red"となっていることがわかる。

さて、このコマンドで各種確認をしてみる。まずはNodeとShardの状態を確認。

◆Nodeの確認
# curl -XGET http://192.168.11.151:9200/_node/cat/nodes
------------------------------
192.168.11.151 192.168.11.151 24 82 3.12 d * Manbot
192.168.11.151 192.168.11.151 46 82 3.12 c - graylog-bbbebd4f-8c8b-406a-8a33-b51f00e6facc
------------------------------

◆Shardの確認
# curl -XGET http://192.168.11.151:9200/_cat/shards
------------------------------
graylog_0 3 p STARTED      1633383 439.5mb 192.168.11.151 Manbot
graylog_0 3 r UNASSIGNED                                      
graylog_0 1 p INITIALIZING                 192.168.11.151 Manbot
graylog_0 1 r UNASSIGNED                                      
graylog_0 2 p STARTED      1632406 438.6mb 192.168.11.151 Manbot
graylog_0 2 r UNASSIGNED                                      
graylog_0 0 p INITIALIZING                 192.168.11.151 Manbot
graylog_0 0 r UNASSIGNED                                      
------------------------------

下線部が"STARTED"ではなく、"INITIALIZING"となっているのがあやしい…。

もっと詳細な状態確認は以下コマンドで実施する。

◆詳細状態確認
# curl -XGET http://192.168.11.151:9200/_cluster/state?pretty=true
------------------------------
{
  "cluster_name" : "graylog",
  "version" : 131,
  "state_uuid" : "-R-stME1QAK2WkC4kZS6tQ",
  "master_node" : "GKmS2bPySZ69oHVcxwbTqg",
  "blocks" : { },
  "nodes" : {
    "GKmS2bPySZ69oHVcxwbTqg" : {
      "name" : "Orphan-Maker",
      "transport_address" : "192.168.11.151:9300",
      "attributes" : { }
    },
    "U9D_Bp0NTpKauX89rKWsvg" : {
      "name" : "graylog-bbbebd4f-8c8b-406a-8a33-b51f00e6facc",
      "transport_address" : "192.168.11.151:9350",
      "attributes" : {
        "client" : "true",
        "data" : "false",
        "master" : "false"
      }
    }
  },

~(中略)~

            "state" : "INITIALIZING",
            "primary" : true,
            "node" : "GKmS2bPySZ69oHVcxwbTqg",
            "relocating_node" : null,
            "shard" : 1,
            "index" : "graylog_0",
            "version" : 36,
            "allocation_id" : {
              "id" : "JFJ78yB9Qf6o6s9TfOnrbw"
            },
            "unassigned_info" : {
              "reason" : "ALLOCATION_FAILED",
              "at" : "2017-05-12T14:37:29.179Z",
              "details" : "failed recovery, failure IndexShardRecoveryException[failed to recovery from gateway]; nested: EngineCreationFailureException[failed to recover from translog]; nested: EngineException[failed to recover from translog]; nested: ElasticsearchException[unexpected exception reading from translog snapshot of /var/opt/graylog/data/elasticsearch/graylog/nodes/0/indices/graylog_0/1/translog/translog-855.tlog]; nested: EOFException[read past EOF. pos [532245] length: [4] end: [532245]]; "
            }
          },

~(以下略)~
------------------------------

"INITIALIZING"の理由が記載されているような気がするが、、、残念ながら、これを見ても解決方法はよくわからなかった。

データを消して復旧

結局直し方がよくわからず、最終手段として過去データを削除してみることにした。

まず"Index"の状態を確認する。これはいわばElasticsearchのデータが蓄えられるデータベース領域のようなものである。

◆Indexの確認
# curl -XGET http://192.168.11.151:9200/_cat/indices
------------------------------
red open graylog_0 4 1 3265789 0 878.1mb 878.1mb
------------------------------

現在は878MBを使っている模様。以下コマンドでデータを削除する。

◆データを削除
# curl -XDELETE http://192.168.11.151:9200/graylog_0
------------------------------
{"acknowledged":false}
------------------------------

再度、Indexの確認をする。

◆Indexの確認
# curl -XGET http://192.168.11.151:9200/_cat/indices
------------------------------
red open graylog_0 4 1 0 0 390b 390b
------------------------------

容量が390Bに減少していることがわかる。ディスク使用量を確認してみる。

# df -h
------------------------------
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G  4.0K  2.0G   1% /dev
tmpfs           396M  692K  395M   1% /run
/dev/dm-0        15G  2.7G   12G  19% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none            2.0G     0  2.0G   0% /run/shm
none            100M     0  100M   0% /run/user
/dev/sda1       236M   74M  150M  34% /boot
/dev/sdb1        40G  805M   37G   3% /var/opt/graylog/data
------------------------------

もともと11GBあったデータが805MBまで減ったことがわかる。

これで一度Shardの状態を確認する

◆Shardの確認
# curl -XGET http://192.168.11.151:9200/_cat/shards
------------------------------
graylog_0 3 p STARTED    0 130b 192.168.11.151 Manbot
graylog_0 3 r UNASSIGNED                            
graylog_0 1 p STARTED    0 130b 192.168.11.151 Manbot
graylog_0 1 r UNASSIGNED                            
graylog_0 2 p STARTED    0 130b 192.168.11.151 Manbot
graylog_0 2 r UNASSIGNED                            
graylog_0 0 p UNASSIGNED                            
graylog_0 0 r UNASSIGNED                            
------------------------------

少なくとも"INITIALIZING"となっているShardはいなくなったように見える。一度OSを再起動して再度確認してみる。

◆Shardの確認
# curl -XGET http://192.168.11.151:9200/_cat/shards
------------------------------
graylog_0 2 p STARTED    2701 751.9kb 192.168.11.151 Steve Rogers
graylog_0 2 r UNASSIGNED                                        
graylog_0 3 p STARTED    2531 772.3kb 192.168.11.151 Steve Rogers
graylog_0 3 r UNASSIGNED                                        
graylog_0 1 p STARTED    2579   762kb 192.168.11.151 Steve Rogers
graylog_0 1 r UNASSIGNED                                        
graylog_0 0 p STARTED    2608 751.5kb 192.168.11.151 Steve Rogers
graylog_0 0 r UNASSIGNED                                        
------------------------------

上記の通り、4つのShardが"STARTED"となった。Elasticsearchの状態も確認してみる。

◆Elasticsearchの状態確認
# curl -XGET http://192.168.11.151:9200/_cluster/health?pretty=true
------------------------------
{
  "cluster_name" : "graylog",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 2,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 4,
  "active_shards" : 4,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 4,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 50.0
}
------------------------------

statusが"yellow"となり"red"よりは解消された。一応この状態であれば、ログの検索は実施できるようではある。さらに"yellow"を"green"にするためには、以下の通り、ReplicaのShardの数を0に設定すればよいようだ。

------------------------------コマンドここから
# curl -XPUT 'http://192.168.11.151:9200/_settings' -d '
{
    "index" : {
        "number_of_replicas" : 0
    }
}'
------------------------------コマンドここまで
------------------------------
{"acknowledged":true}
------------------------------

Shardの状態を確認する。

◆Shardの確認
# curl -XGET http://192.168.11.151:9200/_cat/shards
------------------------------
graylog_0 2 p STARTED 90501 23.6mb 192.168.11.151 Steve Rogers
graylog_0 3 p STARTED 90342 23.5mb 192.168.11.151 Steve Rogers
graylog_0 1 p STARTED 90677 23.6mb 192.168.11.151 Steve Rogers
graylog_0 0 p STARTED 90231 23.5mb 192.168.11.151 Steve Rogers
------------------------------

◆Elasticsearchの状態確認
# curl -XGET http://192.168.11.151:9200/_cluster/health?pretty=true
------------------------------
{
  "cluster_name" : "graylog",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 2,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 4,
  "active_shards" : 4,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}
------------------------------

以上でElasticsearchのステータスを"red"から"green"に回復させることができた。しかし、データをすべて消すという、復旧方法としてはかなり乱暴な方法となってしまったので、データを消さずに復旧する方法は引き続き調査したい。

2017年5月19日金曜日

Graylogの仮想アプライアンスでログ保存領域のディスク拡張を実施する ("Elasticsearch cluster unhealthy (RED)"のエラーを解消する①)

自宅環境のログ統合管理のために、仮想アプライアンスのGraylogを導入しているが、先日以下のようなエラーが出てログが収集できなくなってしまった。

------------------------------
Elasticsearch cluster unhealthy (RED)
The Elasticsearch cluster state is RED which means shards are unassigned. This usually indicates a crashed and corrupt cluster and needs to be investigated.

~(以下略)~
------------------------------


Elasticsearchがエラーを吐いているようだ。とりあえず原因切り分けしていこう。

原因切り分け

仮想アプライアンスのGraylogの場合、Elasticsearchの動作ログは以下URLに記載のある通り、/var/log/graylog/elasticsearchにあるようなので、そのディレクトリにあるgraylog.log確認してみる。

http://docs.graylog.org/en/2.2/pages/configuration/file_location.html#id5

# tail /var/log/graylog/elasticsearch/graylog.log
------------------------------
~(省略)~

at org.elasticsearch.index.engine.InternalEngine.recoverFromTranslog(InternalEngine.java:235)
... 12 more
Caused by: java.io.EOFException: read past EOF. pos [532245] length: [4] end: [532245]
at org.elasticsearch.common.io.Channels.readFromFileChannelWithEofException(Channels.java:102)
at org.elasticsearch.index.translog.ImmutableTranslogReader.readBytes(ImmutableTranslogReader.java:84)
at org.elasticsearch.index.translog.TranslogReader.readSize(TranslogReader.java:91)
... 19 more
[2017-05-12 21:34:21,922][WARN ][cluster.routing.allocation.decider] [Cody Mushumanski Gun Man] high disk watermark [90%] exceeded on [6-FCB92qRk2n76qo6h1PSg][Cody Mushumanski Gun Man][/var/opt/graylog/data/elasticsearch/graylog/nodes/0] free: 987.6mb[6.4%], shards will be relocated away from this node
------------------------------

下線部があやしい…。どうもディスク使用率が90%を超えて、ElasticsearchのShardがNodeから除外された、といったメッセージに見える。
※NodeやShardといった単語はElasticsearchの用語となるが、この説明は今回は割愛する

dfでディスク使用率を確認してみる。

# df -h
------------------------------
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G  4.0K  2.0G   1% /dev
tmpfs           396M  692K  395M   1% /run
/dev/dm-0        15G   14G  981M  94% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none            2.0G     0  2.0G   0% /run/shm
none            100M     0  100M   0% /run/user
/dev/sda1       236M   74M  150M  34% /boot
------------------------------

確かに、/のディスク使用率が94%になっている。どうやらディスク使用率が90%を超えると、Graylogの中で動いているElasticsearchは動作を止めてしまうようだ。ということで、ディスク拡張を行い復旧を試みることにした。

なお、先に言っておくと、ディスク拡張自体は成功したが、冒頭のエラーはディスク拡張だけでは解消しなかった。

ディスク拡張手順

ディスク拡張手順は以下にマニュアルが用意されているので、そのまま実施すればよい。解説を加えつつ実施していこう。

http://docs.graylog.org/en/2.2/pages/configuration/graylog_ctl.html#extend-ova-disk

1. 仮想マシンにディスクを追加

ログ保存用のディスクとして、vSphere Clientで仮想ハードディスクを追加する。


2. Graylogを再起動

ディスクを認識させるため、一度再起動しておく。

$ sudo shutdown -r now

3. Graylogのサービスを停止

作業中はGraylogのサービスを停止しておく。

$ sudo graylog-ctl stop
------------------------------
timeout: run: elasticsearch: (pid 861) 83s, want down, got TERM
ok: down: etcd: 0s, normally up
ok: down: graylog-server: 0s, normally up
ok: down: mongodb: 1s, normally up
ok: down: nginx: 0s, normally up
------------------------------

4. ディスクが認識確認

以下コマンドで確認できる。/dev/sdbとして認識していればOK。今回は40GiBのディスクを追加してみた。

$ sudo lshw -class disk
------------------------------
DMI   SMP   PA-RISC       device-tree           SPD   memory      /proc/cpuinfo             CPUID     PCI (sysfs)           ISA PnP       PCMCIA      PCMCIA      kernel device tree (sysfs)                          USB   IDE   SCSI    Network interfaces                  Framebuffer devices                   Display       CPUFreq       ABI     *-disk
       description: SCSI Disk
       physical id: 0.0.0
       bus info: scsi@2:0.0.0
       logical name: /dev/sdb
       size: 40GiB (42GB)
       configuration: sectorsize=512
  *-disk
       description: ATA Disk
       product: VMware Virtual I
       physical id: 0.0.0
       bus info: scsi@0:0.0.0
       logical name: /dev/sda
       version: 0001
       serial: 00000000000000000001
       size: 19GiB (20GB)
       capabilities: partitioned partitioned:dos
       configuration: ansiversion=5 sectorsize=512 signature=000c6ec2
------------------------------

5. ディスクフォーマット

以下3つのコマンドで/dev/sdbのフォーマットを行う。

$ sudo parted -a optimal /dev/sdb mklabel gpt
------------------------------
Information: You may need to update /etc/fstab.
------------------------------

$ sudo parted -a optimal -- /dev/sdb unit compact mkpart primary  ext3 "1" "-1"
------------------------------
Information: You may need to update /etc/fstab.
------------------------------

$ sudo mkfs.ext4 /dev/sdb1
------------------------------
mke2fs 1.42.9 (4-Feb-2014)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
2621440 inodes, 10485248 blocks
524262 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
320 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
4096000, 7962624

Allocating group tables:   0/320       done                            
Writing inode tables:   0/320       done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information:   0/320       done
------------------------------

6. /mnt/tmpに新ディスクをマウント

データコピーのため、新ディスクを/mnt/tmpにマウントする。

$ sudo mkdir /mnt/tmp
$ sudo mount /dev/sdb1 /mnt/tmp
$ df -h
------------------------------
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G  4.0K  2.0G   1% /dev
tmpfs           396M  692K  395M   1% /run
/dev/dm-0        15G   14G  981M  94% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none            2.0G     0  2.0G   0% /run/shm
none            100M     0  100M   0% /run/user
/dev/sda1       236M   74M  150M  34% /boot
/dev/sdb1        40G   48M   38G   1% /mnt/tmp   ←★マウントされた
------------------------------

7. データコピー

Graylogのデータを旧ディスクから新ディスクにコピーする。データは以下ディレクトリに入っているすべてのファイルとなる。

$ ls -l /var/opt/graylog/data/
------------------------------
total 16
drwxr-x--- 3 graylog graylog 4096 Apr  1 11:59 elasticsearch
drwxr-x--- 3 graylog graylog 4096 May 12 21:40 etcd
drwxr-x--- 3 graylog graylog 4096 May 12 21:41 journal
drwxr-x--- 4 graylog graylog 4096 May 12 21:41 mongodb
------------------------------

cpコマンドでデータをコピーする。容量によっては時間がそこそこ必要となる。

$ sudo cp -ax /var/opt/graylog/data/* /mnt/tmp/

コピー完了後、diffでファイル差分の確認を行う。

$ sudo diff -qr --suppress-common-lines /var/opt/graylog/data  /mnt/tmp
------------------------------
Only in /mnt/tmp: lost+found   ←★この1行だけ表示されればOK
------------------------------

8. 元ディレクトリのデータを削除し、新ディレクトリと入れ替え

旧データを削除する。フォルダを間違えないように注意すること。

$ sudo rm -rf /var/opt/graylog/data/*

一時的にマウントしていた/mnt/tmpの新ディスクをアンマウントする。

$ sudo umount /mnt/tmp

アンマウントした新ディスクを/var/opt/graylog/dataにマウントする。

$ sudo mount /dev/sdb1 /var/opt/graylog/data

マウント結果を確認する。

$ df -h
------------------------------
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G  4.0K  2.0G   1% /dev
tmpfs           396M  692K  395M   1% /run
/dev/dm-0        15G  2.7G   12G  19% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none            2.0G     0  2.0G   0% /run/shm
none            100M     0  100M   0% /run/user
/dev/sda1       236M   74M  150M  34% /boot
/dev/sdb1        40G   11G   27G  29% /var/opt/graylog/data
------------------------------

9. 起動時にマウントされるよう、fstabに追加

fstabに新ディスクが自動でマウントされるよう、1行設定を追加する。

$ echo '/dev/sdb1 /var/opt/graylog/data ext4 defaults 0 0' |  sudo tee -a /etc/fstab
/dev/sdb1 /var/opt/graylog/data ext4 defaults 0 0

fstabの中身を確認する。

$ cat /etc/fstab
------------------------------
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
/dev/mapper/graylog--vg-root /               ext4    errors=remount-ro 0       1
# /boot was on /dev/sda1 during installation
UUID=dc6ba91f-86f9-4218-bc13-ccba72b15e63 /boot           ext2    defaults        0       2
/dev/mapper/graylog--vg-swap_1 none            swap    sw              0       0
/dev/sdb1 /var/opt/graylog/data ext4 defaults 0 0
------------------------------

10. Graylogを再起動

最後にGraylogを再起動しておく。

$ sudo shutdown -r now

以上でディスク拡張作業は完了となるが、前述したとおり、Elasticsearchのエラーは解消しなかった。

解消するために、さらに対応する必要があったが、その方法は別記事にて記載することにする。

2017年5月13日土曜日

Linuxでプロキシ経由でインターネット通信をする (プロキシがある環境化でyumを使う)

ちょっとした小ネタ。

プロキシがある環境でyumを使ったら、なかなか成功しなかったので、備忘録として記載する。OSはCentOS 7.3となる。ちなみに、この手順はapt-getを使うLinuxディストリビューション(Ubuntuなど)でも同様に動作する。

環境変数を設定する

まずは失敗するパターン。

# yum check-update
------------------------------
読み込んだプラグイン:fastestmirror
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was
14: curl#7 - "Failed to connect to 2001:4178:5:200::10: ネットワークに届きません"

~(以下略)~
------------------------------

「ネットワークに届きません」というエラーが出て失敗している。IPv6のアドレスが表示されているので、IPv4ではなくてIPv6のアドレスで接続しようとしているのかと疑ったが、そうではなくてプロキシ設定をしていないことが問題だった。

というわけで、以下のように環境変数を設定する。

# export http_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"
# export https_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"
# export ftp_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"

# export ←確認コマンド
------------------------------
declare -x ftp_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"
declare -x http_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"
declare -x https_proxy="http://<プロキシのIPアドレス>:<プロキシのポート>/"
------------------------------

再度yumを実行すると、以下の通り成功した。

# yum check-update
------------------------------
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.usonyx.net
 * extras: download.nus.edu.sg
 * updates: centos.usonyx.net
base/7/x86_64/primary_db                                   | 5.6 MB   00:00  

NetworkManager.x86_64                     1:1.4.0-19.el7_3               updates
NetworkManager-libnm.x86_64               1:1.4.0-19.el7_3               updates

~(中略)~

wpa_supplicant.x86_64                     1:2.0-21.el7_3                 updates
xfsprogs.x86_64                           4.5.0-9.el7_3                  updates
------------------------------