EC2インスタンス(開発環境)を夜間停止し、さらに祝日にも対応させる
EC2インスタンスを利用しない夜間と祝日は停止させて、平日の朝に起動する
というのをやりたくていろいろググってました。
どっかでcron的なものを回さなければならないんだけど、
どうやらみなさんLambdaを利用しているらしい。
EC2の起動・終了
これだけやれば、夜間停止と朝の起動はできそうだ。
後は祝日対応なんだけど、このスクリプトに付け足していろいろ頑張ってみようと思う。
祝日判定
これ利用すれば良さそう。
DebugMessageをSlackに流したい
これを利用すると良い
最終的なソース
function slack_post(message) { var Slack = require('slack-node'); webhookUri = "__WebHookURL__"; slack = new Slack(); slack.setWebhook(webhookUri); slack.webhook({ channel: "#general", username: "LambdaNotification", text: message, }, function(err, response) { console.log(response); }); }; function holiday_check() { var JapaneseHolidays = require('japanese-holidays'); var today = new Date(); var holiday = JapaneseHolidays.isHoliday(today); if(holiday) { return true; } else { return false; } }; function ec2_start() { var AWS = require('aws-sdk'); AWS.config.update({region: 'ap-northeast-1'}); var ec2 = new AWS.EC2(); var params = { InstanceIds: [ 'INSTANCE_ID', 'INSTANCE_ID' ] }; ec2.startInstances(params, function(err, data) { if (!!err) { console.log(err, err.stack); slack_post(err); } else { console.log(JSON.stringify(data)); slack_post(JSON.stringify(data)); } }); }; exports.handler = function(event, context) { var holiday = holiday_check(); var message = ""; if (holiday) { message = "今日は祝日のため、サーバーの起動は行いません。" console.log(message); slack_post(message) return ; } else { message = "今日は平日です。サーバーの起動を行います。" console.log(message); slack_post(message) ec2_start(); } }
停止する場合は、ec2.startInstances
をec2.stopInstances
に変更するだけで停止処理にできます。
functionの名前も変えて利用してくださいね。
おまけ
沖縄は6/23に慰霊の日というものがあって、その日は祝日になったりします。
(企業さんによっては仕事なんだけど)
japanese-holiday-jsでは、日本の祝日は網羅してあるんだけど、
地方で定められた祝日は対応できないので、どうにかしてがんばってみる。
ソフトウェア/javascript/japanese-holidays - 武内@筑波大
japanese-holiday-jsの開発者さんのページに山の日を追加したときの対応が書かれてて
これなら楽にメンテできそうだったので、uchina-holidays-js
を作成して公開しました。
作成後に気づいたけど、
慰霊の日は普通に仕事だった...(ToT)
レビューをアサインするhubot-reviewer-lottoを使ってみた
レビューを回したいという要望があり、指名スクリプト的なものほしいよねってことでhubot-reviewer-lotto
を入れてみました。
HUBOT_GITHUB_TOKEN HUBOT_GITHUB_ORG HUBOT_GITHUB_REVIEWER_TEAM HUBOT_GITHUB_WITH_AVATAR
上記を環境変数に登録するのだけれど、HUBOT_GITHUB_REVIEWER_TEAM
はTEAM IDを入れる。
(ドキュメントちゃんと読んでなくて、チーム名入れてたよ^^;)
環境構築
- hubotのインストール
$ npm install -g yo generator-hubot $ yo hubot $ ? Owner --> 328 ? Bot name --> test ? Description --> test bot ? Bot adapter campfire --> 何も入力せずEnter
- 動作テスト
$ bin/hubot test> test ping test> PONG #botから返ってきたらOK
- hubot-reviewer-lottoを入れる
$ npm i --save hubot-reviewer-lotto $ vim external-scripts.json -> "hubot-reviewer-lotto"を追記
- 環境変数の設定
$ vim ~/.zshrc export HUBOT_GITHUB_TOKEN=hogehogehoge export HUBOT_GITHUB_ORG=hoge export HUBOT_GITHUB_REVIEWER_TEAM=111111 export HUBOT_GITHUB_WITH_AVATAR=0 $ exec $SHELL
Githubのtokenは事前に作成しておいてくださいね。 Githubのページから Settings -> Personal access tokens で作成できます。
- チームIDがわからない場合
$ curl -u 自分のアカウント:TOKEN https://api.github.com/orgs/ORGANIZATION/teams
上記コマンドを発行後、
ORGANIZATION内のチームに関する情報がjsonで返ってきますので、
レビューを行うチームのIDを控えて、HUBOT_GITHUB_REVIEWER_TEAM
に登録してください。
- 動作テスト
$ bin/hubot hubot> hubot reviwer for REPO PULLREQUESTID 例) hubot review for helloworld 1
これで、GITHUB_REVIEWER_TEAM内の誰かにアサインしてくれます。
Slackとの連携
Slackとの連携部分は結構簡単で、
事前にhubotのインテグレーションを設定してtokenを発行し、zshrcに書くだけ
export HUBOT_GITHUB_TOKEN=xxxxxxx
んで、
$ npm install hubot-slack $ bin/hubot --adapter slack
とやるだけでOKです。
問題点
SlackとGithubのアカウント名が違う場合、ちょっと厄介です。
どこかでマッピング作業をやる必要があります。
とこんな感じでしょうか。
おまけ
slackでコマンドを発行した場合、
自分宛にメンションがつくのでここは不要かなと思い、
forkして自分仕様にカスタマイズしました(^o^)
GitHub - 328--/hubot-reviewer-lotto: A reviewer lottery script for Hubot
Amazon LinuxでDockerコンテナの自動起動設定
どうやるんだろう?とググってたら公式に書いてあった。
- Linux インスタンスでの起動時のコマンドの実行
どうやら/var/lib/cloud/scripts/per-boot/
にスクリプトを配置すると良いらしい。
手順は、
下記をstart_container.sh
という名前で保存し、実行権限を与える。
#!/bin/sh export DOCKER_HOST=tcp://127.0.0.1:7000 docker start CONTAINER_NAME
うまくいかないときは/var/log/cloud-init-output.log
にログが残ってるので見てみると良いかも。
参考
GoLang勉強会に参加してきた
土曜日のこと。
なんとなくGoLang勉強会に参加してきた。2回目の実施らしい。
今回は、もくもく勉強会ということで
Githubのissueにやること書いてそれをやるという感じでした。
最初、hugoのソースでも読もうかと思ったけど、
最初からソース読みに行くのは敷居が高いかなということで
A Tour of Goをやってました。
少し読んだ後に、今まで作ったスクリプトをGoで作ってみようかなという気になったので
ここを見ながら
GoでZabbixのアラート通知をSlackに流すスクリプト作成してみました。(写経ですが...)
package main import ( "fmt" "os" "encoding/json" "io/ioutil" "net/http" "net/url" ) var ( IncomingWebhookUrl string = ""#Webhook URL ) type Slack struct { Text string `json:"text"` Username string `json:"username"` Icon_emoji string `json:"icon_emoji"` Icon_url string `json:"icon_url"` Channel string `json:"channel"` } func main() { params, _ := json.Marshal(Slack{ string(os.Args[1]), "bot君", ":ghost:", "", "#general"}) resp, _ := http.PostForm( IncomingWebhookUrl, url.Values{"payload": {string(params)}}, ) body, _ := ioutil.ReadAll(resp.Body) defer resp.Body.Close() println(string(body)) }
こんな感じでしょうか。
Zabbixの設定は割愛します。
次回も参加できたら
何か書いてみようかな。
おしま。
HubotのSlackインテグレーションをDockerでやる
n番煎じになっちゃいますが、
Slackと連携するHubotをDocker上で動かします。
いろんな人のDockerfileを見てると
- centos6をベースに作成
- nodeをベースにして作成
しているようです。
nodeをベースに作成してもいいんですが、
それだとvimとか入ってないので、開発しづらいかなあ。
centos6も7もそんな変わらん気がするけど、
centos7をベースにDockerfileを書いてみます。
Dockerfile
FROM centos:7 RUN yum update -y RUN yum install -y vim RUN yum install -y epel-release RUN yum install -y nodejs npm RUN npm install -g yo generator-hubot coffee-script hubot-slack RUN useradd -d /home/hubot -m -s /bin/bash -U hubot USER hubot WORKDIR /home/hubot RUN yo hubot --owner "328" --name "bot name" --description "Hubot Slack" --adapter slack CMD cd /home/hubot; bin/hubot --adapter slack
docker-compose.yml
docker-compose書いておくと、環境変数増えた時に楽になるので、一応書いてます。
hubot-slack: build: ./ volumes: - /etc/localtime:/etc/localtime:ro environment: - HUBOT_SLACK_TOKEN=hogehoge - HUBOT_SLACK_TEAM=teams.slack.com - HUBOT_SLACK_BOTNAME=botname
コンテナの時刻をホスト側と合わせるために、/etc/localtime
をread onlyでmountしてます。
ソースはGithubに置いてます。
動作チェック
$docker-compose build $docker-compose up -d
slackのhubotにping
を送るとpong
と返ってくるはずです。
参考
Arukas触ってみた
Arukas
さくらクラウドのDockerホスティングサービス こんな資料もあった
Beta期間中は無料で利用できるようなので遊んでみる。 Githubアカウントでログインできるので、そちらを利用しました。
Docker Hubにあるイメージ(今回はnginx)を画面からぽちぽちーと選択してRUN後、 ENDPOINTを開いたらnginxが上がってる。
そいや、データの永続性とかコンテナ同士のリンクってどうなっているんだろうか。 と、FAQを見たら対応してない模様。今後に期待ですね。
Arukas CLI
ArukasはCLI版もあるっぽい
API Key Createからキー拾って.envに書いたらすぐ使える。
docker ps
とかと同じ感じでarukas ps
って使えるので便利です。
イメージを起動するときは、下記のような感じ
$ arukas run --instances 1 --mem 512 -p 80:tcp httpd
今更始めるDockerの勉強
Docker
KVMやらESXiばっか触ってたせいか、
Dockerは食わず嫌いみたいな感じで触ってなかったんだけど、
そうも言ってられない時代になったし、DockerのInvitation Codeも届いたので
そろそろ本腰入れて勉強を始めようかなと思う。
一昔前だと、boot2dockerやらdocker-machineやら入れなくて
「いろいろめんどくせえなあー」と思ってたけど
資料見返したらそんなこともなかったのね。
Fork爆弾投下
まずやってみたくなるのが、Fork爆弾。
$ docker pull centos:latest $ docker run -t -i centos:latest /bin/bash # :(){ :|:& };:
やってみたら、実行したコンテナはフリーズしたけど、ホストには影響が無かった。
すばらしい。仮想環境で動作させてるから当たり前っちゃ当たり前なんだけど。
Dockerfileを書く
大抵のものはDocker Hubにあるんで、そっからpullしてきて利用したらよろしい。
んだけど、勉強だと思って簡単なものを書いてみる。
vimを入れる
Dockerfileはこんな感じ
FROM centos:7 RUN yum update -y RUN yum install -y vim
下記でビルドを行う
docker build -t yuya/vim ./
イメージを起動
docker run -t -i yuya/vim /bin/bash
ここでvimコマンドが使えるようになっているはず。
こんな感じで書けばいいのね。
WordpressをDockerで動かす
こんなんでいけます。
$ docker pull wordpress $ docker pull mysql $ docker run --name mysql -e MYSQL_ROOT_PASSWORD=bakabakaahoaho -d mysql $ docker run --name wordpress --link mysql:mysql -p 80:80 -d wordpress
mysqlとwordpressをpullしておいて、最初にmysqlのコンテナを起動します。
WordpressはDBに接続できて初めて使えるので、最初にDBを起動させないとダメですよん。
オプションのおさらい
-e 環境変数を設定 --link コンテナ同士の連携 -p ポートマッピング -d バックグラウンドで動作させる
書いた記事が消えないかとかその辺りは少し心配ですが、
docker imageを消さなければデータは残りますんで安心してください。
とは言っても、アプリケーションが動作するコンテナ内にはデータを置かないスタンスなので、
データはどこか別の場所に配置したいですね。
wordpressなら/var/www/html
mysqlなら/var/lib/mysql
かな?
この辺りのディレクトリをどっかからマウントしておいて利用できればOKなはず。
と調べてたらDocker Volumeなるものがあった。
Docker Volume
基本的にはアプリケーションが動作するコンテナ内にデータを置かないのがDockerらしい。
なので、データを配置するためのVolumeを作成してそれをマウントするか、ホストのディレクトリをマウントして利用するかのどちらかになる。
今回は、Volume作ってそれをマウントしようと思う。
Docker beta for Macだと、xhyve上で動作するので、マウントするディレクトリの実体が探せなかったので・・・^^;
/var/lib/mysqlの配置先を変更
まずはvolumeを作成
$ docker volume create --name mysql_volume
-v オプションつけてコンテナ起動
$ docker run -d --name mysql -v mysql_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql 動作チェックのためwordpressも $ docker run --name wp-test --link mysql:mysql -p 80:80 -d wordpress
一応、Wordpressが動作していることを確認する。
mysql_volumeにDB入ってるの?
mysql_volume
を作ったけど、ここに実際にDBの実体があるかどうか確認したい。
なので、mysql_volume
を他のコンテナにマウントして実体を確認する。
centos7のコンテナを起動
$ docker run --name datavolume3 -i -v mysql_volume:/hogehoge -t centos:7 /bin/bash # cd /hogehoge
お、いろいろ入ってる。
じゃあ、これがちゃんと共有されてるのか確認しましょう!
# rm /hogehoge/*
消えた。
そしてwordpressも表示されなくなった。
ちゃんと共有できてるじゃん。
といろいろ試してたんだけど、両方のコンテナにマウントできているかはdocker inspect
で確認できる。
sourceが一緒ですね。
$ docker inspect mysql | jq ".[0].Mounts" [ { "Name": "mysql_data", "Source": "/var/lib/docker/volumes/mysql_volume/_data", "Destination": "/var/lib/mysql", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "rprivate" } ] ---- $ docker inspect datavolume3 | jq ".[0].Mounts" [ { "Name": "mysql_data", "Source": "/var/lib/docker/volumes/mysql_volume/_data", "Destination": "/hogehoge", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "rprivate" } ]
と、wordpressも同じようにvolumeをマウントして使えばいけるはず。
docker-compose
mysqlのROOTのパスワードは環境変数で持っている。
今は環境変数が1つだからいいけど、今後増えたらコマンドラインから実行する時が面倒になる。
そこで利用するのがdocker-composeだ。
docker-composeを使えば、複数のコンテナから構成されるサービスを簡単に管理できる。
例えば、下記のdocker-compose.yml
を準備する。
mysql: image: mysql ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: password wordpress: image: wordpress links: - mysql:mysql ports: - "80:80" environment: WORDPRESS_DB_PASSWORD: password
そして
$ docker-compose up -d # コンテナの起動
コマンド1つでらくらくちん。便利だな〜。
停止・削除もまとめてできる。
$ docker-compose stop # コンテナの停止 $ docker-compose rm # コンテナの削除
1回目はこの辺で終わり。
もう少しDockerで遊んでみるかな。