/var/log/soymsk

id:soy_msk


PPTP vs L2TP/IPSec vs OpenVPN vs IKEv2

iOS10からPPTPクライアントが廃止されてしまい、 家のバッファロールータで動いていたPPTPサーバにアクセスできなくなってしまったので、この際きちんとVPNサーバーを立ててみる。

まずはVPNの方式について調査。

VPN方式の違い

PPTP

古くからある方式だが、脆弱性があるため現在は基本的に使用しない。

  • メリット
    • 歴史が古く、多くのクライアントがある。
    • 構築がかんたん
    • 高速
  • デメリット
    • 安全ではない(が、今でも広く使われている)

L2TP or L2TP/IPsec

現在一般的な方式。L2TP単体ではなくIPsecと組み合わせて構築する。

  • メリット
    • 安全(と思われる)
    • 構築がかんたん
    • 対応クライアントが多い
    • OpenVPNより高速
  • デメリット
    • クラック済みといううわさがある(詳しくは参考記事を参照)
    • UDP:500を使用するためポートフォワーディングが必要

OpenVPN

SSLの仕組みに乗っかる形のVPN. 

  • メリット
    • 柔軟な設定
    • 高い安全性(ここで比較しているどの方式と比較しても安全)
    • SSLポートを使用しているのでファイヤウォールに穴をあける必要がない
    • 暗号化アルゴリズムを選択できる
    • オープンソース実装がベース
  • デメリット
    • 標準で対応しているクライアントが少ない
    • 設定難
    • バイルデバイス(iOS, Android)対応がいまいち

SSTP

Microsoftが開発した比較的新しい方式。

  • メリット

    • 高い安全性
    • Windowsとの親和性が高い
    • ほとんどのファイヤウォールを通過できる
  • デメリット

IKEv2

MicrosoftCiscoが開発した方式

  • メリット
    • 一時的な接続断があっても再接続を行うなど、安定性が高い。モバイル向き(←これ、ポイント高い)
    • PPTP, SSTP, L2TPより高速
    • 高い安全性
    • 構築がかんたん
  • デメリット
    • クライアントが限られる(とはいえ、最近のiOS, macOSでは対応済み)
    • 実装が難しく、開発が難しい(潜在的なバグのリスク?)

まとめ

参考サイトにある通り、OpenVPN > iKEv2 > L2TP/IPsec >> SSTP >>>>> PPTP(論外) という感じかな。

  • サードパーティ製のクライアントが必要な点を除けば、OpenVPNが最良
  • 不安定な接続環境下であればiKEv2
  • それ以外はやや安全性が劣るもののL2TP/IPsec

クライアントは主にiOS, macOSだし、外出先からつなぎたいケースがほとんどだから、IKEv2で作ってみよう。

参考

非常にわかりやすい解説だった。

Docker on vagrant on Windows10

Docker on vagrant

Dockerをvagrant上に構築してみる。 ネット上の情報を参考にしてみてもうまくいかなかったので、だいぶ試行錯誤した

目指す構成は以下のとおり

Docker Container (CentOS6)
on
Vagrant (CentOS6)
on
Windows 10

※今回はHadoopクラスタ構築を目標にしているので、Hadoopという文字列がちらほら出てきますが、そこは任意です

Why docker on vagrant

ネット上の記事を見ると、vagrantで仮想環境を立てて、その上にさらにDockerによるコンテナを構築する例が多いけど、 docker(仮想) on vagrant (仮想)と、2重に仮想環境を構築する意味が最初わからなかった。

自分で調べてみたところでは、

  • DockerはLXCを利用しており、Linux上でしか動作しない
  • そのため、OSXWindows上では、VagrantでまずLinux環境を構築してから、Dockerを入れる。
    • その際のLinux環境は最小限のもので構わないので、boot2dockerなどの軽量Linuxを用いる
  • 逆にホストOSが最初からLinuxであれば、Dockerコンテナを直に立てればいい。

利点として、どのOSで作業をしようが、どこでもDockerコンテナを立てることができるので、 別OSに環境を移植する際もDockerコンテナを持っていけばよいということかな。

Vagrantごと持って行くと、Linux上ではLinux - Vagrant - Dockerとなり、 コンテナ型仮想化であるDockerを直接利用するよりオーバーヘッドが大きい)

Docker provision vs Docker provider

VagrantでDockerを扱うには、provisionとproviderが2つあって、どちらを使えばいいのかよくわからなかったので整理。

VagrantでDockerを立てる方法は主に2つある。

Provision:

  • Vagrantが立てるVM上に、Dockerを構築する。
    あくまでVMを立ててからDockerをインストールする形になるので、ホストOSがLinuxである場合にもLinux - VM - Dockerという構成になる。
    Vagrant v1.6まではこの構成?

Provider:

  • Vagrant ver1.6から追加された機能。
    VagrantVMを構築する際に、VirtualBox等によるVMでなく、Dockerによるコンテナを指定できるというもの。
    MacWindowsなど、直接Dockerが構築できないホストOS上では、Vagrantが自動で中間のLinux VMを立ててくれる。
    一方で、ホストOSがLinuxの場合は直接Dockerコンテナを立てるため、無駄がないのかな(未確認)。

どのOSでも使え、設定が簡単そうなProviderがよさそう。

Docker on Vagrant on Window10

Windows10にVagrant を立てて、その上にDockerコンテナを構築する

準備

以下をインスト-ル(詳細は割愛)

Vagrantfile

mkdir {任意のディレクトリ}/hadoop # 以下、D:/virtualbox_vms/hadoopとする
cd D:/virtualbox_vms/hadoop
mkdir host

hadoop/Vagrantfile にDockerコンテナ自体の構築手順を、   hadoop/host/Vagrantfile にDockerをインストールするVMのVagrantfileを置く。

ここらへんは、ドキュメントも豊富なのでそちらを参考に。。(そのうち追記するかも)

Vagrantfile

VAGRANTFILE_API_VERSION = "2"
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "hadoop-container" do |h|
    h.vm.provider "docker" do |docker|
      docker.vagrant_vagrantfile = "./host/Vagrantfile"
      docker.name = 'hadoop-container'
      docker.build_dir = '.'
    end
  end
end

Dockerfile

FROM centos:centos6

RUN yum update -y

### 以下、Dockerコンテナの構築コマンド(省略

host/Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|

  config.vm.hostname = "docker-host"

  config.vm.box = "bento/centos-6.7"

  config.vm.box_check_update = false

  # provisoned by docker
  config.vm.provision "docker"
end

以上のファイルを準備したら、hadoopディレクトリ以下で、

vagrant up

と実行すれば、host/以下のVMも含めてdocker コンテナの立ち上げまでやってくれる。 はずだった。。

Permisson denied

DockerでのProvider実行時にPermisson Deniedになった。

D:\virtualbox_vms\hadoop>vagrant up
Bringing machine 'hadoop-container' up with 'docker' provider...
==> hadoop-container: Docker host is required. One will be created if necessary...
    hadoop-container: Docker host VM is already ready.
==> hadoop-container: Building the container from a Dockerfile...
    hadoop-container: stat /var/lib/docker/docker_build_7afac34b3a4f4be525c3d67a8eef89c3:
permission denied
A Docker command executed by Vagrant didn't complete successfully!
The command run along with the output from the command is shown
below.

Command: "docker" "build" "/var/lib/docker/docker_build_7afac34b3a4f4be525c3d67a8eef89c3"

Stderr: stat /var/lib/docker/docker_build_7afac34b3a4f4be525c3d67a8eef89c3: permission den
ied

Stdout:

同様の事例がissueに報告されている。 https://github.com/mitchellh/vagrant/issues/6822

これは、/var/lib/dockerがvagrant構築時にはroot権限になっているが、dockerコマンドを実行するのはvagrantユーザーであるから。

以下の行をhost/Vagrantfileに追記し、/var/lib/dockerディレクトリをvagrantユーザーのものにしておく。

# provisoned by docker
config.vm.provision "docker"
## 追記
config.vm.provision "shell", inline: <<-SHELL
  sudo chown vagrant:vagrant /var/lib/docker
SHELL

privisonは複数指定できるみたい。

これでとりあえずDockerコンテナが立ち上がるところまで確認できた。

MarkdownからConfluence HTMLを生成するConverterを作った。

サーバー上での作業途中など、普段の業務メモは手元のエディタにmarkdown表記で記録している。

ところが、技術系の資料はConfluenceにまとめることになっているため、作業終了後はmarkdownで書いた記録を、再度Confluence上で作成しなおすことになる。

そのConfluenceも、あるバージョンからwiki記法が使えなくなり、仕方なくウェブUIで編集しているが、
これが頻繁にレイアウトがおかしくなったり、けっして使い勝手が良いとはいえない状態。

Confluenceにはmarkdownマクロも用意されてはいるものの、コードブロックの表示にシンタックスハイライトがきかずに、全体的な見た目もいまいち。

markdownからHTMLに変換するライブラリは世の中にたくさんあるので、少しConfluence用にカスタマイズすればできるのでは?ということで、ConfluenceのHTMLを自動生成するツールを作った。 github.com

見た目にもずいぶんましになったし、ちまちま手で移行させる必要もないので便利ー

今後追加したい機能

  • Upload機能

Capistranoでオペレーション自動化をしようとして諦めた

社内のチームで数十台~のサーバーを管理していて、その上でElasticSearchやHadoopを構築している。 これまで、そのクラスタのオペレーションをほぼ手作業なりシェルスクリプトでやっていて、 手順の再利用性もないし何よりめんどくさいので、 何か自動化できるツールを導入したいと思った。

そこで注目したのがCapistranoだった。

Capistranoはデプロイツールであるけれども、シェルコマンドの自動化にも使えるらしい。

qiita.com

以下、実験的にいくつかオペレーションをCapistrano3に移行してみて、結果挫折した話。

なぜCapistranoを選んだか

チームにRubyエンジニアが多く、また構成管理はChefがデファクトになりつつあって、 Rubyで書ける仕組みが欲しかった。

デプロイ作業もrsync上等!でやっていて、将来的にきちんとCI環境を整えたく、 後々デプロイツールとしても利用できるものを使いたかった。

Capistranoの壁

実際にタスクをCapistranoにしてみて、いくつか壁があった。

学習コストが高い

Capistranoは学習コストが高い。 確かにきちんと環境とタスクを切り離して管理したり、HostFilterの仕組みも便利だった。

しかし、仕組みがしっかり作られることによって、逆に学習コストが高くなってしまっている。 Chefと同じくタスクの記述がDSLになっていて、いちいち覚える事が多い。

設定ファイルのローディング順やCapistranoがどうやってタスクを生成しているか理解していないと、

  • setした値がfetchできない
  • setできてるのにタスクに反映されない

みたいなことが頻繁にあり、

「あれ、この記述どこに書けばいいんだっけ」

となることが多かった。

さらに、Capistrano3になってからオプションや記述方法の変更が入っていて、 ネット上のノウハウも2と3が混在してしまっている状況。

別に自分たちがバージョンを上げなければ問題ない話なのだけれど、せっかく積み上げたネット上のノウハウが 陳腐化したりバージョンで分断されたりするのはもったいない。。

チームで使っていくにあたって、ここらへんの学習コストなりツールの更新によるメンテナンスが問題になりそうだなぁとは初期の段階から感じた。

並列志向であること

もともとデプロイツールということを考えると仕方がないところだけど、Capistranoは並列志向だ。 原則、タスクは並列に実行される。

デプロイツールではそれで問題ないというか、そのほうが反映ラグが少なくていいのだろうけど、 サーバーオペレーションだと並列に実行するというシチュエーションはそれほど多くないと思う。

むしろ1台ずつ状況を確認しながら実行したいし、 やりたかったのがESのローリングリスタートだったので、なおさら直列にしか実行してはいけないものだった。

一応Capistranoでも、タスクにin: sequenceとかけばを直列実行できるオプションは用意されている。

でもこいつが曲者。

例えば、あるタスク(parent task)から別のタスク(child task)を呼び出すような場合

role :web, %w{host1, host2}

task :parent do
  on roles(:web), in: :sequence do |host|
    puts 'parent start@%s' % host
    invoke 'child'
    puts 'parent end@%s' % host
  end
end


task :child do
  on roles(:web) do |host|
    puts 'child exec@%s' % host
  end
end


"""
$ cap production parent
parent start@host1,
child exec@host1,
child exec@host2
parent end@host1,
parent start@host2
parent end@host2
"""

host02のchildがparentより先に呼ばれてしまっている。

最初にあれ?っと思ったけど、よくよく調べればinvoke 'child'の時点でhost02も呼ばれてしまうのだった。 これはchildにin: :sequenceを指定しても変わらない。

んー、仕組みがわかれば納得なんだけど、全然直感的じゃないというか、 普通にtask AからBを呼ぶ、みたいなことはやるわけで、それがさくっとできないのはつらい。

capistrano2ではinvoke 'child', hosts=>hostとすれば実現できた。なぜなくなったし。。

カスタマイズしづらい

上の入れ子タスクの問題をなんとか実行時に解決するすべはないかとコードを追ってみたけれど、 Capistranoはタスク設定時にroleやhostを決めてしまっていて、 実行時にset :hosts, XXXでむりやり実行サーバーを限定する、のようなことができなかった。

残念

結論: Capistranoはデプロイツールであってオペレーションツールではない

そもそもCapistranoはデプロイツールなわけで、がんばってオペレーションもこれでできなくはないけど、 そこまでする意味はなかったかなと。。

すでにCapistranoガッツリ使ってるわけでないのであれば、わざわざ学習してまで導入するメリットはなさそう。 もちろんCapistranoのが悪いわけではなく、デプロイツールとしては実績あるいいフレームワークだと思う。

そしてFabricへ

結局、Capistranoは諦めてFabricを導入することにした。

FabricはCapistranoに比べて学習コストが低く、チームで導入しても負担が少ない。 (そもそもほとんどシェルコマンドだし)

薄いフレームワークだけ提供されているので、 コードを読むのも楽だし、独自の処理を差し込むのが簡単だ。

実際、CapistranoにあるHostFilter、RoleFilterの機能をデコレーターを独自に実装して導入している。

今回学んだことは、

  • ツールは本来の目的に使用してこそ力を発揮する
    • いろんなツールが混在するのもよくないが、かといって1つのツールでなんでもやろうとしてはいけない。
  • 学習コストを慎重に検討するべき。まず試すならシンプルなものを。 simple is best

ということ。

しばらくFabricを試してみよう。

GangliaでHDD温度監視

Gangliaにカスタムモジュールを入れてHDDの温度監視をしてみる。

前提
CentOS 7.1
Gangalia 3.7

セキュリティを重視していないので、実験用環境での使用を想定しています

Package インストール

python モジュールで拡張するので、以下のパッケージをインストールする

ganglia-3.7.2-2.el7.x86_64
ganglia-gmetad-3.7.2-2.el7.x86_64
ganglia-web-3.7.1-2.el7.x86_64
ganglia-gmond-python-3.7.2-2.el7.x86_64
ganglia-gmond-3.7.2-2.el7.x86_64

ganglia-gmond-python package

ganglia-gmond-pythonパッケージには以下のファイルが入っている

...
/usr/lib64/ganglia/modpython.so
/etc/ganglia/conf.d/modpython.conf
...

modpython.soはPython拡張を有効にするためのモジュール。 modpython.confの中身は以下のようになっている。

modules {
  module {
    name = "python_module"
    path = "modpython.so"
    params = "/usr/lib64/ganglia/python_modules"
  }
}

include ("/etc/ganglia/conf.d/*.pyconf")
  • modules ... Python拡張モジュールを有効にするための、modpython.soを読み込んでいる。 また、拡張モジュールの配置場所をpathによって設定している。
  • include ... Python拡張モジュール用の設定ファイルであるpyconfファイルを、conf.d以下から一括で読み込むように指定している。

拡張用Pythonモジュールの書き方

上のpython拡張パッケージがインストールされていれば、pythonモジュールは使えるようになっているはず。

あとは拡張用モジュールの用意と、設定ファイルを用意する。

Python モジュール

拡張用のPythonモジュールでは、以下の関数を実装すればよい。

  • def metric_init(params): 初期化のために一度だけ実行される関数
  • def metric_cleanup(): gmondが終了する時に一度だけ呼ばれる関数
  • def metric_handler(name): 監視目的の値を返す関数。名前は自由

詳細は https://github.com/ganglia/monitor-core/wiki/Ganglia-GMond-Python-Modules

コード

例えば、/dev/sdaの温度をsmartctlから取得するコードは以下。

# -*- coding: utf-8 -*-
import os
import re
import random
from subprocess import check_output

NAME_PREFIX = 'disk_temp'

def get_disktemp(name):
    disk = name.replace(NAME_PREFIX + '_', '')
    disk_info = check_output(['sudo', '/sbin/smartctl', '-a', '/dev/%s' % disk])
    temp_line = [line for line in disk_info.split('\n') if line.find('Temp') >= 0][0]
    return float(re.split('[\s\t]+', temp_line)[-1])

def metric_init(params):
    units = 'Celcius'
    disks = ['sda']
    descriptors = [{
        'name': '_'.join([NAME_PREFIX, disk]), # metircs name
        'call_back': get_disktemp,
        'time_max': 60,
        'value_type': 'float',
        'units': units,
        'slope': 'both',
        'format': '%f',
        'description': 'Disk temperature (%s) on disk /dev/%s' % (units, disk),
        'groups': 'disk'
    } for disk in disks]
    return descriptors

def metric_cleanup():
    pass

このファイルをdisktemp.pyとして、/usr/lib64/ganglia/python_modulesに配置する

pyconf 設定ファイル

実装した拡張モジュールで監視を行うための設定を追加する

modules {
  module {
    name = "disktemp" # my python module name
    language = "python"
  }
}

collection_group {
    collect_every  = 180 # metrics span
    time_threshold = 60 # metrics send span

    metric {
        name_match = "disk_temp_(.+)"
    }
}

ここでは取得間隔を180sec、gmetadへの通知間隔を60secにしている。

sudoers設定

gangliaを実行しているユーザーがroot出ない場合(例えばgangliaユーザー)、sudoersの設定が必要

# ttyなしでsudo実行
Defaults:ganglia !requiretty
# /sbin/smartctl 実行許可
Cmnd_Alias LOOK_SMART = /sbin/smartctl -a /dev/*
ganglia  ALL=(ALL) NOPASSWD: LOOK_SMART

結果

gmondを再起動して、ちゃんとメトリクスが収集されているか確認 f:id:soy_msk:20151210003946p:plain

※うまく収集されていない、gmondが起動しない場合、/var/log/messagesを確認する。

github.com

descriptorについて

今回遭遇したトラブル

  1. descriptorのvalue_typeとformatが違っていてgmondが起動しない
    • 公式によると予期せぬ測定値になるとあるが、エラーを吐いて起動しなかった
    • value_type: float, format: %f にちゃんと揃える
  2. value_typeを途中から変更した場合にgmetadがエラー
    • おそらく過去のrrdデータと不整合が起きるためだと思う。 int -> floatは問題ないが、逆だとだめそう。
    • rrdtoolのデータを削除して解決

CentOS7のKernelを最新版に更新する(yumで)

docker1.9のoverlay networkを試すにはLinux kernel3.16が必要だが、CentOS7では3.10までしか提供されていない。 kernelの更新はelrepoを使えば簡単にできるようなので試してみた。

注意: kernelの更新は危険なオペレーションのため、壊れても良い環境で試して下さい。

現在のkernel
3.10.0-229.14.1.el7.x86_64

elrepoの追加

yumのrepolistにelrepoを追加

$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org 
$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

elrepo-kernelを有効にする。enabled=0になっているのでenabled=1とする

$ vim /etc/yum.repos.d/elrepo.repo
----
[elrepo-kernel]
name=ELRepo.org Community Enterprise Linux KÂernel Repository - el7
baseurl=http://elrepo.org/linux/kernel/el7/$basearch/
        http://mirrors.coreix.net/elrepo/kernel/el7/$basearch/
        http://jur-linux.org/download/elrepo/kernel/el7/$basearch/
        http://repos.lax-noc.com/elrepo/kernel/el7/$basearch/
        http://mirror.ventraip.net.au/elrepo/kernel/el7/$basearch/
mirrorlist=http://mirrors.elrepo.org/mirrors-elrepo-kernel.el7
enabled=1 <==== 0から1に変更
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

install

# 古いkernelのパッケージを削除
$ yum remove kernel-headers-3.10.0-123.9.2.el7.x86_64 kernel-tools-3.10.0-123.9.2.el7.x86_64 kernel-tools-libs-3.10.0-123.9.2.el7.x86_64

$ yum update
$ yum install kernel-ml.x86_64 kernel-ml-devel.x86_64 kernel-ml-headers.x86_64 kernel-ml-tools.x86_64 kernel-ml-tools-libs.x86_64

grub起動設定変更

$ awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg

---
CentOS Linux 7 (Core), with Linux 4.3.0-1.el7.elrepo.x86_64
CentOS Linux 7 (Core), with Linux 3.10.0-229.20.1.el7.x86_64
CentOS Linux 7 (Core), with Linux 3.10.0-229.14.1.el7.x86_64

更新したいKernel4.3が1行目にあるので

# 起動Kernel
$ grub2-set-default 0
# 設定反映
$ grub2-mkconfig -o /boot/grub2/grub.cfg
# 再起動
$ reboot

再起動後、

$ uname -r
4.3.0-1.el7.elrepo.x86_64

更新されている!

kernel version

以下のページから利用できるrpmを知ることができるが、kernel3はもうないみたい http://elrepo.org/linux/kernel/el7/x86_64/RPMS/

参考

http://wiki.mikejung.biz/CentOS_7#Upgrade_CentOS_7_Kernel_to_4.0.1

RundeckからGmailを使ってメール送信する

Rundeckをジョブスケジューラとして使い始めて、メールをGmail経由で送れるようにした。 OSはCentOS7だが、他でも変わらないはず。

Rundeckのインストール

インストールは難しくない。yumで入るはず。 起動もsystemctl start rundeckd.serviceでできる。

詳細は割愛

設定

※以下、rundeckの設定は/etc/rundeck配下にあるものとしています。

公式ドキュメントには一応設定はある。 http://rundeck.org/docs/administration/email-settings.html localhostsmtpサーバーを立てている場合は

grails.mail.host=localhost
grails.mail.port=25

でいいらしいが、今回はSSL認証が必要はため別の手段が必要。

rundec-config.groovy

まずはより詳細な設定ができるように設定ファイルをGroovy形式のファイルに置き換える。

rundeck-config.propertiesと同じディレクトリにrundeck-config.groovyを作成する。

デフォルトのpropertiesは使わないので適当にリネームしておく。

  $ mv rundeck-config.properties rundeck-config.propertties.bak
  $ touch rundeck-config.groovy

基本設定はrundeck-config.propertiesと同じになるようにする。 それにメール設定を以下のように設定する。

// #### デフォルト設定 ####
loglevel.default="INFO"
rdeck.base="/var/lib/rundeck"
rss.enabled=false
dataSource {
        dbCreate="update"
        url="jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true;TRACE_LEVEL_FILE=4"
}

grails {
        serverURL="http://localhost:4440"
        // #### Mail 設定 ####
        mail {
                host="smtp.gmail.com"
                port = 465
                username="XXXXXX@gmail.com"
                password="XXXXXXX"
                props = ["mail.smtp.auth":"true",
                      "mail.smtp.socketFactory.port":"465",
                      "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
                      "mail.smtp.socketFactory.fallback":"false"]
        }
}

grails.mail以下に上のようにGmail用の設定を記述すればOK.

起動オプション変更

上記で作成した.groovyファイルを読み込んで起動するように、 CONFIG_DIR/profile ファイルに以下の行を追加

# Add to load custom config
RDECK_JVM="$RDECK_JVM -Drundeck.config.location=/etc/rundeck/rundeck-config.groovy"

systemctl restart rundeckd.serviceでちゃんと再起動するか確認。 エラーが出る場合はgroovyファイルに間違いがないかどうか確認する。

ジョブ作成

メールは送信できるようになっているはずなので、あとはNotificationにメールを設定するだけだ。 f:id:soy_msk:20150917222026p:plain

うーん、それにしてもRundeckが相当DiskIO食ってるんだけどなんでだろう。。IO waitかなり出ている。。