背景
OpenShift是目前比較主流的基于Kubernetes的容器云解決方案,OpenShift在kubernetes基礎(chǔ)上提供了快速部署k8s集群的Ansible腳本廊敌,DevOps能力以及一個(gè)易于使用的前端界面拇厢。本文主要討論如何在OpenShift上拉起Storm集群拯勉。
Storm架構(gòu)
Storm的架構(gòu)是Slave-Master模式的贼涩,一個(gè)完整的Storm集群需要以下四種服務(wù):
- 一個(gè)或多個(gè)Nimbus服務(wù)言缤,storm集群的管理節(jié)點(diǎn),可以實(shí)現(xiàn)基于Zookeeper的HA方案
- 一個(gè)UI服務(wù)导而,提供監(jiān)控集群和拓?fù)?topology)運(yùn)行前端界面
- 一個(gè)DRPC服務(wù)忱叭,提供了用戶(hù)和正在運(yùn)行的拓?fù)浣换サ姆植际絉PC接口
- 若干個(gè)Supervisor服務(wù),storm集群的計(jì)算節(jié)點(diǎn)
Zookeeper方案
Storm集群的正常運(yùn)行還需要依賴(lài)Zookeeper今艺,因?yàn)镾torm各組件的服務(wù)發(fā)現(xiàn)韵丑,nimbus節(jié)點(diǎn)的HA以及topology的信息都是存儲(chǔ)在Zookeeper里的。
可以通過(guò)兩種方式來(lái)為OpenShift上的Storm編排提供Zookeeper服務(wù):
- 獨(dú)占的Zookeeper集群: 在OpenShift集群上為每個(gè)Storm集群動(dòng)態(tài)的啟動(dòng)一個(gè)獨(dú)占的Zookeeper集群的編排虚缎,其至少包含三個(gè)Zookeeper鏡像并提供外部存儲(chǔ)方案(如GlusterFS)來(lái)持久化Zookeeper的數(shù)據(jù)
- 共享的Zookeeper集群:提前創(chuàng)建一個(gè)zookeeper集群撵彻,各storm集群實(shí)例共享使用;共享的zookeeper集群可以由OpenShift托管的zookeeper編排,也可以是在OpenShift集群外部的若干臺(tái)與OpenShift集群保持網(wǎng)絡(luò)連通的虛擬機(jī)或物理機(jī)器上手工搭建的Zookeeper集群陌僵;共享zk的方式需要考慮多個(gè)storm集群之間的數(shù)據(jù)沖突問(wèn)題轴合,因?yàn)閟torm集群會(huì)默認(rèn)將數(shù)據(jù)存儲(chǔ)到zookeeper的"/storm"目錄下,所以每個(gè)storm集群實(shí)例在zookeeper上都需要有自己獨(dú)立的數(shù)據(jù)存儲(chǔ)目錄碗短,可以通過(guò)storm的配置項(xiàng)“storm.zookeeper.root”來(lái)指定值桩。
Storm鏡像構(gòu)建
我們需要為storm的每個(gè)組件構(gòu)建單獨(dú)的docker鏡像,即storm編排需要一個(gè)nimbus鏡像豪椿,一個(gè)ui鏡像奔坟,一個(gè)supervisor鏡像以及一個(gè)drpc鏡像。由于storm的apache官方安裝包里包含了所有的組件搭盾,管理員可以根據(jù)不同的配置文件(conf/storm.yaml)和啟動(dòng)命令來(lái)決定當(dāng)前啟動(dòng)的是哪一個(gè)組件咳秉,所以用于構(gòu)建各個(gè)組件鏡像的Dockerfile也只有啟動(dòng)命令和配置文件的差異。
以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里的啟動(dòng)命令:
- nimbus的啟動(dòng)命令是"bin/storm nimbus"鸯隅,storm.yaml如下:
storm.zookeeper.servers:
- 10.128.0.46
storm.zookeeper.root: "/storm_001"
nimbus.thrift.port: 6627
storm.yaml三個(gè)參數(shù)分別指出了zookeeper集群的地址澜建,storm數(shù)據(jù)在zookeeper里的存儲(chǔ)位置,nimbus的thrift監(jiān)聽(tīng)端口
- ui的啟動(dòng)命令是"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里的四個(gè)參數(shù)分別代表zookeeper集群地址炕舵,storm數(shù)據(jù)在zookeeper里的存儲(chǔ)目錄,nimbus的thrift監(jiān)聽(tīng)端口跟畅,nimbus服務(wù)的列表(nimbus HA場(chǎng)景下需要配多個(gè))咽筋,ui服務(wù)的監(jiān)聽(tīng)端口
- supervisor的啟動(dòng)命令是"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里的四個(gè)參數(shù)分別代表zookeeper集群地址徊件,storm數(shù)據(jù)在zookeeper里的存儲(chǔ)目錄奸攻,nimbus的thrift監(jiān)聽(tīng)端口,nimbus服務(wù)的列表(nimbus HA場(chǎng)景下需要配多個(gè))
- drpc的啟動(dòng)命令是"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里的五個(gè)參數(shù)分別代表zookeeper集群地址睹耐,storm數(shù)據(jù)在zookeeper里的存儲(chǔ)目錄,nimbus的thrift監(jiān)聽(tīng)端口部翘,nimbus服務(wù)的列表(nimbus HA場(chǎng)景下需要配多個(gè))硝训,drpc服務(wù)監(jiān)聽(tīng)端口
storm編排
storm的編排將啟動(dòng)包含1個(gè)nimbus服務(wù),1個(gè)ui服務(wù)新思,1個(gè)drpc服務(wù)以及2個(gè)supervisor服務(wù)在內(nèi)的storm集群環(huán)境窖梁。要實(shí)現(xiàn)這樣的配置的storm集群,需要為nimbus/ui/drpc/supervisor分別創(chuàng)建rc(replication controller)表牢,由kubernetes保證各個(gè)組件的服務(wù)可用性以及備份數(shù)目窄绒,具體配置如下:
- nimbus的rc贝次,啟動(dòng)一個(gè)運(yùn)行storm nimbus服務(wù)的pod并開(kāi)放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,將啟動(dòng)一個(gè)運(yùn)行storm ui服務(wù)的pod并開(kāi)放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將啟動(dòng)2個(gè)運(yùn)行storm supervisor服務(wù)的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將啟動(dòng)一個(gè)運(yùn)行storm drpc服務(wù)的pod并開(kāi)放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: {}
各個(gè)組件的rc創(chuàng)建后,我們還需要考慮服務(wù)暴露的問(wèn)題堰燎,即將storm集群中需要被用戶(hù)和應(yīng)用訪問(wèn)的服務(wù)暴露為kubernetes的service掏父;在storm集群環(huán)境中用戶(hù)或應(yīng)用程序需要連接nimbus服務(wù)去提交topology的jar包,需要訪問(wèn)storm ui查看storm的集群狀態(tài)和topology執(zhí)行情況秆剪,需要通過(guò)drpc服務(wù)提供的drpc接口與topology交互赊淑。所以,我們需要為nimbus仅讽,ui陶缺,drpc各自創(chuàng)建一個(gè)service。
在OpenShift/Kubernetes中洁灵,可以通過(guò)兩種方式將service暴露到集群之外:
- nodeport饱岸,在OpenShift/Kubernetes集群的所有node節(jié)點(diǎn)上開(kāi)放一個(gè)指定端口,在集群外部可以用集群內(nèi)任何一個(gè)node的ip/hostname加上該指定端口訪問(wèn)service
- external IP徽千,將service綁定到OpenShift/Kubernetes集群內(nèi)的某個(gè)指定節(jié)點(diǎn)的指定端口上苫费,在集群外部可以通過(guò)該節(jié)點(diǎn)的ip/hostname加端口訪問(wèn)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
測(cè)試
1 登陸OpenShift集群
2 通過(guò)oc命令創(chuàng)建nimbus/ui/supervisor/drpc的rc
3 通過(guò)oc命令創(chuàng)建nimbus/ui/supervisor/drpc的service
4 通過(guò)oc命令查看storm集群的pods以及services的運(yùn)行狀況
5 打開(kāi)瀏覽器双抽,通過(guò)storm-ui service提供的external IP和8080端口訪問(wèn)storm ui: http://10.1.236.92:8080
6 在客戶(hù)端機(jī)器(比如自己的laptop)上下載與集群上運(yùn)行的storm版本一致apache storm的安裝包百框,如:http://apache.cs.utah.edu/storm/apache-storm-0.10.0/apache-storm-0.10.0.tar.gz
7 解壓并進(jìn)入目錄apache-storm-0.10.0/conf,修改storm.yaml配置文件牍汹,指向storm集群的nimbus service暴露出來(lái)的external ip和端口(詳見(jiàn)步驟4的截圖):
storm.zookeeper.servers:
- 10.128.0.46
nimbus.thrift.port: 6627
nimbus.host: 10.1.236.92
8 通過(guò)storm命令行遠(yuǎn)程連接到storm的nimbus服務(wù)琅翻,查看storm集群中在執(zhí)行的topology列表(當(dāng)前列表為空)
9 如果需要提交topology的jar包到storm集群,則可以在客戶(hù)端直接執(zhí)行./bin/storm jar ?<topology-jar-path> <topology-jar-class>
改進(jìn)
未來(lái)可以改進(jìn)的地方包括:
1 通過(guò)docker的啟動(dòng)腳本動(dòng)態(tài)注入storm.yaml需要的配置項(xiàng)柑贞,包括:
- 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的配置項(xiàng)名稱(chēng)從nimbus.host修改為了nimbus.seeds)
3 支持supervisor數(shù)目的動(dòng)態(tài)配置钧嘶,目前是固定的一個(gè)編排啟動(dòng)2個(gè)supervisor