架构解密从分布式到微服务,微服务和分布式最大区别

首页 > 经验 > 作者:YD1662022-10-28 06:22:00

在 RedHat的方案中,GlusterFS集群被部署在独立的服务器集群上,这适用于较大的集群规模及对性能和存储要求高的场景。在机器有限的情况下,我们也可以把Kubernetes集群的每个Node节点都当作一个GlusterFS的存储节点,并采用DaemonSet的调度方式将GlusterFS部署到Kubernetes集群上,具体的部署方式在Kubernetes 的 GitHub网站中有详细的说明文档,以Pod方式部署GlusterFS集群也使得GlusterFS 的部署和运维都变得非常简单。

提供全文检索能力的ElasticSearch集群也很容易被部署到Kubernetes中,前面提到的日志集中收集与查询分析的三件套ELK目前基本上全部以Pod的方式部署,以实现Kubernetes集群日志与用户应用日志的统一收集、查询、分析等功能。

在当前热门的大数据领域中,很多系统也都能以容器化方式部署到Kubernetes集群中,比如Hadoop、HBase、Spark 及 Storm等重量级集群。下一节将给出 Storm On Kubernetes 的建模方案,并且将其部署到Kubernetes集群中,最后提交第6章的WordCountTopology 作业并且观察运行结果。

Storm On Kubernetes 实战

通过第6章的学习,我们知道一个 Storm集群是由ZooKeeper、Nimbus (Master)及一些Supervisor (Slave)节点组成的,集群的配置文件默认保存在 conf/storm.yaml中,最关键的配置参数如下。

从上述关键配置信息及Storm集群的工作原理来看,我们首先需要将ZooKeeper建模为Kubernetes Service,以便提供一个固定的域名地址,使得Nimbus 与Supervisor能够访问它。下面是ZooKeeper 的建模过程(为了简单起见,我们只建模一个ZooKeeper节点)。

首先,定义ZooKeeper对应的Service,Service名称为ku8-zookeeper,关联的标签为app=ku8-zookeeper 的Pod:

apiVersion: v1kind: Servicemetadata: name: ku8-zookeeperspec: ports: name: clientport: 2181selector: app: ku8-zookeeper

其次,定义ZooKeeper对应的RC:

apiversion: v1 kind: Replicationcontrollermetadata: name: ku8-zookeeper-lspec: replicas: 1template: metadata: labels: app: ku8-zookeeperspec: containers: name: server image: jplock/ zookeeper imagePu1lPolicy: IfNotPresentports: -containerPort: 2181

接下来,我们需要将Nimbus也建模为Kubernetes Service,因为Storm客户端需要直接访问Nimbus服务以提交拓扑任务,所以在conf/storm.yaml中存在nimbus.sceds参数。由于Nimbus在6627端口上提供了基于Thrift的 RPC服务,因此对Nimbus服务的定义如下:

apiversion: v1kind: Servicemetadata: name: nimbusspec: selector: app: storm-nimbusports: -name: nimbus-rpc port: 6627 targetPort:6627

考虑到在storm.yaml配置文件中有很多参数,所以为了实现任意参数的可配置性,我们可以用Kubernetes的Config Map资源对象来保存storm.yaml,并映射到Nimbus(以及 Supervisor)节点对应的Pod实例上。下面是在本案例中使用的storm.yaml 文件(storm-conf.yaml)的内容:

storm.zookeeper.servers: [ku8-zookeeper] nimbus.seeds: [nimbus]storm.log.dir: "log" storm. local.dir: "storm-data"supervisor.slots.ports: -6700 670167026703

将上述配置文件创建为对应的ConfigMap ( storm-config),可以执行下面的命令:

kubelet create configmap storm-config --from-file=storm-conf.yaml

然后,storm-config 就可以被任意Pod 以 Volume方式挂载到容器内的任意指定路径上了。接下来,我们可以继续建模 Nimbus服务对应的Pod。在从Docker Hub上搜寻相关 Storm镜像并进行分析后,我们选择了Docker 官方提供的镜像storm:1.0。相对于其他Storm镜像来说,官方维护的这个镜像有以下优点。

采用storm:1.0镜像定义Nimbus Pod的YAML文件如下:

apiversion: v1kind: Pod metadata: name: nimbuslabels: app: storm-nimbusspec: volumes: name: config-volumeconfigMap: name: storm-configitems: 一key:storm-conf.yaml path:storm.yaml containers: - name: nimbus image: storm: 1.0 imagePullPolicy: IfNotPresentports: -containerPort: 6627 command:【"storm" ,"nimbus" ]volumeMounts: - name: config-volumemountPath: /conf restartPolicy: Always

这里我们需要关注两个细节:第1个细节是ConfigMap 的使用方法,首先要把之前定义的ConfigMap ——storm-config映射为Pod的一个Volume,然后在容器中将此Volume挂接到某个具体的路径上;第2个细节是容器的参数 command,上面的command: [ "storm" , "nimbus"]表示此容器启动的是nimus进程。

类似地,我们定义storm-ui服务,这是一个Web管理程序,提供了图形化的Storm管理功能,因为需要在Kubernetes集群之外访问它,所以我们通过NodePort方式映射8080端口到主机上的30010。storm-ui服务的YAML定义文件如下:

apiversion: v1kind: Servicemetadata: name: storm-uispec: type: NodePortselector: app:storm-uiports: -name: web port: 8080 targetPort: 8080nodePort:30010

最后,我们来建模Supervisor。Supervisor看似不需要被建模为Service,因为Supervisor 不会被主动调用,但实际上Supervisor节点之间会相互发起通信,因此Supervisor节点注册到ZooKeeper 上的地址必须能被相互访问,在 Kubernetes平台上有两种方式解决此问题。

第1种方式,Supervisor节点注册到ZooKeeper上时,不用主机名(Pod名称),而是采用Pod的P地址。

第2种方式,用Headless Service模式,每个Supervisor节点都被建模为一个HeadlessService,并且确保Supervisor节点的容器名称(主机名)与Headless Service的名称一样,此时Supervisor节点注册到ZooKeeper 上的地址就跟Headless Service名称一样了,Supervisor节点之间都能用对方的Headless Service的域名进行通信。

其中,第1种方式需要修改Supervisor的启动脚本和对应的参数才能进行,实现起来比较麻烦,第②种方式无须修改镜像就能实现,所以我们采用了第﹖种方式建模。下面是某个Supervisor节点的Service定义,注意 clusterIP: None的特殊写法:

apiversion: v1 kind: Servicemetadata: name:storm-supervisorspec: clusterIP:Noneselector: app:storm-supervisorports: - port: 8000

storm-supervisor 这个节点对应的 Pod定义如下,需要注意Pod 的名称为storm-supervisor,并且command的值为[ "storm", "supervisor"]:

apiversion: v1kind: Pod metadata: name: storm-supervisorlabels: app: storm-supervisorspec: volumes: name: config-volumeconfigMap: name: storm-configitems: 一key:storm-conf.yaml path: storm.yaml containers: name: storm-supervisorimage: storm: 1.0 imagePullPolicy: IfNotPresent command:["storm", "supervisor" ]volumeMounts: -name: config-volumemountPath: /conf restartPolicy:Always

我们可以定义多个Supervisor 节点,比如在本案例中定义了两个Supervisor节点。在成功部署到Kubernetes集群后,我们通过Storm UI的30010端口进入Storm的管理界面,可以看到如下界面。

架构解密从分布式到微服务,微服务和分布式最大区别(21)

下面这个截图验证了两个Supervisor 节点也可以被成功注册在集群中,我们看到每个节点都有4个Slot,这符合我们在storm.yaml中的配置。

架构解密从分布式到微服务,微服务和分布式最大区别(22)

至此,Storm集群在Kubernetes 上的建模和部署已经顺利完成了。接下来我们看看如何在Storm集群中提交之前学习过的WordCountTopology作业并且观察它的运行情况。

首先,我们可以去 https:/ljar-download.com/下载编译好的 WordCountTopology 作业的JAR文件storm-starter-topologies-1.0.3.jar,然后通过Storm Client工具将该Topology作业提交到Storm集群中,提交作业的命令如下:

storm jar/userlib/storm-starter-topologies-1.0.3.jar org.apache.storm.starter.ordcountTopology topology

由于在storm:1.0镜像中已经包括了Storm Client 工具,所以最简便的方式是定义一个Pod,然后把下载下来的storm-starter-topologies-1.0.3.jar作为Volume映射到Pod里的/userlib/目录下。将容器的启动命令设置为上述提交作业的命令即可实现,下面是此Pod 的YAML定义:

apiversion: v1 kind: Podmetadata: name: storm-topo-examplespec: volumes: name:user-libhostPath: path: /root/stormname: config-volumeconfigMap: name:storm-configitems: -key: storm-conf.yaml path: storm. yaml containers: name: storm-topo-exampleimage: storm: 1.0 imagePullPolicy: IfNotPresent command: [ "storm","jar", "/userlib/storm-starter-topologies-1.0.3.jar", "org.apache.storm.starter.WordCountTopology", "topology" ] volumeMounts: - name: config-volumemountPath: /conf name:user-lib mountPath: /userlib restartPolicy: Never

上述定义有如下关键点。

创建上述 Pod以后,我们查看该Pod 的日志,如果看到下面这段输出,则表明WordCountTopology的拓扑作业已经被成功提交到Storm集群中了。

架构解密从分布式到微服务,微服务和分布式最大区别(23)

接下来,我们进入Storm UI去看看作业的执行情况。下图是WordCountTopology的汇总信息,状态为Active,运行了8分钟,占用了3个Worker进程,总共运行了28个Task。

架构解密从分布式到微服务,微服务和分布式最大区别(24)

上一页23456下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.