Storm on OpenShift

背景

OpenShift是目前比较主流的基于Kubernetes的容器云解决方案,OpenShift在kubernetes基础上提供了快速部署k8s集群的Ansible脚本,DevOps能力以及一个易于使用的前端界面。本文主要讨论如何在OpenShift上拉起Storm集群。

Storm架构

Storm的架构是Slave-Master模式的,一个完整的Storm集群需要以下四种服务:
- 一个或多个Nimbus服务,storm集群的管理节点,可以实现基于Zookeeper的HA方案

- 一个UI服务,提供监控集群和拓扑(topology)运行前端界面

- 一个DRPC服务,提供了用户和正在运行的拓扑交互的分布式RPC接口

- 若干个Supervisor服务,storm集群的计算节点

Zookeeper方案

Storm集群的正常运行还需要依赖Zookeeper,因为Storm各组件的服务发现,nimbus节点的HA以及topology的信息都是存储在Zookeeper里的。

可以通过两种方式来为OpenShift上的Storm编排提供Zookeeper服务:

- 独占的Zookeeper集群: 在OpenShift集群上为每个Storm集群动态的启动一个独占的Zookeeper集群的编排,其至少包含三个Zookeeper镜像并提供外部存储方案(如GlusterFS)来持久化Zookeeper的数据

- 共享的Zookeeper集群:提前创建一个zookeeper集群,各storm集群实例共享使用;共享的zookeeper集群可以由OpenShift托管的zookeeper编排,也可以是在OpenShift集群外部的若干台与OpenShift集群保持网络连通的虚拟机或物理机器上手工搭建的Zookeeper集群;共享zk的方式需要考虑多个storm集群之间的数据冲突问题,因为storm集群会默认将数据存储到zookeeper的"/storm"目录下,所以每个storm集群实例在zookeeper上都需要有自己独立的数据存储目录,可以通过storm的配置项“storm.zookeeper.root”来指定。

Storm镜像构建

我们需要为storm的每个组件构建单独的docker镜像,即storm编排需要一个nimbus镜像,一个ui镜像,一个supervisor镜像以及一个drpc镜像。由于storm的apache官方安装包里包含了所有的组件,管理员可以根据不同的配置文件(conf/storm.yaml)和启动命令来决定当前启动的是哪一个组件,所以用于构建各个组件镜像的Dockerfile也只有启动命令和配置文件的差异。

以nimbus镜像的Dockerfile为例:

FROM docker.io/nathonfowlie/centos-jre

# 0.10.0

ENV STORM_VERSION 0.10.0

ENV APACHE_MIRROR http://apache.cs.utah.edu/storm

RUN curl -o /opt/apache-storm.tar.gz ${APACHE_MIRROR}/apache-storm-${STORM_VERSION}/apache-storm-${STORM_VERSION}.tar.gz && \

tar -C /opt -xzf /opt/apache-storm.tar.gz && \

rm /opt/apache-storm.tar.gz && \

mv /opt/apache-storm-${STORM_VERSION} /opt/apache-storm && \

mkdir -p /opt/apache-storm/storm-local && \

mkdir -p /opt/apache-storm/logs && \

mkdir -p /opt/apache-storm/logback-dist && \

mkdir -p /opt/apache-storm/conf-dist && \

cp /opt/apache-storm/conf/* /opt/apache-storm/conf-dist/

COPY logback-cluster.xml /opt/apache-storm/logback/cluster.xml

COPY logback-cluster.xml /opt/apache-storm/logback-dist/cluster-console.xml

COPY storm.yaml /opt/apache-storm/conf/

WORKDIR /opt/apache-storm

RUN chmod 777 -R /opt/apache-storm

EXPOSE 6700 6701 6702 6703 8080 6627 3772

VOLUME ["/opt/apache-storm/conf", "/opt/apache-storm/logback", "/opt/apache-storm/logs", "/opt/apache-storm/storm-local"]

CMD ["bin/storm nimbus"]

各镜像的Dockerfile差异主要在storm.yaml和CMD里的启动命令:

- nimbus的启动命令是"bin/storm nimbus",storm.yaml如下:

storm.zookeeper.servers:

- 10.128.0.46

storm.zookeeper.root: "/storm_001"

nimbus.thrift.port: 6627

storm.yaml三个参数分别指出了zookeeper集群的地址,storm数据在zookeeper里的存储位置,nimbus的thrift监听端口

- ui的启动命令是"bin/storm ui",storm.yaml如下:

storm.zookeeper.servers:

- 10.128.0.46

storm.zookeeper.root: "/storm_001"

nimbus.thrift.port: 6627

nimbus.host: "sb-instanceid-sn"

ui.port: 8080

storm.ymal里的四个参数分别代表zookeeper集群地址,storm数据在zookeeper里的存储目录,nimbus的thrift监听端口,nimbus服务的列表(nimbus HA场景下需要配多个),ui服务的监听端口

- supervisor的启动命令是"bin/storm supervisor",storm.yaml如下:

storm.zookeeper.servers:

- 10.128.0.46

storm.zookeeper.root: "/storm_001"

nimbus.thrift.port: 6627

nimbus.host: "sb-instanceid-sn"

storm.yaml里的四个参数分别代表zookeeper集群地址,storm数据在zookeeper里的存储目录,nimbus的thrift监听端口,nimbus服务的列表(nimbus HA场景下需要配多个)

- drpc的启动命令是"bin/storm drpc",storm.yaml如下:

storm.zookeeper.servers:

- 10.128.0.46

storm.zookeeper.root: "/storm_001"

nimbus.thrift.port: 6627

nimbus.host: "sb-instanceid-sn"

drpc.port: 3772

storm.yaml里的五个参数分别代表zookeeper集群地址,storm数据在zookeeper里的存储目录,nimbus的thrift监听端口,nimbus服务的列表(nimbus HA场景下需要配多个),drpc服务监听端口

storm编排

storm的编排将启动包含1个nimbus服务,1个ui服务,1个drpc服务以及2个supervisor服务在内的storm集群环境。要实现这样的配置的storm集群,需要为nimbus/ui/drpc/supervisor分别创建rc(replication controller),由kubernetes保证各个组件的服务可用性以及备份数目,具体配置如下:

- nimbus的rc,启动一个运行storm nimbus服务的pod并开放6627端口,nimbus rc的yaml如下:

apiVersion: v1

kind: ReplicationController

metadata:

    name: storm-nimbus

spec:

    replicas: 1

    selector:

        storm: nimbus

    template:

        metadata:

            labels:

                storm: nimbus

        spec:

            containers:

                - name: nimbus

                   image: storm_nimbus:0.10.0

                   ports:

                        - containerPort: 6627

            volumeMounts:

            - name: storm-data

              mountPath: /opt/apache-storm/storm-local

        volumes:

       - name: storm-data

         emptyDir: {}

- ui的rc,将启动一个运行storm ui服务的pod并开放8080端口,ui rc的yaml如下:

apiVersion: v1

kind: ReplicationController

metadata:

    name: storm-ui

spec:

    replicas: 1

    selector:

        storm: ui

    template:

        metadata:

            labels:

                storm: ui

        spec:

           containers:

           - name: ui

             image: storm_ui:0.10.0

             ports:

                 - containerPort: 8080

             volumeMounts:

             - name: storm-data

               mountPath: /opt/apache-storm/storm-local

           volumes:

           - name: storm-data

             emptyDir: {}

- supervisor的rc将启动2个运行storm supervisor服务的pod,supervisor rc的yaml文件如下:

apiVersion: v1

kind: ReplicationController

metadata:

    name: storm-supervisor

spec:

    replicas: 2

    selector:

        storm: supervisor

    template:

        metadata:

            labels:

                storm: supervisor

        spec:

           containers:

           - name: supervisor

             image: storm_supervisor:0.10.0

             volumeMounts:

             - name: storm-data

               mountPath: /opt/apache-storm/storm-local

           volumes:

           - name: storm-data

             emptyDir: {}

- drpc的rc将启动一个运行storm drpc服务的pod并开放3772端口,drpc rc的yaml文件如下:

apiVersion: v1

kind: ReplicationController

metadata:

    name: storm-drpc

spec:

    replicas: 1

    selector:

        storm: drpc

    template:

        metadata:

            labels:

                storm: drpc

        spec:

            containers:

            - name: drpc

              image: storm_drpc:0.10.0

              ports:

                  - containerPort: 3772

             volumeMounts:

             - name: storm-data

               mountPath: /opt/apache-storm/storm-local

           volumes:

           - name: storm-data

             emptyDir: {}

各个组件的rc创建后,我们还需要考虑服务暴露的问题,即将storm集群中需要被用户和应用访问的服务暴露为kubernetes的service;在storm集群环境中用户或应用程序需要连接nimbus服务去提交topology的jar包,需要访问storm ui查看storm的集群状态和topology执行情况,需要通过drpc服务提供的drpc接口与topology交互。所以,我们需要为nimbus,ui,drpc各自创建一个service。

在OpenShift/Kubernetes中,可以通过两种方式将service暴露到集群之外:

- nodeport,在OpenShift/Kubernetes集群的所有node节点上开放一个指定端口,在集群外部可以用集群内任何一个node的ip/hostname加上该指定端口访问service

- external IP,将service绑定到OpenShift/Kubernetes集群内的某个指定节点的指定端口上,在集群外部可以通过该节点的ip/hostname加端口访问service

以下以external IP方式为例,nimbus/ui/drpc的service的yaml文件示例如下:

- nimbus的service

apiVersion: v1

kind: Service

metadata:

    name: storm-nimbus

spec:

    selector:

        storm: nimbus

    ports:

    - protocol: TCP

      port: 6627

    externalIPs:

    - 10.1.236.92

- ui的service

apiVersion: v1

kind: Service

metadata:

    name: sb-instanceid-su

spec:

    selector:

        sb-instanceid-storm: ui

    ports:

    - protocol: TCP

      port: 8080

    externalIPs:

    - 10.1.236.92

- drpc的service

apiVersion: v1

kind: Service

metadata:

    name: sb-instanceid-sd

spec:

    selector:

        sb-instanceid-storm: drpc

    ports:

    - protocol: TCP

      port: 3772

    externalIPs:

    - 10.1.130.155

测试

1 登陆OpenShift集群

2 通过oc命令创建nimbus/ui/supervisor/drpc的rc

3 通过oc命令创建nimbus/ui/supervisor/drpc的service

4 通过oc命令查看storm集群的pods以及services的运行状况

Storm on OpenShift_第1张图片

5 打开浏览器,通过storm-ui service提供的external IP和8080端口访问storm ui: http://10.1.236.92:8080

Storm on OpenShift_第2张图片

6 在客户端机器(比如自己的laptop)上下载与集群上运行的storm版本一致apache storm的安装包,如:http://apache.cs.utah.edu/storm/apache-storm-0.10.0/apache-storm-0.10.0.tar.gz

7 解压并进入目录apache-storm-0.10.0/conf,修改storm.yaml配置文件,指向storm集群的nimbus service暴露出来的external ip和端口(详见步骤4的截图):

storm.zookeeper.servers:

- 10.128.0.46

nimbus.thrift.port: 6627

nimbus.host: 10.1.236.92

8 通过storm命令行远程连接到storm的nimbus服务,查看storm集群中在执行的topology列表(当前列表为空)

9 如果需要提交topology的jar包到storm集群,则可以在客户端直接执行./bin/storm jar  

改进

未来可以改进的地方包括:

1 通过docker的启动脚本动态注入storm.yaml需要的配置项,包括:

- storm.zookeeper.servers

- storm.zookeeper.root

- nimbus.thrift.port

- nimbus.host

- drpc.port

- ui.port

2 支持nimbus HA,目前仅支持单nimbus (nimbus HA特性只支持storm 1.0.0以上的storm版本,并且nimbus的配置项名称从nimbus.host修改为了nimbus.seeds)

3 支持supervisor数目的动态配置,目前是固定的一个编排启动2个supervisor

你可能感兴趣的:(Storm on OpenShift)