QNAP NAS上でnode_exporterをデーモン化しつつ自動起動

前回prometheus+grafanaを導入してNASのモニタリングも開始してみた、の続きで

dasalog.hatenablog.jp

雑に起動していたQNAP NAS上のnode_exporterをNAS再起動時に自動起動するようにする小ネタ。

やること

これだけでOK。

環境はQNAP TS-220(QTS 4.3.3.0299)

以下順に

雑いinitスクリプト書く

/etc/init.d以下のスクリプトを眺めつつ、こちら

QNAP TS-469Lをmackerelを使ってモニタリングする | misty-magic.h

でmackerel-agentをQNAP上で起動されてる事例を参考に、というか割と流用させて頂きつつとりあえずstop、startだけ出来るスクリプトを用意。 他のスクリプトでも使われている/sbin/daemon_mgrでpid管理などをよしなにやってくれる模様。ちょっと楽。

github.com

/etc/config/qpkg.confに設定を追加して自動起動する

作成した起動スクリプトに実行権限をつけ、起動、停止確認ができたらqpkg.confに設定を追記する。 こんな感じで

[node_exporter]
Name = node_exporter
Version = 0.16.0
Author = prometheus
Date = 2018-05-15
Shell =  /usr/local/node_exporter/etc/init.d/node_exporter.sh
Install_Path = /usr/local/node_exporter
QPKG_File = /usr/local/node_exporter/DUMMY
Enable = TRUE

QPKG_FileはダミーでOK。 Authorとかいろいろ適当だが、meもなにか違うしまあオレオレということで・・。 なお、パス配置は起動スクリプトを素直に/etc/init.d/node_exporter.shに置くとNASの再起動で消えて悲しいことになるので、ひとまず/usr/local/node_exporter以下に諸々配置する構成にしている。

qpkg.confに書いた時点でAppCenter上で見えるようになり、サービスの起動、停止が出来るようになる。

f:id:egmc:20180802001257p:plain

この状態でNASを再起動すると、アプリケーション起動処理の中でnode_exporterも自動で起動されるようになる。

f:id:egmc:20180802001355p:plain

ブラウザで9100を確認、ちゃんと起動している。

f:id:egmc:20180802001803p:plain f:id:egmc:20180802101855p:plain

これで停電があっていつのまにか再起動してたわー的なことがあっても勝手に起動してくれるはず。

2018-08-19追記

再起動では消えないもののQTSのアップデートで/usr/local以下に配置したnode_exporter一式は消えてしまったので、普通にマウントしたディスク領域の共有フォルダ以下に置いた方がよさそう。

/share/MD0_DATA/

以下に置いてひとまず様子見。

prometheus+grafanaで各種サーバとついでにQNAP NASの状態を可視化する

お仕事柄サーバの監視システムを管理、運用しているものの自鯖の監視は適当に導入したmuninやmackerelにお任せという状態だったので、きちんと1から構築してみよう、ということでprometheus+grafanaを導入しつつ、ついでに自宅に置いてるNASのメトリクス取得もやってみたら意外と簡単だったやないかい、というメモ。

三行で

  • prometheus、grafanaを管理サーバ、node_exporterを監視対象サーバでそれぞれ立ち上げ
  • prometheusの設定をちょろっと書いて
  • gradanaにログインしてdatasourceの設定を追加、適当なダッシュボードをimport

でこんな感じのダッシュボードで15秒精度のメトリクスが見れるようになり、なかなか楽しい。

f:id:egmc:20180721235623p:plain
grafana dashboard

構成

  • 監視元&監視対象 GCP上のf1-microなサーバ(ubuntu xenial)
  • 監視対象:さくらVPSサーバ(CentOS)
  • 監視対象:QNAP NAS(TS-220、QTS)

GCP上にprometheusを立ててグローバル越しにnode_exporterを導入したサーバを監視対象にしていく感じで。 デーモン化はsupervisorに任せる方針。

各種設定

node_exporter

バイナリ落としてきて適当に配置して起動するだけ。 config的なものとは特になく、collectorの追加オプションがあるだけなので好みで入れる。 何も指定しなくてもデフォルトで結構取ってくれる。

[program:node_exporter]
command=/usr/local/node_exporter/node_exporter
user=monitor
autorestart=true

雑にsupervisorでデーモン化する 起動後に9100ポートにアクセスして諸々取れてることを確認。

prometheus

バイナリ落としてきて適当に配置してprometheus.yml書くだけ ほかは特にいじらず(おもむろにscrape_configs->static_configsで対象のホスト名:9100を並べていけばOK。

job_nameはgrafanaダッシュボード設定時にラベル合わせればなんでもいいんだけどnode_exporter使うダッシュボードはjob=nodeというラベルを期待してる空気を感じたのでそんな感じにしておくと楽やも。

[program:prometheus]
command=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml
directory=/usr/local/prometheus
user=monitor
autorestart=true

雑にsupervisorでデーモン化する 起動後に9090ポートにアクセスし、適当なクエリを投げ、各ホストからメトリクスが取得できラベルが付与されてることを確認。

grafana

Installing on Debian / Ubuntu | Grafana Documentation

を眺めつつaptで。 3000ポートで起動するのでログインしてdata sourceにprometheusを追加。

であとは適当なダッシュボードを

Grafana Dashboards - discover and share dashboards for Grafana. | Grafana Labs

から探してきてインポートする。 今回はNode Exporter Full 0.16を拝借してみた。

インポートしたダッシュボードで表示されないメトリクスはnode_exporter側でrenameされてたりするので合わせたりする必要があるが大体いい感じに表示される。

https://github.com/prometheus/node_exporter/releases

Many metrics have been renamed/modified to include base units, for example node_cpu is now node_cpu_seconds_total.

とかこういうの。

なおnode_exporterもgrafanaもprometheusもdockerイメージが提供されてるのでそっちを使うのもよさげ。

NASも監視してみる

手持ちのQNAP NASはTS-220というモデルでQTSというLinuxベースのNAS用OSが稼働しており、ここからも各種メトリクスを取得してみる。

f:id:egmc:20180721232649p:plain

(標準のビューでもCPU、メモリ使用率、トラフィック、温度等はなんとなく見れてアプリからも確認できるのでこれはこれでいいのだけど)

TS-220のCPUはMarvell6282(ARMv5)1.6Ghz、でnode_exporterのリリースページをおもむろに覗きにいくとlinux-armv5なバイナリが既に用意されているのでこれを落としてきて起動するだけでイケる。お手軽ですね。 デーモン化はひとまずおいといて、雑にscreen貼って起動しっぱなしにしているが、QTSも/etc/init.d/以下に起動スクリプト置けばイケるはずなのでそのうち対応。

NASは自宅のネットワーク内にいるので9100宛のTCP通信を

  • ルータ側でポートマッピングを行ってNASの9100へ
  • かつインターネット側からのアクセスを監視元のIPに制限(いちおう)

な設定でアクセスできるように。

自宅のインターネット回線は特に固定IPというわけではないので、今回はQNAPが提供するDDNS的なサービス(myqnapcloud)を利用しつつ、自分の管理ドメインから適当にCNAMEを設定して名前解決を行うようにしてみた。

grafanaのビューでみるとこんな感じ。

f:id:egmc:20180721232837p:plain f:id:egmc:20180721232854p:plain

MacのTime Machineバックアップが走ってるときなどはそれなりに書き込みが走ったりするので、ガリガリやってる内訳が観測できて結構楽しい。

gdbで死んでるphpプロセスから諸々の情報を得るメモ

手法は色々出回っているがちょうど某サービスでcronジョブの途中でお亡くなりになっているプロセスがいるので便利コマンドを試しておく。

環境

php -v
PHP 5.5.8 (cli) (built: Feb  4 2014 16:57:24)

$ gdb -v
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)

対象

2017年からご存命の6792さんを調べる

  6777  0.0  0.0 275812    52 ?        S     2017   0:00 php -q /home/xxxx/momochro.me/app/Console/cake.php -working /home/xxx/momochro.me/app update_and_notify -app /home/xxxx/momochro.me/app
  6791  0.0  0.0 273184   200 ?        S     2017   0:00  \_ /usr/local/bin/php /home/xxx/momochro.me/app/Console/do.php update_momo_items
  6792  0.0 17.4 280772 177860 ?       S     2017   0:00      \_ php -q /home/xxx/momochro.me/app/Console/cake.php -working /home/xxx/momochro.me/app update_momo_items -app /home/xxx/momochro.me/app

外から眺める

psで

$ ps -eopid,wchan:30,comm  |grep 6792
 6792 sk_wait_data                   php

sk_wait_dataで止まってる

sudo strace -p 6792
Process 6792 attached
read(10,

lsofで

$ sudo  lsof -i |grep 6792
php        6792      %USER%   10u  IPv4  937985628      0t0  TCP %HOSTNAME%:42784->202x6x245x194:https (ESTABLISHED)

202x6x245x194にestablishedになってる。 ということでhttpsなリクエストの最中に死んでそう。

gdb

phpソース直下の.gdbinitを読ませる

$ gdb -p 6792  --init-command=/usr/local/src/php-5.5.8/.gdbinit
(gdb) zbacktrace
[0x7ff32cff5860] file_get_contents("https://api.dmm.com/affiliate/v3/ItemList?api_id=xxxxxx&affiliate_id=xxx.....") /home/xxx/momochro.me/app/Lib/MomoParser/DMMItemParser.php:29
[0x7ff32cff5640] DMMItemParser->getList() /home/xxx/momochro.me/app/Console/Command/UpdateMomoItemsShell.php:41
[0x7ff32cff5498] UpdateMomoItemsShell->main() /home/xxx/momochro.me/lib/Cake/Console/Shell.php:393
...

file_get_contentsで雑にapi呼んでるところで止まってるのがわかる

$ dig +short api.dmm.com
202.6.245.194

上記をcoreを吐かせてgdb

$ gcore 6792
$ gdb /usr/local/bin/php core.6792  --init-command=/usr/local/src/php-5.5.8/.gdbinit

参考諸々

だいたいここを参照

PHPのcoredumpを読んでなぜSEGVで落ちたかを知りたい - Qiita

Robert Ames (.com!)

Amazon EchoのAlexaスキル開発で地味にはまったところをメモしておく

解決してしまえば大したことないが時間がもったいない系の色々

対話モデルの設定でサンプル発話のスロット前後にスペースがないとエラーになる問題

エラー

AddHomeShoppingIntent {Item}を追加

Error: There was a problem with your request: Parsing error in sample: AddHomeShoppingIntent {Item}を追加

以下はOK

AddHomeShoppingIntent {Item} を追加

パースエラーとしか言ってくれないし、ドキュメントのサンプルをみても特にスペースとか入ってない、のでこれをこのまま入れると怒られる。 スペース入れればおっけー。 エラーメッセージもアレだがドキュメントに書いて欲しい。

Echosim.ioで無限にsomething went Wrong. Oopsと言われる

フォーラムでのやりとりを見る限り、どうもEchosim.ioの不具合っぽい。 一応自分の環境はChromeだが特にブラウザどうこうという話でもなさそう。 再ログインして一時的に復活したりもするが一度エラーのループに入ると、「アレクサ、今日の天気を教えて」的なリクエストも全部上記のエラーとなってしまう。 このパターンはスキル側の不具合を疑っても時間の無駄なのでひとまず開発者コンソールからのリクエストで問題なければおっけーと考えた方がよさそう。 Amazon mShop appを使うと良いという回答がついているが、ようわからんので、このあたりは何かわかったら追記するやも。 amazon shoppingのアプリにalexaが搭載されており、英語で話しかける分にはテスト出来るが、こちらはamazon.comのみで英語はEngishとSpanishのみ。日本語はamazon.co.jpでしか使えず、amazon.co.jpでは音声での商品検索が出来るだけでalexaが起動するわけではないのでテストすることはやはり出来ない。

Alexa Skills Kit SDK for Node.jsでAlexa.handlerにいわゆるLambdaのcallbackを渡すとemitした段階でレスポンスを返してくれない

alexa-skills-kit-sdk-for-nodejs/response.js at master · alexa/alexa-skills-kit-sdk-for-nodejs · GitHub

このあたりの処理を見る限りcontext.succeedの形式もcallbackの形式も両対応してるようなんだけど、どうも何らかのイベントが実行され続けているらしく常にタイムアウトしてしまう。 f:id:egmc:20171128231855p:plain

AWS Solutions Architect ブログ: AWS LambdaでNode.js 4.3.2が利用可能になりました

[12/9追記]

単にメッセージを返すだけの処理でも発生するので、sdkの問題っぽい。 ローカル実行してプロファイラでおっかけたところwunderlistのsdkでした、alexa-sdkは無罪。

issueもあがってた Script Hangs · Issue #12 · wunderlist/wunderlist.js · GitHub

wunderlistsdkをnewした段階で何らかのイベントが動き続けていてタイムアウトまで実行し続けていた模様、対応は↓の通りで変わりなく、まあ必要な処理が終わった段階でのcallbackなのでcallbackWaitsForEmptyEventLoopは基本falseでもいいんじゃないかとは思う。

[/追記おわり]

回避策としてはcallbackを渡さない古いスタイルで書くか、↑の通りcontext.callbackWaitsForEmptyEventLoop = false;を指定しておけばOK。

レポジトリのサンプルではcallbackを渡しているが

https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs

ブログのチュートリアルでは渡してなかったりするのはこのあたりにはまる人が多いのやも?

Alexaスキル開発トレーニングシリーズ 第2回 対話モデルとAlexa SDK : Alexa Blogs

nodejsのsslまわりメモ

自鯖に設定したLets'e EncryptのSSL証明書の設定をミスっていて(おそらく中間証明書が設定できておらず)、だいぶ回り道をしたが、折角なのでメモを残しておく。

  • nodeが使うroot証明書はハードコードされてる。拡張方法が提供されるっぽいやりとりされていたが・・。
    • node_root_certs.hにいる
    • バージョンによって異なりそうだが、今回必要だったDST Root CA X3はv0.1.45時点で既に入ってそう
$ find . -name 'node_root_certs.h' |xargs grep  'DST Root CA X3'
./v0.10.45/node-v0.10.45/src/node_root_certs.h:/* DST Root CA X3 */
./v4.3.2/node-v4.3.2/src/node_root_certs.h:/* DST Root CA X3 */
./v7.8.0/node-v7.8.0/src/node_root_certs.h:/* DST Root CA X3 */

letsencrypt.org

この辺とか、各所で議論してるっぽい

github.com

  • root証明書がいない問題が発生したらこのあたりが使えそう、ただし初回リクエストでダウンロードが発生したので、lambdaとかの実行環境だとnodeが入れ替わったタイミングで困るのでちょっと扱いづらい Daplie / node-ssl-root-cas · GitLab

  • 先の中間証明書がない問題で検証に失敗していた場合も.addFileで中間証明書をリクエスト元でセットしてやると成功した(本来やることはないだろうけど・・)

とりあえずエラーメッセージはきちんと読もう。

certbot設定メモ

諸事情により取得していたrapidsslの証明書の有効期限が切れたのでletsencryptに切り替えたメモ。

大体公式とこちらの記事参考でなんとかなった。

https://certbot.eff.org/

CentOSにLet's EncryptのSSL証明書を導入する - オープンソースこねこね

apacheをソースからインストールしてしまっていたのでパスまわりは適当に。

Cent6+Apache2.4

  • 手順に従ってインストール
  • 初回の確認でhttpでアクセスされるのでバーチャルホストでアクセス出来るように設定
  • 発行された証明書を手動でパス設定

すれば発行後の更新は

certbot-auto renew --force-renewal --post-hook "/usr/sbin/apachectl graceful"

OKapacheのreloadがいるのでrootでやらせておく。

force-renewalな状態でcronに仕込んで、実際に証明書の期限が更新されればOK

openssl s_client -connect ssl.eg2mix.com:443 < /dev/null 2> /dev/null | sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p'|openssl x509 -noout -startdate -enddate

f:id:egmc:20170312194930p:plain f:id:egmc:20170312194939p:plain

めでたい。

土善旅館を激推しする

概要

土善旅館を激推しします。

11月に開発合宿でお世話になり、参加者のみなさまとよかったねーという話をしていたらタイムリーにこちらの記事で紹介されていました。

qiita.comf:id:egmc:20161212132406j:plain

宿の対応も素晴らしいという話なんですが、ワイ的にはここ良かったやで!というやつを書きます。
一応自分の開発合宿歴としてはとあるコミュニティで年二回くらいのペースで参加していて、過去には

  • マホロバマインズ三浦
  • 山喜旅館
  • まるも+かぢや旅館
  • KANAYABASE(閉鎖済)+かぢや旅館
  • 梁山泊

あたりに行ってます(手配はお任せで毎回良い場所をチョイス頂いてます)。

その中でも今回行った土善旅館さんがだいぶ良かったので、激推ししてみます。

温泉

もしかしたら部屋によるかもしれませんが、今回使用させて頂いた会議室のすぐ横に風呂(温泉)があります。

風呂が近いというのは超大事であり、そしてほぼ24時間好きな時に入れる、というのは素晴らしいことです。
大体自分は風呂が好きであり、開発中には足湯が常にあるといいと思っており、なんならこのブログも足湯をしつつ書いており、眠くなったらすぐそこに風呂があると良いという考えの人間なので風呂がそこにあるだけでとても安心感があります。

温泉宿での開発合宿は良いのですが、単に夜風呂に入れるだけであることと、開発中に風呂に入ることは大きな差がありますので、ロケーションは大事ですね。

ちなみに土善旅館さんの風呂は、お湯は常に温かいのですが、冷めにくくするためにプールで使うようなでかい発泡スチロール的なサムシングが湯船に設置してあり、まあまあ重いのでそこだけちょっと頑張りましょう。
お湯はちょっと長めに出し続けるとそのうちあったかくなります。

回線

合宿場所のインターネット回線は当然ながら大事なんですが、場所によっては回線がいささか貧弱であったりして結局自分たちで用意したポケットwifiのお世話になったりテザリングしたりすることもあったりするわけです。

土善旅館さんはどうしたことかOCNとIIJ二回線引かれており、切り替えることができます。 今回は10人少々の合宿であり、OCN回線は十分に高速で特に予備のお世話にはならなかったですが、安心感がありますね。

外見にはどう見ても古き良き旅館といった風情であり、フロントもいい感じのおばちゃんで経営されているこの旅館にこういった回線導入、wifi整備の意思決定がどのように行われたのか非常に気になるところです。

事前情報ほぼ無しで行ったので、値段的に正直そこまで期待していなかったのですがだいぶ期待を超えたご飯でした。

夕飯までに食い過ぎないように気をつけましょう。

あとqiitaの方も書いてますが、夕飯時の🍺は旅館の方で注文しましょう。

交通

これはまあ致し方ないところなのですが、都内からはちょい遠いです。

ただ宿から5分程度のセブンイレブンに京成バスの東庄というバス停があり、ここから東京駅、浜松町駅まで一本で行くことが出来ます。
予約は出来ないとことはありますが、日曜夜の帰りのバスは割と空いていて10人近くの合宿メンバー全員余裕で乗ることが出来ました。

お値段は2000円ちょい。

備品

開発合宿の際は電源タップなど大体持参して行くんですが、今回はまったく使いませんでした。

電源タップ、外部モニター、変換アダプタと揃っておりまったく不足なし。 特に電源タップが回転式で邪魔にならないタイプでこれは気がきいてるで、という感じでした。

多分これ

おまけ:本棚

推しポイントとはちょい違うんですが本棚のラインナップが色々おかしかったので載せておきます。

弓道場があり合宿にも使われるということで、弓道コーナーもありました。

現場からは以上です。

土善旅館[弓道合宿・開発合宿]