designetwork

ネットワークを軸としたIT技術メモ

Win10 svchost.exe (LocalServiceNoNetwork, netsvcs) のCPU負荷対策

f:id:daichi703n:20180107174701p:plain

Windows 10で数ヶ月前から常時CPU使用率が20%程度となり始めた。タスクマネージャでプロセスを確認したところ、svchost.exe (LocalServiceNoNetwork, netsvcs)であることを特定した。Microsoftのサポートコミュニティ等の情報を元に対策をしたところ、CPU負荷がなくなり正常状態になったので、確認ポイント、修正方法を記載する。

※私の環境でしか確認できていないため、各種変更は自己責任でお願いします。

環境
HP Pavilion, Core i3 RAM 3GB, Windows 10 HOME (Windows 7からバージョンアップ)

原因プロセス
事象発生中のタスクマネージャーの状態を取得し忘れたが、CPU使用率が常時高かったプロセスは以下の二つ。(カラム右クリックでコマンドラインを表示している)

サービスホスト: ローカルサービス (ネットワークなし)
C:¥WINDOWS¥system32¥svchost.exe -k LocalServiceNoNetwork -p
異常時 CPU使用率 約15%

サービスホスト: ローカルシステム
C:¥WINDOWS¥system32¥svchost.exe -k netsvcs -p
異常時 CPU使用率 約5%

f:id:daichi703n:20180103193656p:plain

異常サービス調査

各プロセスのいずれかのサービスが異常となっていると推測し、サービス管理画面からサービスの一覧を確認した。サービス管理画面はタスクマネージャのプロセス右クリックから遷移できる。

一覧を確認したところ、Internet Connection Sharing (ICS)のサービスが開始中のままになっていることが分かった。

f:id:daichi703n:20180103193706p:plain

プロパティを確認したところ、SharedAccess, Internet Connection Sharing (ICS) サービスの実行ファイルパスが、C:¥WINDOWS¥system32¥svchost.exe -k netsvcs -p と、異常プロセスの一つであることが分かった。

f:id:daichi703n:20180103193703p:plain

サービスの状態は開始中のままで停止はできない。

Microsoft Windowsサポートコミュニティの情報

完全に一致するわけではないが、LocalServiceNoNetwork関連のコミュニティディスカッションがある。

answers.microsoft.com

こちらの解決策として提示されているのは、Windows Defender Firewallを既定値(デフォルト)に戻すこと。

Windows Firewall の設定をデフォルトに戻す

詳細な関連は不明だが、CPU負荷が高騰しているプロセスの中にWindows Defender Firewallのサービスも含まれているため、試行してみる。

設定 > Windows Defender > Windows Defender セキュリティ センターを開きます

f:id:daichi703n:20180103193709p:plain

ファイアウォールとネットワーク保護 > ファイアウォールを既定値に復元する

f:id:daichi703n:20180103193711p:plain

Firewall設定変更後の状態確認

再度SharedAccessサービスの状態を確認すると、以下の通り、正常に「停止」になっている。(設定変更後に再起動が必要だったかも)

f:id:daichi703n:20180103193713p:plain

これにより、CPU負荷が軽減され、平常時はCPU使用率0%〜数%となった。

まとめ - Win10 svchost.exe (LocalServiceNoNetwork, netsvcs) のCPU負荷対策

svchost.exe(LocalServiceNoNetwork, netsvcs) のCPU負荷はSharedAccess, Internet Connection Sharing (ICS) サービスが原因で、Windows Defender Firewallの設定値をデフォルトに戻すことでCPU負荷高騰を解消できた。

Firefoxをフルスクリーンで起動させるアドオン mFull

f:id:daichi703n:20171107232521p:plain

2018/2月時点 最新版のFirefoxでは使用できません

Firefoxを起動時からフルスクリーン・キオスク(Kiosk)モードにしたいときに使えるアドオンを紹介する。

想定シーン

  • デジタルサイネージ的に特定ページを表示し続けたい
  • Windows PCであることを認識させたくない
  • PC起動直後からフルスクリーンにしたい
  • 管理者以外は操作できないようにしたい

FirefoxアドオンmFull

こちらのアドオンを使用することで、起動時からFirefoxをフルスクリーンのキオスクモードで使用することができる。

mFull: Full Screen Mode for Firefox – Firefox 向けアドオン

インストール・設定

アドオンのダウンロード・インストールは上記リンクから。

mFullのインストールが完了すると以下のメッセージが表示される。OKをクリックするとブラウザが再起動し、mFullが有効な状態になる。

f:id:daichi703n:20171107230302p:plain

再起動後は設定メニューが表示されるため、Always start in full screenにチェックを入れる。Appearance1, Appearance2の設定は適宜変更する。

f:id:daichi703n:20171107230440p:plain

キオスクモードで立ち上がった後は、メニューが表示されず、Alt等でもメニューが表示されない。mFull, Firefoxの設定変更は右クリック > mfullからできる。なお、Alt+F4でFirefoxの終了は可能。

Note: マウス・キーボード操作はできるため管理に注意。

f:id:daichi703n:20171107230733p:plain

PC起動直後に自動起動させる

(Windows前提)表示するページが決定している場合、Windowsスタートメニュー > スタートアップ にリンクのショートカットを格納しておけば、PC起動直後に自動起動されるようになる。(Firefoxを標準ブラウザにしておく必要あり。)

不具合 - 設定に関わらずメニューが表示され続けてしまう

2017/11月時点の最新版のFirefox v56では、mFullの設定でメニューバー、お気に入りバーを表示しないようにしても、起動時にメニューが表示されてしまう。

f:id:daichi703n:20171107230630p:plain

対処として、Firefox v55以前を使用する。ダウンロード・インストールはこちらから。

support.mozilla.org

まとめ - Firefoxをフルスクリーンで起動させるアドオン mFull

FirefoxアドオンmFullを使用して、常にFirefoxをフルスクリーンのキオスク(Kiosk)モードで起動できるようにした。これにより、通常のPCディスプレイをデジタルサイネージのように使用することができる。

FluentdでIPアドレスから名前解決してホスト名フィールドを追加する(fluent-plugin-resolv)

f:id:daichi703n:20171014160852p:plain

こちらの記事でHerokuのアクセスログ (はてなブログに仕込んだJavaScript) を収集したが、単純なパースでアクセス元はIPアドレスでの表示となっている。

designetwork.hatenablog.com

ログから知りたいことの一つとして「だれ・どこからアクセスされているか」があるため、IPアドレスDNS逆引きしてドメイン・企業がわかるようにする。

DNS逆引きFluentdプラグイン

2017/10月時点では以下の二つのプラグインがメジャーだと思われる。

  • fluent-plugin-resolv

github.com

d.hatena.ne.jp

  • fluent-plugin-filter-resolv

fluent-plugin-resolvはメンテナンスが止まっており、filterディレクティブに対応していないため、tagルーティング設計が必要だった。Filterプラグインを作成してみようかとも思ったが、既に開発しリリースされているものがあった。

github.com

プラグインでの実装

それぞれのプラグインを導入し、アクセス元のホストFQDNのフィールドを追加する。

ログは以下の通りパースされている状態から開始する。

2017-10-10T22:12:07+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"103.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/12/05/home-server-selection"}
2017-10-10T22:15:33+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"117.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/11/19/sync-request-post-node-js"}
2017-10-10T22:19:43+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"27.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/04/09/Windows-Server-2016-Technical-Preview"}

バージョンはこちら

$ td-agent --version
td-agent 0.12.31

fluent-plugin-resolv

(参考)こちらで実装例の紹介あり。

komeiy.hatenablog.com

$ sudo td-agent-gem install fluent-plugin-resolv

sourceディレクティブで前述の形式でログを取り込んでいる。record_transformerでフォールドをコピーして追加し、resolvでコピーで作成したフィールドsrc_hostを名前解決してホスト名に変換する。

fluent-plugin-resolvプラグインは、IPアドレスのフィールドをFQDNに変換するものだが、他用途を考慮してIPアドレスの状態でも保存しておきたいため、record_transformerプラグインでフィールドを複製する。

tagルーティングのために変換前はtagプレフィクスを付与しておく必要があある。プレフィクス除外後は他ログと同様のoutputフローに乗せる。

<source>
  @type tail
  path /var/log/td-agent/designetwork/access_log.raw.*.b*
  pos_file /var/log/td-agent/pos/designetwork/access_log.raw.pos
  format multiline
  multiline_flush_interval 5s
  format_firstline /heroku router/
  format1 /.*\"message\":\"\d+ <\d+>\d+ (?<time>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\+\d+:\d+) (?<container_id>[^ ]+) .* fwd=\\\"(?<src_ip>\d+\.\d+\.\d+\.\d+)\\\" .*/
  format2 /.*://(?<access_host>[^/]+)(?<access_path>[^"]+)\\" .*/
  time_key time
  tag pre_resolv.designetwork.access_log.heroku
</source>

<filter pre_resolv.designetwork.access_log.heroku>
  @type record_transformer
  <record>
    src_host ${record["src_ip"]}
  </record>
</filter>

<match pre_resolv.designetwork.access_log.heroku>
  @type resolv
  key_name src_host
  remove_prefix pre_resolv
</match>

fluent-plugin-filter-resolv

プラグインをインストールする。

$ sudo td-agent-gem install fluent-plugin-resolv-filter

こちらはFilterプラグインなので、tagプレフィクス等を考慮する必要なく、処理順序(設定ファイル読み込み順)のみを意識すればよくシンプルにできる。

fluent-plugin-resolvで実装されておらず独自設計したフィールドのコピーがこちらでは含まれており、key_postfixを付与してフィールドを追加してくれる。DNSタイムアウト値も設定できる。

<source>
  @type tail
  path /var/log/td-agent/designetwork/access_log.raw.*.b*
  pos_file /var/log/td-agent/pos/designetwork/access_log.raw.pos
  format multiline
  multiline_flush_interval 5s
  format_firstline /heroku router/
  format1 /.*\"message\":\"\d+ <\d+>\d+ (?<time>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\+\d+:\d+) (?<container_id>[^ ]+) .* fwd=\\\"(?<src_ip>\d+\.\d+\.\d+\.\d+)\\\" .*/
  format2 /.*://(?<access_host>[^/]+)(?<access_path>[^"]+)\\" .*/
  time_key time
#  tag pre_resolv.designetwork.access_log.heroku
  tag designetwork.access_log.heroku
</source>

<filter designetwork.access_log.heroku>
  @type resolv
  key_name src_ip
  key_postfix fqdn
  dns_timeout 2
</filter>

ホスト名フィールド追加ログ

それぞれの実装でいずれも逆引き名前解決されたホスト名フィールド(src_host/src_ip_fqdn)が追加されている。

# fluent-plugin-resolv
2017-10-14T07:54:28+09:00       designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"175.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/10/18/win-symbolic-link-deletion","src_host":"xxx.xxx.catv-yokohama.ne.jp"}
2017-10-14T08:56:33+09:00       designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"126.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2017/05/05/esxi-vib-from-web","src_host":"softbankXXX.bbtec.net"}
...
# fluent-plugin-filter-resolv
2017-10-14T15:37:22+09:00       designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"103.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/04/09/Windows-Server-2016-Technical-Preview","src_ip_fqdn":"x.x.x.x.shared.user.transix.jp"}
2017-10-14T15:37:57+09:00       designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"118.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2017/03/05/ubuntu-kernel-version","src_ip_fqdn":"KDxxx.ppp-bb.dion.ne.jp"}

まとめ - FluentdでIPアドレスから名前解決してホスト名フィールドを追加する(fluent-plugin-resolv)

fluent-plugin-resolv, fluent-plugin-resolv-filterにより、ログのIPアドレスから逆引き名前解決してホスト名フィールドを追加した。

これにより、アクセス元の企業・ドメインを確認できる。

Herokuのアクセスログを自前のFluentdで収集する

f:id:daichi703n:20171011013620p:plain

Herokuでは各種サービス (Add-ons) が組み込まれており、ログ収集関連も豊富に揃っている。Treasure Data のサービスも提供されているが、Hadoopでの解析までを含めたクラウドサービスのため有償で、$5,000/monthと、個人で気軽には使用できない。

これらはTreasure Dataのサービスを使用する場合の設定手順。

elements.heroku.com

docs.fluentd.org

シンプルなログ管理サービスだと、 Papertrail のアドオンがシンプルに使えるが、パースして集計したりといった処理はできない。

elements.heroku.com

そのため、自前の Fluentd (td-agent) にアクセスログを送信して、好きなように集計できる環境を構築する。

前提環境

  • Herokuアプリ (PHP + JavaScript)
  • Heroku CLI
  • インターネットからアクセス可能なFluentdサーバ

Heroku アプリの Syslog を転送する

Heroku CLIを使用して、HerokuアプリのSyslog (標準出力 STDOUT) を外部に転送することができる。

Heroku CLIのインストールはこちら。Macの場合はbrewでインストールできる。

devcenter.heroku.com

以下を参考にプッシュ済みアプリにSyslog drainの設定をする。

devcenter.heroku.com

$ heroku drains:add syslog://[FQDN or IP]:[PORT] -a access-log-js
Successfully added drain syslog://HOME.dip.jp:PORT

$ heroku drains -a access-log-js
=== Drains
syslog://HOME.dip.jp:PORT (d.fd8d2572-7604-4521-94df-9fe4dae8fabb)
=== Add-on Drains
papertrail:choklad (papertrail-metric-35971)

Fluentd (td-agent) での Syslog 受信設定

上記設定により、TCP Syslogでログが転送されるため、Fluentd (td-agent) で受信設定をする。最低限の受信設定は以下の通り、TCPの受信設定でログを受け取れる。(Fluentd基本設定は割愛)

<source>
  @type tcp
  port 514xx (syslog drain PORT)
  bind 0.0.0.0
  tag designetwork.access_log.heroku
  format none
</source>

受信したログは以下の通り。(一部マスク)

2017-10-10T19:52:42+09:00   designetwork.access_log.heroku  {"message":"317 <158>1 2017-10-10T10:52:42.350627+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb heroku router - - at=info method=GET path=\"/script/access_log.js\" host=access-log-js.herokuapp.com request_id=bacbef15-abdc-40ae-b9e4-32f0ba13414b fwd=\"x.x.x.x\" dyno=web.1 connect=0ms service=2ms status=200 bytes=327 protocol=http"}
2017-10-10T19:52:43+09:00   designetwork.access_log.heroku  {"message":"250 <190>1 2017-10-10T10:52:42.350167+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb app web.1 - - 10.65.79.7 - - [10/Oct/2017:10:52:42 +0000] \"GET /script/access_log.js HTTP/1.1\" 200 84 \"-\" \"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"}
2017-10-10T19:58:39+09:00   designetwork.access_log.heroku  {"message":"317 <158>1 2017-10-10T10:58:39.053006+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb heroku router - - at=info method=GET path=\"/script/access_log.js\" host=access-log-js.herokuapp.com request_id=bf3e5470-6036-4fb0-a0e7-046ea646769b fwd=\"x.x.x.x\" dyno=web.1 connect=0ms service=1ms status=200 bytes=327 protocol=http"}
2017-10-10T19:58:40+09:00   designetwork.access_log.heroku  {"message":"393 <190>1 2017-10-10T10:58:39.052405+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb app web.1 - - 10.13.233.121 - - [10/Oct/2017:10:58:39 +0000] \"GET /script/access_log.js HTTP/1.1\" 200 84 \"http://designetwork.hatenablog.com/entry/2016/04/09/Windows-Server-2016-Technical-Preview\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"}
2017-10-10T20:07:32+09:00   designetwork.access_log.heroku  {"message":"316 <158>1 2017-10-10T11:07:32.046948+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb heroku router - - at=info method=GET path=\"/script/access_log.js\" host=access-log-js.herokuapp.com request_id=cedeb331-609d-49e1-915b-7b0bc3b103d2 fwd=\"x.x.x.x\" dyno=web.1 connect=0ms service=1ms status=304 bytes=127 protocol=http"}
2017-10-10T20:07:32+09:00   designetwork.access_log.heroku  {"message":"307 <190>1 2017-10-10T11:07:32.050362+00:00 d.fd8d2572-7604-4521-94df-9fe4dae8fabb app web.1 - - 10.145.25.250 - - [10/Oct/2017:11:07:32 +0000] \"GET /script/access_log.js HTTP/1.1\" 304 - \"http://designetwork.hatenablog.com/entry/2017/01/21/esxi6.5-centos7.3\" \"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"}

(参考)サンプルログ

サンプルログとして、はてなブログの記事中にScriptを埋め込み、Heroku上のJavaScriptを取得するようにしている。(自身でのアクセスログ解析のため)

<script type="text/javascript" src="http://access-log-js.herokuapp.com/script/access_log.js"></script>

Heroku Router を考慮したパース

Herokuは内部でHTTPリクエストルーティングが組み込まれており、すべての通信はHeroku Routerを経由する。そのため、アクセスログheroku routerapp web.xという二つ一組で出力される。

f:id:daichi703n:20171011015006p:plain

アクセス元IPアドレスの取得がやや面倒で、app web.xで見えるIPアドレス10.x.x.xはHeroku RouterのIPアドレスで、実際のアクセス元IPアドレスheroku routerfwd=\"x.x.x.x\"部分になる。

上記を踏まえて、Fluentdではmultiline Parser Pluginを使用して二行をまとめてパースする。

事前準備としてpos管理用ディレクトリを作成

$ sudo mkdir -p /var/log/td-agent/pos/designetwork
$ sudo chown td-agent:td-agent /var/log/td-agent/pos
$ sudo chown td-agent:td-agent /var/log/td-agent/pos/designetwork

multiline Parser Plugintailインプットのみで使用可能なため、一旦ファイルに保存し、それを再度取り込む構成とする。

<source>
  @type tcp
  port 51411
  bind 0.0.0.0
  tag designetwork.access_log.heroku.raw
  format none
</source>

<match designetwork.access_log.heroku.raw>
  @type file
  path /var/log/td-agent/designetwork/access_log.raw
  append true
</match>

<source>
  @type tail
  path /var/log/td-agent/designetwork/access_log.raw.*
  pos_file /var/log/td-agent/pos/designetwork/access_log.raw.pos
  format multiline
  multiline_flush_interval 5s
  format_firstline /heroku router/
  format1 /.*\"message\":\"\d+ <\d+>\d+ (?<time>\d+-\d+-\d+T\d+:\d+:\d+\.\d+\+\d+:\d+) (?<container_id>[^ ]+) .* fwd=\\\"(?<src_ip>\d+\.\d+\.\d+\.\d+)\\\" .*/
  format2 /.*://(?<access_host>[^/]+)(?<access_path>[^"]+)\\" .*/
  time_key time
  tag designetwork.access_log.heroku
</source>

見直しの余地はあるが、上記の通り二行にまたがる正規表現でマッチングすることにより、以下の通り、src_ip, access_host, access_pathを抽出できた。

2017-10-10T22:12:07+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"103.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/12/05/home-server-selection"}
2017-10-10T22:15:33+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"117.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/11/19/sync-request-post-node-js"}
2017-10-10T22:19:43+09:00   designetwork.access_log.heroku  {"container_id":"d.fd8d2572-7604-4521-94df-9fe4dae8fabb","src_ip":"27.x.x.x","access_host":"designetwork.hatenablog.com","access_path":"/entry/2016/04/09/Windows-Server-2016-Technical-Preview"}

アクセス元IPアドレスFQDNに変換する

こちらの設定を追加すればログ中のIPアドレスFQDNに変換できる。

designetwork.hatenablog.com

継続課題

上記方式だとログの順序性が要求される。Heroku Router -> Web Appの順でログを受信しない場合にはパースが機能しない。場合によってはHeroku Routerのログは不要となるため、ログフォーマットに合わせたパース形式を検討する必要がある。

パースフォーマット検討の際はPapertrailのログを併用することで取りこぼしを防げる。

まとめ - Herokuのアクセスログを自前のFluentdで収集する

継続課題はあるものの、以下を実装した。

  • HerokuからSyslogを外部送信 (Syslog drain)
  • HerokuからのSyslogをFluentdで受信
  • Heroku Routerを考慮した複数行(multiline)パース

ESXiマウントDell PERC RAID1を高速化する(HDDキャッシュ有効化)

f:id:daichi703n:20170918235313p:plain

PowerEdge T110 Ⅱ PERC H200A でRAIDディスクの速度が遅いため調査したところ、PERC 200 RAIDコントローラはキャッシュを持っておらず、パフォーマンスが悪いという問題が発覚した。

communities.vmware.com

[PERC] キャッシュのないRAIDコントローラのパフォーマンスに関する懸念点(H330、H310、S130、S110、S300、S100、H200、SAS 6/iR、SAS 5/iR) | Dell

なお、RAIDコントローラでなく、HDD自体はキャッシュを持っているのだが、ESXiとPERC 200の組み合わせ動作時には、HDDキャッシュが無効化されるようだ。停電時等のデータロストを防ぐためには適切な対応に思うが、DISKの速度が遅すぎて実用に耐えない場面が多々ある。

私の環境は試験用で、最悪データロストしても困らないため、強制的にHDDキャッシュを有効にすることでパフォーマンス改善を図る。

※この手順はデータロストのリスクを増加させる可能性があるため、検討のうえ各人の責任で適用してください。

状態確認

ディスク速度が遅いと感じているVM (CentOS7) で ddコマンドによりディスクの書込み速度を試験する。

$ dd if=/dev/zero of=~/perf/test bs=1M count=1024
1024+0 レコード入力
1024+0 レコード出力
1073741824 バイト (1.1 GB) コピーされました、 1.5644 秒、 686 MB/秒
$ dd if=/dev/zero of=~/perf/test bs=1M count=1024
1073741824 バイト (1.1 GB) コピーされました、 1.14801 秒、 935 MB/秒
$ dd if=/dev/zero of=~/perf/test bs=1M count=1024
1073741824 バイト (1.1 GB) コピーされました、 0.460856 秒、 2.3 GB/秒

この出力を見ると、数百MB/sの性能が発揮できているように見える。しかし、これはOS上の認識だけで実体の書き込みを待っておらず、vmstatでCPU負荷状況を見るとこちらの通り。iowaitが100%になる、SSH CLI操作がままならなず応答しない状態になる。

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  2      0 2473280   1008 1230940    0    0    20     0  106  123  0  0 44 57  0
 0  2      0 2473280   1008 1230940    0    0     0     0   89   96  0  0 50 50  0
 0  2      0 2473280   1008 1230940    0    0     0     0  134  146  0  0 50 50  0
 1  2      0 2474016   1008 1230948    0    0     4     0  223  332  1  1 38 61  0
 1  3      0 2474056   1008 1230952    0    0     4 16388  145  176  0  0  0 100  0
 0  3      0 2474056   1008 1230960    0    0     0     0  145  215  0  0  0 100  0
 0  3      0 2474056   1008 1230960    0    0     0     0  139  191  0  0  0 100  0

vSphere (ESXi) Web Clientから仮想マシンの状態を見ると以下の通り。

f:id:daichi703n:20170829224242p:plain

書き込み速度:5.44MB/s (≒44Mbps)
最大待ち時間:4,955 ms

調子のいいときでもこのように、1秒程度のDISK IO待ちが発生している。

書き込み速度:24.60MB/s (≒200Mbps)
最大待ち時間:1,087 ms

f:id:daichi703n:20170829224554p:plain

前提作業

HDDキャッシュを有効化するにあたり、Dell PowerEdgeの管理ツールOMSA ( OpenManage Server Administrator ) をESXiにインストールする必要がある。インストールはVIBパッチ適用により実施できる。

OSMAのインストールはこちらの手順を参照。ログ収集目的メインで記載されているが、VIBインストール手順は同様。

ログ収集のために、VMWareにDell™ OpenManage Server Administrator(OMSA)をインストールする方法 | Dell 日本

この先の設定手順は6. WindowsでのOMSA 8.5のダウンロードおよびインストール(オプション)を実施したWindowsから操作する。CentOS等にもOSMAをインストールできるようだが、私の環境ではうまくいかなかった。

OSMAからキャッシュ有効化する

OSMAをインストールしたWindowsスタートメニュー > Dell OpenManager Applications > Server Administrote を起動する。(私の環境はWindows Server 2016)

f:id:daichi703n:20170918225110p:plain

ESXiのrootアカウントでログインする。

f:id:daichi703n:20170918225304p:plain

ツリーから システム > ストレージ > PERC H200 Adapter > 仮想ディスク を選択する。

初期状態では ディスクキャッシュポリシー:無効 となっている。変更対象の仮想ディスク (RAID) のタスクプルダウンから「ポリシーの変更…」を選択し実行する。

f:id:daichi703n:20170918230030p:plain

ディスクキャッシュポリシーが有効になった。

f:id:daichi703n:20170918230142p:plain

私の環境では再起動の必要なくパフォーマンス改善されたが、状況に応じて要再起動。

キャッシュ有効化による改善結果

冒頭と同様にパフォーマンスを測定する。

書き込み速度:75.60MB/s (≒600Mbps)
最大待ち時間:363 ms

パフォーマンスが3倍以上(実質10倍程度)向上し、かつ安定している。待ち時間が300ms程度あるが、2秒おきに1GB書き込みという厳しめの環境なのでしょうがないものと考える。

f:id:daichi703n:20170919015159p:plain

理論値6Gbpsから比べるとまだ遅いが、十分に実用的な速度となっている。また、iowaitも減りディスクアクセスが速くなったことが実感できた。

参考情報

Slow write with Perc H200 and VMWare ESXi | Technology and Me

community.spiceworks.com

https://www.weblab360.com/User:xltran/App/Dell/PowerEdge_R510/PERC_H200

まとめ - ESXiマウントDell PERC RAID1を高速化する(HDDキャッシュ有効化)

Dell PowerEdgeの管理ツールOMSA ( OpenManage Server Administrator ) をESXiにインストールし、強制的にHDDキャッシュを有効化した。これにより、PERC 200 でのRAIDディスクのパフォーマンスが3倍以上(実質10倍程度)向上し速くなった。

※この手順はデータロストのリスクを増加させる可能性があるため、検討のうえ各人の責任で適用してください。

Macのzshでコマンド履歴(上キー・history)の重複を排除する

f:id:daichi703n:20170918184900p:plain

Maczshで上キーでコマンド履歴をたどるときに、同じコマンドを複数回打った履歴を除外する。

ネットワークエンジニアだと複数のコマンドを繰り返し実行するようなケースが多い。例えば、pingやtracerouteで複数への疎通・経路確認を繰り返すパターンなど。

デフォルトだと、このように、同じコマンドを複数回実行した場合は全て履歴に保存される。そのため、ターミナルで履歴をたどるときに上キーを押す回数が多くなってしまう。

$ history
  174  traceroute google.com
  175  traceroute google.com
  176  traceroute google.com
  177  traceroute example.com
  178  traceroute example.com
  179  traceroute example.com

zshの設定によりコマンド履歴の重複を排除する。

コマンド履歴の重複を除外する

.zshrcに以下のコマンドを追加することで、上キーでの履歴、historyでの重複を除外できる。

vi ~/.zshrc

setopt hist_ignore_dups

設定を反映させる。

source ~/.zshrc

このようにhistoryに重複して表示されない。実際の操作は冒頭と同様に3回ずつ同じコマンドを実行している。

$ history
  181  vi .zshrc
  182  source .zshrc
  183  traceroute google.com
  184  traceroute example.com

なお、この設定を無効化したい場合は以下の通りunsetする。

unsetopt hist_ignore_dups

参考情報

ぴったりのタイトルのものがなかったため新規に記事を書きましたが、zsh関連では以下の記事が参考になりました。

qiita.com

minus9d.hatenablog.com

まとめ - Maczshでコマンド履歴(上キー)の重複を排除する

zshrcの設定でコマンド履歴の重複を排除した。これで、2,3個のコマンドを繰り返し実行するような作業の効率が向上する。

ZOOT NATIVE & VyOSでDS-Lite (IPv4 over IPv6) インターネット接続する

f:id:daichi703n:20170904022032p:plain

こちらの記事でZOOT NATIVE & CentOSでのDS-Liteインターネットアクセスを実装した。

designetwork.hatenablog.com

しかし、CentOS (Linux) をルータとして運用していくのは面倒(慣れの問題)なので、VyOSで同等のDS-Lite環境を構築する。本当はフレッツ光PPPoEインターネットルータとして使用しているCisco ASA5505がいいのだが、ASAはIPv4 over IPv6トンネル(そもそもトンネル機能全般)をサポートしていないため、VyOSで代替する。

事前準備 ZOOT NATIVE(インターリンク)契約

今回使用するプロバイダであるInterlinkのZOOT NATIVEの契約に関してはこちらを参照。2ヶ月の無料お試し期間を利用してDS-Liteによるインターネット速度改善を検証する。

gigazine.net

ネットワーク構成

前記事でも記載の通り、Catalyst2960でoutside VLANとしてONUアクセスをマルチポイント化している。

f:id:daichi703n:20170904014729p:plain

VyOSインタフェース設定

VyOSにDS-Lite接続のための設定をする。(ベース設定・デフォルト設定は割愛)

inside側インタフェースはIPv4設定のみとする。

set interfaces ethernet eth0 address '192.168.1.2/24'
set interfaces ethernet eth0 duplex 'auto'
set interfaces ethernet eth0 smp_affinity 'auto'
set interfaces ethernet eth0 speed 'auto'
  • outside側物理NIC

outsideにはVLANインタフェースで接続する。物理インタフェースにはIPアドレス設定なし。

set interfaces ethernet eth1 duplex 'auto'
set interfaces ethernet eth1 smp_affinity 'auto'
set interfaces ethernet eth1 speed 'auto'
  • outsideサブインタフェース

outside側VLANインタフェースはZOOT NATIVEからRA・DHCPv6でIPv6アドレスを取得する。トンネルのアンダーレイインタフェースとなる。

set interfaces ethernet eth1 vif 99 ipv6 address 'autoconf'
set interfaces ethernet eth1 vif 99 ipv6 'disable-forwarding'
set interfaces ethernet eth1 vif 99 ipv6 dup-addr-detect-transmits '1'

IPv6アドレス・疎通確認

ZOOT NATIVEの契約が完了していることを確認した上で、outsideインタフェースでIPv6アドレスの取得、IPv6通信が可能となっていることを確認する。

2409:10:24e0:2000::/64IPv6グローバルアドレスを取得できている。

$ show interfaces ethernet eth1 vif 99
eth1.99@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 00:0c:29:05:52:3b brd ff:ff:ff:ff:ff:ff
    inet6 2409:10:24e0:2000:20c:29ff:fe05:xxxx/64 scope global dynamic
       valid_lft 2591863sec preferred_lft 604663sec
    inet6 fe80::20c:29ff:fe05:xxxx/64 scope link

網内対向機器のリンクローカルアドレスが見えている。

$ show ipv6 neighbors
fe80::221:d8ff:fe9a:d1c1 dev eth1.99 lladdr 00:21:d8:9a:d1:c1 router REACHABLE
  • IPv6デフォルトルート

網内対向機器のリンクローカルアドレス宛にIPv6デフォルトルートが設定されている。設定されない場合はset protocols static route6 ::/0 next-hop xxxxで自分でも設定可能。

$ show ipv6 route
Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,
       I - ISIS, B - BGP, * - FIB route.

S   ::/0 [1/0] via fe80::221:d8ff:fe9a:d1c1, eth1.99
K>* ::/0 via fe80::221:d8ff:fe9a:d1c1, eth1.99
C>* ::1/128 is directly connected, lo
C>* 2409:10:24e0:2000::/64 is directly connected, eth1.99
  • DS-Lite疎通確認

DS-Lite IPv4 over IPv6トンネルの対向機器宛の疎通確認をする。対向アドレスは2404:8e00::feed:100 (2017/9月現在) 今後変更の可能性あり。随時ZOOT NATIVE(インターリンク)、transix(インターネットマルチフィード)の最新情報を確認する。

$ ping 2404:8e00::feed:100
PING 2404:8e00::feed:100(2404:8e00::feed:100) 56 data bytes
64 bytes from 2404:8e00::feed:100: icmp_seq=1 ttl=59 time=8.07 ms
64 bytes from 2404:8e00::feed:100: icmp_seq=2 ttl=59 time=3.13 ms

$ traceroute 2404:8e00::feed:100
traceroute to 2404:8e00::feed:100 (2404:8e00::feed:100), 30 hops max, 80 byte packets
 1  2409:10:24e0:2000::fffe (2409:10:24e0:2000::fffe)  1.830 ms  2.385 ms  2.384 ms
 2  * * *
 3  * * *
 4  * * *
 5  * 2404:8e00:feed:ff00::a (2404:8e00:feed:ff00::a)  6.766 ms *
 6  2404:8e00:feed:ff07::2 (2404:8e00:feed:ff07::2)  8.938 ms  5.160 ms  5.095 ms
 7  2404:8e00::feed:100 (2404:8e00::feed:100)  12.168 ms  16.176 ms  12.136 ms

IPv4 over IPv6トンネル設定

transix (インターネットマルチフィード) 宛のIPv4 over IPv6 トンネルを設定する。トンネルIPv4アドレスの指定は必要ない。

local-ipはDHCPv6で割り当てられたアドレスを使用する。

set interfaces tunnel tun0 encapsulation 'ipip6'
set interfaces tunnel tun0 local-ip '2409:10:24e0:2000:20c:29ff:fe05:xxxx'
set interfaces tunnel tun0 multicast 'disable'
set interfaces tunnel tun0 remote-ip '2404:8e00::feed:100'
  • IPv4 ルーティング設定

トンネル宛にデフォルトルートを設定する。

set protocols static interface-route 0.0.0.0/0 next-hop-interface 'tun0'
  • OSPF設定(オプション)

私の環境ではCisco ASA5505がLAN-PCからのデフォルトゲートウェイになるようにしているため、VyOSとASAでOSPFにより経路交換している(Static再配信)。本当はVRRPなどでゲートウェイ冗長化したいが、ASAは未サポート。従来PPPoEは継続しているため、VyOS停止時には切り替わる。

IPv4疎通確認

ここまででDS-Lite通信に必要となる設定が完了している。

tracerouteで逆引きDNSを見ると、transix.jpを経由してIPv4インターネットアクセスできていることがわかる。

$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_req=1 ttl=61 time=4.56 ms
64 bytes from 8.8.8.8: icmp_req=2 ttl=61 time=4.04 ms

$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  ike-gw00.transix.jp (14.0.9.66)  3.461 ms  3.910 ms  3.899 ms
 2  ike-bbrt10.transix.jp (14.0.9.65)  3.976 ms  3.961 ms  3.946 ms
 3  210.173.176.243 (210.173.176.243)  4.726 ms  4.555 ms  5.002 ms
 4  108.170.242.161 (108.170.242.161)  4.994 ms 108.170.242.97 (108.170.242.97)  4.984 ms  5.273 ms
 5  108.170.238.35 (108.170.238.35)  5.264 ms 108.170.236.181 (108.170.236.181)  5.254 ms 72.14.236.33 (72.14.236.33)  4.938 ms
 6  google-public-dns-a.google.com (8.8.8.8)  4.624 ms  4.387 ms  7.371 ms

速度比較

従来の@nifty IPv4 フレッツ光PPPoEと、ZOOT NATIVE DS-Lite (IPv4 over IPv6)での通信速度を比較する。

従来IPv4 フレッツ光PPPoE

@nifty IPv4 PPPoE + Cisco ASA5505
-> 約5.8Mbps

f:id:daichi703n:20170903163444p:plain

ZOOT NATIVE DS-Lite

ZOOT NATIVE DS-Lite + VyOS
-> 約61Mbps

f:id:daichi703n:20170904021328p:plain

約10倍の通信速度(スループット)となっている。ESXiの都合上、VyOSは100Mbps 1NIC構成となっているため頭打ちとなっているが、1Gbps-NICを使用すればさらに速度向上すると考えられる。

IPoEも使用可能

ZOOT NATIVEはDS-LiteとともにIPoE方式でのIPv6ネイティブ通信もサポートしている。そのため、こちらの記事で書いたCisco ASA 5505 での IPv6 NAPT方式によるIPv6インターネットアクセスも可能。

designetwork.hatenablog.com

まとめ - ZOOT NATIVE & VyOS でDS-Lite (IPv4 over IPv6) インターネット接続する

VyOS を使用して、IPv6プロバイダZOOT NATIVE経由で transix (インターネットマルチフィード) へ DS-Lite (IPv4 over IPv6) インターネット接続した。これにより、IPv4インターネット網への通信速度が10倍程度向上した。引き続き無料期間はDS-Liteを使用し、ZOOT NATIVEを継続利用するか検討する。