Docker 与 Traefik 助微服务腾飞

1,625
原文链接: mp.weixin.qq.com


几周之前我发现了一款叫做Tradefik(https://docs.traefik.io/)的小而美的HTTP反向代理。它可以作为一款为动态后端服务的前端代理,这个动态后端可以是Docker。

你发现了这个动态特性的重要性了吗?

Traefik真正与众不同的特点是,它能通过监听Docker事件来增加或移除容器后端服务。所以当一个Dcoker容器启动或停止时,Traefik都可以知道这个情况并能将将容器添加到它的活动后端服务列表中。


有了这个能力Traefix可以取代Nginx或者HAProxy,因为后者需要非常复杂的操作步骤且需要诸如Registrator、Consul和Consul-Template等工具来完成相同的功能。

所以让我向你展示一个小例子来说明开始使用Traefik是多么简单的事情…

你能看到下面的架构图中我们有一个简单的HTTP服务来响应请求。

我们有多个后端服务,因为要做高可用和负载均衡,它们运行在多个物理节点上。Traefik作为前端代理将请求均匀分发给可用的后端服务上。

Traefik同时作为一个后端服务运行在Docker Swarm集群中的容器内。在这个例子中每个后端服务将会响应所在的独立的容器ID,以此来区分到底是哪个服务做出的响应。


在开始之前我们需要运行一套Docker Swarm集群。

创建Docker Swarm集群

一个最快速并且便捷地得到一套Docker Swarm集群的方法是使用我们的Hypriot Cluter Lab(https://github.com/hypriot/cluster-lab)。

因为Cluster Lab已经预装在树莓派操作系统HypriotOS的“Barbossa”发行版中,我将向你展示怎样使用它去设置Swarm集群。

为了能跟上我的操作,你至少需要三台树莓派主机。我将会使用具有五个节点的Pico-Cluster。


第一步是将HypriotOS镜像烧录到SD中。

将Hypriot仓库克隆到你作为烧录机的操作系统中合适的目录里。

$ git clone https://github.com/hypriot/flash.gi://github.com/hypriot/flash.git
$ cd flash/Darwin

使用flash命令,我们可以为我们的主节点准备好SD卡。

$ ./flash --hostname cl-leader https://downloads.hypriot.com/hypriotos-rpi-v0.8.0.img.zip

为从节点重复此过程。

$ for i in {1..4} do; ./flash --hostname cl-follower${i} https://downloads.hypriot.com/hypriotos-rpi-v0.8.0.img.zip; done

当从节点还在烧录时,你就可以启动主节点了。

SSH到主节点并切换到root用户:

$ ssh pirate@cl-leader.local
$ sudo su

为了能使Cluster Lab与Traefik进行工作,我们需要升级它到最新版本:

$ apt-get update
$ apt-get install hypriot-cluster-lab=0.2.13-1

然后启动Hypriot Cluster Lab,并使用verbose参数来启用日志输出功能:

$ VERBOSE=true cluster-lab start

当Cluster Lab启动,你能观察到它是如何自我配置和进行自检的。如果所有步骤不是绿的,你可以停下它并重新启动。如果还是失败,你需要看一下错误指导部分(https://github.com/hypriot/cluster-lab#troubleshooting)。

当主节点准备好后,是时候启动其他的从节点了,步骤也是先升级然后使用相同的方式启动Cluster Lab。现在你可以尝试做做看,当一切搞定后我们再继续。

好了,我们可以执行下面的命令检查我们是否已经有了五个健康的Swarm Cluster 节点:

DOCKER_HOST=tcp://192.168.200.1:2378 docker info | grep Nodes
Nodes: 5

瞧我们的集群中真的有了五个节点了。恭喜恭喜!

当你完成了以上的步骤,那么剩下的就是小菜一碟了!

使用Traefik组建我们的微服务

我们的微服务示例由两部分组成。Traefik前端和WhoAmI后端应用。对于这两部分我已经为你准备好了Docker镜像,你可以从Docker Hub中拉取到本地。

Traefik镜像叫做hypriot/rpi-traefik ,WhoAmI镜像叫做hypriot/rpi-whoami。两个镜像的Dockerfile可以在Github的相关仓库(https://github.com/hypriot)中找到。

因为这两个Dockerfile也是Go语言为基础的镜像的好示例,我将会在这里解释一下其中的内容。

“rpi-traefik”的Dockerfile:

FROM hypriot/rpi-alpine-scratch
RUN apk update &&\
apk upgrade &&\
apk add ca-certificates &&\
rm -rf /var/cache/apk/*
ADD https://github.com/containous/traefik/releases/download/v1.0.0-beta.771/traefik_linux-arm /traefik
RUN chmod +x /traefik
EXPOSE 80 8080
ENTRYPOINT ["/traefik"]

它表示我们刚刚在Alpine linux镜像之中增加了Traefik的可执行文件。这个镜像非常精巧仅仅只有41MB。如果你静态编译Traefik可执行文件到一个空镜像中,它的体积将会更小。

你将会在下面的WhoAmI镜像的Dockerfile中看到这是怎么做的:

“rpi-whoami”的Dockerfile:

FROM scratch

ADD http /http

ENV PORT 8000
EXPOSE 8000

CMD ["/http"]

仅仅只有3MB的镜像,这真是非常的小。

好了,现在是时候将组件放入一个Docker Compose应用中了。

克隆下面的仓库到你的集群主节点中:

$ git clone https://github.com/hypriot/rpi-cluster-lab-demos

当克隆结束后切换到‘traefik’目录,并使用Docker Compose在我们的微型Docker Swarm集群中启动我们的应用:

$ cd rpi-cluster-lab-demos/traefik
$ DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose up -d
Creating network "traefik_default" with the default driver
Creating traefik_traefik_1
Creating traefik_whoami_1

这些命令将会使Docker Compose启动两个容器。一个主节点中Traefik容器,另一个是在四个从节点中启动一个WhoAmI容器。

让我们查看一下是否真是如此:

$ DOCKER_HOST=tcp://192.168.200.1:2378 docker ps | grep 'traefik\|whoami'
cba8d9a7d8f7        hypriot/rpi-whoami         "/http"                  About a minute ago   Up About a minute   8000/tcp                                                 cl-follower1/traefik_whoami_1
7dc2b48a24e2        hypriot/rpi-traefik        "/traefik --web --doc"   About a minute ago   Up About a minute   192.168.200.1:80->80/tcp, 192.168.200.1:8080->8080/tcp   cl-leader/traefik_traefik_1

看起来不错。那么让我们发送一些HTTP请求到前端来测试一下我们的应用:

$ for i in {1..5}; do curl -H Host:whoami.docker.localhost http://192.168.200.1; done
I'am f72892c9187c
I'am f72892c9187c
I'am f72892c9187c
I'am f72892c9187c
I'am f72892c9187c

正如你所见,所有的响应全部来自于同一个后端容器,并且这正是我所期望的。

接下来我们将会在Docker Compose scale命令的帮助下增加后端容器的数量。

$ DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose scale whoami=5
Creating and starting traefik_whoami_2 ... done
Creating and starting traefik_whoami_3 ... done
Creating and starting traefik_whoami_4 ... done
Creating and starting traefik_whoami_5 ... done

我们观察到Docker Compose通知Docker Swarm增加了更多的容器。

让我们再次检查一下是否现在已经有五个后端容器运行了:

$ for i in {1..5}; do curl -H Host:whoami.docker.localhost http://192.168.200.1; done
I'm 5d829fecbdaa
I'm 5eb115353885
I'm e0313ac24554
I'm 642b5d2c8d09
I'm f72892c9187c

非常好。很显然Traefik刚才识别出了我们已经启动了更多的容器并且使他们自动与前端相连。

我们能通过Traefik容器的日志观察到具体的执行过程:

$ DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose logs traefik
...
traefik_1  | time="2016-06-07T06:50:38Z" level=debug msg="Configuration received from provider docker: {\"backends\":{\"backend-whoami\":{\"servers\":{\"server-traefik_whoami_1\":{\"url\":\"http://10.0.0.3:8000\",\"weight\":1},\"server-traefik_whoami_2\":{\"url\":\"http://10.0.0.5:8000\",\"weight\":1},\"server-traefik_whoami_3\":{\"url\":\"http://10.0.0.6:8000\",\"weight\":1},\"server-traefik_whoami_4\":{\"url\":\"http://10.0.0.4:8000\",\"weight\":1},\"server-traefik_whoami_5\":{\"url\":\"http://10.0.0.7:8000\",\"weight\":1 } } } },\"frontends\":{\"frontend-Host-whoami-docker-localhost\":{\"backend\":\"backend-whoami\",\"routes\":{\"route-frontend-Host-whoami-docker-localhost\":{\"rule\":\"Host:whoami.docker.localhost\"}},\"passHostHeader\":true} } }"
traefik_1  | time="2016-06-07T06:50:38Z" level=debug msg="Last docker config received less than 2s, waiting..."
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Waited for docker config, OK"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating frontend frontend-Host-whoami-docker-localhost"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Wiring frontend frontend-Host-whoami-docker-localhost to entryPoint http"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating route route-frontend-Host-whoami-docker-localhost Host:whoami.docker.localhost"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating backend backend-whoami"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating load-balancer wrr"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating server server-traefik_whoami_4 at http://10.0.0.4:8000 with weight 1"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating server server-traefik_whoami_3 at http://10.0.0.6:8000 with weight 1"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating server server-traefik_whoami_2 at http://10.0.0.5:8000 with weight 1"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating server server-traefik_whoami_1 at http://10.0.0.3:8000 with weight 1"
traefik_1  | time="2016-06-07T06:50:40Z" level=debug msg="Creating server server-traefik_whoami_5 at http://10.0.0.7:8000 with weight 1"

通过日志我们能清楚的看到Traefik是怎么获取Docker事件并作出反应的。

这难道不很帅吗?

好了。这就是我们的快速设置Docker和Traefik的简单微服务例子。

剩下唯一要做的就是再次清理容器。

$ DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose down -v

你们注意到了“-v”参数了吗?这应该对清除所有的容器,包括overlay网络都非常的重要。没有“-v”参数,我们在下次使用Docker Compose启动应用的时候会产生一个错误。

在你关闭树莓派之前停止所有的节点中的Cluster Lab也是一个必要的步骤。

所以在所有节点上执行一下$ cluster-lab stop命令。

在这么短小的一篇博客中使用了这么多有趣的技术是非常棒的一件事情。并且使它们运行起来一点都不难,是不是?

这都归功于Hypriot Cluster Lab的功劳,当然Docker-Engine、Docker-Swarm和Docker-Compose也居功至伟。

所以一定要试试我们的Hypriot Cluster,并且尝试一下Hypriot Cluster Lab Demos(https://github.com/hypriot/rpi-cluster-lab-demos)仓库中的例子,或者添加一些你自己的例子。同时也欢迎大家提Pull request。

推荐一个培训

【基于Docker的DevOps实战培训 | 南京站】培训内容涉及容器编排框架(应用部署)、Ansible 简介、持续集成常用方式、典型案例分析、容器的选择、架构设计(百万级日活,亿级API 请求)、数据系统构建、持续集成的开发流程等,点击下面图片即可查看具体培训内容。



点击阅读原文链接可直接报名。