プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

ローカルサーバーにsshで接続する

misocaのブログngrokの紹介が載っていて、あ、面白そうなサービス、と思っていたところ、NATの内側にあるローカルサーバーに外部からSSHで接続する必要が生じたので、早速試してみました。

インストール

インストールはなにも難しくありません。

mor@LaptopDev:~/bin$ wget https://dl.ngrok.com/ngrok_2.0.19_linux_386.zip
mor@LaptopDev:~/bin$ unzip ngrok_2.0.19_linux_386.zip

ダウンロードする際は、32bit版/64bit版がわかれているので、そこだけ注意してください(32bit版は、More Platforms を開くとでてきました)。

早速動かしてみます。

mor@LaptopDev:~/bin$ ./ngrok tcp 22
Tunnel session failed: Non http-protocols are only available after you signup at https://ngrok.com/signup
mor@LaptopDev:~/bin$ 

おっと、SSHの場合は、サインアップが必要だそうです。なので、 https://ngrok.com/ からサインアップします(GitHubアカウントがあったのですぐでした)。

サインアップした時点では、freeプランなので、お金もかかりません。

サインアップ後、ngrokサイトのダッシュボード画面で表示されるauthtokenを指定してやります。

mor@LaptopDev:~/bin$ ./ngrok authtoken xxxxxxxxxxxxxxxxxxx

設定ファイルが、~/.ngrok2/ngrok.yml に作成されます。

これで、

mor@LaptopDev:~/bin$ ./ngrok tcp 22

とすると、見事にポートフォワーディングをしてくれました。

設定ファイルの作成

これでも十分使えるのですが、今回の場合対象のサーバーがリモートにあるので、OS起動後に自動的に ngrok の設定ができていると嬉しいです。

~/.ngrok2/ngrok.yml の内容を追記します。設定ファイルの内容はngrokのDocumentationに詳しく載ってます。

authtoken: xxxxxxxxxxxxxxxxxxxxxxxx
log_level: info
log_format: logfmt
log: /var/log/ngrok.log
tunnels:
  ssh:
    proto: tcp
    addr: xxx

addr でポート番号を指定します。ssh のポート番号を変える場合は、/etc/ssh/sshd_config 側の設定も確認してください。 これを呼び出すには、

mor@LaptopDev:~/bin$ ./ngrok start --config=~/.ngrok2/ngrok.yml ssh

のように呼び出します。コマンドライン上のsshは、設定ファイル中のssh(トンネル名?というのかな)に対応しています。この名前はユーザーが任意につけられるようです。 今回は、簡単に確認するため、cronで起動時に、これを呼び出すようにしてみます。

mor@LaptopDev:/etc/cron.d$ cat ngrok 
# /etc/cron.d/ngrok: crontab entries for ngrok

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

@reboot  root    /opt/ngrok/bin/ngrok start --config=/opt/ngrok/ngrok2/ngrok.yml ssh >> /var/log/ngrok.log 2>&1
mor@LaptopDev:/etc/cron.d$ 

設定ファイル等はrootの持ち物にして、それっぽい場所におきました。設定後、再起動してから、ngrok.comのダッシュボードを見ると

f:id:junichim:20160825154802p:plain

のように接続用のURLが登録されていることがわかります。もし、接続用のURLやポート番号を固定にしたい場合は、有料プランに変更すればよいようです。

ここまで、無料でつかえるなんて、ngrokさんありがたすぎです。

ディスク使用量を監視する

もともと、redmineを運用していたサーバーのディスク空き容量が厳しかったので、ディスク使用量を監視しようと思ってました(まあ、その設定をしようとサーバーをみたら、『[Ubuntu] unattended-upgrade 実行失敗と復旧』で書いたように痛い目にあってしまいましたので、なおさら必然性がでてしまったのですが・・・)。

で、『[Ubuntu] unattended-upgrade の通知設定』で書いたように既にメール設定を導入したので、自分でディスク使用量の監視スクリプトとcronを書けば事足りるのですが、CloudWatch を使いたいというのがあったので、今回はこちらで実現しました。

EC2だと、CloudWatch を使えば、いくつかの指標(メトリックス)に関しては、デフォルトかつ無料(5分単位の監視の場合)で利用可能なのですが、デフォルトで提供されているものには、ディスク使用量は含まれていません。

ちょっと調べてみると、Amazon CloudWatch Monitoring Scripts for Linux を使えば簡単にディスク使用量の監視をカスタムメトリックスとして CloudWatch に追加できるようです。

以下の作業はこちらの記事を参考にさせていただきました。

CloudWatchでEC2のディスク容量のチェックをおこなう

準備

説明ページあるように、必要なパッケージをインストールしておきます。

bitnami@ip-10-132-190-144:~$ sudo apt-get install libwww-perl libdatetime-perl

 問題なくインストールできれば、準備完了です。

CloudWatchの設定

インストールはスクリプトファイルをダウンロードして、設置すれば終わりです。

bitnami@ip-10-132-190-144:~$ wget http://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip
bitnami@ip-10-132-190-144:~$ cd /usr/local/bin
bitnami@ip-10-132-190-144:/usr/local/bin$ sudo unzip /home/bitnami/CloudWatchMonitoringScripts-1.2.1.zip 
bitnami@ip-10-132-190-144:/usr/local/bin$ 

試してみます。ここで、認証情報は、AWS_ACCESS_KEYとAWS_SECRET_KEYに入っているとしています。

--verifyオプションをつけると、実際にメトリックスを送信することなく、認証を含めて指定の値がとれるか確認します。これで、問題なければ、下記のように表示がされます。

bitnami@ip-10-132-190-144:/usr/local/bin/aws-scripts-mon$ ./mon-put-instance-data.pl --disk-space-avail --disk-path=/ --verify --verbose --aws-access-key=${AWS_ACCESS_KEY} --aws-secret-key=${AWS_SECRET_KEY}   
DiskSpaceAvailable [/]: 4.74913787841797 (Gigabytes)
Endpoint: https://monitoring.ap-northeast-1.amazonaws.com
Payload: {"MetricData":[{"Timestamp":1442134385,"Dimensions":[{"Value":"/dev/xvda1","Name":"Filesystem"},{"Value":"xxxxxxxxxx","Name":"InstanceId"},{"Value":"/","Name":"MountPath"}],"Value":4.74913787841797,"Unit":"Gigabytes","MetricName":"DiskSpaceAvailable"}],"Namespace":"System/Linux","__type":"com.amazonaws.cloudwatch.v2010_08_01#PutMetricDataInput"}

Verification completed successfully. No actual metrics sent to CloudWatch.

bitnami@ip-10-132-190-144:/usr/local/bin/aws-scripts-mon$ 

問題無いようですね。

ちなみに、ここで使用した認証情報に対応する、IAMユーザーは、AmazonEC2FullAccess をポリシーとして持っています。このポリシーの詳細を表示してみると、

f:id:junichim:20160825154800p:plain

のようになっているので、デフォルト状態で、CloudWatchの権限があることがわかります。

それでは、cronから呼び出すようにします。cron から呼び出す場合は、--from-cron オプションを設定してください。

bitnami@ip-10-132-190-144:/etc/cron.d$ cat ec2_monitor_cloudwatch 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

# m h dom mon dow user  command
*/5 * * * * root /etc/ec2/ec2-cloudwatch.sh
bitnami@ip-10-132-190-144:/etc/cron.d$ 

さきほどコマンドラインから実行した内容は、ec2-cloudwatch.sh にまとめています。

bitnami@ip-10-132-190-144:/etc/ec2$ cat ec2-cloudwatch.sh 
#!/bin/bash
#
# monitor some metrics and push to CloudWatch
#
# writen by Junichi MORI, 2015/9/13

EC2_ENV=/etc/ec2/bash_ec2env

. ${EC2_ENV}

MON_DIR=/usr/local/bin/aws-scripts-mon
MON_SCRIPT=mon-put-instance-data.pl

${MON_DIR}/${MON_SCRIPT} --disk-space-avail --disk-path=/ --aws-access-key=${AWS_ACCESS_KEY} --aws-secret-key=${AWS_SECRET_KEY} --from-cron
bitnami@ip-10-132-190-144:/etc/ec2$ 

認証情報は、EC2_ENV で指定しているファイルで設定しています。

確認

しばらくすると(5分以上)待って、AWSコンソールからCloudWatchを開くと、『メトリックス』に『Linuxシステム』というのが追加されています。

アラームの設定

CloudWatchでカスタムメメトリックスを設定したので、せっかくなので、アラームも設定してみましょう。

『AWSコンソール』から『CloudWatch』を開いて、ダッシュボード中の『アラームの作成』ボタンを押します。下記のようなアラームの設定画面が表示されるので、画面に従って、必要事項を入力していきます。

f:id:junichim:20160825154744p:plain

最初はアラームを設定するメトリックスを選択します。メトリックスを選択すると、アラーム定義画面に移ります。

f:id:junichim:20160825154745p:plain

始めに、アラームの名称・説明を入力し、次に、アラームの閾値を設定します。

f:id:junichim:20160825154748p:plain

この例の場合は、ディスクの残り領域が、4.7GB以下が1回連続した場合にアラームを発行するという基準にしています。

次に、アラームの閾値に対して、どのような行動を取るかを指定します。

『アラームが次の時』の意味は、対象となるメトリックスがアラーム閾値の条件を満たし場合が『警告』、満たさない場合が『OK』になります。『不足』はメトリックスが取得できていないなどの状態です。

『警告』を選択すると、アラームが閾値を満たした場合(上記の場合だと、ディスクの残り容量が4.7GBを切ったとき)に通知が飛びます。同じ閾値に対して『OK』を選択すると、ディスクの残り容量が4.7GBより大きい場合に通知が発行されます。

f:id:junichim:20160825154749p:plain

『通知の送信先』には、アラーム基準を満たした場合の通知先を入力します。ただし、この欄は、Amazon SNS のトピックとして入力する必要があります。

まだ、SNSを設定していない場合は、『新しいリスト』を選択します。すると、

f:id:junichim:20160825154751p:plain

のように、『メールリスト』欄が現れます。

この『メールリスト』欄に、送信先のメールアドレスを入力します。さらに、『通知の送信先』にSNSのトピック名を入力します。今回は新規での作成になるため、トピック名としては(使える文字・記号と文字列の長さは守る必要がありますが)任意の文字列を指定すればよいと思います。

メールアドレスだけ指定すればいいと勝手に思い込んでいたもんで、実は、ここで結構はまりました。『通知の送信先』が空欄だと、『アラームの作成』ボタンを押しても、エラーとなり、そのエラーメッセージも文字種別の不正、のような内容のため、メールアドレスが間違っているのかと勘違いしてました。

問題なく入力できていると、入力したメールアドレス宛に、すぐに確認メールが送られます。こんな感じです。

f:id:junichim:20160825154752p:plain

メールに記載されているリンクをクリックすることで、メールアドレスが登録されます。画面もすぐに下記のように変わります。

f:id:junichim:20160825154754p:plain

問題なく設定できると、CloudWatchの画面で

f:id:junichim:20160825154756p:plain

こんな感じで、アラームが設定されたことがわかります。

なお、CloudWatchのアラームの作成については、こちらのリファレンスなどをご参考にしてください。ちゃんと読むとSNS設定のことなども載ってますね。

確認

では、実際にアラームを発生させてみます。

監視対象のサーバーにログインして、適当なファイルをコピーして、ディスクの空き容量を4.7GB以下にします。

すると、そのうち、

f:id:junichim:20160825154758p:plain

のように、設定したアラームがアラーム状態に変化します(紛らわしい・・・)。 メールも送られているはずなので、確認してみると、

You are receiving this email because your Amazon CloudWatch Alarm "LowFreeDiskSpace" in the APAC - Tokyo region has entered the ALARM state, because "Threshold Crossed: 1 datapoint (4.4244499206543) was less than or equal to the threshold (4.7)." at "Sunday 13 September, 2015 10:56:13 UTC".

View this alarm in the AWS Management Console:
https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#s=Alarms&alarm=LowFreeDiskSpace

Alarm Details:
- Name:                       LowFreeDiskSpace
- Description:                Low free disk space
- State Change:               OK -> ALARM
- Reason for State Change:    Threshold Crossed: 1 datapoint (4.4244499206543) was less than or equal to the threshold (4.7).
- Timestamp:                  Sunday 13 September, 2015 10:56:13 UTC
- AWS Account:                xxxxxxxxxxxx

Threshold:
- The alarm is in the ALARM state when the metric is LessThanOrEqualToThreshold 4.7 for 300 seconds. 

Monitored Metric:
- MetricNamespace:            System/Linux
- MetricName:                 DiskSpaceAvailable
- Dimensions:                 [Filesystem = /dev/xvda1] [InstanceId = xxxxxxxxxx] [MountPath = /]
- Period:                     300 seconds
- Statistic:                  Average
- Unit:                       not specified

State Change Actions:
- OK: 
- ALARM: [arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:ec2administrator]
- INSUFFICIENT_DATA: 

こんな感じのメールが送られていました。無事に監視できているようです。

その他

カスタムメトリックを利用するとCloudWatch の料金が発生しますが、CloudWatchの料金の説明を読むと、

新規および既存のお客様は、10 メトリックス(Amazon EC2 インスタンスまたはカスタムメトリックス、または CloudWatch Logs* の詳細モニタリングに適用)、10 アラーム、および 100 万の API リクエストを追加料金なしでご利用いただけます。

とあるので、10メトリックスまでなら無料で使えそうです。

また、SNS も料金の説明を読むと無料利用枠があるので、数個のアラームに使う分には追加料金も不要のようです。ありがたいことです。

あと、CloudWatch を少し触ってみた印象としては、サーバーの状態の中でも数値が刻々と変化していく指標に使うのが良さそうです。グラフィカルに変化を見ることができるので、これを利用しない手はないという印象です。もちろん、エラーの有無などをメトリックスにしてアラームを設定することも可能ですが、わざわざCloudWatchを使わなくても良さそうです。気になる指標が出てきたら、いろいろ追加して使ってみようと思います。

unattended-upgrade の通知設定

[Ubuntu] セキュリティアップデートの自動インストール』 でセキュリティアップデートを自動でインストールするようにしていましたが、こちらの記事『[Ubuntu] unattended-upgrade 実行失敗と復旧』で書いたように、ディスクフルでセキュリティアップデートに失敗することがありました。お恥ずかしい話ですが、ログを見ると一ヶ月ぐらい前に発生していました。

ということで、セキュリティアップデートに関する通知をメールで飛ばすようにしたので、まとめておきます。

 

準備

メールを送れる環境にしておく必要があります。

今回は、『[s3fs] s3fsが予期せずアンマウントされた場合への対策』で行ったのと同じように、ssmtp と mailutils を使った環境をセットアップしました。詳しい設定方法は、リンク先の記事をご覧ください。

 

設定方法

設定方法は、対して難しくなく、/etc/apt/apt.conf.d/50unattended-upgrades 設定ファイルにメールアドレスを記述するだけです。

unattended-upgrades パッケージインストール直後は、Unattended-Upgrade::Mail がコメントアウトされているので、通知をしたいメールアドレスを書き込むだけです。

// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed.
Unattended-Upgrade::Mail "username@my_domain_name";

とりあえずセキュリティアップデートがかかった場合とエラー時にメールを受け取るようにしました。

エラー時のみでよい場合は、 Unattended-Upgrade::MailOnlyOnError をtrueに設定してください。

 

その他

Unattended-Upgrades にはいろいろと設定ができます。たとえば、

  • 適用するパッケージ種別の選択
  • 除外したいパッケージの指定
  • アップデート時の通知
  • エラー発生時のみ通知
  • パッケージのアップデートの自動再起動(デフォルトでは再起動されません)

などです。詳しくは、こちらの記事『Debian and Ubuntu Automatic Security Updates』などを参考にご自分の環境にあったセットアップを行ってみてください。