週末新人軟件工程師 その2

Ryohei Tsuda
12 min readJan 6, 2019

--

前回 → その1

前回の要約

  • プログラミングを始めた
  • Python でちょっとしたツールを作った

今回やること

  • レスポンスのステータスコードが異常を示す場合にのみ通知する
  • 自分で作ったプログラムをリモートのサーバを使って動かす(AWS — Amazon Web Services を使ってみる)

条件分岐 in Python

Python で条件によって処理を分けるには、 if / else 文を使う。

例えば、ある変数 x の値が 100 以上であれば OK 、 100 未満であれば NG を返す場合は Python を起動して

x = 1000
if x >= 100:
print('OK')
else:
print('NG')

上記のように入力すれば結果が得られる。

詳しくは公式ドキュメント参照。

リモートのサーバで動かす

一定間隔で特定の Web サイトを監視するとして、常に監視プログラムを動かすためには PC を開きっぱなしにしていなければならない。流石にそれは現実的では無いので、リモートのサーバで動かす方法を考える。

サーバには Amazon Web Services ( AWS )を使う。 AWS はただのサーバだけではなく様々な機能を提供しているほか、エントリー用の無料枠が用意されている。例えばAmazon EC2 は最初の12ヶ月間、月間で750時間まで無料で使うことができる。 AWS Lambda では永久無料で月間100万回のプログラム実行ができる。

AWS アカウント作成→動かすまで

新しいアカウントの作成はこちら。アカウント作成にメールアドレスと電話番号が必要。電話番号認証有り。

趣味なので無料を選択

1. インスタンスを作る

CLI を通じて aws コマンドでインスタンスを作成することもできるが、今回はマネジメントコンソールからぽちぽち選択していく方式で作る。まずは、サイドメニューの「インスタンス」からインスタンスの起動に必要なソフトウェアを選択する。

Amazon Linux AMIを選択

2. インスタンスタイプを選ぶ

テスト用なので無料枠の範囲内で t2.micro を選択する。

3. インスタンスの詳細設定

インスタンス数は1で、設定はデフォルトのままにする。ここ弄ったら何が変わるかとかは調べてない。

4. ストレージの追加

「合わせて削除」にチェックを入れると、インスタンス削除時にストレージも削除される(消し忘れると課金されるのでチェックを入れておく)。

5. タグの追加

インスタンスを識別するタグをつける。「キー」と「値」をセットで設定する。これを使って課金額の分類をしたりプログラムから自動的にインスタンスを操作したりできるらしい。

6. セキュリティグループの追加

事前にマネジメントコンソールのサイドメニュー「セキュリティグループ」から新しくセキュリティグループを作っておく。ここではインバウンドでSSH(22番ポート)とHTTP(80番ポート)HTTPS(443番ポート)を開けたセキュリティグループ「my-security-group」を事前に作成しておいたので、それを適用する。

セキュリティグループは通信の制御を行うために AWS が用意している仕組み。デフォルトではサーバに入ってくる通信(インバウンド)は全て閉じられていて、サーバから出ていく通信(アウトバウンド)は全て開いている。インスタンスに外からアクセスする場合にはインバウンドのポートを明示的に指定して開けなければならない。

7. インスタンス作成の確認

内容を確認する。セキュリティグループの設定で「送信元」を「任意の場所」にしている場合には、ここで「世界に向けて開かれています」というアラートが出る。利用する内容によってはオフィスや自宅のIPからのみ接続を許可するなどの設定にした方がよいだろうが、今回はテストなのでそのまま作成した。

8. キーペアの選択

インスタンスに ssh 接続するためのキーペアを作成する。マネジメントコンソールから別途作成している場合は「既存のキーペアの選択」を選ぶ。

9. インスタンスの作成完了

ここで「請求アラートの作成」をしておくと、無料利用枠を超えた際にメール通知を受け取ることができるので設定しておくとよい。

10. 作成したインスタンスの表示

「ステータスチェック」が「2/2 OK」になればインスタンスに接続が可能。

11. Elastic IP の割り当て

インターネットからアクセスできる固有の IP アドレスを取得するには、 Elastic IP を使う。マネジメントコンソールのサイドメニューから割り当てが可能。後述の実行中のインスタンスへの関連付けをしない場合は課金が発生するので注意すること。

12. Elastic IP の割り当て完了

割り当てが完了すると、 画面上に IP アドレスが表示される。

13. Elastic IP と EC2 インスタンスの関連付け

サイドメニューの Elastic IP で「アクション」から「アドレスの関連付け」を行う。

14. Elastic IP と EC2 インスタンスの関連付け完了

「関連付け」を押せば完了。

15. 作ったEC2インスタンスにsshで接続

ssh で Elastic IP を関連付けたインスタンスに接続する。書式は下記の通り。

ssh -i [キーペアの名前] ec2-user@[Elastic IPで関連付けたアドレス]

ec2-user (下記の図ではタイプミスしている…)は Amazon Linux においてデフォルトで作成されているユーザーで、最初はこのユーザーを使って公開鍵認証でログインする必要がある。

秘密鍵が bad permissions ということで接続できなかった。

16. EC2インスタンスへの接続完了

chmod で秘密鍵のパーミッションを変更し再度 ssh 接続する。今度はうまくいった。 ~/.ssh/~ の部分は鍵のある場所を指定する。

17. nginxをインストールしてアクセスしてみる

nginx は Web サーバのソフトウェア。サーバが外から http で接続できることを確認するためにインストールしてみる。

sudo yum install nginxsudo service nginx startして http://x.x.x.x(xは Elastic IP で割り当てたアドレス)にアクセスすると、 nginx が起動していることを示すページが表示されるはず。

ここまでやって、ようやく AWS のEC2 でプログラムを動かすことのできる環境を手に入れた。次に、EC2 で自分の作ったプログラムを動かしてみる。

18. サーバにファイルを転送する

サーバ側でディレクトリを作り、そこに自分が作ったスクリプトを scp コマンドで送る。

scpコマンドの書式は Qiita を参考にした(記事

19. 定常的に実行するために cron を設定する

次に、 scp で転送したプログラムを定時実行するために crontab の設定を行う。

crontab の設定は crontab -l で確認できる。

20. cron のログ確認

cron で実行された結果はサーバに届いたメール、または /var/log/cron で確認することができる。

ちゃんと動いていた。今回はテストなので crontab -r で削除しておく。

ここまでやって、プログラム単位で動かすのは Lambda を使った方がよいなと思い直したので Lambda を使ってみることにする。

AWS Lambda で動かす

Lambda は AWS が提供するコンピューティングサービスの一つで、これを使うとサーバーの設定をすることなくプログラムを実行できる。サーバーの設定・管理のような面倒な作業で躓くことが無いので、私のようなプログラミング初心者にお勧めできる。

Lambda に置いたプログラムは AWS の各種サービスで起きる「イベント」に応答して実行され、実行された回数分のみ課金される(月 100 万件の無料枠あり)。

Lambdaの料金表(2019年1月)

Lambda のトリガーとなるイベントには様々なものがある。 S3 (ストレージ)へのファイルアップロードや DynamoDB (データベース)のテーブル内のデータ変更、 CloudWatch (リソースのモニタリング)を利用した定時実行など。

Lambda の制約

Lambda の仕様上の制限はこちら。特に重要なものは「外部モジュールの利用」と「実行時間」だと思う。

外部モジュールの利用

例えば Python で外部モジュールを import して使うとき、そのモジュールは事前に pip 等で実行環境にインストールしておく必要がある。しかし、 Lambda の環境で外部モジュールを使うには、そのモジュールをまとめて .zip 等の形式でアップロードしなければならない。

実行時間

呼び出しごとの最大実行時間は 300 秒( 5 分)に制限されている。遅いことで有名らしい Python でも実行時間が 5 分を超えるプログラムを書いたことは無いが、頭には入れておく。

Lambda で動かす手順

  1. 外部モジュールを含めてプログラムをzip化する
  2. Lambdaで関数を作る
  3. コードエントリタイプで「.ZIPファイルをアップロード」を選択してプログラムをアップロードする
  4. 実行する関数を関数コードの「ハンドラ」で指定する

zip化

まずは必要なモジュールをインストールする。そのために、作った python のファイルと同じディレクトリに requirements.txt を作り、。

homebrew でインストールした Python を使っている場合は、 ~/.pydistutils.cfg に下記の事項を書いておく。

[install]
prefix=

必要な外部モジュールの名前をrequirements.txtに書いて保存しておく(今回で言えばrequests)。

pip3 install -U -r requirements.txt -t ./vendor で vendor ディレクトリに必要な外部モジュールをインストールする。

zip -r hoge.zip 作ったPythonのファイル名 vendor で作ったpythonのファイルとvendorディレクトリをzip化する。

マネジメントコンソールから Lambda 関数を作成する。

Lambda 関数を一から作成する。ランタイムは Python 3.6 を選択する。

Lambda に合わせてちょっとだけコードを書き換える必要がある。外部モジュール(私の場合は requests )の import をしている場合は、次のようにモジュールの読み込み対象ディレクトリを指定する必要がある。下記の 'vendor' が読み込み対象となる。ここでは zip 化する前に外部モジュールをインストールしたディレクトリを指定する。

import os
import sys
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), ‘vendor’))
import requests

終わったら zip でアップロードする。ちなみにアップロード後にインラインで編集することもできる。

あとは Lambda のドキュメントを見ながらイベントの設定をし、「テスト」を押せば Lambda 上でプログラムを実行できる。

CloudWatch で定時実行を設定する

Lambda を cron のように定時実行するためには、 Lambda のトリガーとしてCloudWatch Eventsを追加する。スケジュール式はこちらを参照。タイムゾーンは UTC なので、スケジュールを設定する際には日本時間より9時間前であることに注意すること。

次回やること

  • 実行結果をデータベースに書き込み、書き込んだ結果を取り出す
  • 異常を検知したとき Twillio から電話や SMS を送る

近い内にやりたいこと

  • 監視する先の URL を Web から登録できるようにする
  • レスポンスのヘッダやボディに期待する値を予め設定しておき、それが含まれないときに異常を通知する

--

--

No responses yet