TalkingData的Spark On Kubernetes实践

众所周知,Spark是一个快速、通用的大规模数据处理平台,和Hadoop的MapReduce计算框架类似。但是相对于MapReduce,Spark凭借其可伸缩、基于内存计算等特点,以及可以直接读写Hadoop上任何格式数据的优势,使批处理更加高效,并有更低的延迟。实际上,Spark已经成为轻量级大数据快速处理的统一平台。
Spark作为一个数据计算平台和框架,更多的是关注Spark Application的管理,而底层实际的资源调度和管理更多的是依靠外部平台的支持:

Spark官方支持四种Cluster Manager:Spark standalone cluster manager、Mesos、YARN和Kubernetes。由于我们TalkingData是使用Kubernetes作为资源的调度和管理平台,所以Spark On Kubernetes对于我们是最好的解决方案。

如何搭建生产可用的Kubernetes集群

部署

目前市面上有很多搭建Kubernetes的方法,比如Scratch、Kubeadm、Minikube或者各种托管方案。因为我们需要简单快速地搭建功能验证集群,所以选择了Kubeadm作为集群的部署工具。部署步骤很简单,在master上执行:

kubeadm init

在node上执行:

kubeadm join --token  : --discovery-token-ca-cert-hash sha256:

具体配置可见官方文档:https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/。
需要注意的是由于国内网络限制,很多镜像无法从k8s.gcr.io获取,我们需要将之替换为第三方提供的镜像,比如:https://hub.docker.com/u/mirrorgooglecontainers/。

网络

Kubernetes网络默认是通过CNI实现,主流的CNI plugin有:Linux Bridge、MACVLAN、Flannel、Calico、Kube-router、Weave Net等。Flannel主要是使用VXLAN tunnel来解决pod间的网络通信,Calico和Kube-router则是使用BGP。由于软VXLAN对宿主机的性能和网络有不小的损耗,BGP则对硬件交换机有一定的要求,且我们的基础网络是VXLAN实现的大二层,所以我们最终选择了MACVLAN。
CNI MACVLAN的配置示例如下:

{"name": "mynet","type": "macvlan","master": "eth0","ipam": {"type": "host-local","subnet": "10.0.0.0/17","rangeStart": "10.0.64.1","rangeEnd": "10.0.64.126","gateway": "10.0.127.254","routes": [{"dst": "0.0.0.0/0"},{"dst": "10.0.80.0/24","gw": "10.0.0.61"}]}
}

Pod subnet是10.0.0.0/17,实际pod ip pool是10.0.64.0/20。cluster cidr是10.0.80.0/24。我们使用的IPAM是host-local,规则是在每个Kubernetes node上建立/25的子网,可以提供126个IP。我们还配置了一条到cluster cidr的静态路由10.0.80.0/24,网关是宿主机。这是因为容器在macvlan配置下egress并不会通过宿主机的iptables,这点和Linux Bridge有较大区别。在Linux Bridge模式下,只要指定内核参数net.bridge.bridge-nf-call-iptables = 1,所有进入bridge的流量都会通过宿主机的iptables。经过分析kube-proxy,我们发现可以使用KUBE-FORWARD这个chain来进行pod到service的网络转发:

-A FORWARD -m comment --comment "kubernetes forward rules" -j KUBE-FORWARD
-A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
-A KUBE-FORWARD -s 10.0.0.0/17 -m comment --comment "kubernetes forwarding conntrack pod source rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A KUBE-FORWARD -d 10.0.0.0/17 -m comment --comment "kubernetes forwarding conntrack pod destination rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

最后通过KUBE-SERVICES使用DNAT到后端的pod。pod访问其他网段的话,就通过物理网关10.0.127.254。
还有一个需要注意的地方是出于kernel security的考虑,link物理接口的macvlan是无法直接和物理接口通信的,这就导致容器并不能将宿主机作为网关。我们采用了一个小技巧,避开了这个限制。我们从物理接口又创建了一个macvlan,将物理IP移到了这个接口上,物理接口只作为网络入口:

$ cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
IPV6INIT=no
BOOTPROTO=none
$ cat /etc/sysconfig/network-scripts/ifcfg-macvlan
DEVICE=macvlan
NAME=macvlan
BOOTPROTO=none
ONBOOT=yes
TYPE=macvlan
DEVICETYPE=macvlan
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPADDR=10.0.0.61
PREFIX=17
GATEWAY=10.0.127.254
MACVLAN_PARENT=eth0
MACVLAN_MODE=bridge

这样两个macvlan是可以互相通信的。

Kube-dns

默认配置下,Kubernetes使用kube-dns进行DNS解析和服务发现。但在实际使用时,我们发现在pod上通过service domain访问service总是有5秒的延迟。使用tcpdump抓包,发现延迟出现在DNS AAAA。进一步排查,发现问题是由于netfilter在conntrack和SNAT时的Race Condition导致。简言之,DNS A和AAAA记录请求报文是并行发出的,这会导致netfilter在_nf_conntrack_confirm时认为第二个包是重复的(因为有相同的五元组),从而丢包。具体可看我提的issue:https://github.com/kubernetes/kubernetes/issues/62628。一个简单的解决方案是在/etc/resolv.conf中增加options single-request-reopen,使DNS A和AAAA记录请求报文使用不同的源端口。我提的PR在:https://github.com/kubernetes/kubernetes/issues/62628,大家可以参考。我们的解决方法是不使用Kubernetes service,设置hostNetwork=true使用宿主机网络提供DNS服务。因为我们的基础网络是大二层,所以pod和node可以直接通信,这就避免了conntrack和SNAT。

Spark与Kubernetes集成

由于Spark的抽象设计,我们可以使用第三方资源管理平台调度和管理Spark作业,比如Yarn、Mesos和Kubernetes。目前官方有一个experimental项目,可以将Spark运行在Kubernetes之上:https://spark.apache.org/docs/latest/running-on-kubernetes.html。

基本原理

当我们通过spark-submit将Spark作业提交到Kubernetes集群时,会执行以下流程:

  • Spark在Kubernetes pod中创建Spark driver
  • Driver调用Kubernetes API创建executor pods,executor pods执行作业代码
  • 计算作业结束,executor pods回收并清理
  • driver pod处于completed状态,保留日志,直到Kubernetes GC或者手动清理

先决条件

  • Spark 2.3+
  • Kubernetes 1.6+
  • 具有Kubernetes pods的list, create, edit和delete权限
  • Kubernetes集群必须正确配置Kubernetes DNS[1]

如何集成

Docker镜像

由于Spark driver和executor都运行在Kubernetes pod中,并且我们使用Docker作为container runtime enviroment,所以首先我们需要建立Spark的Docker镜像。
在Spark distribution中已包含相应脚本和Dockerfile,可以通过以下命令构建镜像:

$ ./bin/docker-image-tool.sh -r <repo> -t my-tag build
$ ./bin/docker-image-tool.sh -r <repo> -t my-tag push

提交作业

在构建Spark镜像后,我们可以通过以下命令提交作业:

$ bin/spark-submit \--master k8s://https://: \--deploy-mode cluster \--name spark-pi \--class org.apache.spark.examples.SparkPi \--jars https://path/to/dependency1.jar,https://path/to/dependency2.jar--files hdfs://host:port/path/to/file1,hdfs://host:port/path/to/file2--conf spark.executor.instances=5 \--conf spark.kubernetes.container.image= \https://path/to/examples.jar

其中,Spark master是Kubernetes api server的地址,可以通过以下命令获取:

$ kubectl cluster-info
Kubernetes master is running at http://127.0.0.1:6443

Spark的作业代码和依赖,我们可以在--jars、--files和最后位置指定,协议支持http、https和HDFS。
执行提交命令后,会有以下输出:

任务结束,会输出:

访问Spark Driver UI

我们可以在本地使用kubectl port-forward访问Driver UI:

$ kubectl port-forward <driver-pod-name> 4040:4040

执行完后通过http://localhost:4040访问。

访问日志

Spark的所有日志都可以通过Kubernetes API和kubectl CLI进行访问:

$ kubectl -n=<namespace> logs -f <driver-pod-name>

如何实现租户和资源隔离

Kubernetes Namespace

在Kubernetes中,我们可以使用namespace在多用户间实现资源分配、隔离和配额。Spark On Kubernetes同样支持配置namespace创建Spark作业。
首先,创建一个Kubernetes namespace:

$ kubectl create namespace spark

由于我们的Kubernetes集群使用了RBAC,所以还需创建serviceaccount和绑定role:

$ kubectl create serviceaccount spark -n spark
$ kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=spark:spark --namespace=spark

并在spark-submit中新增以下配置:

$ bin/spark-submit \--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \--conf spark.kubernetes.namespace=spark \...

资源隔离

考虑到我们Spark作业的一些特点和计算资源隔离,前期我们还是选择了较稳妥的物理隔离方案。具体做法是为每个组提供单独的Kubernetes namespace,计算任务都在各自namespace里提交。计算资源以物理机为单位,折算成cpu和内存,纳入Kubernetes统一管理。在Kubernetes集群里,通过node label和PodNodeSelector将计算资源和namespace关联。从而实现在提交Spark作业时,计算资源总是选择namespace关联的node。
具体做法如下:
1、创建node label

$ kubectl label nodes <node_name> spark:spark

2、开启Kubernetes admission controller 
我们是使用kubeadm安装Kubernetes集群,所以修改/etc/kubernetes/manifests/kube-apiserver.yaml,在--admission-control后添加PodNodeSelector。

$ cat /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
kind: Pod
metadata:annotations:scheduler.alpha.kubernetes.io/critical-pod: ""creationTimestamp: nulllabels:component: kube-apiservertier: control-planename: kube-apiservernamespace: kube-system
spec:containers:- command:- kube-apiserver- --secure-port=6443- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt- --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,PodNodeSelector
...

3、配置PodNodeSelector
在namespace的annotations中添加scheduler.alpha.kubernetes.io/node-selector: spark=spark。

apiVersion: v1
kind: Namespace
metadata:annotations:scheduler.alpha.kubernetes.io/node-selector: spark=sparkname: spark

完成以上配置后,可以通过spark-submit测试结果:

$ spark-submit
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark 
--conf spark.kubernetes.namespace=spark 
--master k8s://https://xxxx:6443     
--deploy-mode cluster     
--name spark-pi     
--class org.apache.spark.examples.SparkPi     
--conf spark.executor.instances=5     
--conf spark.kubernetes.container.image=xxxx/library/spark:v2.3     
http://xxxx:81/spark-2.3.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.3.0.jar

我们可以看到,Spark作业全分配到了关联的hadooptest-001到003三个node上。

待解决问题

Kubernetes HA

Kubernetes的集群状态基本都保存在etcd中,所以etcd是HA的关键所在。由于我们目前还处在半生产状态,HA这方面未过多考虑。有兴趣的同学可以查看:https://kubernetes.io/docs/setup/independent/high-availability/。

日志

在Spark On Yarn下,可以开启yarn.log-aggregation-enable将日志收集聚合到HDFS中,以供查看。但是在Spark On Kubernetes中,则缺少这种日志收集机制,我们只能通过Kubernetes pod的日志输出,来查看Spark的日志:

$ kubectl -n=<namespace> logs -f <driver-pod-name>

收集和聚合日志,我们后面会和ES结合。
监控
我们TalkingData内部有自己的监控平台OWL[2](已开源),未来我们计划编写metric plugin,将Kubernetes接入OWL中。
混合部署
为了保证Spark作业时刻有可用的计算资源,我们前期采用了物理隔离的方案。显而易见,这种方式大幅降低了物理资源的使用率。下一步我们计划采用混部方案,通过以下三种方式实现:

  • 将HDFS和Kubernetes混合部署
  • 为Spark作业和Kubernetes node划分优先级,在低优先级的node上同时运行一些无状态的其他生产服务
  • 利用云实现资源水平扩展,以防止资源突增

资源扩展

在采用以下两种方法增加资源使用率时,集群可能会面临资源短缺和可用性的问题:

  • 混合部署
  • 资源超卖

这会导致运行资源大于实际物理资源的情况(我称之为资源挤兑)。一种做法是给资源划分等级,优先保证部分等级的资源供给。另一种做法是实现资源的水平扩展,动态补充可用资源,并在峰值过后自动释放。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE使用批量插入100万测试数据

CREATE TABLE test_data (ID varchar2(32),NAME1 varchar2(9),NAME2 varchar2(100),NAME3 varchar2(100) ); COMMENT ON TABLE test_data IS 测试表;beginfor i in 1 .. 1000000 loopINSERT INTO "DCA"."TEST_DATA" ("ID", "NAME1", &…

阿里技术男的成长史:越想证明自己死得越快……

在上海工作8年后&#xff0c;身为部门经理的钱磊&#xff0c;管理着一家ERP公司的百十来号员工&#xff0c;“再往上爬就是老板和他儿子了……从这个领域的技术角度来讲算是做到了顶。”05年&#xff0c;钱磊就开始关注一家名字奇怪&#xff0c;做事也奇怪的公司。 要不要折腾…

程序员1w5以下的,2020年就要面对现实了...

BOSS直聘最近发布&#xff0c;“互联网行业30%新增岗位&#xff0c;全都是技术岗&#xff01;各公司开启了新一轮抢人计划”。大家在这个春招一定有很多目标&#xff0c;找到理想工作&#xff0c;换个大房子住&#xff0c;给爸妈多寄点钱&#xff0c;给女朋友换个新手机……CSD…

对话亲历者|鲁肃:我在支付宝“拧螺丝“的日子

对话亲历者&#xff1a;他是支付宝技术平台的奠基人之一&#xff0c;但是他总说“这还不是我心中最完美的架构”&#xff1b;他行事低调但却有着“此时此地&#xff0c;非我莫属”的豪气&#xff1b;他曾无数次充当救火大队长&#xff0c;但自评只是“没有掉队的那个人”。 在2…

Flutter高内聚组件怎么做?阿里闲鱼打造开源高效方案!

fish_redux是闲鱼技术团队打造的flutter应用开发框架&#xff0c;旨在解决页面内组件间的高内聚、低耦合问题。开源地址&#xff1a;https://github.com/alibaba/fish-redux 从react_redux说起 redux对于前端的同学来说是一个比较熟悉的框架了&#xff0c;fish_redux借鉴了re…

AI赋能红外测温助力精准防控疫情……

文章来源&#xff1a;北京领邦智能装备股份公司 疫情发生以来&#xff0c;全国上下倾力奋战得到有效控制&#xff0c;科技抗疫逐渐成为有效抓手&#xff0c;而AI红外热成像测温仪无疑将成为抗疫一线的一把利剑&#xff0c;斩断疫情传播的途径。 需求引领技术变革 2003年非典后…

阿里巴巴中间件在 Serverless 技术领域的探索

Serverless 话题涉及范围极广&#xff0c;几乎包含了代码管理、测试、发布、运维和扩容等与应用生命周期关联的所有环节。AWS Lambda 是 Serverless 领域的标志性产品&#xff0c;但如果将其应用于核心业务&#xff0c;可能会遇到以下难题&#xff1a;&#xff08;仅代表作者个…

从零单排HBase 02:全面认识HBase架构(建议收藏)

作者 | 阿丸笔记责编 | 徐威龙封图| CSDN 下载于视觉中国在网上看过很多HBaes架构相关的文章&#xff0c;内容深浅不一&#xff0c;直到发现了一篇MapR官网的文章&#xff0c;写得实在太生动了。https://mapr.com/blog/in-depth-look-hbase-architecture/#.VdMxvWSqqko&#xf…

开发函数计算的正确姿势 —— 移植 next.js 服务端渲染框架

首先介绍下在本文出现的几个比较重要的概念&#xff1a; 函数计算&#xff08;Function Compute&#xff09;: 函数计算是一个事件驱动的服务&#xff0c;通过函数计算&#xff0c;用户无需管理服务器等运行情况&#xff0c;只需编写代码并上传。函数计算准备计算资源&#xff…

SpringBoot xml层SQL update之foreach循环的坑

在做二级分类批量删除置父级目录一级分类num-1时&#xff0c;发现数组里放了一样的pid&#xff0c;但是循环里只默认一个pid 145&#xff0c;所以只成功执行了一次num-1 可以选择在mapper接口层执行循环

Zookeeper UI管理界面安装

文章目录1. 安装java环境2. 安装maven打包环境3. 在线安装Git4. 安装zookeeper服务5. 安装zkui6. 开放防火墙7. 浏览器访问1. 安装java环境 下载 略 环境变量 export JAVA_HOME/app/jdk1.8.0_202 export PATH$PATH:$GOROOT/bin export CLASSPATH.:${JAVA_HOME}/jre/lib/rt.j…

虎牙在全球 DNS 秒级生效上的实践

本文整理自虎牙中间件团队在 Nacos Meetup 的现场分享&#xff0c;阿里巴巴中间件受权发布。 这次分享的是全球 DNS 秒级生效在虎牙的实践&#xff0c;以及由此产生的一些思考&#xff0c;整体上&#xff0c;分为以下5各部分&#xff1a; 背景介绍&#xff1b;方案设计和对比…

MySQL 狠甩 Oracle 稳居 Top1,私有云最受重用,大数据人才匮乏! | 中国大数据应用年度报告...

整理 | 屠敏出品 | CSDN&#xff08;ID:CSDNnews&#xff09;科技长河&#xff0c;顺之者昌&#xff0c;错失者亡。在这个技术百态之中&#xff0c;中国专业的 IT 社区CSDN 创始人&董事长蒋涛曾多次在公开活动中表示&#xff0c;开发者是对技术变革最敏感的人群。这不仅源于…

JS中split对多个分隔符的处理

关于JavaScript split() 方法&#xff0c;菜鸟教程是这样介绍的&#xff1a; split() 方法用于把一个字符串分割成字符串数组。 提示&#xff1a; 如果把空字符串 ("") 用作 separator&#xff0c;那么 stringObject 中的每个字符之间都会被分割。 注意&#xff1…

分布式6大核心专题_分布式ID

文章目录一、号段模式1. 拉取项目源码编译2. springboot集成Leaf3. 配置leaf.properties4. 创建数据库5. 初始化表结构和数据6. 测试案例7. 浏览器测试美团Leaf的号段模式和雪花算法模式生成分布式全局唯一id方式2种 一、号段模式 目前jar在maven仓库中没有上传 1. 拉取项目源…

现代编程语言大 PK,2020 年开发者关心的七大编程语言!

【CSDN 编者按】“如果我们把人类文明想象成汽车的话&#xff0c;那么软件开发行业就相当于汽车的引擎&#xff0c;编程语言就像引擎的燃料。”作为一名开发者&#xff0c;需跟随技术潮流的发展来学习新技术。2020年&#xff0c;你有计划新学一门编程语言吗&#xff1f;本文作者…

一文读懂深度学习:从神经元到BERT

阿里妹导读&#xff1a;自然语言处理领域的殿堂标志 BERT 并非横空出世&#xff0c;背后有它的发展原理。今天&#xff0c;蚂蚁金服财富对话算法团队整理对比了深度学习模型在自然语言处理领域的发展历程。从简易的神经元到当前最复杂的BERT模型&#xff0c;深入浅出地介绍了深…

启动redis闪退/失败

问题&#xff1a;正常启动redis-server.exe时&#xff0c;项目出现闪退情况 解决方式&#xff1a;按照下图完整流程输出即能正常启动

阿里开发者招聘节 | 2019阿里巴巴技术面试题分享:20位专家28道题

为帮助开发者们提升面试技能、有机会入职阿里&#xff0c;云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出&#xff08;面试题官方参考答案将在专辑结束后统一汇总分享&#xff0c;点此进入答题并围观他…

uniapp页面传参使用encodeURIComponent转义特殊符号

答主在uniapp页面跳转传imgUrl&#xff08;地址为&#xff1a;https://metting.oss-cn-beijing.aliyuncs.com/20210615153312771.9AT5NO.jpg?Expires4779415992&OSSAccessKeyIdLTAI4GKXzR3eLCustbbLYxFf&Signature***********&#xff09;时&#xff0c;图片无法正常显…