资讯专栏INFORMATION COLUMN

服务发现与 Docker

DataPipeline / 2644人阅读

摘要:为了动态配置管理,当我们启动和停止一个新容器的时候,我们想后端能自动注册进负载均衡器。这是基本需求,叫做服务发现我们想负载均衡器能自动发现提供服务的容器。一个团队开发的简单的服务发现的工具。服务发现目标是减少或消除组件之间的手动的连接。

  

注:该文由 adetante 编写,原文地址为 Service discovery with Docker

这篇博客的第一篇文章,我将写一篇基于 Docker 容器构建一个不可变架构的解决方案的文章。

这个主题将通过系列文章来描述,从最简单的案例到更复杂的架构。

总体的思想是设计一个“基于概念验证”的解决方案,它允许:

启动和停止一个新容器,如果系统需要扩展或是下线

当一个新版本的应用准备推送到生产,这时使用新容器替换老的容器

使用服务注册和发现来自动把新的容器推送到生产架构

概述

这个逻辑架构是非常简单的,一个无状态的应用通过负载均衡器访问。

每个应用的实例运行在它自己的 docker 容器中。

为了动态配置管理,当我们启动和停止一个新容器的时候,我们想后端能自动注册进负载均衡器。这是基本需求,叫做**服务发现***:我们想负载均衡器能自动发现提供服务的容器。

在这篇文章中,所有的节点将运行在相同的 docker 主机上。这是非常简单的,但是这是实现基础概念的第一个方法。然后我们将通过允许在不同主机上透明的部署来是架构复杂化。

工具集

第一个示例将使用以下工具实现:

Docker。一个运行应用容器的开源平台

Synapse。一个 Airbnb 团队开发的简单的服务发现的工具

Haproxy。一个负载一个后端节点列表的 TCP 流量代理,它打开一个本地的端口,然后把流量传递进这个后端节点的端口。

服务发现

目标是减少或消除组件之间的“手动”的连接。当你把你的应用程序推送进生产的时候,所有的这些事情都可以配置:数据库服务器的主机和端口,REST 服务的 URL 等等,在一个高可扩展的架构中,这些连接可以动态改变。一个新的后端可以被添加,一个数据库节点可以被停止。你的应用需要适应这种动态环境。

这里有一些工具可以管理这些需求(Apache Zookeeper, etcd, ...)。这些工具的普遍原则是:当启动的时候,一个服务的实例必须注册进配置服务器。当停止的时候(完美停止或是 Crash 了),节点必须从配置服务中移除掉。注册后,其他服务可以在配置服务器中搜索到提供制度服务的实例列表(主机和端口)。

Synapse

Synapse 是一个简单的服务发现的工具。Synapse 与以下俩个组件一起使用:

Watcher:它们经常检查一组服务器提供的服务。这可以通过连接 Zookeeper,etcd 或是通过使用 Docker API 来检查 Docker 容器来实现。

Haproxy:Synapse 根据 watcher 的结果来自动改变 HAproxy 的配置。这个意味着当一个新的实例被 watcher 发现,一个后端会被添加进 HAproxy 并且可以通过代理的本地端口访问的。同样地,当实例停止的时候,Synapse 移除后端节点。

第一个解决方案

第一个解决方案将使用 Synapse 和 检查 Docker 容器实现。

Synapse 管理一个运行在安装了 Docker 的相同的主机上的以 8080 端口运行着的 HAproxy 实例。

Synapse 检查 Docker 来发现容器是否运行着一个指定镜像并且暴露一个指定端口。为每一个匹配的容器,Synapse 把其添加进 HAproxy 的配置。

对于这个示例,我们从一个干净的 *Ubuntu 14.04 amd64 安装开始。

安装 Docker

安装步骤已经在 Docker 的文档中描述了:

$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update
$ sudo apt-get install lxc-docker

把以下行添加进 /etc/default/docker,使得 Docker API 在 tcp 上可用:

DOCKER_OPTS="-H 127.0.0.1:4243"

重起 docker:

$ sudo service docker restart

最后,定义以下环境变量来以便 docker 客户端使用 tcp API:

$ export DOCKER_HOST=tcp://127.0.0.1:4243
为 web(nodejs)应用程序创建镜像

从 Docker 仓库获取最新的 Ubuntu 镜像

$ sudo -E docker pull ubuntu:latest

启动一个新的容器

$ sudo -E docker run -ti ubuntu bash

在这个容器中,安装 nodejs

$ apt-get update && apt-get install -y nodejs

在这个容器中,使用以下内容创建一个简单的 nodejs 脚本 /server.js

var http = require("http");
var os = require("os");

var server = http.createServer(function (request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.end("Hello from " + os.hostname() + "
");
});

server.listen(8000);

console.log("Server running at http://127.0.0.1:8000/");

在这个容器中,使用以下内容编写启动脚本 /run.sh

#! /bin/sh
/usr/bin/nodejs /server.js

$ chmod a+x /run.sh

停止容器并且创建一个新的镜像:

$ exit
# Get the ID of the container
$ sudo -E docker ps -a
# Change 3796ab3f5b76 in the following command with the ID listed above
$ sudo -E docker commit 3796ab3f5b76 local/nodeapp
# Remove the old container
$ sudo -E docker rm 3796ab3f5b76

在主机上安装 synapse

$ sudo apt-get install build-essential ruby ruby-dev haproxy
$ sudo gem install synapse

编辑 /etc/default/haproxy 把 ENABLED 设置成 1

启动一个后端实例

启动一个 webapp 容器的实例:

$ sudo -E docker run -d -p 8000 local/nodeapp /run.sh

通过直接在这个容器中调用 nodejs 来测试。我们必须首先获取暴露的公共端口。

# Get the public port (mapped to 8000 in the container, here 49153)
$ sudo docker ps
$ curl http://127.0.0.1:49153
# Responds with "Hello from {container_id}"

使用 Synapse 自动配置 HAproxy

使用以下内容创建一个 /etc/synapse.json.conf 配置文件:

{
  "services": {
    "nodesrv": {
      "discovery": {
        "method": "docker",
        "servers": [
          {
            "name": "localhost",
            "host": "localhost"
          }
        ],
        "container_port": 8000,
        "image_name": "local/nodeapp"
      },
      "haproxy": {
        "port": 8080,
        "listen": [
          "mode http",
          "option httpchk /",
          "http-check expect string Hello"
        ]
      }
    }
  },
  "haproxy": {
    "reload_command": "service haproxy reload",
    "config_file_path": "/etc/haproxy/haproxy.cfg",
    "do_writes": true,
    "do_reloads": true,
    "global": [
      "chroot /var/lib/haproxy",
      "user haproxy",
      "group haproxy",
      "daemon"
    ],
    "defaults": [
      "contimeout 5000",
      "clitimeout 50000",
      "srvtimeout 50000"
    ]
  }
}

我们可以在这个文件中看到:

services.nodesrv.discovery: 配置的观察者。这里我们使用 Docker API 来发现容器运行的名为 local/nodeapp 的镜像以及它暴露的 8080 端口

services.nodesrv.haproxy:配置与 nodesrv service 有关的相关的 HAproxy 端口

haproxy:被 Synapse 管理的全局配置实例

启动 HAproxy 和 Synapse

$ sudo service haproxy start
$ sudo synapse -c /etc/synapse.json.conf

通过直接调用 HAproxy(监听 8080 端口)来测试

$ curl http://localhost:8080
# Responds Hello from {container_id}

用 nodeapp 启动第二个容器:

$ sudo -E docker run -d -p 8000 local/nodeapp /run.sh

通过 HAproxy 测试一些请求。几秒后,每个节点都将响应。
在一个新的 shell 中,运行一下循环,每两秒调用一次 HAproxy:

while :
do
    curl http://localhost:8080
    sleep 2
done

HAproxy 不是通过 container1 就是通过 container2 响应。

停止其中一个容器:

$ sudo -E docker stop {container_id}

几秒后,仅仅剩下的容器响应。

但是在之前我们可以看到一些 503 Service Unavailable 错误。这是由于 Synapse 发现停止的容器并且从代理移除它的时候。

总结

在第一篇文章中,我配置 HAprxoy 从 Docker 容器发现后端节点。Synapse 对使这个进程自动化给予了很多帮助。尽管如此,这个解决方案还有一些缺点:

因为 Synapse 使用 Docker API 发现后端服务,所有的被组织在一个 HAprxoxy 前端的服务必须是在同一个 Docker 主机上。

正如我们所看到的,当停止容器的时候,会有一些中断。这是由于 Synapse 定期的调用 Docker API 来发现新的或是已经移除的容器。

在下一篇文章中,这个解决方案将被扩展成允许在多主机透明部署。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/26343.html

相关文章

  • 基于 Docker 1.12 Swarm 的集群管理开发实践

    摘要:由于没有了中心化的负载均衡器,集群不会因某台机器异常而导致整个服务对外不可用,很好的避免了单点问题,同时也带了可扩展性。 Mesos/Marathon 折腾久了,我们一直希望有机会深入到 Swarm 内部一探究竟。 另外, Mesos 这一套东西虽然是久经企业级考验的, 但是安装、部署和使用相对复杂,上手有门槛。同时,在今年的 DockerCon 上,内置了Swarm 功能的 Dock...

    My_Oh_My 评论0 收藏0
  • Docker 服务发现 - 2

    摘要:是一个键值存储,用于共享配置以及服务发现。对于我们而言,意味着注册进程必须考虑到端口映射。这个方法被用于管理服务发现。如果未指定,将被从的端口映射找到意味着,你必须在运行的命令中指定它,比如。为了测试取消登记,停止一个容器将立即从中移除。 注:该文由 adetante 编写,该文的原文地址为 Service discovery with Docker - 2 该文紧接着上篇文...

    madthumb 评论0 收藏0
  • 运行在 Docker 上的微服务 - 服务发现注册

    摘要:运行在上的微服务服务发现与注册在上一节中,我们学习了如何在上构建一个风格的微服务。接下来,我们将学习如何把运行在上的微服务暴露在服务中心上,以便客户端的调用。资源服务在关闭时需要将服务实例在服务中心进行注销操作。响应用户的终止。 运行在 Docker 上的微服务 - 服务发现与注册 tags: Docker Microservice RESTful etcd Author: And...

    陈伟 评论0 收藏0
  • 技术实践 | Mesos 全方位“烹饪”指南

    摘要:之前提到的文件即可利用以下模板生成请注意,其中的与就是占位符。如将某一特定部署至生产环境并运行个实例。而另一种方式则是使用等负载均衡器即服务器端发现。可重配置且能够在变更发生后立即将请求路由至新实例。 如今与Mesos相关的文章可谓层出不穷,不过展示能够直接用于生产的完整基础设施的资料却相当少见。在今天的文章中,我将介绍各组件的配置与使用方式,旨在帮助大家利用Mesos构建起持续交付且...

    archieyang 评论0 收藏0
  • Docker Swarm介绍

    摘要:后续将其他节点加入集群都会用到这个值将节点加入集群查看节点信息相关命令创建服务更新服务删除服务减少服务实例增加服务实例查看所有服务查看服务的容器状态查看服务的详细信息。前言本篇是Docker第十三篇,Docker的使用至此就介绍完成,接下来继续Kubernetes。Docker系列文章:为什么要学习DockerDocker基本概念Docker镜像基本原理Docker容器数据卷Dockerfi...

    番茄西红柿 评论0 收藏2637

发表评论

0条评论

最新活动
阅读需要支付1元查看
<