LoginSignup
19
19

More than 5 years have passed since last update.

CoreOS + fleet でhubotを立ち上げてみた話

Posted at

概要

  • 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を見てもらえればわかると思いますが、簡単なシェルスクリプト実行で行ってます。

start.sh
#! /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の立ち上げになります。

redis.service
[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するようになっています。

hubot.service
[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も是非使ってみてください。
今後、その辺の運用ノウハウも公開していきます。

19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19