概要
- CoreOS上にfleetのunitとしてhubotを立ち上げてみた
- 複数ホスト間でのLINKとかなければfleetは単純なツールなので使いやすかったという話
前提
- Vagrantとvagrant-digitaloceanがインストール済み
- 手元にDocker開発環境が整備済み
やったこと
1. CoreOSを立ち上げる
今回はvagrant経由でdigitalocean上にCoreOSのdropletsを立ち上げます。
Vagrantfileは下記のようになってます。
適宜、pathやファイル名など書き換えて使って下さい。
Vagrant.configure('2') do |config|
config.ssh.username = 'core'
config.vm.define "core-hubot" do |config|
config.vm.provider :digital_ocean do |provider, override|
override.ssh.private_key_path = '/path/to/your/ssh_key'
override.vm.box = 'digital_ocean'
override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
provider.token = "YOUR digitalocean API TOKEN"
provider.image = 'coreos-stable'
provider.region = 'sgp1'
provider.size = '512MB'
provider.ssh_key_name = "YOUR SSH KEY NAME"
provider.setup = false
provider.private_networking = true
provider.user_data = File.read('user-data.yml')
end
end
end
また、今回はCoreOSを立ち上げるに当たって、下記のuser-data.ymlをCoreOSにセットさせてます。
# cloud-config
coreos:
etcd:
# curl -w "\n" https://discovery.etcd.io/new
discovery: https://discovery.etcd.io/YOUR_DISCOVERY_PATH
addr: $private_ipv4:4001
peer-addr: $private_ipv4:7001
fleet:
public-ip: $private_ipv4
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
etcdのホスト検出APIはcurl -w "\n" https://discovery.etcd.io/new
で各位取得して下さい。
ただし、今回はシングルホストなので特に用途はありません。CoreOSをクラスタ化して運用する際に重要なものになります。
2. hubotのDockerイメージを作成する
今回はシングルホストで運用するので、HubotとRedisは別々のコンテナとして運用し、LINKして運用する形式を採用しました。
hubotの開発自体はDocker外のローカル環境で行い、そのファイルをdocker build時にADDしています。
開発時のディレクトリ構成はこんな感じになってます。
.
├── Dockerfile # hubot用Dockerfile
├── Vagrantfile
├── redis.service # redis用serviceファイル
├── hubot # hubotの関連ファイル群
│ ├── Procfile
│ ├── README.md
│ ├── bin
│ ├── external-scripts.json
│ ├── hubot-scripts.json
│ ├── node_modules
│ ├── package.json
│ ├── scripts
│ └── start.sh
├── hubot-bot.service # hubot用serviceファイル
└── user-data.yml
hubot自体の開発に関する説明は割愛しますが、この辺を見るとわかると思います。
https://github.com/github/hubot/blob/master/docs/README.md
Dockerfileはnode.jsのコンテナをベースにするとhubotがサクッとインストールできるので楽だと思います。ちなみに今回はSlack投稿向けのhubotになってるので、そのへんの設定が追加されてます。
FROM node:latest
MAINTAINER my@email.address
RUN npm install -g hubot coffee-script hubot-slack
RUN mkdir -p /root/hubot
ADD hubot/package.json /root/hubot/package.json
ADD hubot/bin /root/hubot/bin
RUN cd /root/hubot && npm install
ADD hubot/hubot-scripts.json /root/hubot/hubot-scripts.json
ADD hubot/external-scripts.json /root/hubot/external-scripts.json
ADD hubot/scripts /root/hubot/scripts
ADD hubot/start.sh /root/hubot/start.sh
RUN chmod a+x /root/hubot/start.sh
ENV HUBOT_SLACK_TOKEN YOUR_SLACK_TOKEN
CMD ["/root/hubot/start.sh"]
hubotの起動については、最後のCMDを見てもらえればわかると思いますが、簡単なシェルスクリプト実行で行ってます。
# ! /bin/sh
export REDIS_URL="redis://$REDIS_PORT_6379_TCP_ADDR:$REDIS_PORT_6379_TCP_PORT"
cd /root/hubot/
bin/hubot -a slack
ここでRedisのURLをredisという名前でlinkした前提で構築しています。
こちらのDockerfileをbuildし、docker hubのprivate registryにPUSHすればDockerのhubotイメージの準備完了です。
3. hubot、およびRedis用のserviceファイルを作る
fleetはsystemdに近い設定ファイルを用いてクラスタ内に指定しただけのサービスのunitを立ち上げます。
こちらはredisの立ち上げになります。
[Unit]
Description=Redis
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill hubot-redis
ExecStartPre=-/usr/bin/docker rm hubot-redis
ExecStartPre=/usr/bin/docker pull redis:latest
ExecStart=/usr/bin/docker run --name hubot-redis -v /var/lib/redis:/data redis:latest redis-server --save 600 1
ExecStop=/usr/bin/docker stop redis
見てもらえればわかりますが、ExecStart
にてdocker hubに公開されてるredisのイメージをベースにhubot-redis
と言う名前で走らせてます。
また、Start前に今動いているコンテナを殺して、最新のコンテナをpullするようになっています。
[Unit]
Description=Hubot
After=redis.service
Requires=redis.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill hubot
ExecStartPre=-/usr/bin/docker rm hubot
ExecStartPre=/usr/bin/docker pull ymatsuwitter/hubot
ExecStart=/usr/bin/docker run --name hubot --link hubot-redis:redis ymatsuwitter/hubot
ExecStop=/usr/bin/docker stop hubot
User=core
hubotはredisに依存しているので、Unit節にて依存している旨を宣言しています。
それ以外は、--link hubot-redis:redis
にてRedisをlinkしているところが先ほどと違います。
こちらの2つのサービスファイルができたらデプロイしてみましょう。
4. fleetctlでデプロイしてみる
とりあえず今回はCoreOSにログインして、そこにserviceファイルを配置、動作させるという手順を踏んでますが、別にログインせずともfleetctlは利用できるのでfleetctl help
を確認してみましょう。
では早速デプロイですが、先ほどのserviceファイル2つをCoreOS上にscpなりで持って来たら、
$ fleetctl load redis.service
$ fleetctl start redis.service
$ fleetctl load hubot.service
$ fleetctl start hubot.service
を実行すればすぐにhubotが動き始めるはずです。
もし何か問題がでている場合は、fleetctl journal <service名>.service
で標準出力を確認できるので利用してみてください。
今後デプロイする際は、Dockerfileをビルド、Pushした後、
$ fleetctl stop hubot.service
$ fleetctl start hubot.service
すれば完了します。
最後に
今回CoreOS上でhubotを動作させてみての感想ですが、サーバ跨いでのlinkがdockerには出来ないため、ここの解決さえ出来れば(例えばAWSならPrivate DNSの利用なりConsulを使うなり)、非常に夢のあるツールかなと思いました。kubernetesでもいいのかもしれませんが、名前解決関連を気にしない場合は非常にシンプルなツールなのでfleetも是非使ってみてください。
今後、その辺の運用ノウハウも公開していきます。