文档章节

在Docker中使用Serf

马金凯
 马金凯
发布于 2014/02/24 08:39
字数 1512
阅读 2268
收藏 35

#在Docker中使用Serf

编写思路来自 Decentralizing Docker: How to Use Serf with Docker 本文已提交 dockboard 发布,在此利用开源中国的知名度扩散,感谢。

在之前的 Docker Link使用示例 中,我们对 Docker 的link特性进行了简单的演示,这次的主题是使用 Serf 实现更加低耦合的容器关系结构,最终达到的效果是服务化各个服务。

Serf 是一个去中心化的服务发现和编排的解决方案,特点是轻量级和高可用,同时具备容错的特性。

##构建Serf镜像

在这我并没有使用 Supervisord 来启动Serf服务,大家可以参照后面的示例来启动Serf。

Dockerfile_serf

FROM ubuntu:12.04
MAINTAINER Marker.King <majk@vip.qq.com>
RUN echo "deb http://mirrors.aliyun.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y wget unzip
RUN wget --no-check-certificate https://dl.bintray.com/mitchellh/serf/0.4.1_linux_amd64.zip
RUN unzip 0.4.1_linux_amd64.zip
RUN rm 0.4.1_linux_amd64.zip
RUN mv serf /usr/bin/
EXPOSE 7946 7373
CMD ["-tag", "role=serf-agent"]
ENTRYPOINT ["serf", "agent"]

构建Serf镜像

$ docker build -t serf - < Dockerfile_serf

##构建mysql镜像

这一步比较复杂,我们将编写多个shell脚本,用于启动supervisor、启动mysql、创建数据库用户、创建数据库等,先让我们看一下目录结构

mysql +
      | - create_db.sh
      | - create_mysql_admin_user.sh
      | - Dockerfile
      | - join-cluster.sh
      | - my.cnf
      | - run.sh
      | - start-serf.sh
      | - start.sh
      | - supervisord-mysqld.conf
      | - supervisord-serf.conf

create_db.sh

#!/bin/bash

read -r line
if [ -n "$line" ]; then
	echo "=> Creating database $line"
	mysql -uroot -e "CREATE DATABASE $line"
	echo "=> Done!"
else
	echo "Usage: $0 <db_name>"
	exit 1
fi

create_mysql_admin_user.sh

#!/bin/bash

if [ -f /.mysql_admin_created ]; then
	echo "MySQL 'admin' user already created!"
	exit 0
fi

/usr/bin/mysqld_safe > /dev/null 2>&1 &

PASS=$(pwgen -s 12 1)
echo "=> Creating MySQL admin user with random password"
RET=1
while [[ RET -ne 0 ]]; do
	sleep 5
	mysql -uroot -e "CREATE USER 'admin'@'%' IDENTIFIED BY '$PASS'"
	RET=$?
done

mysql -uroot -e "GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION"

mysqladmin -uroot shutdown

echo "=> Done!"
touch /.mysql_admin_created

echo "========================================================================"
echo "You can now connect to this MySQL Server using:"
echo ""
echo "    mysql -uadmin -p$PASS -h<host> -P<port>"
echo ""
echo "Please remember to change the above password as soon as possible!"
echo "MySQL user 'root' has no password but only allows local connections"
echo "========================================================================"

join-cluster.sh

#!/bin/bash
exec serf join $SERF_AGENT_PORT_7946_TCP_ADDR:$SERF_AGENT_PORT_7946_TCP_PORT

my.cnf

[mysqld]
bind-addres=0.0.0.0

run.sh

#!/bin/bash
if [ ! -f /.mysql_admin_created ]; then
	/create_mysql_admin_user.sh
fi
exec supervisord -n

start-serf.sh

#!/bin/bash
exec serf agent -tag role=db \
	-event-handler="user:create_db=/create_db.sh"

start.sh

#!/bin/bash
exec mysqld_safe

supervisord-mysqld.conf

[program:mysqld]
command=/start.sh
numprocs=1
autostart=true
autorestart=true

supervisord-serf.conf

[program:serf]
command=/start-serf.sh
numprocs=1
autostart=true
autorestart=true

[program:serf-join]
command=/join-cluster.sh
autorestart=false

Dockerfile

FROM ubuntu:12.04
MAINTAINER Marker King <majk@vip.qq.com>

RUN echo "deb http://mirrors.aliyun.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y upgrade
RUN ! DEBIAN_FRONTEND=noninteractive apt-get -qy install unzip supervisor mysql-server pwgen; ls

ADD https://dl.bintray.com/mitchellh/serf/0.4.1_linux_amd64.zip serf.zip
RUN unzip serf.zip
RUN rm serf.zip
RUN mv serf /usr/bin/

ADD /run.sh /run.sh
ADD /start.sh /start.sh
ADD /start-serf.sh /start-serf.sh
ADD /join-cluster.sh /join-cluster.sh
ADD /supervisord-mysqld.conf /etc/supervisor/conf.d/supervisord-mysqld.conf
ADD /supervisord-serf.conf /etc/supervisor/conf.d/supervisord-serf.conf
ADD /my.cnf /etc/mysql/conf.d/my.cnf
ADD /create_mysql_admin_user.sh /create_mysql_admin_user.sh
ADD /create_db.sh /create_db.sh
RUN chmod 755 /*.sh

EXPOSE 3306 7946 7373
CMD ["/run.sh"]

大家可能看到了,这里使用了ADD https://dl.bintray.com/mitchellh/serf/0.4.1_linux_amd64.zip serf.zip来添加一个远程文件到镜像中,这跟Serf服务镜像构建时使用的方法不一样,但是达到了同样的效果。在此我需要解释一下,RUN wget <url>是可以被缓存的,而ADD <url> <name>是不能够被缓存的,也就是说每次构建都会再次下载这个文件,RUN wget <url>则会使用缓存,从而加快构建速度。大家可以试一下分别构建两次镜像,可以发现Serf镜像第二次全部使用了缓存,而mysql会在Step 6再次下载文件。

进入mysql目录构建镜像:

$ docker build -t mysql .

##测试Serf连接

通过Serf镜像启动一个容器:

$ SERF_ID=$(docker run -d -p 7946 -p 7373 -name serf_agent serf)

让我们测试一下Serf是否正常工作,在我们的宿主机上(安装docker的机器)也安装Serf,来连接容器的Serf:

$ wget --no-check-certificate https://dl.bintray.com/mitchellh/serf/0.4.1_linux_amd64.zip
$ unzip 0.4.1_linux_amd64.zip
$ rm 0.4.1_linux_amd64.zip
$ sudo mv serf /usr/bin/
$ nohup serf agent &
$ serf members
packer-virtualbox    10.0.2.15:7946    alive

现在,在我们的机器上就拥有了一个可用的Serf,你可以连接Docker的Serf代理容器来看看效果:

$ serf join $(docker port $SERF_ID 7946)
Successfully joined cluster by contacting 1 nodes.
$ serf members
precise64        10.0.2.15:7946      alive    
9be517551dda     172.17.0.2:7946     alive    role=serf-agent

##测试Serf事件派发到mysql服务

让我们启动一个mysql容器,并与serf_agent连接,使用-link参数,注意格式为name:alias,这里alias必须使用serf_agent,因为在join-cluster.sh中固定调用了SERF_AGENT_PORT_7946_TCP_ADDRSERF_AGENT_PORT_7946_TCP_PORT两个环境变量,可以按照不同的名称要求做连接,命令如下:

$ MYSQL_ID=$(docker run -d -p 3306 -p 7946 -p 7373 -link serf_agent:serf_agent mysql)

在宿主机中查看Serf集群情况:

$ serf members
precise64        10.0.2.15:7946     alive    
9be517551dda     172.17.0.2:7946    alive    role=serf-agent
410d5a7f709a     172.17.0.3:7946    alive    role=db

因为在mysql容器启动时,执行了join-cluster.sh脚本连接到了serf_agent,因此在宿主机中我们可以看到之后加入进来的mysql。

此时我们可以通过docker logs $MYSQL_ID查看mysql输出的用户名和密码信息(可以通过修改create_mysql_admin_user.sh来改变用户信息或输出格式等)。

$ docker logs $MYSQL_ID
=> Creating MySQL admin user with random password
=> Done!
========================================================================
You can now connect to this MySQL Server using:

    mysql -uadmin -paWQD8mdb3N1j -h<host> -P<port>

Please remember to change the above password as soon as possible!
MySQL user 'root' has no password but only allows local connections
========================================================================

执行自定义命令,通知mysql创建数据库:

$ serf event create_db wordpress
Event 'create_db' dispatched! Coalescing enabled: true

连接数据库,并查看数据库是否创建成功:

$ mysql -uadmin -paWQD8mdb3N1j -h127.0.0.1 -P49157
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| wordpress          |
+--------------------+
5 rows in set (0.00 sec)

成功了!我们看到了数据库已经被创建。

#总结

今天的示例就写到这里,大家可以继续发散思考,我的mysql容器已经具备了接受命令的功能,那么如果我再创建一个wordpress容器,当容器启动时会发送create_db命令给serf_agent,这样mysql就达到了服务化的目的。当然能够服务化的还很多,例如:负载均衡、memcached、redis等等。如果大家有什么更好的想法,可以共享出来,我的邮箱地址是:majk@vip.qq.com

© 著作权归作者所有

共有 人打赏支持
马金凯

马金凯

粉丝 59
博文 2
码字总数 1803
作品 1
济南
程序员
加载中

评论(6)

相见欢
相见欢
关注docker很久了,博主的文章从实践中来,非常难得!回头我也在机器上跑一下
马金凯
马金凯

引用来自“关红福”的评论

可以介绍一下 Serf 是干嘛用的

Serf 是一个去中心化的服务发现和编排的解决方案,特点是轻量级和高可用,同时具备容错的特性。
xxx2xxx
xxx2xxx
可以介绍一下 Serf 是干嘛用的
此用户已关机
此用户已关机

引用来自“马金凯”的评论

引用来自“除美灭日平韩”的评论

“因为在mysql容器启动时,执行了join-cluster.sh脚本”

这个没看出来。。。。。

run.sh -> exec supervisord -n -> supervisord-serf.conf

好吧,原谅俺是小白
不明白 exec supervisord -n是干什么的
我只知道 exec 是shell命令 后面是什么不知道
马金凯
马金凯

引用来自“除美灭日平韩”的评论

“因为在mysql容器启动时,执行了join-cluster.sh脚本”

这个没看出来。。。。。

run.sh -> exec supervisord -n -> supervisord-serf.conf
此用户已关机
此用户已关机
“因为在mysql容器启动时,执行了join-cluster.sh脚本”

这个没看出来。。。。。
基于Docker快速搭建多节点Hadoop集群

一. 项目简介 GitHub: kiwanlau/hadoop-cluster-docker 博客:基于Docker快速搭建多节点Hadoop集群 直接用机器搭建Hadoop集群是一个相当痛苦的过程,尤其对初学者来说。他们还没开始跑wordc...

颓废的幻想者
2016/03/30
101
1
基于Hadoop的Docker service API--Cloudbreak

Cloudbreak 是首个基于hadoop的docker service API。Cloudbreak 建立于Apache Ambari, Docker containers, Serf 和 dnsmasq 这类云提供者的API之上。它是一个与云无关的解决方案——这是因为...

叶秀兰
2014/08/01
1K
0
解决mac使用svn: E170000: Unrecognized URL scheme for h

原文章链接:http://blog.csdn.net/mhmyqn/article/details/46317107 mac系统版本 OS X版本:10.10.3 说明 10.10.3自带了svn,但是版本是1.7,如果项目是使用1.8的svn,就必须升级到1.8,才能...

品鉴初心
2017/12/26
0
0
soucetree中使用svn

新仓库从 url克隆 如果提示 Subversion 1.5.0 or later required, but no bindings were foundSubvertpy 0.7.4 or later required, but not found Please install either Subvertpy or the ......

openlab
2015/11/23
59
0
CentOS7 源码安装svn1.9.5及httpd配置(ldap验证/ad域验证)

环境:CentOS-7-x86_64-1611 + subversion-1.9.5 一、源码安装: 1、安装ldap: 2、安装APR: 3、安装APR-util: 4、安装pcre: 5、安装apache: 开启防火墙80 端口: 将httpd加入服务: 6、安...

魔力小小鸟
2017/02/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Go语言_通神之路(2)

1、包 每个Go程序都是由包构成,从main包开始运行,就是我上一篇讲到的,都是从main函数开始执行,但是必须在main包下面! package mainimport ( "fmt" "math/rand")func ...

木九天
昨天
5
0
51.php-fpm的pool 慢日志 open_basedir 进程管理

12.21 php-fpm的pool 12.22 php-fpm慢执行日志(测试时报错) 12.23 open_basedir 12.24 php-fpm进程管理 12.21 php-fpm的pool: php-fpm里的pool也叫池子,咱们之前加入过www的配置,这个w...

王鑫linux
昨天
0
0
java内存模型概述

1、Java虚拟机运行时数据分区图 程序计数器:线程私有,是一块较小的内存空间,它是当前线程所执行的字节码文件的行号指示器 java虚拟机栈:线程私有,其生命周期与线程相同,这也就是我们平...

京一
昨天
2
0
shell学习之test语法

因为if-then语句不能测试退出状态码之外的条件,所以提供了test, 如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0;如果条件不成立,test命令就会退出并返回非零的退出状态...

woshixin
昨天
0
0
openJDK之如何下载各个版本的openJDK源码

如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK的项目 链接...

汉斯-冯-拉特
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部