0717-7821348
500万彩票网电脑版

500万彩票网电脑版

您现在的位置: 首页 > 500万彩票网电脑版
TalkingData的Spark On Kubernetes实践
2019-05-29 22:12:02

众所周知,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  -t my-tag build
$ ./bin/docker-image-tool.sh -r -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

咱们能够在TalkingData的Spark On Kubernetes实践本地运用kubectl port-forward拜访Driver UI:

$ kubectl port-forward  4040:4040

履行完后经过http://localhost:4040拜访。

拜访日志

Spark的一切日志都能够经过Kubernetes API和kubectl CLI进行拜访:

$ kubectl -n= logs -f 

怎么完结租户和资源阻隔

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 --clusTalkingData的Spark On Kubernetes实践terrole=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  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: null
labels:
component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: 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=spark
name: 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= logs -f 

搜集和聚合日志,咱们后面会和ES结合。

监控

咱们TalkingData内部有自己的监控渠道OWL[2](已开源),未来咱们计划编写metric plugin,将Kubernetes接入OWL中。

混合布置

为了确保Spark作业时间有可用的核算资源,咱们前期选用了物理阻隔的计划。清楚明了,这种办法大幅降低了物理资源的运用率。下一步咱们计划选用混部计划,经过以下三种办法完结:

  • 将HDFS和Kubernetes混合布置
  • 为Spark作业和Kubernetes node区分优先级,在低优先级的node上一起运转一些无状况的其他出产服务
  • 使用云完结资源水平扩展,以避免资源突增

资源扩展

在选用以下两种办法添加资源运用率时,集群可能会面对资源缺少和可用性的问题:

  • 混合布置
  • 资源超卖

这会导致运转资源大于实践物理资源的状况(我称之为资源挤兑)。一种做法是给资源区分等级,优先确保部分等级的资源供应。另一种做法是完结资源的水平扩展,动态弥补可用资源,并在峰值往后主动开释。我在另一篇文章中论述了这种规划理念:https://xiaoxubeii.github.io/articles/k8s-on-cloud/。

TalkingData有自研的多云办理渠道,咱们的处理办法是完结独自的Kubernetes tdcloud-controller-manager作为资源的provider和maTalkingData的Spark On Kubernetes实践nager,经过TalkingData OWL监控告警,完结资源的水平扩展。

原文链接:http://www.ipshop.xyz/7889.html

作者:开源大数据EMR