一个基于 Docker 的负载均衡实例

前言

近年来,云计算的概念席卷了整个 IT 圈。抛开忽悠概念的因素,云计算的发展和应用极大地改变了 IT 产业的研发、运营和管理。作为云计算最重要的核心技术之一,虚拟化技术的发展促成了这一巨大的变革,而容器技术作为最具有代表性的虚拟化技术革新,目前已经得到了业界的广泛关注,其中以 Docker 最具有代表性,最为火爆,鹅厂目前很多应用也或多或少使用到了 docker。本文目地主要是给大家简单安利一下目前最火的容器产品 Docker 及其所涉及的相关技术,并通过一个实际例子演示一下容器技术的典型应用场景。

简单扯扯容器

虚拟化技术的核心在于资源划分、隔离和管理。围绕着这个核心,在不同层次上发展出了多种虚拟化技术,如以虚拟机为代表的硬件级虚拟化(Hardware Virtualization)技术以及以容器(Container)为代表的操作系统级虚拟化(Operating System Level Virtualization)技术。容器并不是一个全新的技术体系,下图是从 Wikipedia 摘录的容器实现全家福,可以看到此项技术可以追溯到 1982 年,并且覆盖了多种操作系统。近年来,随着 Docker 的快速崛起,容器技术再次吸引了 IT 业界的广泛关注。

为什么要用"再"?这就需要聊聊容器的特点以及跟虚拟机的区别和联系。随着技术的发展,IT 基础设施的能力越来越大,原来需要多个硬件单元完成的任务现在仅用一个硬件单元的一部分就能够完成了,那么为了资源的合理分配,将资源集合划分为更细粒度的资源单元,就是虚拟化技术的意义。下图是虚拟机和容器技术的对比示意图。左图中,在宿主机操作系统(Host OS)之上,通过 Hypervisor 将资源划分为资源单元,每个单元有自己的操作系统(Guest OS)、工具和库,在其上运行各自的 app 互不干扰,每个资源单元就是一个虚拟机;右图中在宿主机操作系统之上,通过容器管理器(Container Manager)将一部分资源隔离出来形成资源单元,每个资源单元没有自己的操作系统,有自己的工具和库,在这之上运行自己的 app,这里每个资源单元就是一个容器。

通过上图的分析可以看到,虚拟机和容器技术在隔离的层次上并不相同,虚拟机有从操作系统开始的完整的基础设施,而容器仅在工具、库这个层次及以上形成了自己的特有区域。这个特点决定了两者的属性,容器是比虚拟机更轻量的资源单元。轻量,意味着快速启停、迁移、分发等优良的性质,并且在资源总量一样的情况下,能够支持的容器单元数量将数倍于虚拟机。

下面扯点题外话,人类善于通过逻辑思维的手段从不同的事物中抽取出本质并加以推广。举个例子,运输业是一个很古老的行业,运输业的发展推动了人类的进步,当人类的运输需求变得越来越复杂,遇到了下面的问题,如何用标准的交通工具运输各种各样需求不同的物品?

为了解决这个问题,人们发明了集装箱,它将运输品所需满足的条件(光照、冷藏、密封等)限制在集装箱之内,对外而言它只是一个提供标准运输接口的单元,这样的单元可以通过各种使用标准运输接口的交通工具运输。

看到这里大家应该不难理解,通过类比,IT 攻城狮们再次发现虚拟化技术所蕴含的巨大潜力,虚拟化可以充当集装箱的角色,将 app 运行所需满足的条件(依赖、工具、库等)限制在资源单元之内,对外提供标准的接口,并且能够装载于各类服务器基础设施。并且在比较了各类虚拟化技术后,容器轻量的特点让它更适宜与成为集装箱。在重新审视了容器技术的巨大价值之后,各方势力纷纷开始占山头立门户,在这个过程中诸多新的容器技术相继发布,其中就以取名为码头工人的 Docker 最具代表性。

WoW,Docker 来了!它是谁?能干嘛?

Docker 是谁?Docker 是由 dotCloud 公司在 2013 年开源的一款开源容器引擎,后来 Docker 火了干脆公司就改名为 Docker 了……

Docker 是一种基于 Linux 内核隔离技术的容器实现,用 Go 语言编写,其功能特性归纳为:

  • 资源隔离,包括文件系统、进程、网络等;
  • 资源控制;
  • 文件系统,具有写时复制、日志记录、版本管理等;
  • 提供控制 API;
  • 提供镜像分发、重用的生态系统。

Docker 的实现依赖了以下技术:

  • Namespace,利用 Linux 内核提供的 namespace 机制,容器能够建立资源隔离单元,隔离内容包括进程(PID)、网络(Net)、进程交互(IPC)、文件目录(Mnt)、hostname 及用户和用户组等。
  • CGroup,利用 CGroup 机制来处理不同容器之间竞争宿主机系统资源的问题,实现对资源的配额和度量。
  • LXC,在 Docker 发展的过程中,早期使用 LXC 来共享内核,实现容器的快速启停以及减少内存的消耗,在后来的发展中,docker 主键用 libcontainer 替代并扩展了 LXC 的功能。
  • AUFS,Docker 默认使用 AUFS 构建容器的文件系统,提供写时复制(Copy On Write)的特性,这是 Docker 镜像保存、修改及分发的基础。

基于 docker 提供的基础功能和其开源的属性,业界巨头和初创公司纷纷以此为基础开发出各种框架和工具,在分布式特性、网络特性、存储特性以及管理特性等方面对 Docker 进行扩展和补充,鹅厂 IEG 内部使用的 Docker 管理平台以及 TEG 的 Gaia 系统都是很好的例子。关于 docker 技术原理的文章能够很容易搜索到,本文就不在这里展开了,下面将根据容器的特点介绍几个典型的应用场景,并给大家介绍如何从零开始写一个简单的基于 Docker 的负载均衡器。

根据前述,Docker 作为一种容器,能够快速启停、占用较少的系统资源,同时根据其自身实现技术特点,又具备写时复制、保存分发等特点。所以不难想到以下几种应用场景很适合使用 Docker 实现:

  • 平台即服务(PAAS),沙箱的完美替代品;
  • 自动测试及持续集成,测试妹纸笑开了花;
  • 构建标准化无状态运行环境及快速部署,你知道重装环境有多么烦么;
  • 高可用(HA)和负载均衡(LB)系统,让故障和攻击陷入人民战争的汪洋大海,一会慢慢讲。

夸了那么多,难道 Docker 就没有缺点么?不是的,目前 Docker 正在快速发展过程中,在人们使用的过程中逐渐暴露了 Docker 的很多问题,其中不乏一些很严重的问题:

  • 隔离性问题,docker 依赖 Linux 内核提供的隔离机制,相比虚拟机而言,级别和程度都有不少下降,这也是追求轻量带来的副作用
  • 安全性问题,跟隔离性分不开,目前 Docker 存在诸如 root 权限提升,共享宿主信息等安全漏洞,这阻碍了其推广到企业级应用的脚步
  • 性能问题,由于引入了 AUFS,提供了很好的 COW 特性,但是这也会对 I/O 性能造成一定影响,因此不建议用 docker 负担有状态的任务
  • Docker 提供用于镜像分发和重用的生态系统,全球开发者都能够通过这个平台进行交流,但随之而来的就是如何保证镜像的质量、可靠性和安全性,PS.别人做的你敢用?

尽管存在诸多问题,但是这并不妨碍 docker 前进的脚步。业界也在期盼 docker 的快速成长。

别光看,动手做吧

感谢您能够看到这里,啰嗦结束之后,我们来动手做一个简单的基于 Docker 的负载均衡器实例。

负载均衡,顾名思义就是对负载进行分流实现均衡的目的。在 web 网站以及 web service 发展的过程中,负载和处理能力的矛盾使得负载均衡成为必须考虑的问题,如下图所示:

  1. 当请求负载在单节点处理能力之下时,没有必要设置负载均衡器,所有的请求都由一台服务器搞定;
  2. 当请求达到一定数量,超过了单台服务器处理能力,那么现在就需要添加多台服务器,并且使用负载均衡器(Load Balancer)进行流量分发,保证业务请求平均地分散到各 web 服务器;
  3. 业务的流量特点很多变,流量高峰何时到来谁也不知道,如果使用多台 web 服务器在后台值班,这样难免会造成资源的浪费,并且这样也有可能无法应对流量峰值,因此需要一个自动的负载均衡器,它能够实时检测当前到来的业务流量,并且能够控制后端资源池快速完成资源的申请、释放以及路由切换,这样就可以通过实时的流量检测数据完成 web 服务器的动态配置,在后端资源池能力足够的情况下,轻松应对多变的请求量。

为了实现 3 的目标,我们的系统需要以下几大功能模块,如下图所示:

  • 负载均衡器:负责分发流量请求,并且在节点数目变化时完成路由切换。在本实例中,我选取了开源的 HAProxy 作为负载均衡器的实现,它支持多种流量分发算法,本例采用了简单的轮询(RoundRobin)模式。
  • 负载监控器:负责监控当前负载请求量,并且根据设定阈值决定下一步动作。本例中由 Python 实现,配合 Web 服务器实时上报的当前流量状况决定是否动态申请资源,实现 Scale-Out,具体代码请移步微码: https://github.com/kevinjs/docker-demo/blob/master/lb_demo/watch.py
  • 资源控制器:封装 docker 的操作 API,根据监控器的指令完成添加或删除服务节点的具体操作,本例中由 Python 实现,具体代码请移步微码: https://github.com/kevinjs/docker-demo/blob/master/lb_demo/control.py
  • Web 服务器:发挥 docker 的特点,将业务所需的 WebServer 功能组件,负载获取上报模块等打包成为镜像并注册于镜像库中,根据控制器的指令启停。

Docker 服务镜像的准备按照以下步骤进行:

  1. 安装 docker 及相关服务组件;
  2. Docker pull 拉取空白的实例;
  3. 安装所需的基础组件,部署业务代码;
  4. 将实例保存为镜像(类比 OOM 中创建了一个类);
  5. Docker push 可以将此镜像上传到公共、私有镜像库,完成分发或重用(类比将 4 中创建的类发布,供其他人继承或是实例化对象并使用)。

本例所使用的镜像已经上传至 docker 官方镜像库,可以通过以下 docker 命令下载使用:

docker pull kevinjs/ubuntu:py27tor2

运行效果

通过模拟 http 请求访问负载均衡器服务 IP,控制访问量观察后端服务节点的数目和响应情况,最后将数据可视化输出如下图所示,可以看到,随着访问量的上升,监控器准确地反馈了流量的变化,并在短时间内通知后端资源池添加服务节点,从一个服最终增加到 18 个服务节点,在每一时刻都尽量保证每个服务节点都分布到平均的负载压力,并且在负载下降后及时减少服务节点以节省资源。需要解释一下的是,从图中可以看出每隔一一定时间访问量有突降的情况,这是由于需要在自动添加服务节点后重启负载均衡器 HAProxy 造成的,这里是一个简单的实现,如果换用能够动态加载配置的负载均衡器方案,就能做到流量的平滑过渡。

下图是总的访问量与平均访问量之间的对比,在总请求量暴涨的情况下,通过快速反馈调节后端 web 服务实例的数量,平均访问量快速收敛,实现负载均衡。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java架构

微服务:Java EE的拯救者还是掘墓人?

1693
来自专栏沃趣科技

据说,数据库备份的新时代已经来了……

根据《Boston Computing Network》做过的一项调查,全球约有 34% 的公司没有检查他们的备份是否有效 77% 的公司曾发现过备份失效的问题...

4166
来自专栏小石不识月

微服务 —— 你需要付出什么?又能有何收获?

如果您阅读过我的文章 —— 微服务中的语义扩散,您可能会识得此标题。本文是那篇文章的一个延续,其目的是强调,只有当我们付出足够的努力来处理我们将要面对的组织和分...

1274
来自专栏大魏分享(微信公众号:david-share)

一份微服务学习笔记,来自一位前研发同事的分享

正文 ? ? 单体应用架构中,每个应用有多个组件模块。一个应用开发通常由一个团队完成。 微服务架构中,每个微服务可独一运行、可独立开发、微服务之间使用Restf...

3816
来自专栏张善友的专栏

MongoDB新版本特性

MongoDB 2.4已经发布,该版本增加了一些新特性,如文本搜索、基于哈希的分片、更好的地理空间功能、支持GeoJSON以及一些性能和工具方面的提升。我们还和...

1795
来自专栏韩伟的专栏

经典软件架构模式(三)

REST模式 让我们回到服务器端开发。一直以来,互联网服务就以数据互通为最重要的业务特性。我们来看看一个微博系统的案例。 ? 【此案例并非完全真实情况,有一定提...

2807
来自专栏SDNLAB

保护微服务架构的10个有效方式

微服务是一种创新的方式来加速和改进软件开发。该术语是指可以单独开发的应用程序子组件,并且通常专注于一个特定功能。例如,用于在线购物的电子商务应用需要具备订单收集...

3454
来自专栏SDNLAB

数据中心里的NFV

网络功能虚拟化(NFV)始于服务提供商试图通过专用硬件去解耦网络功能(如路由、防火墙和负载均衡)来实现IT更加简便、灵活并降低成本。随着在标准的Intel x8...

3148
来自专栏大数据

大数据和云计算技术周报:NoSQL特辑

写在第8期特辑 “大数据” 三个字其实是个marketing语言,从技术角度看,包含范围很广,计算、存储、网络都涉及。为了满足众多同学学习和工作的需要,后面社区...

1748
来自专栏SDNLAB

SDN实战团分享(三):Docker网络使用体验

我今天和大家分享一下Docker的网络,主要是基于我的使用体验和对这里面的一些技术的理解,也顺便听取一下大家的建议。我是做培训的,大多数时候和理论的东西打交道,...

3216

扫码关注云+社区