Docker与Traefik助微服务腾飞
ykwz2382
8年前
<p>【编者的话】Govind Fichtner是一位从业15年的德国IT老兵。先后担任过开发工程师,系统管理员,咨询师,架构师,敏捷训练师,项目经理,部门经理甚至CTO。白天他是一位勤奋的DevOps,晚上则变身为狂热的ARM设备爱好者。他现在为Hypriot成员,该组织成员以“Docker海盗”自称,发布了多款ARM架构中的Docker应用。他们的身上完美的体现了Geek精神</p> <p>几周之前我发现了一款叫做 <a href="/misc/goto?guid=4959674635477279977" rel="nofollow,noindex">Tradefik</a> 的小而美的HTTP反向代理。它可以作为一款为动态后端服务的前端代理,这个动态后端可以是Docker。</p> <p>你发现了这个 <strong>动态</strong> 特性的重要性了吗?</p> <p>Traefik真正与众不同的特点是,它能通过监听Docker事件来增加或移除容器后端服务。所以当一个Dcoker容器启动或停止时,Traefik都可以知道这个情况并能将将容器添加到它的活动后端服务列表中。</p> <p><img src="https://simg.open-open.com/show/2fc37a04d810dd055eab8c2a7ed4c829.png"></p> <p>有了这个能力Traefix可以取代Nginx或者HAProxy,因为后者需要非常复杂的操作步骤且需要诸如 <a href="/misc/goto?guid=4958967317393867577" rel="nofollow,noindex">Registrator</a> , <a href="/misc/goto?guid=4958967317511997269" rel="nofollow,noindex">Consul</a> 和 <a href="/misc/goto?guid=4958967317608731033" rel="nofollow,noindex">Consul-Template</a> 等工具来完成相同的功能。</p> <p>所以让我向你展示一个小例子来说明开始使用Traefik是多么简单的事情...</p> <p>你能看到下面的架构图中我们有一个简单的HTTP服务来响应请求。</p> <p>我们有多个后端服务,因为要做高可用和负载均衡,它们运行在多个物理节点上。Traefik作为前端代理将请求均匀分发给可用的后端服务上。</p> <p>Traefik同时作为一个后端服务运行在Docker Swarm集群中的容器内。在这个例子中每个后端服务将会响应所在的独立的容器ID,以此来区分到底是哪个服务做出的响应。</p> <p><img src="https://simg.open-open.com/show/1561239abe981e456140bb6b66a08e23.jpg"></p> <p>在开始之前我们需要运行一套Docker Swarm集群。</p> <h2>创建Docker Swarm集群</h2> <p>一个最快速并且便捷地得到一套Docker Swarm集群的方法是使用我们的 <a href="/misc/goto?guid=4959674635653067486" rel="nofollow,noindex">Hypriot Cluter Lab</a> 。</p> <p>因为Cluster Lab已经预装在树莓派操作系统HypriotOS的“Barbossa”发行版中,我将向你展示怎样使用它去设置Swarm集群。</p> <p>为了能跟上我的操作,你至少需要三台树莓派主机。我将会使用具有五个节点的Pico-Cluster</p> <p><img src="https://simg.open-open.com/show/7a57fd62779ddd2fb969514b7e80d48b.jpg"></p> <p>第一步是将HypriotOS镜像烧录到SD中。</p> <p>将Hypriot仓库克隆到你作为烧录机的操作系统中合适的目录里。</p> <pre> $ git clone https://github.com/hypriot/flash.gi://github.com/hypriot/flash.git $ cd flash/Darwin </pre> <p>使用flash命令,我们可以为我们的 <strong>主节点</strong> 准备好SD卡。</p> <pre> $ ./flash --hostname cl-leader https://downloads.hypriot.com/hypriotos-rpi-v0.8.0.img.zip </pre> <p>为 <strong>从节点</strong> 重复此过程。</p> <pre> $ for i in {1..4} do; ./flash --hostname cl-follower${i} https://downloads.hypriot.com/hypriotos-rpi-v0.8.0.img.zip; done </pre> <p>当从节点还在烧录时,你就可以启动主节点了。</p> <p>SSH到主节点并切换到root用户:</p> <pre> $ ssh pirate@cl-leader.local $ sudo su </pre> <p>为了能使Cluster Lab与Traefik进行工作,我们需要升级它到最新版本:</p> <pre> $ apt-get update $ apt-get install hypriot-cluster-lab=0.2.13-1 </pre> <p>然后启动Hypriot Cluster Lab,并使用verbose参数来启用日志输出功能:</p> <pre> $ VERBOSE=true cluster-lab start </pre> <p>当Cluster Lab启动,你能观察到它是如何自我配置和进行自检的。如果所有步骤不是绿的,你可以停下它并重新启动。如果还是失败,你需要看一下 <a href="/misc/goto?guid=4959674635736264141" rel="nofollow,noindex">错误指导部分</a> 。</p> <p>当主节点准备好后,是时候启动其他的从节点了,步骤也是先升级然后使用相同的方式启动Cluster Lab。现在你可以尝试做做看,当一切搞定后我们再继续。</p> <p>好了,我们可以执行下面的命令检查我们是否已经有了五个健康的Swarm Cluster 节点:</p> <pre> DOCKER_HOST=tcp://192.168.200.1:2378 docker info | grep Nodes Nodes: 5 </pre> <p>瞧我们的集群中真的有了五个节点了。恭喜恭喜!</p> <p>当你完成了以上的步骤,那么剩下的就是小菜一碟了!</p> <h2>使用Traefik组建我们的微服务</h2> <p>我们的微服务示例由两部分组成。Traefik前端和WhoAmI后端应用。对于这两部分我已经为你准备好了Docker镜像,你可以从Docker Hub中拉取到本地。</p> <p>Traefik镜像叫做 <a href="/misc/goto?guid=4959674635830725336" rel="nofollow,noindex">hypriot/rpi-traefik</a> ,WhoAmI镜像叫做 <a href="/misc/goto?guid=4959674635917193652" rel="nofollow,noindex">hypriot/rpi-whoami</a> 。两个镜像的Dockerfile可以在Github的 <a href="/misc/goto?guid=4959674636001824668" rel="nofollow,noindex">相关仓库</a> 中找到。</p> <p>因为这两个Dockerfile也是Go语言为基础的镜像的好示例,我将会在这里解释一下其中的内容。</p> <p>“rpi-traefik”的Dockerfile:</p> <pre> 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"] </pre> <p>它表示我们刚刚在Alpine linux镜像之中增加了Traefik的可执行文件。这个镜像非常精巧仅仅只有41MB。如果你静态编译Traefik可执行文件到一个空镜像中,它的体积将会更小。</p> <p>你将会在下面的WhoAmI镜像的Dockerfile中看到这是怎么做的:</p> <p>“rpi-whoami”的Dockerfile:</p> <pre> FROM scratch ADD http /http ENV PORT 8000 EXPOSE 8000 CMD ["/http"] </pre> <p>仅仅只有3MB的镜像,这真是非常的小。</p> <p>好了,现在是时候将组件放入一个Docker Compose应用中了。</p> <p>克隆下面的仓库到你的集群主节点中:</p> <pre> $ git clone https://github.com/hypriot/rpi-cluster-lab-demos </pre> <p>当克隆结束后切换到‘traefik’目录,并使用Docker Compose在我们的微型Docker Swarm集群中启动我们的应用:</p> <pre> $ 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 </pre> <p>这些命令将会使Docker Compose启动两个容器。一个主节点中Traefik容器,另一个是在四个从节点中启动一个WhoAmI容器。</p> <p>让我们查看一下是否真是如此:</p> <pre> $ 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 </pre> <p>看起来不错。那么让我们发送一些HTTP请求到前端来测试一下我们的应用:</p> <pre> $ 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 </pre> <p>正如你所见,所有的响应全部来自于同一个后端容器,并且这正是我所期望的。</p> <p>接下来我们将会在Docker Compose scale命令的帮助下增加后端容器的数量。</p> <pre> $ 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 </pre> <p>我们观察到Docker Compose通知Docker Swarm增加了更多的容器。</p> <p>让我们再次检查一下是否现在已经有五个后端容器运行了:</p> <pre> $ 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 </pre> <p>非常好。很显然Traefik刚才识别出了我们已经启动了更多的容器并且使他们自动与前端相连。</p> <p>我们能通过Traefik容器的日志观察到具体的执行过程:</p> <pre> $ 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_1 | time="2016-06-07T06:50:40Z" level=info msg="Server configuration reloaded on :80"</pre> <p>通过日志我们能清楚的看到Traefik是怎么获取Docker事件并作出反应的。</p> <p>这难道不很帅吗?</p> <p>好了。这就是我们的快速设置Docker和Traefik的简单微服务例子。</p> <p>剩下唯一要做的就是再次清理容器。</p> <pre> $ DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose down -v </pre> <p>你们注意到了“-v”参数了吗?这应该对清除所有的容器,包括overlay网络都非常的重要。没有“-v”参数,我们在下次使用Docker Compose启动应用的时候会产生一个错误。</p> <p>在你关闭树莓派之前停止所有的节点中的Cluster Lab也是一个必要的步骤。</p> <p>所以在所有节点上执行一下</p> <pre> $ cluster-lab stop </pre> <p>命令。</p> <p>在这么短小的一篇博客中使用了这么多有趣的技术是非常棒的一件事情。并且使它们运行起来一点都不难,是不是?</p> <p>这都归功于 <a href="/misc/goto?guid=4959674635653067486" rel="nofollow,noindex">Hypriot Cluster Lab</a> 的功劳,当然Docker-Engine,Docker-Swarm和Docker-Compose也居功至伟。</p> <p>所以一定要试试我们的Hypriot Cluster,并且尝试一下 <a href="/misc/goto?guid=4959674636090814119" rel="nofollow,noindex">Hypriot Cluster Lab Demos</a> 仓库中的例子,或者添加一些你自己的例子。同时也欢迎大家提Pull request。</p> <p>原文链接: <a href="/misc/goto?guid=4959674636175228100" rel="nofollow,noindex">Microservices Bliss with Docker and Traefik</a> (翻译:高洪涛)</p> <p>===========================================</p> <p>译者介绍</p> <p>高洪涛,当当网架构师,开源数据库分库分表中间件Sharding-JDBC作者。目前从事Docker相关研究工作。</p> <p> </p> <p>来自: <a href="/misc/goto?guid=4959674636257346636" rel="nofollow">http://dockone.io/article/1418</a></p> <p> </p>