写点什么

数据中心的 Yarn on Docker 集群方案

  • 2017-03-21
  • 本文字数:4126 字

    阅读完需:约 14 分钟

当前数据中心存在的问题

数据中心中的应用一般独立部署,为了保证环境隔离与方便管理,保证应用最大资源 数据中心中普遍存在如下问题:

  1. 主机资源利用率低
  2. 部署和扩展复杂
  3. 资源隔离无法动态调整
  4. 无法快速响应业务

方案选型

Yarn on Docker 有哪些特点?

彻底隔离队列

  • 为了合理利用 Hadoop yarn 的资源,队列间会互相抢占计算资源,造成重要任务阻塞
  • 根据部门申请的机器数量划分 Yarn 集群方便财务管理
  • 更细粒度的资源分配

统一的资源分配

  • 每个 NodeManager 和容器都可以限定 CPU、内存资源

  • Yarn 资源划分精确到 CPU 核数和内存大小

弹性伸缩性服务

  • 每个容器中运行一个 NodeManager,增减 yarn 资源只需增减容器个数

  • 可以指定每个 NodeManager 拥有的计算资源多少,按需申请资源

Docker 集群管理系统:Kubernetes or Swarm?

关于容器集群管理系统的选型,用 Kubernetes 还是 Swarm?我们结合自己的经验和业务需求,对比如下:

特性

Kubernetes

Swarm

功能

功能强大

功能单一,基本够用

扩展

难以扩展,灵活性低

丰富的插件机制,兼容 docker api

文档

文档少,当时用的版本较低

docker 官方文档支持,丰富易读

使用

结构复杂,部署麻烦

简单易用

基于以上四点,我们最终选择了 Swarm,它基本满足我们的需求,掌握和开发时常较短。

解决方案的优势

选用 Yarn on Docker 的好处有以下两点:

Swarm 统一集群资源调度

  • 统一资源
  • 增加 Docker 虚拟化层,降低运维成本

增加 Hadoop 集群资源利用率

  • For datacenter:避免了静态资源隔离
  • For cluster:加强集群内部资源隔离

系统架构

比如数据中心中运行的 Hadoop 集群,我们将 HDFS 依然运行在物理机上,即 DataNode 依然部署在实体机器上,将 Yarn 计算层运行在 Docker 容器中,整个系统使用二层资源调度,Spark、Flinek、MapReduce 等应用运行在 Yarn 上。

Swarm 调度最底层的主机硬件资源,CPU 和内存封装为 Docker 容器,容器中运行 NodeManager,提供给 Yarn 集群,一个 Swarm 集群中可以运行多个 Yarn 集群,形成圈地式的 Yarn 计算集群。

具体流程

  1. swarm node 向 swarm master 注册主机资源并加入到 swarm cluster 中
  2. swarm master 向 cluster 申请资源请求启动容器
  3. swarm 根据调度策略选择在某个 node 上启动 docker container
  4. swarm node 的 docker deamon 根据容器启动参数启动相应资源大小的 NodeManager
  5. NodeManager 自动向 YARN 的 ResourceManager 注册资源一个 NodeManager 资源添加完成。

Swarm 为数据中心做容器即主机资源调度,每个 swarm node 的节点结构如图:

一个 Swarm node 就是一台物理机,每台主机上可以起多个同类型的 docker container,每个 container 的资源都有限制包括 CPU、内存 NodeManager 容器只需要考虑本身进程占用的资源和需要给主机预留资源。假如主机是 24 核 64G,我们可以分给一个容器 5 核 12G,NodeManager 占用 4 核 10G 的资源提供给 Yarn。

技术详解

(一) 镜像制作与发布

镜像制作和发布流程如下图:

用户从客户端提交代码到 Gitlab 中,需要包含 Dockerfile 文件,通过集成了 docker 插件的 Jenkins 的自动编译发布机制,自动 build 镜像后 push 到 docker 镜像仓库中,同一个项目每提交一次代码都会重新 build 一次镜像,生成不同的 tag 来标识镜像,Swarm 集群使用该镜像仓库就可以直接拉取镜像。

Dockerfile 的编写技巧

Dockerfile 相当于 docker 镜像的编译打包流程说明,其中也不乏一些技巧。

很多应用需要配置文件,如果想为每次启动容器的时候使用不同的配置参数,可以通过传递环境变量的方式来修改配置文件,前提是需要写一个 bash 脚本,脚本中来处理配置文件,再将这个脚本作为 entrypoint 入口,每当容器启动时就会执行这个脚本从而替换配置文件中的参数,也可以通过 CMD 传递参数给该脚本。

启动容器的时候通过传递环境变量的方式修改配置文件:

复制代码
docker run -d
--net=mynet
-e NAMESERVICE=nameservice
-e ACTIVE_NAMENODE_ID=namenode29 \
-e STANDBY_NAMENODE_ID=namenode63 \
-e HA_ZOOKEEPER_QUORUM=zk1:2181,zk2:2181,zk3:2181 \
-e YARN_ZK_DIR=rmstore \
-e YARN_CLUSTER_ID=yarnRM \
-e YARN_RM1_IP=rm1 \
-e YARN_RM2_IP=rm2 \
-e CPU_CORE_NUM=5
-e NODEMANAGER_MEMORY_MB=12288 \
-e YARN_JOBHISTORY_IP=jobhistory \
-e ACTIVE_NAMENODE_IP=active-namenode \
-e STANDBY_NAMENODE_IP=standby-namenode \
-e HA=yes \
docker-registry/library/hadoop-yarn:v0.1 resourcemanager

最后传递 resourcemanager 或者 nodemanager 参数指定启动相应的服务。

(二) 集群管理

我们自行开发程序调用 docker 的 API 来管理集群,也可以通过其他开源可视化页面来管理集群,比如 shipyard。

(三)自定义网络

Docker 容器跨主机互访一直是一个问题,Docker 官方为了避免网络上带来的诸多麻烦,故将跨主机网络开了比较大的口子,而由用户自己去实现。我们开发并开源了 Shrike 这个 docker 网络插件,大家可以在这里下载到: https://github.com/talkingdata/shrike

目前 Docker 跨主机的网络实现方案也有很多种, 主要包括端口映射,ovs, fannel 等。但是这些方案都无法满足我们的需求,端口映射服务内的内网 IP 会映射成外网的 IP,这样会给开发带来困惑,因为他们往往在跨网络交互时是不需要内网 IP 的,而 ovs 与 fannel 则是在基础网络协议上又包装了一层自定义协议,这样当网络流量大时,却又无端的增加了网络负载,最后我们采取了自主研发扁平化网络插件,也就是说让所有的容器统统在大二层上互通。架构如下:

我们首先需要创建一个 br0 自定义网桥,这个网桥并不是通过系统命令手动建立的原始 Linux 网桥,而是通过 Docker 的 cerate network 命令来建立的自定义网桥,这样避免了一个很重要的问题就是我们可以通过设置 DefaultGatewayIPv4 参数来设置容器的默认路由,这个解决了原始 Linux 自建网桥不能解决的问题. 用 Docker 创建网络时我们可以通过设置 subnet 参数来设置子网 IP 范围,默认我们可以把整个网段给这个子网,后面可以用 ipam driver(地址管理插件)来进行控制。还有一个参数 gateway 是用来设置 br0 自定义网桥地址的,其实也就是你这台宿主机的地址。

复制代码
docker network create
--opt=com.docker.network.bridge.enable_icc=true
--opt=com.docker.network.bridge.enable_ip_masquerade=false
--opt=com.docker.network.bridge.host_binding_ipv4=0.0.0.0
--opt=com.docker.network.bridge.name=br0
--opt=com.docker.network.driver.mtu=1500
--ipam-driver=talkingdata
--subnet= 容器 IP 的子网范围
--gateway=br0 网桥使用的 IP, 也就是宿主机的地址
--aux-address=DefaultGatewayIPv4= 容器使用的网关地址
mynet

IPAM 驱动是专门管理 Docker 容器 IP 的, Docker 每次启停与删除容器都会调用这个驱动提供的 IP 管理接口,然后 IP 接口会对存储 IP 地址的 Etcd 有一个增删改查的操作。此插件运行时会起一个 Unix Socket, 然后会在 docker/run/plugins 目录下生成一个.sock 文件,Docker daemon 之后会和这个 sock 文件进行沟通去调用我们之前实现好的几个接口进行 IP 管理,以此来达到 IP 管理的目的,防止 IP 冲突。

通过 Docker 命令去创建一个自定义的网络起名为“mynet”,同时会产生一个网桥 br0,之后通过更改网络配置文件(在 /etc/sysconfig/network-scripts/ 下 ifcfg-br0、ifcfg- 默认网络接口名)将默认网络接口桥接到 br0 上,重启网络后,桥接网络就会生效。Docker 默认在每次启动容器时都会将容器内的默认网卡桥接到 br0 上,而且宿主机的物理网卡也同样桥接到了 br0 上了。其实桥接的原理就好像是一台交换机,Docker 容器和宿主机物理网络接口都是服务器,通过 veth pair 这个网络设备像一根网线插到交换机上。至此,所有的容器网络已经在同一个网络上可以通信了,每一个 Docker 容器就好比是一台独立的虚拟机,拥有和宿主机同一网段的 IP,可以实现跨主机访问了。

(四)集群监控

如果使用 shipyard 管理集群会有一个单独的监控页面,可以看到一定时间段内的 CPU、内存、IO、网络使用状况。

我们自己开发了基于大数据的监控系统 Owl 也即将支持 docker 容器的监控。 https://github.com/TalkingData/OWL-v3

性能瓶颈与优化

大家可能会担心自定义网络的性能问题,为此我们用 iperf 进行了网络性能测试。我们对比了不同主机容器间的网速,同一主机上的不同容器和不同主机间的网速,结果如下表:

从表中我们可以看到,在这一组测试中,容器间的网速与容器是在想通主机还是在不同主机上的差别不大,说明我们的网络插件性能还是很优异的。

Hadoop 配置优化

因为使用 docker 将原来一台机器一个 nodemanager 给细化为了多个,会造成 nodemanager 个数的成倍增加,因此 hadoop 的一些配置需要相应优化。

  • yarn.nodemanager.localizer.fetch.thread-count 随着容器数量增加,需要相应调整该参数
  • yarn.resourcemanager.amliveliness-monitor.interval-ms 默认 1 秒,改为 10 秒,否则时间太短可能导致有些节点无法注册
  • yarn.resourcemanager.resource-tracker.client.thread-count 默认 50,改为 100,随着容器数量增加,需要相应调整该参数
  • yarn.nodemanager.pmem-check-enabled 默认 true,改为 false,不检查任务正在使用的物理内存量
  • 容器中 hadoop ulimit 值修改,默认 4096,改成 655350

关于未来

我们未来规划做的是 DC/OS,基于 Docker 的应用自动打包编译分发系统,让开发人员可以很便捷的申请资源,上下线服务,管理应用。要达到这个目标还有很多事情要做:

  • Service Control Panel:统一的根据服务来管理的 web 页面
  • Load balance:容器根据机器负载情况自动迁移
  • Scheduler:swarm 调度策略优化
  • 服务配置文件:提供镜像启动参数的配置文件,所有启动参数可通过文件配置
  • 监控:服务级别的监控

(点击放大图像)

作者简介

宋净超,TalkingData 大数据及云计算工程师。拥有多年的 Hadoop 大数据集群部署、管理、优化和实战经验,对 Hadoop 和 Docker 的结合落地进行了丰富的探索,主导了 TalkingData 的 Yarn on Docker 的改造和微服务落地,关注大数据开源软件及微服务的前沿发展。


感谢木环对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-03-21 17:314547

评论

发布
暂无评论
发现更多内容

一个例子形象地理解同步与异步

EquatorCoco

Java 前端 异步 同步

一种快速开发适配鸿蒙的App思路:基于小程序技术

FinFish

鸿蒙操作系统 小程序容器 小程序技术 鸿蒙Next 鸿蒙5.0

C# Break 和 Continue 语句以及数组详解

小万哥

C# 程序人生 编程语言 软件工程 后端开发

外贸独立站如何SEO优化推广?

九凌网络

高效工作必备神器:这款在线软件能完美替代Visio!

彭宏豪95

在线白板 办公软件 绘图工具 效率软件 Visio

定向减免!函数计算让 ETL 数据加工更简单

Serverless Devs

容器 云原生 中间件 函数计算 函数计算FC

秒级弹性!探索弹性调度与虚拟节点如何迅速响应瞬时算力需求?

阿里巴巴云原生

阿里云 云原生 弹性调度

小红书多模态团队建立新「扩散模型」:解码脑电波,高清还原人眼所见

小红书技术REDtech

CV 计算机视觉 脑机接口 扩散模型 AAAI

电商平台接口自动化测试框架设计与实现

技术冰糖葫芦

API

2023 IoTDB Summit:中核武汉核电运行技术股份有限公司主管工程师方华建《IoTDB 在核电数字化转型过程中的应用实践》

Apache IoTDB

《凤凰架构:构建可靠的大型分布式系统》PDF

程序员李木子

百万并发!API 网关抗住了亚运会流量高峰

阿里巴巴云原生

阿里云 云原生

惊为天人!这个保存推特视频到手机相册的办法真的一绝!

frank

twitter

如果查看iPhone的GPU

雪奈椰子

一文搞清楚Java中的包、类、接口

不在线第一只蜗牛

Java 前端 开发

i人事2023:在不确定性的年份做正确的事情

ToB行业头条

百度智能云千帆AppBuilder新手指南

AI大咚咚

AI API LLM AI原生应用

左耳听风 - 分布式架构「读书打卡 day 14」

Java 工程师蔡姬

读书笔记 程序员 个人成长 分布式 职业发展

听GPT 讲Rust源代码--compiler(28)

fliter

动态规划-序列比对-最长公共子序列

alexgaoyh

Java 编辑距离 最长公共子序列 Smith-Waterman 序列对比

写作,写作,先写后作

zhumingwu

阿里云 SAE 2.0 正式商用丨云原生 2023 年 12 月产品技术动态

阿里巴巴云原生

阿里云 云原生

SpringBoot3集成Zookeeper

Java 架构 SpringBoot3 Zookeeper3.8 Curator5.5

聚道云连接器:实现航信费控与用友NCC对接,助力某商贸集团业务升级

聚道云软件连接器

案例分享

实现定时任务的六种策略

不在线第一只蜗牛

前端 定时任务 开发

杭绍甬高速杭绍段等浙3条高速通车,三思再树标杆工程。

电子信息发烧客

二、nextjs API路由如何做好JWT登录鉴权、身份鉴权,joi字段校验,全局处理异常等(c-shopping电商开源)

Geek_9da61c

开源 JWT next.js joi

元宇宙技术对于虚拟仿真应用的一些帮助

3DCAT实时渲染

虚拟仿真 元宇宙 元宇宙解决方案

基于 pytorch-openpose 实现 “多目标” 人体姿态估计

北桥苏

Python OpenCV PyTorch MediaPipe Pytorch-OpenPose

《Java核心编程》PDF

程序员李木子

钉钉飞书的AI大战,一场繁花还是一地鸡毛?

脑极体

AI

数据中心的Yarn on Docker集群方案_语言 & 开发_宋净超_InfoQ精选文章