/ dinp

Dinp Docker化安装记录

Dinp是小米公司开源的Paas系统,基于Docker开发。
Dinp各个组件并没有详细的安装文档,也没有提供Dockerfile来实现Docker化(dockerize),所以这次Dinp的安装历时3天,在此记录,方便后人。

基础环境配置

本次安装的主要目的是体验Dinp的各项功能,因此我会把所有组件都安装在同一台服务器上。我习惯于使用Centos,服务器使用的是Centos6.6。由于Centos内核版本比较低,不适用Docker,如果直接使用会有很大概率导致系统panic,所以第一步是升级内核版本。可以通过安装EL repo,然后从EL repo中安装最新的内核(参考Dockerpool):

rpm -Uvh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm yum --enablerepo=elrepo-kernel install kernel-lt -y

新内核安装之后需要修改grub启用,修改/etc/grub.conf,将default的值改成0,然后重启服务器。重启之后通过uname -a命令可以看到当前的内核版本应该为3.10了。

然后就可以安装docker了:

yum install -y docker-io service docker start

首先要pull几个镜像到本机 :

docker pull jenkins #uic和dashboard是java web项目,需要使用ant构建,jenkins可以让整个过程自动化 docker pull redis #server和router两个组件需要使用redis docker pull mysql #作为数据存储 docker pull memcached #dashboard需要使用 docker pull registry #builder构建的镜像需要push到一个registry docker pull ubuntu:12.04 #scribe服务器需要用到 docker pull tomcat:8 #java web项目需要用到 docker pull golang:1.4#go语言的项目需要用到

由于国内连接docker hub速度很不理想,可以使用国内的加速镜像,修改/etc/sysconfig/docker

other_args="-H tcp://服务器内网IP:2375 -H unix://var/run/docker.sock --insecure-registry 服务器内网IP:5000 --insecure-registry --registry-mirror=http://docker.mirrors.ustc.edu.cn"

这里就–registry-mirror是在配置镜像,其他配置之后有用,等用到了再详细解释。

修改之后重启docker:

service docker restart

最后选择一个数据目录,部分容器需要永久性存储数据,本文使用/root/dinp/data。

Jenkins容器配置

mkdir -p /root/dinp/data/jenkins \ && docker run -d --name jenkins -p 8089:8080 -v /root/dinp/data/jenkins:/var/jenkins_home -v /usr/bin/docker/:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -u root jenkins

-p参数是端口映射,将容器的8080端口映射到宿主机的8089端口;第一个-v是挂载宿主机目录到容器中,可以持久化jenkins的任务、插件等;第二个和第三个-v目的是将docker命令挂载到容器里,这样在容器里也可以执行命令了,而且创建的镜像、容器和宿主机同步;-u root是为了让jenkins在容器中以root帐户启动,否则可能会因为没有权限写入挂载目录导致启动失败。

现在通过外网IP:8089来访问jenkins了

第一步是给jenkins安装git插件,因为之后构建的时候需要从git仓库获取代码。在“系统管理”->“管理插件”->“可选插件”,搜索git,这里会有很多结果,只要安装“Git Plugin”即可,注意不要选错。勾选之后点击下方“直接安装”,jenkins会找出几个依赖的插件,一并安装了。jenkins在安装插件之前会检查网络是否联通,还自作聪明的选择了google作为判断标准,果真是不知道生活在GFW内的痛苦,所以这个过程会比较漫长(主要时间花在检查网络连通性了……),建议勾选下面的“安装完成后重启jenkins”。

第二步是配置ant,在“系统管理”->“系统设置”中找到Ant这一段,点击“Ant安装”按钮,Name随便填一个,勾选“自动安装”,点击“新增安装”->“install from apache”,选择最新版本就行,保存即可。

Registry容器

启动一个registry容器的目的有三个,1.存放Dinp container的基础镜像,如php环境基础镜像。2.存放包含了代码的镜像,比如在php镜像基础上叠加了某个版本代码的镜像。3.假如jenkins容器在另一台服务器上,可以将构建生成的镜像push到私有registry中,方便共享。

这个很简单,就不详细解释了:

mkdir -p /root/dinp/data/registry \ && docker run --name registry -d -v /root/dinp/data/registry:/tmp/registry -p 5000:5000 registry

Memcached容器

docker run --name memcached -d memcached

这里memcached容器并没有对外映射端口,因为只有dashboard才需要mc,而mc和dash装在同一台服务器上的话,可以通过–link来联通两个容器。

Redis容器

docker run --name redis -d -p 6379:6379 redis

因为redis需要被server和router两个组件连接,所以映射了端口(本文这两个组件安装在同一台服务器上,是可以不映射端口的,同样可以通过–link来联通)

Mysql容器

mkdir -p /root/dinp/data/mysql \ && docker run --name mysql -v /root/dinp/data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=toor -d mysql

-v挂载mysql数据目录,这样可以持久化数据库的数据,不会因为容器销毁而数据丢失;-e设置环境变量,MYSQL_ROOT_PASSWORD=root代表设定mysql初始密码为toor

UIC容器

uic是一个SSO系统,使用java编写,作为builder和dashboard用户统一登录入口。UIC容器没有现成的镜像,需要我们自己来构建,这里就用到了jenkins容器。

在jenkins页面上创建一个新任务,item名称填写UIC,选择“构建一个自由风格的软件项目”,点击OK,创建成功后会进入项目配置页面。

“源码管理”那一段选择Git,Repository Url填

https://git.oschina.net/leo108/docker_uic.git

我这个git仓库只包含了Dockerfile,UIC的源码使用submodule来引入,所以需要在“Additional Behaviours”处点击“Add”->“Advanced Sub-modules behaviors”,然后勾选“Recursively update submodules”。

再往下拉到“构建”,点击“增加构建步骤”->“Invoke Ant”,在“Ant version”那里选择我们之前在jenkins中配置的那个(不要选Default)。再点击“高级”,“Build File”填入

uic/build.xml

再增加一个构建步骤,这回选择“Execute shell”,内容如下:

ln -s -f /lib/x86_64-linux-gnu/libdevmapper.so.1.02.1 /lib/x86_64-linux-gnu/libdevmapper.so.1.02 docker build -t uic .

第一行是为了让docker命令在jenkins容器中能正常使用,第二行则是根据Dockerfile打包成镜像,之前提到过,jenkins容器通过-v挂载共享了宿主机的docker,因此在jenkins容器中创建的镜像也会出现在宿主机中。

这样就配置好了,点击最下面的“保存”,然后点击界面左侧的“立即构建”。第一次构建的时候会去clone git仓库,以及下载ant,所以会比较慢。等到构建完成之后,在宿主机执行docker images,应该就能看到uic这个镜像了。

在启动UIC容器之前,需要先在Mysql数据库中创建UIC的表。

在宿主机执行

docker exec -ti mysql bash

就进入Mysql容器,在容器中执行

mysql -uroot -ptoor

进入Mysql管理,导入这个sql即可。

接下来就可以启动UIC容器了:

docker run --name uic --link memcached:memcached --link mysql:mysql -e DB_NAME=uic -e DB_USER=root -e DB_PWD=toor -e UIC_TOKEN=123456 -d -p 8080:8080 uic

通过–link将memcached和mysql两个容器连通uic容器,具体如何使用请参考这里,几个-e参数用于指定数据名、数据库用户名和密码,UIC_TOKEN是其他系统和UIC系统通信的令牌,现在可以随便选择一个,之后其他容器记住配置成统一的就可以了。

这样就可以通过外网IP:8080访问UIC了,使用root帐号,密码abc即可登录UIC。

Builder容器

Builder容器是一个构建镜像的容器,用户在Builder界面上选择基础镜像,提供代码包下载地址或者直接上传代码包,Builder就会构建出一个拥有代码的镜像,并且将生成的镜像push到registry中。

cd /root/dinp \ && git clone https://git.oschina.net/leo108/docker_dinp_builder.git builder \ && cd builder \ && docker build -t dinp_builder .

不出意外的话docker就会构建出一个dinp_builder的镜像。

和UIC一样,在启动容器之前需要先创建数据库。进入数据库的方法不在缀叙,先执行create database builder;然后导入这个sql

然后就可以启动容器了:

docker run -d --name dinp_builder --link mysql:mysql -e DB_NAME=builder -e DB_USER=root -e DB_PWD=toor -e UIC_URL=http://外网IP:8080 -e UIC_TOKEN=123456 -e REGISTRY_URL=内网IP:5000 -p 7788:7788 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker dinp_builder

-e参数设置数据库信息,UIC_URL配置我们刚刚启动的UIC的外网访问地址,UIC_TOKEN一定要和启动UIC时设置的一致,REGISTRY_URL是Registry容器的访问地址,同样Builder容器也共享了宿主机的Docker,因为要用到Docker构建镜像。

然后我们就可以通过外网IP:7788来访问builder平台,因为之前登录过UIC,所以我们就自动以root身份登录进builder平台。

Scribe容器

Scribe是facebook开源的一个日志收集软件,Dinp使用scribe来收集各个Paas Container产生的日志文件,例如access_log,这样不会因为容器的销毁导致日志丢失。

cd /root/dinp \ && git clone https://git.oschina.net/leo108/docker_scribe.git scribe \ && cd scribe \ && docker build -t scribe .

build成功之后就可以启动了:

mkdir -p /root/dinp/data/scribe \ && docker run -d --name scribe -p 1463:1463 -v /root/dinp/data/scribe:/tmp/scribetest scribe

映射1463端口用于container上报日志内容。

Server容器

server负责收集agent信息,控制agent启动、销毁container。

cd /root/dinp \ && git clone https://git.oschina.net/leo108/docker_dinp_server.git server \ && cd server \ && docker build -t dinp_server .

Server需要连接数据库,查询某个App需要部署的container数量,但这个数据库结构是在dashboard项目里。

按之前连接Mysql的方法进入Mysql终端,创建一个数据库:

create database dash;

然后导入这个sql

然后就可以启动容器:

docker run -d --name dinp_server --link mysql:mysql --link redis:redis --link scribe:scribe -e DB_USER=root -e DB_PWD=toor -e DB_NAME=dash -e DOMAIN=dinp.leo108.com -p 1980:1980 -p 1970:1970 dinp_server

-e DOMAIN是配置Paas平台域名,所有创建的app都会默认分配app_name.DOMAIN的域名。例如我创建一个haha的App,系统分配的域名就是haha.dinp.leo108.com。需要在域名DNS那边配置泛域名*.dinp.leo108.com指向服务器的外网IP。

Dashboard容器

这也是一个Java web项目,管理员可以在Dashboard页面上创建App、扩缩容、部署等等操作。因为需要ant构建,所以还得放到jenkins里。操作步骤和构建UIC容器的镜像完全一致,Git仓库的地址修改成

https://git.oschina.net/leo108/docker_dinp_dashboard.git

记得设置submodule behavior。

增加ant构建步骤,Build File填“dash/build.xml”,execute shell填:

ln -s -f /lib/x86_64-linux-gnu/libdevmapper.so.1.02.1 /lib/x86_64-linux-gnu/libdevmapper.so.1.02 docker build -t dinp_dashboard .

保存之后即可构建。

构建完成之后可在宿主机看到dinp_dashboard的镜像,启动之:

docker run -d --name dinp_dash --link mysql:mysql --link memcached:memcached -e DB_NAME=dash -e DB_USER=root -e DB_PWD=toor -e UIC_URL=http://外网IP:8080 -e UIC_TOKEN=123456 -e BUILDER_URL=http://外网IP:7788 -e SERVER_URL=http://内网IP:1980 -e DOMAIN=dinp.leo108.com -p 8082:8080 dinp_dashboard

UIC_TOKEN、DOMAIN这两个配置需要和之前启动其他容器时设置的参数值一致。因为本机的8080端口被UIC占用,所以这里把本机的8082端口映射到容器的8080端口。

直接访问外网IP:8082,就会自动以root身份登录dashboard系统。

Agent容器

agent会定时上报自己服务器的当前状态,例如有多少个container,同时也会根据server发出的指令来启停container。

cd /root/dinp \ && git clone https://git.oschina.net/leo108/docker_dinp_agent.git agent \ && cd agent \ && docker build -t dinp_agent .

build成功之后可以直接启动容器:

docker run -d --name dinp_agent -e SERVER_HOST=内网IP -e SERVER_PORT=1970 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -e AGENT_IP=内网IP dinp_agent

server上会通过这里设置的AGENT_IP:2375来控制agent的docker,所以这就是本文最上方配置/etc/sysconfig/docker时需要加上

-H tcp://服务器内网IP:2375 -H unix://var/run/docker.sock

的原因,让服务器的docker既支持tcp协议控制,也支持unix socket控制。

Router容器

router是所有用户请求的入口,router根据用户请求的域名,将请求分发到对应的后端container里。Server会将各个app的container列表写入到redis,而router则会读取redis的数据,来判断用户的请求应该分发到哪些container。

cd /root/dinp \ && git clone https://git.oschina.net/leo108/docker_dinp_router.git router \ && cd router \ && docker build -t dinp_router .

build成功之后可以立刻启动:

docker run -d --name dinp_router --link redis:redis -p 8083:8082 -p 80:8888 dinp_router

这里做了两个端口映射,容器中的8082端口是状态查询端口,可以用来查看路由表、健康检查状态等,8888端口则是用户请求入口。因为8082端口被之前的dashboard容器占用,因此换到8083,而通常用户习惯于使用80端口作为http请求端口,因此把8888映射到宿主机的80端口。

开始使用

现在所有的必备的容器都已经启动完毕(还有一个HM健康检查模块没起,但不影响使用),下面开始使用Dinp创建第一个container。

构建基础镜像

cd /root/dinp \ && git clone https://github.com/dinp/Dockerfile.git

这个Dockerfile项目是Dinp各个基础镜像的Dockerfile,我们先来构建一个php的基础镜像。

cd Dockerfile/php,编辑build文件,将REGISTRY=registry.com:5000改成REGISTRY=内网IP:5000,然后就可以通过./build来构建镜像。这个build文件会在镜像构建完毕后将镜像push到私有registry,这就是本文最开始编辑/etc/sysconfig/docker时要加上–insecure-registry 服务器内网IP:5000的原因,否则push会失败。

构建部署镜像

访问外网IP:7788进入Builder平台,app名称填app1,app版本填1,备忘留空,from base image选择php,代码可以通过提供http下载链接或者直接上传。注意一下,php的代码目录必须包含htdocs,入口文件应该放在这个目录里。我这里提供一个测试的包,里面就一个文件,显示phpinfo,代码包链接。之后点击build按钮即可。build页面不会自动刷新,需要自己手动刷,等页面顶部的蓝字显示successful就代表构建成功。点击右上角的History按钮,可以看到这个镜像的地址,记一下,之后要用到。

创建APP

访问外网IP:8082,进入dashboard平台。点击“create app”按钮,Dinp设定每一个app都应该属于UIC中的一个Team,所以需要先在UIC里创建一个Team,在Dashboard页面上点击“Create Team”会自动前往UIC创建Team页面,Team名称填team1,成员加上root,点击“创建”即可。回到创建App页面,刷新之后就可以看到有team1这个Team了,App名字填app1,Health interface留空即可。

部署APP

在Dashboard页面,点击app1右边的deploy,要部署的实例数填1,image地址填写我们之前在build平台生成的地址,点击submit按钮。在新页面点击refresh按钮,应该很快就能看到有一个实例出来了。

这个时候访问app1.dinp.leo108.com,应该就能看到phpinfo页面了。

扩容

在Dashboard页面,点击app1右边的scale,instance count填2,点击scale按钮。点refresh按钮,很快就能看到两个实例出来了。

访问app1.dinp.leo108.com,不断刷新,可以看到System那一栏显示的机器名会改变,说明我们的请求会被随机分发到两个container中的一个。

查看scribe抓取的日志

在宿主机的/root/dinp/data/scribe目录下应该可以看到app1_access目录,cd进去之后就可以通过less命令来查看日志内容了。

Dinp Docker化安装记录
Share this