Amazon Web Servicesを使ってみたいSIer系エンジニアに捧ぐ口実「月末、期末だけに使うサーバに毎日お金払うのはもったいないです！だから！」

# はじめに。

ソフトウェアエンジニアの皆様

お疲れ様です。

まずはじめに、本投稿は個人の見解であり、必ずしも私めの雇用主、関係者の立場、戦略、意見を代表するものではありません。あしからず。

さて、ことシステムインテグレーション業界に属する皆様方にあたっては、[COBOLの絶滅](http://blog.livedoor.jp/itsoku/archives/46591708.html)や[マイナンバー制度特需](http://biz-journal.jp/2013/08/post_2660.html)でお忙しいと存じます。

新しい需要に応えるため、日々、新しい技術習得に邁進されていることとぞんじ、、、、あれ？新しいことやらせてもらってない？COBOLも以前残り続けてて、新しいって言っても結局Javaでしょ？ですって？なんとなんと。…なんとなんと。

## 新技術、使いたいですよね。
クラウド使ってみたいですよね。
最新の言語で処理を組みたいですよね。

では、こういうのはいかがです？今のシステムにスグに役立ちそうな新しめの技術を取り入れることで、なし崩しに業務に新風を吹き込んでみるのは！

というわけで、皆様に本投稿をお送りします。
題して、
「Amazon Web Servicesを使ってみたいSIer系エンジニアに捧ぐ口実「月末、期末だけに使うサーバに毎日お金払うのはもったいないです！」」

## これまでの不幸。
こんなこと、ありますよね。
月末や期末におもーーーーーいバッチ処理が必要で、そのためにサーバを調達したり、SQLを必死にチューニングする。
しばらくはそれで、定刻以内に処理が終わっていたが、データの増量やデータの偏りによって時間以内に終わらなくなって大惨事、各所に調整を入れなければならない。

不幸。

新しい技術を使って、不幸に対応してやりましょう！

## 新しい技術がもたらす、これからの希望（エサ）
月末や期末、だけ、クラウドサーバを調達。高スペックなクラウドサーバにデータをぶっこんで高速にバッチ処理を行う。処理が終わったら、データを引っこ抜いて、サーバは返却。月末、期末以外はお金はかかりません。
処理に時間がかかるようになってきたら、性能の良いサーバに置き換えてやればいいんです！
AWSなら、CPU36コア、メモリ60Gのマシンが一時間300円未満で調達できます！
もう嫌ですよね！夜中に呼び出されるのは！
。。。って、お客様や上司に訴えてみるのはいかがでしょう？
この口上で、皆様が新しい技術に飛び込めたら幸せです。

# 閑話休題
本投稿では、Node.jsを使って、AWSからサーバ（インスタンス）を調達、起動し、起動したインスタンスにssh接続を行なってコマンド実行を行う方法を示します。コマンド実行はApacheのインストールおよび実行を行いますが、皆様に於かれましては、高負荷の処理に置き換えてお読みください。

# Node.js で AWSのサーバを操作する。
技術のビッグウェーブの代表格、Node.jsとAWSサーバで希望を照らしましょう。

## Node.js、その慣れ親しんだ新しいランタイム。
[Node.js](https://nodejs.org/)をご存知ですか？JavaScriptの実行環境です。誰もが一度は書いたことがある（？）JavaScriptも今やブラウザだけの言語ではありません。
スマートフォンもJavaScriptでネイティブアプリが作れます。[NativeScript](https://www.nativescript.org/)や、[React Native](https://facebook.github.io/react-native/)で。
いろんなクラウドでPaaSを構築できますし、[AWS Lambda](http://docs.aws.amazon.com/lambda/latest/dg/welcome.html)とともにサーバレスアーキテクチャにも使える。
更には[Electron](http://electron.atom.io/)を使ってデスクトップアプリも作れてしまいます。
一度覚えれば何度も美味しい言語です。
その中でNode.jsはJavaScriptの火付け役になったJavaScript実行環境で、Webアプリを非常シンプルに構築することができます。進化の早いプロダクトですが、最近、長期サポートを行うバージョンがリリースされ、安定した使用が期待できます。今から覚えるのならJavaScriptです。

## Amazon Web Services、クラウドの旗振り役。
言わずと知れた[Amazon Web Service](http://aws.amazon.com/)。クラウドといえばこちらです。機能豊富で、新しい機能がどんどん出てきます。取付くなら、AWSです。

# Node.js で AWSのサーバを操作する手順。
さて、ここからが、Node.jsを使ってプログラミングでサーバを調達・起動するための手順です。

## AWSで、サーバ構築用アカウント、SSHログイン用の鍵と、サーバのセキュリティー設定を作成します。
[AWS コンソール](https://aws.amazon.com/jp/console/)にログインして、サーバ構築用アカウントを作成し、APIアクセスキーを取得します。

![スクリーンショット 2015-10-13 12.14.35.png](https://qiita-image-store.s3.amazonaws.com/0/25176/74d7fce5-4922-03ea-3dd0-ddcbea537b6a.png)
Identity & Access Managementから、
![スクリーンショット 2015-10-13 12.15.13.png](https://qiita-image-store.s3.amazonaws.com/0/25176/76a817a2-052c-982c-78c8-86e5bbf971e7.png)
「ユーザ」を選択し、![スクリーンショット 2015-10-13 12.16.03.png](https://qiita-image-store.s3.amazonaws.com/0/25176/5fdea87a-7ae5-c90d-da49-3b627a1151ff.png)
ユーザ名を入力、ユーザーごとにアクセスキーを生成にチェックを入れて、作成を押します。
これでAWSにAPIアクセスするための鍵を作れます。あとから使うので、取っておいてください。
![スクリーンショット 2015-10-13 12.24.58.png](https://qiita-image-store.s3.amazonaws.com/0/25176/7a58c356-a323-6f32-11a7-de51ef4ecf23.png)
そして、このアカウントにポリシーをアタッチしてください。今回だとEC2を作成する、AmazonEC2FullAccessがあればよいでしょう。
![スクリーンショット 2015-10-19 15.27.35.png](https://qiita-image-store.s3.amazonaws.com/0/25176/478c0e65-428c-99d5-e4f9-71c2afd90336.png)


次は、作ったインスタンスにSSHログインするための鍵を作成します。
![スクリーンショット 2015-10-19 15.29.32.png](https://qiita-image-store.s3.amazonaws.com/0/25176/89edb4f2-87e7-e17e-30bf-b3494a5803fb.png)
EC2で、
![スクリーンショット 2015-10-19 15.30.11.png](https://qiita-image-store.s3.amazonaws.com/0/25176/5de78173-d9fc-836d-43fa-cd5faf811b06.png)
キーペアを選択し、キーペアの作成を行います。あとから使うので、取っておいてください。

AWS コンソールでの操作の最後、サーバのファイアウォールの設定を作っておきます。
![スクリーンショット 2015-10-19 15.29.32.png](https://qiita-image-store.s3.amazonaws.com/0/25176/89edb4f2-87e7-e17e-30bf-b3494a5803fb.png)
EC2で、
![スクリーンショット 2015-10-19 15.37.04.png](https://qiita-image-store.s3.amazonaws.com/0/25176/9c340e4e-a456-53c2-a830-84fd64e28b55.png)
セキュリティーグループを選択、セキュリティーグループの作成から、![スクリーンショット 2015-10-19 15.39.56.png](https://qiita-image-store.s3.amazonaws.com/0/25176/16a8708e-a229-2d85-1163-3362c2482cc9.png)
セキュリティーグループの作成を行います。sshとhttpにアクセスできるようにしてください。
これでコンソールでの作業は終了です。

## Node.jsをインストールします。
[こちら](https://nodejs.org/dist/v4.2.1/)から必要なファイルをダウンロードし、解凍、PATH通しを行ってください。

# Node.jsでサーバ操作を書く！
Node.js にはnpmというパッケージマネージャがあり、それを利用して依存ライブラリを取得します。
空のディレクトリを作って、その中にpackage.jsonをコピペで作成してください。

```js:package.json
{
  "name": "awsinspect",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "dependencies": {
    "aws-sdk": "^2.2.9",
    "bluebird": "^2.10.2",
    "proxy-agent": "^2.0.0",
    "simple-ssh": "^0.8.6",
    "socksv5": "0.0.6",
    "ssh2": "^0.4.11"
  }
}
```

ディレクトリの中で、以下のコマンドを実行します。

```bash
npm install
```

これで依存パッケージがインストールされます。
そして、いよいよ、インスタンスを作成するアプリを最高に素敵な言語JavaScriptで作成します。

```js:index.js
var AWS = require('aws-sdk');
var Promise = require('bluebird');
var config = require("./config.json");
AWS.config.loadFromPath('./config.json');
var execSync = require('child_process').execSync;
var SSH = require("simple-ssh");
var http = require('http');

// 使えるAPI群はこちら。https://aws.amazon.com/jp/sdk-for-node-js/
var ec2 = Promise.promisifyAll(new AWS.EC2());// APIをPromiseで呼べるようにします。
// EC2のAPIもこんなにたくさん。http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2.html
var instanceId;
var dnsName;
// インスタンスを作成します。
ec2.runInstancesAsync({
    ImageId : 'ami-9c2fb89c', // AMIを選択します。
    // Amazon Linuxの選択肢はこちら。https://aws.amazon.com/jp/amazon-linux-ami/
    // 用意されてるものは時々代わります。
    InstanceType : 't1.micro',// サーバのスペックを選択
    KeyName : config.ssh.keyName,// 作成したsshキーの名前を選択します。
    MinCount : 1,
    MaxCount : 1,
    SecurityGroupIds : [ config.securityGroupId ]
// 作成したセキュリティーグループを選択します。
}).then(function(data) {
    console.log("instance created " + JSON.stringify(data))
    instanceId = data.Instances[0].InstanceId;
    // Nameタグをつけます。この名前でAWSコンソールに表示されます。
    return ec2.createTagsAsync({
	Resources : [ instanceId ],
	Tags : [ {
	    Key : 'Name',
	    Value : 'tito_api_inspect_' + new Date().getTime()
	} ]
    });
}).then(function(data) {
    // 起動するまで待ちます。
    return ec2.waitForAsync("instanceRunning", {
	InstanceIds : [ instanceId ]
    });
}).then(function(data) {
    // DNS情報を取得するためにインスタンスの情報取得APIを叩きます。
    return ec2.describeInstancesAsync({
	InstanceIds : [ instanceId ]
    });
}).then(function(data) {
    dnsName = data.Reservations[0].Instances[0].PublicDnsName
    console.log("instance started " + dnsName);
    return new Promise(function(success) {
	setTimeout(success, 60000);// SSHサーバが立ち上がるまでたっぷり待ちます。
    })
}).then(function() {
    var registHostCommand = "/usr/bin/ssh-keyscan -H " + dnsName + " >> ~/.ssh/known_hosts";
    execSync(registHostCommand);
    // SSH接続します。
    var ssh = new SSH({
	host : dnsName,
	user : "ec2-user",
	key : require("fs").readFileSync(config.ssh.keyFilePath)
    });
    ssh.on("error", function(err) {
	console.log(err);
	ssh.end();
    });
    // httpdをインストールします。
    ssh.exec("sudo yum install -y httpd", {
	pty : true,
	out : console.log.bind(console)
    // httpdを起動します。
    }).exec("sudo service httpd start", {
	pty : true,
	out : function(stdout) {
	    var url = "http://" + dnsName;
	    // できたことを確認するため、httpアクセスします。
	    http.get(url, function(res) {
		var body = '';
		res.setEncoding('utf8');
		res.on('data', function(chunk) {
		    body += chunk;
		});
		res.on('end', function(res) {
		    console.log(body);
		});
	    }).on('error', function(e) {
		console.log(e.message);
	    });
	}
    }).start();
})["catch"](function(err) {
    console.log("error ---- " + err);
    if (err.stack) {
	console.log(err.stack);
    } else {
	console.stack(err);
    }
});
```

やってることはソースコード中のコメントに入れておきましたが、コメントが無くても単純なAPI呼び出しなので、理解していただけると存じます。

コードの最後に、コンフィグファイルを作成します。

```js:config.json
{
    "accessKeyId" : "AWSコンソールで作成したアカウントのaccessKeyId",
    "secretAccessKey" : "AWSコンソールで作成したアカウントのsecretAccessKey",
    "region" : "ap-northeast-1",
    "securityGroupId" : "AWSコンソールで作成したsecurityGroupId",
    "ssh" : {
	"keyName" : "AWSコンソールで作成した鍵名",
	"keyFilePath" : "AWSコンソールで作成した鍵ファイルへのローカルパス"
    }
}
```

あとはこのコードをNode.jsで実行します。

```bash
node index.js
```

これでサーバが作成され、ApacheへのHTTPアクセスが実行され、HTMLがダンプされます。
あとは、HTTPアクセスの部分を月次、期末のおもーい処理に変更して、インスタンスタイプをt1.microからいいやつに変更して、実行コマンドをcronに設定してやれば、AWSのクラウドの恩恵に即あやかることができます。

# さぁ！Node.js+AWSで最近の技術に足を踏み入れましょう。
Node.jsやAWSの周りでは、新しいパラダイムがどんどん発生しています。
Nodeを触っていくことで、パッケージマネージャやCIのパラダイムにふれることができます。
また、AWSにふれることでイミュータブルインフラストラクチャーなどの新しい考え方に接することができます。
この2つの技術を業務に取り入れることで、あなたが仕事をパラダイムシフトするきっかけができたらすごく幸せです。