大数据组件包括Hadoop(HDFS、YARN)、Hbase、Spark等等。优劣势是什么?生产环境下会存在哪些问题或隐患?什么类型的场景适合使用这种方式?什么类型的公司适合使用这种架构?


Kubernetes Docker 你会遇到什么问题

netkiller:Kubernetes Docker 你会遇到什么问题?

zhuanlan.zhihu.com图标

在项目中实施容器技术,你可以遇到下列问题

镜像遇到的问题

目前docker 镜像,没有统一标准,体现在一下几个方面。

使用OS发行版不统一

在使用过程中会遇到过各种本班的 OS。包括 alpine, debian, ubuntu, centos, oraclelinux, redhat 等等……

经过裁剪的 OS 面目全非,不完整

即使是镜像采用 CentOS 母版,很多镜像制作者会给操作系统减肥。经过优化后,已经不是官方版本,在使用过程中你会遇到各种麻烦。例如调试的时候需要 curl,wget,telnet,nslookup 等工具在镜像中没有。甚至 ps, top, free, find, netstat, ifconfig 命令都没有。

很多容器都不带 iptables 所以,即使带有iptables 在容器中修改规则也很麻烦。

安装位置不统一

传统OS 以 CentOS为例,有严格的安装规范,例如:

通常安装位置是:

/etc/example 配置文件

/bin/sbin 二进位文件

/var/lib/example 数据文件

/var/log/example 日志文件

/var/run/example PID 文件

/etc/sysconfig/example 启动参数文件

/etc/system.d/example 启动脚本

或者被安装在:

/usr/local/etc 配置文件

/usr/local/bin 可执行文件

/usr/local/share 文档

最后一种是独立安装在:

/usr/local/example 下

容器镜像那可是五花八门,没有统一标准,如果不看 Dockerfile 根本不知道作者将文件安装到了哪里。

常常存储目录被放置在根目录。例如 /data

Linux 系统也存在BUG

在我的20年执业生涯中是遇到过 Linux 系统有BUG的,还向 Redhat 提交过 BUG。如果你采用的镜像有BUG,你想过怎么去debug 吗?

容器遇到的问题

程序启动的区别

在Linux是一般是采用守护进程方式启动。启动后进入后台,启动采用 systemd 。

容器中启动通常是直接运行,这样的运行方式,相当于你在linux的Shell 终端直接运行一样,是在前台运行,随时 CTRL + C 或者关闭终端窗口,程序就会退出。容器采用这种方式启动,就是为了让 docker 管理容器,docker 能够感知到容器的当前状态,如果程序退出,docker 将会重新启动这个容器。

守护进程方式需要记录 pid 即父进程ID,用于后面管理该进程,例如可以实现 HUP 信号处理。也就是 reload 操作,不用退出当前程序实现配置文件刷新。处理 HUP 信号,无需关闭 Socker 埠,也不会关闭线程或进程,用户体验更好。

容器是直接运行(前台运行),所以没有 PID 也不能实现 reload 操作。 配置文件更新需要重新启动容器,容器启动瞬间TCP Socker 埠关闭,此时用户会 timeout。甚至该服务可能会引起集群系统的雪崩效应。

很多镜像制作者更趋向使用环境变数传递启动参数。

当然你也可以在容器中使用 systemd ,这样做容器不能直接感知到容器的运行状态,systemctl stop example 后,容器仍然正常。需要做存活和健康检查。通过健康状态判断容器的工作情况。如果处于非健康状态,将该节点从负载均衡节点池中将它踢出去。

Linux 启动一个应用远远比docker 启动一个容器速度要快。因为物理机或者虚拟机的Linux操作系统已经启动,虚拟机也分配了资源,运行可执行文件基本上是瞬间启动。而 docker 启动容器,要分配资源(分配内存和CPU资源,新建文件系统),相当于创建一个虚拟机的过程,最后载入约200MB左右的镜像,并将镜像运行起来,所以启动所需时间较长,有时不可控,尤其是Java应用更为突出。

存储面临的问题

传统 Linux 直接操作本地硬碟,IO性能最大化。

私有云还好办公有云处处受限。

自建的 Docker 或 Kubrnetes 可以使用宿主主机资源,公有云只能使用网路文件系统和分散式系统。

这也是我的架构中 KVM,Docker,Kubernetes,物理机混合使用的原因,根据业务场景的需要来选择哪种方案。

物理机上部署 docker 可以分配宿主主机的所有资源,适合做有状态的服务的存储持久化的需求。

私有云 Kubernetes 适合做 CPU密集型运算服务,虽然通过local 卷和 hostPath 可以绑定,但是管理起来不如 Docker 更方便。

NFS 基本是做实验用的,不能用在生产环境。我20年的职业生涯遇到过很多奇葩,例如 NFS 卡顿,NFS 用一段时间后访问不了,或者可以访问,文件内容是旧的等等。

无论是NFS是更先进的分散式文件系统,如果不是 10G乙太网,基本都不能用在生产环境。10年前我用4电口1G网卡做埠聚合勉强可以用于生产环境,不过10年前的互联网生态跟当今不同,那时还是以图文为主,确切的说是文字为主,配图还很少。

所以涉及到存储使用分散式文件系统的前提是必须是 10G以上乙太网或者8G以上的FC 存储。这样才不会有IO瓶颈。任何分散式文件系统都不可能比本地文件系统稳定,除了速度还有延迟等等。

10GB 电口,光口乙太网已经出来十几年了,相对比较便宜,可以使用 4光口 10G网卡,然后做埠聚合,变成 40G 网口。

现在 40G光口交换机都在10-20万之间。一个40G的交换口可以分出四个10GB口。

如果使用40GB以上的乙太网,那么总成本可能会超过物理机+虚拟机的解决方案。

内部域名DNS

由于在集群环境中容器名称是随机,IP地址是不固定的,甚至埠也是动态的。为了定位到容器的节点,通常集群中带有DNS功能,为每个节点分配一个域名,在其他容器中使用域名即可访问到需要的容器。

看似没有问题,我的职业生涯中就遇到过DNS的问题,bind,dnsmseq 我都用过,都出现过事故。解析卡顿,ping www.domain.com 后迟迟解析不出IP。最长一次用了几分钟才解析到IP地址。

所以后面就非常谨慎,配置文件中我们仍然使用域名,因为修改配置文件可能需要 reload 应用,或者重新部署等等。域名写入配置,方便IP地址变更。例如 db.host=db.netkiller.cn 同时我们会在 /etc/hosts 中增加 xxx.xxx.xxx.xxx db.netkiller.cn 。这样主要使用 /etc/hosts 做解析,一旦漏掉 /etc/hosts 配置 DNS 还能工作。

故障分析,DNS 使用 UDP 协议 53 埠,UDP 在网路中传输不会返回状态,有无数种可能导致 DNS 解析失败。例如内部的交换机繁忙,背板带宽不够(用户存储转发数据包,你可以理解就是交换机的内存),路由的问题等等……

容器与网路

相比传统网路,容器中的网路环境是十分复杂的。传统网路中一个数据包仅仅经过路由器,交换机,达到伺服器,最多在服务前在增加一些防火墙,负载均衡等设备。

容器网路部分实现方式SDN(软体定义网路)相比物理机(路由器、交换机、无服务)实现相对复杂。容器里面使用了IP转发,埠转发,软路由,lvs,7层负载均衡等等技术…… 调试起来非常复杂。docker 的 iptables 规则很头痛。

例如一个TCP/IP 请求,需要经过多层虚拟网路设备(docker0,bridge0,tun0……)层层转发,再经过4层和7层的各种应用拆包,封包,最终到达容器内部。

有兴趣你可以测试一下对比硬体设备,容器的网路延迟和吞吐量。

容器的管理

传统服务可以通过键盘和显示器本地管理,OpenSSH 远程管理,通过配置还能使用串口。

容器的管理让你抓狂 docker exec 和 kubectl exec 进入后与传统Linux差异非常大,这是镜像制作者造成了。

有些镜像没有初始化 shell 只有一个 $ 符号

没有彩色显示

可能不支持 UTF-8,中文乱码

可能不是标准 ANSI/XTerm 终端

键盘定义五花八门,可能不是美式104键盘

国家和时区并不是东八区,上海

HOME 目录也是不是 /root

想查看埠情况,发现 netstat 和 ss 命令没有。

想查看IP地址,发现 ifconfig, ip 命令没有。

想测试IP地址是否畅通,发现 ping, traceroute 没有。

想测试URL,发现 curl , wget 没有。

有些镜像 dnf,yum,apk,apt 可以使用,有些镜像把包管理也给阉割了,你想安装上述工具都安装不了。

卧槽!!! 一万匹草泥马

然后就自己用 Dockerfile 编译,整出200MB的镜像,卧槽这么大。

容器与安全

很多容器的镜像中是不包含 iptables 的,所以无法做颗粒度很细的容器内部网路安全设置。即使你制作的镜像带有iptables ,多数容器的侧咯,IP地址和埠是随机变化的。

绑定IP地址又带了容器的复杂性。

一旦攻入一个容器,进入容器后,容器与容器间基本是畅通无阻。

在容器中藏一个后门比物理机更容易,如上文所说很多容器中没有调试相关命令,限制了你排查后门的难度。所以Dockerfile 制作镜像,最好使用官方镜像衍生出你的镜像。

容器与监控

谈到监控,跳不开 prometheus(普罗米修斯),它并不能覆盖到所有监控。

我曾经写过一篇文章《监控的艺术》网上可以搜到。

容器与CI/CD

在DevOps场景中,使用 docker 或 kubernetes 做 CI/CD 是很扯淡的。

当 git 产生提交后,gitlab/jenkins 启动容器,下载代码,编译,打包,测试,产生构建物,编译 Dockerfile ,上传 docker 镜像到 registry,最后部署到容器执行。

卧槽!!!速度能急死你。

于是乎,我们做了 Cache。 不用每次都 pull 镜像,缓存 Maven 的 .m2 库,不再清理代码(mvn clean)提速不少,测试环境凑合用吧。 注意不mvn clean 有时会编译出错

至于生产环境,我就不说了,有多少人真用CD部署生产环境。

人员的问题

现实中真正精通容器应用的人很少,容器实在太复杂。Google 将 Kubernetes 设计成大而全系统,想用 Kubernetes 解决所有问题。它涵盖了几大块。

操作系统,虚拟化,软体定义网路,存储,容器管理,用户体系,许可权体系……

我们的大学教育是本科教育专科化,本科教育本应该重视通识教育,我们的教育却按照专科标准教育。本科是面向学术的起点,专科是面向工作,解决实际问题。

你问一个中国大学生他会什么,他会说:我会Java,我会Linux……

反应到工作上,就是程序猿不懂运维知识,运维攻城狮不会写程序。员工更趋向深耕一个领域,很类似现在的医生教育和医院体系,专科化,割裂化,导致很多跨科的疾病难以诊断。

于是我提出了「多维度架构」。

最后总结

使用物理机,虚拟机,学习成本,试错成本,部署成本远远低于容器技术。

Google 官方也曾经说过,未来 kubernetes 重点可能会转向虚拟机。

我个人认为容器更适合CPU密集型的业务。

我的架构中 KVM,Docker,Kubernetes,物理机混合使用,根据业务场景的需要来选择最佳方案。

前期制作符合你需求的镜像,可能需要花费很长时间。

netkiller:Kubernetes(minikube) 私有 registry 使用详解?

zhuanlan.zhihu.com图标netkiller:Kubernetes Registry?

zhuanlan.zhihu.com图标

分享一下大猪厂基于 Kubernetes 和 Docker 构建构建猛犸大数据平台机器学习模块(内部代号Dolphin )的一些思考。

Dolphin 基础设施中包括了 GPU 和 CPU 的混合计算服务节点,通过 Docker 对多种机器学习框架、用户开发环境进行实例化和运行,通过 Kubernetes 提供计算集群的部署、维护、 扩展机制等功能,计算框架主要是 Tensorflow。

Why Tensorflow on Kubernetes?

如果让数据科学家直接使用 Tensorflow,他们会遇到例如租户隔离、资源隔离、网路隔离、难以指定 GPU 进行任务调度等等一系列软体工程问题。

  1. 资源隔离:Tensorflow 资源无法隔离
    ,Kubernetes 提供租户隔离,容器资源隔离和网路隔离等多种机制
  2. GPU 调度:Tensorflow 缺乏 GPU 资源的调度
    ,Kubernetes 1.4 开始支持 GPU 调度
  3. 进程管理:Tensorflow 存在进程遗留问题、无法区分正常完成还是故障退出
    ,Kubernetes 提供容器生命周期管理,进程和容器共生死
  4. 伺服器定位
    :Kubernetes 提供 DNS 伺服器提供伺服器位置,省去了 Tensorflow 的计算集群的服务节点 IP 地址配置
  5. 监控:Tensorflow 不方便日志查看
    ,Kubernetes 提供了较为完善的 Monitoring 和 Logging 功能
  6. 存储:Tensorflow 存在训练数据和模型存储问题
    ,Kubernetes 支持对接 Cephfs,GlusterFS 等 Read 性能更好的分散式存储系统
  7. 多框架支持
    :通过定制化开发 Kubernetes 的 Custom Resource 和 Operator 介面支持 MXNet 等其他机器学习框架

当然,基于当时两个项目在任务管理方面的实际进展,团队也做了相应的优化:

  • 开发了基于队列的任务调度系统,解决了 Kubernetes 没有队列服务的问题
  • 开发了计算节点的 GPU 监控服务,解决了 Kubernetes 目前无法监控 GPU 的资源使用情况的问题
  • 开发了 Kubernetes 中训练服务的参数服务的生命周期管理模块,解决了 Tensorflow 的参数服务在训练完毕无法自我关闭的问题

最后,Dolphin 可以根据数据科学家选用的不同的机器学习演算法框架,通过 Kubernetes 编排出相应的机器学习计算集群。

如下图所示,通过 Dolphin 调度起来的 Tensorflow 计算集群,创建出 Parameter Server 和 Work 的 POD 以及 SVC,通过 HDFS Mount 模块将用户数据空间映射到 Docker Container 中,执行用户的演算法脚本进行模型训练和服务发布。

by 刘勋,网易大数据团队攻城狮


这个问题我们团队是做过一些相关实践的,当初希望使用K8s治理和编排Docker容器,然后实现spark等大数据组件的一个容器化管理。先说下产生这个想法的背景和遇到的坑:

1,背景:多版本计算资源,再明确一点来说就是,我们存在著一个场景,很多用户有自己的spark任务,但是他们的spark的版本都不同,但是想在我们的集群上跑。

2,解决方案1:客户自己去改代码,支持我们的版本(不现实,他们才懒得改);解决方案2:利用yarn的支持,安装几个版本的spark依赖,此方案可行,但是你会发现一个问题,基本上只能兼容spark1和spark2两个大版本,小版本不行;解决方案3:容器化spark计算节点,然后封装各个版本的spark镜像。

3,最后我们选了方案3,其实也是想试试这种方案是否可行,然后遇到了一些坑,也和你的提问有关系。

第一个坑,存储资源不要用容器化去封装,hdfs的DataNode节点要是容器化了,你会发现非常难处理,绑定本底卷?不行,万一一台机器上的DataNode挂了在另一个机器上重启了,如何继续保持对应关系,而且资源不好隔离,监控上每个进程看到的存储基本都是物理机真实存储大小,导致了资源统计翻倍。

第二个坑,我们当时使用的是Rancher可视化k8s的编排工作,但是默认情况下,所有容器间的数据传输是加密的,导致了计算速度减慢了75%,后来发现了这个原因进行了无加密传输。

第三个坑,社区版的spark镜像bug很多,现在可能好很多了,计算节点之间要维护状态,当容器毁掉了一个,重新初始化的时候如何能够正常工作,其实需要考虑很多细节。

说了这么多来回答你的问题

优势:灵活,兼容多版本,计算资源可以随时销毁和建立,而且有个可视化的工具,看起来更直观

劣势:大数据和容器在一起真的会打架,容器对大数据不友好,慢又不稳定。所说的不稳定基本都是一些镜像上的bug和考虑不全面的地方。

隐患:当你有紧急任务的时候,万一报错了,不知道错误原因,可能是镜像本身的问题,那么修复起来很难。

适合场景:偏研究的环境,存储类的资源全部物理机实体化,上层只封装计算资源,基本上我觉得线上的环境最好不要用这种方式,一些线下计算的场景可以使用。


以往跑在 Kubernetes 上的大多数都是一些在线服务类型的应用,很容易发现,对于在线服务,很多是有流量的峰谷的,白天请求多,晚上请求少,应用如果是在物理机或者虚拟机,怎么把空闲的 CPU/Memory/Network 利用起来呢?挺难搞的反正,一般应用或者一些 crontab 任务跑不满 cpu,而且由于资源隔离的问题,谁敢在一个重要的在线服务的机器上乱搞事情呢,把机器搞挂了,你也得挂了。

Kubernetes 上就简单多了,在离线混合部署,共用一套集群,Spark on Kubernetes 就是把原来 on Yarn 的那一套 Cluster Manager 换掉,Spark 2.3 开始已经官方开始搞了,更不说现在一堆的大数据相关的 Operator 了,敢搞的 xxx on Kubernetes 基本问题不大的。在某些方面,优势还是很明显的,以前运维搞一套环境,这个库不合适那个库不兼容,虚拟机下搞得头都大,现在打一个镜像就 ojbk 想要什么依赖什么库自己搞就得了,省了很多跟运维打交道的时间,这不就非常大的优势吗。还没想到有什么劣势,可能学习成本是一个,至少你得看一眼 Docker。


(`?ω?′)

运行在docker里worker环境统一 少很多傻逼问题

我们有hive语句utc timestamp不同机器出来时间不一致的问题 刚好八个小时

细想肯定是装机时有些机器设locale有些机器改了时间 吃到屎 没法查 那么多机器怎么查

还有op下环境没下光导致集群任务分到这台机器就花式失败

docker内一把梭就没有这些问题 要死都是一起死的

不过hadoop fs本身是个有状态的东西 还有一些支持的问题就不说了


k8s目前有两个难解决的点:

1.有状态服务不好做 (能做,但在国内落地的少)2.docker对性能或多或少有些损耗

hdfs、hbase这种存储系统,甚至消息队列kafka,都是有状态的。决定了他们上k8s很难。

hbase、kafka甚至mysql此类系统,又常用于生产系统,对SLA,latency要求越快越好,因此直接用物理机符合让业务更快这个终极目标。

如果在「对SLA」要求不高的场景,把hbase、kafka、mysql上k8s也未尝不可。国内也有些公司这么做了。

另外计算类框架,基本都是无状态居多。spark/flink目前都出了run on k8s的版本。

就说这么多把。


性能会有一定的影响,但是打通了开发,测试和运维的壁垒,极大的提升了工作效率。

典型的DevOps思想到实践的落地。

降低了低端运维的人数,提高了高端运维的人数,运维人员定位问题,又多了一层。


有哪些公司开始用了?感觉用了性能,运维都是问题


说个让人讨厌的答案,黑猫白猫,能抓住老鼠的就是好猫。其实这些大数据组件,可以用于数据处理和应用,也可以用户纯粹的后端应用场景,我自荐自己的专栏,让数据能赚钱,从头开始讲数据和技术是怎么产生价值的。

对于如何评价让大数据组件运行在Kubernetes、Docker,其实就是自行车骑得熟练了,发现不扶车把骑车会更轻松一点,比弯著腰强。


推荐阅读:
相关文章