基于go的微服务搭建(五) - 部署docker swarm

标题: 部署docker swarmjava

这部分,咱们启动咱们的accountservice,运行在本地的docker swarm集群中.同时讨论几个容器部署的重要概念
这篇博客主要讲一下几点:node

  • docker swarm和容器部署
  • 用docker做为容器运行accountservice
  • 创建一个本地的docker swarm集群
  • 将accountservice做为swarm服务部署
  • 基测和结果

其实写完这一章,我发现这一章和go没有关系.但但愿你喜欢.linux

什么是容器部署


在实践开始以前,一个容器部署的简单介绍:
当一个应用愈来愈复杂,而且开始有更高的负载,将会有成百个服务在不少硬件上运行.容器部署让咱们在一个节点上管理咱们的硬件
一篇文章上总结的:git

抽象主机的基础结构,部署工具容许用户在一个部署目标上控制整个集群.

这总结的很好.用kubernetes或者docker swarm这种容器部署工具来部署咱们的各个服务在不一样的节点上.对于docker来讲,swarm模式管理docker engine的集群.kubernetes用一种稍微不一样的抽象方法,可是总体概念上是一致的.
容器部署不只控制咱们服务的生命周期,也提供其余服务,例如:服务发现,负载均衡,内部地址和日志.github

docker swarm核心概念


在docker swarm中,有三个核心概念:spring

  • 节点: 一个节点就是一个docker engine的实例.理论上讲,他是一个拥有cpu资源,内存和网络接口的主机.一个节点能够是一个manager节点或者worker节点.
  • 服务: 服务就是worker节点上运行的指令.一个服务能够是复制的或者全局的.一个服务能够抽象的当作是任意数量的容器组成的逻辑上的服务.这个服务能够用它的名字来调用,而不须要知道它内部的网络结构.
  • 任务: 一个任务能够是docker容器,docker文件定义任务为:拥有并运行docker容器和指令.manager节点分发任务给worker节点的服务.

下图展现一个简单的微服务框架.两个服务accountservice和quotes-service抽象为两个节点,运行在五个容器的实例中.docker

![图片上传中...]json

代码


这部分没有改go方面的代码.
clipboard.png
cker.你能够获得这一章完整的代码api

git checkout P5

容器化咱们的accountservice


docker安装


你须要安装docker.我用的是docker toolbox 和vitualbox.可是你能够直接用docker.浏览器

建立dockerfile


一个dockerfile能够当作是你想建立什么样的docker镜像的配方.让咱们在accountservice文件夹中建立文件Dockerfile:

FROM iron/base

EXPOSE 6767
ADD accountservice-linux-amd64 /
ENTRYPOINT ["./accountservice-linux-amd64"]

解释:

  • FROM-定义咱们的基础镜像.咱们会在这个镜像上开始.iron/base是一个能够运行go程序的小巧的镜像
  • EXPOSE-定义一个端口,做为外部请求的端口
  • ADD-增长一个文件accountservice-linux-amd64到root(/)目录下
  • ENTRYPOINT-定义启动哪个程序,当docker开启这个镜像容器

不一样操做系统下的编译


咱们的文件名字包含linux-amd64.咱们能够叫他任何名字,可是我喜欢把操做系统和cpu型号放进执行文件名字中.我用的是mac OSX 系统.因此我若是直接编译go的执行文件,用go build的话,这产生一个执行文件在同一个文件夹中.然而这个执行文件不能再docker上运行,由于docker容器的环境是linux.所以,咱们须要设定一些环境参数,这样咱们的编译器才知道咱们要给其余的系统或者cpu环境编译文件.
在goblog/accountservice文件夹下面运行:

export GOOS=linux
go build -o accountservice-linux-amd64
export GOOS=darwin

-o表示产生二进制执行文件.我常常用脚本文件自动作这些东西(后面会有)
由于OS X和linux容器都在AMD64 cpu架构上,咱们不须要设置GOARCH参数.可是你若是用32位系统,或者ARM处理器,你要设置GOARCH参数

建立docker镜像


如今咱们建立第一个docker镜像,包含咱们的执行文件.去accountservice的上层文件夹,就是$GOPATH/src/github.com/callistaenterprise/goblog.
对于docker镜像,咱们常常用一个前缀来标注名字.我常常用个人github名字做为前缀,例如eriklupander/myservicename.这里,我用someprefix做为前缀.执行下面的命令来建立Docker镜像:

> docker build -t someprefix/accountservice accountservice/

Sending build context to Docker daemon 13.17 MB
Step 1/4 : FROM iron/base
 ---> b65946736b2c
Step 2/4 : EXPOSE 6767
 ---> Using cache
 ---> f1147fd9abcf
Step 3/4 : ADD accountservice-linux-amd64 /
 ---> 0841289965c6
Removing intermediate container db3176c5e1e1
Step 4/4 : ENTRYPOINT ./accountservice-linux-amd64
 ---> Running in f99a911fd551
 ---> e5700191acf2
Removing intermediate container f99a911fd551
Successfully built e5700191acf2

好了,咱们有啦一个someprefix/accountservice镜像.若是咱们要在多节点下运行或者分享镜像,咱们能够用docker push来使咱们的镜像被别的主机pull.
咱们如今运行镜像:

> docker run --rm someprefix/accountservice
Starting accountservice
Seeded 100 fake accounts...
2017/02/05 11:52:01 Starting HTTP service at 6767

然而,咱们的容器不是在你的主机系统下运行,他运行在本身的网络中,咱们不能直接从咱们的主机来请求他.有办法来解决这个问题,但如今咱们放一放,咱们继续组建咱们的docker swarm和部署accountservice.

建立单节点Docker swarm集群


一个docker swarm集群包括至少一个swarm manager和零到多个swarm worker.个人例子会包含一个swarm manager.这节事后,你会有一个swarm manager运行.
你能够参考别的文章来看如何运行swarm.下面这条命令初始化docker主机为swarm-manager-1做为一个swarm节点,同时让swarm-manager-1节点地址和主机同样

> docker $(docker-machine config swarm-manager-1) swarm init --advertise-addr $(docker-machine ip swarm-manager-1)

若是咱们要建立多节点的swarm集群,咱们要把这条命令产生的join-token记录下来,这样咱们能够加入其余的节点到这个swarm中.

建立网络


一个docker网络的用处是,当咱们想请求同一个swarm集群上的其余的容器,并不须要知道真实的集群分布.

docker network create --driver overlay my_network

my_network是咱们的网络名称

部署accountservice


如今咱们要部署咱们的accountservice进Docker swarm服务中.这个docker服务命令有不少参数设置,但不要怕.这里咱们来部署accountservice

docker service create --name=accountservice --replicas=1 --network=my_network -p=6767:6767 someprefix/accountservice
ntg3zsgb3f7ah4l90sfh43kud

快速看一下这些参数

  • -name:给服务的名字.这也是集群中其余服务请求咱们的名字.因此另外一个服务来请求accountservice的话,这个服务只须要Get请求http://accountservice:6767/accounts/10000
  • -replicas: 咱们服务的实例数量.若是咱们有多节点的docker swarm集群,swarm engine会自动分发实例到不一样的节点上.
  • -network: 这里咱们告诉咱们的服务用刚刚咱们建立的网络my_network
  • -p: 映射[内部端口]:[外部端口].这里咱们用6767:6767.若是咱们用6767:80,从外部请求要用80端口.注意这部分使咱们的服务能够被外界请求.大多数状况,你不该该让你的服务暴露给外界.你应该用一个EDGE-server(例如反向代理),包括路由机制和安全检查,因此外界不能随意请求你的服务
  • someprefix/accountservice: 指明咱们想让容器运行哪个镜像.

让咱们看看咱们的服务是否运行了

> docker service ls

太好了,咱们应该能够curl或者用浏览器请求咱们的api.惟一要知道的就是咱们swarm的ip地址.即便咱们只运行一个服务实例,咱们的网络和swarm也会须要咱们的服务外部端口,这意味着两个服务不能用同一个外部端口.他们能够有一样的内部端口,但对于外部来讲,swarm是一个总体.

> echo $ManagerIP
192.168.99.100

若是你换了terminal,你能够从新导出:

> export ManagerIP=`docker-machine ip swarm-manager-0`

curl请求:

> curl $ManagerIP:6767/accounts/10000
{"id":"10000","name":"Person_0"}

部署可视化


用docker的命令来查看swarm的状态不容易看,一个图形化的方法比较好.例如manomarks docker swarm visualizer能够被部署为一个Docker swarm的服务.这能够给咱们提供咱们集群分布的图形,同事确保咱们在集群中外部暴露的服务可不能够请求到.
初始化这个可视器在容器镜像中

docker service create \
 --name=viz \
 --publish=8080:8000/tcp \
 --constraint=node.role==manager \
 --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
 manomarks/visualizer

这将在8000端口产生一个服务.让咱们用浏览器浏览http://$ManagerIP:8000

clipboard.png

额外内容


我也作了一个swarm的可视化界面叫作dvizz,展现docker 远程api和D3.js force图.你能够安装她

docker service create \
 --constraint=node.role==manager \
 --replicas 1 --name dvizz -p 6969:6969 \
 --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
 --network my_network \
 eriklupander/dvizz

浏览 http://$ManagerIP:6969

clipboard.png

加入quote-service

只有一个服务的微服务不能看出微服务的全貌.让咱们部署一个基于spring boot的quotes-service.我把这个容器镜像放在docker hub中的eriklupander/quotes-service.

> docker service create --name=quotes-service --replicas=1 --network=my_network eriklupander/quotes-service

若是你输入docker ps来看那些docker容器在运行:

> docker ps
CONTAINER ID    IMAGE                       COMMAND                 CREATED         STATUS                           PORTS                                           NAMES
98867f3514a1    eriklupander/quotes-service "java -Djava.security"  12 seconds ago  Up 10 seconds

注意,咱们没有暴露一个外界端口给这个服务,因此咱们只能在集群内部的端口8080内请求.咱们会集成这个服务在第七部分同时看一下服务探索和负载均衡.
若是你加入了dvizz,你应该能看到quotes-service和accountservice

copyall.sh脚本

咱们来作一个脚本帮助咱们编译和部署.在root/goblog文件夹中,建立一个脚本文件叫作copyall.sh

#!/bin/bash
export GOOS=linux
export CGO_ENABLE=0

cd accountservice; go get; go build -o accountservice-linux-amd64;echo build `pwd`;cd ..

export GOOS=darwin
docker build -t someprefix/accountservice accountservice/

docker service rm accountservice
docker service create --name=accountservice --replicas=1 --network=my_network -p=6767:6767
someprefix/accountservice

这段脚本编译执行文件,从新编译docker镜像,部署到docker swarm服务上.
我喜欢脚本的简化,虽然有时我用gradle plugin.

性能


如今开始,全部的基测都在docker swarm上进行.这意味以前的结果不能用来和以后的比较
cpu使用率和内存使用会用 docker stats来收集.咱们也会用gatling测试.
若是你喜欢压力测试,第二节的仍然能够用,但须要改变-baseUrl参数

> mvn gatling:execute -dusers=1000 -Dduration=30 -DbaseUrl=http://$ManagerIP:6767

内存使用率

> docker stats $(docker ps | awk '{if(NR>1) print $NF}')

CONTAINER                                    CPU %               MEM USAGE / LIMIT    
accountservice.1.k8vyt3dulvng9l6y4mj14ncw9   0.00%               5.621 MiB / 1.955 GiB
quotes-service.1.h07fde0ejxru4pqwwgms9qt00   0.06%               293.9 MiB / 1.955 GiB

启动后,包含linux和咱们accountservice的容器用5.6mb的内存,java开发的quotes-service用了300mb.虽然这能够经过调整jvm来下降.

cpu和内存使用压力测试


CONTAINER                                    CPU %               MEM USAGE / LIMIT   
accountservice.1.k8vyt3dulvng9l6y4mj14ncw9   25.50%              35.15 MiB / 1.955 GiBB

在1K req/s下,虚拟机中运行的swarm和在第二三节中的OS x系统相比,内存稍微升高,cpu大略相同.

性能


![图片上传中...]


延迟上升到4ms.这和直接运行有所升高,缘由有几点.我认为gatling测试经过桥接的网络和swarm上的路由会有一些延迟.可是4ms的延迟也不错.毕竟咱们从boltDB读数据,序列化到json并输出到HTTP.

总结


咱们学习如何启动docker swarm和部署accountservice到swarm上.下一节,咱们会给咱们的微服务加入healthcheck.

相关文章
相关标签/搜索