用CoreOS和fleet部署hubot的经历
总结
-
- CoreOS上にfleetのunitとしてhubotを立ち上げてみた
- 複数ホスト間でのLINKとかなければfleetは単純なツールなので使いやすかったという話
前提- 这个词用来指代一种前提条件或者先决条件,它是指在探讨或实施某事物之前需要满足的一种基础或者限制。
-
- Vagrantとvagrant-digitaloceanがインストール済み
- 手元にDocker開発環境が整備済み
做过的事情
1. 启动CoreOS
本次我们将通过Vagrant,在DigitalOcean上创建一个CoreOS的droplet。
Vagrantfile的内容如下所示。
请根据需要进行相应的路径和文件名修改后使用。
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
请使用curl -w “\n” https://discovery.etcd.io/new来获取etcd主机发现API。然而,由于本次是单一主机,所以没有特定的用途。但在运营CoreOS集群时是非常重要的。
创建hubot的Docker镜像
这次我们使用单个主机进行运营,所以我们选择将Hubot和Redis作为独立的容器运营,并采用链接运营的形式。Hubot的开发本身是在Docker外的本地环境进行的,在docker构建时将其文件添加进去。开发时的目录结构如下所示。
.
├── 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,就可以知道我们是通过执行简单的Shell脚本来进行的。
#! /bin/sh
export REDIS_URL="redis://$REDIS_PORT_6379_TCP_ADDR:$REDIS_PORT_6379_TCP_PORT"
cd /root/hubot/
bin/hubot -a slack
在这里,我们假设已经使用名称为redis的link将Redis的URL构建起来。
将此Dockerfile构建并推送到Docker Hub的私有注册表中,即可完成Docker Hubot镜像的准备工作。
创建用于hubot和Redis的服务文件
Fleet会使用类似于systemd配置文件的配置文件,在集群内启动指定的服务单元。
這是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的容器。
另外,在启动之前,我们会先停止正在运行的容器,然后拉取最新的容器。
[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,这一点与之前不同。
我们试着部署这两个服务文件一次它们准备好了。
尝试使用 fleetctl 进行部署。
首先,我们要先登录到CoreOS,并在那里配置和运行service文件。但是,其实即使不登录,我们也可以使用fleetctl命令,所以让我们试着查看一下fleetctl的帮助信息吧。
在部署之前,如果你能把之前提到的两个service文件通过scp命令传输到CoreOS上,那就可以立即开始部署了。
$ fleetctl load redis.service
$ fleetctl start redis.service
$ fleetctl load hubot.service
$ fleetctl start hubot.service
只要执行这个它,hubot应该立即开始运行。
如果遇到任何问题,可以尝试使用fleetctl journal <service名称>.service命令来查看标准输出并进行确认。
将来部署时,构建并推送 Dockerfile。
$ fleetctl stop hubot.service
$ fleetctl start hubot.service
只要做完就可以了。
最后
这次在CoreOS上运行hubot的感想是,由于docker无法进行跨服务器的链接,所以只要解决这个问题(比如在AWS上使用私有DNS或使用Consul),就会是非常有潜力的工具。可能在kubernetes上也可以实现,但如果不考虑名称解析相关问题的话,fleet也是一个非常简单的工具,请务必试用一下。
未来,我也会公开一些相关的运维经验。