在学习Ambari的路上,欢迎提出问题并相互交流,共同成长
基础思路框架
一、Pulsar服务部署
- ZooKeeper 集群(3 个 ZooKeeper 节点组成)
- Broker 集群(3 个 Pulsar 节点组成)
- Bookkeeper 集群(也称为 Bookie 集群,3 个 BookKeeper 节点组成)
1.1 依赖环境
节点数要求:3台
JDK版本要求:jdk1.8+
依赖服务:Zookeeper
1.2 集群初始化
bin/pulsar initialize-cluster-metadata \
--cluster pulsar-cluster \
--zookeeper pulsar-node1:2181,pulsar-node2:2181,pulsar-node3:2181/pulsar-meta \
--configuration-store pulsar-node1:2181,pulsar-node2:2181,pulsar-node3:2181/pulsar \
--web-service-url http://pulsar-node1:8080,pulsar-node2:8080,pulsar-node3:8080 \
--web-service-url-tls https://pulsar-node1:8443,pulsar-node2:8443,pulsar-node3:8443 \
--broker-service-url pulsar://pulsar-node1:6650,pulsar-node2:6650,pulsar-node3:6650 \
--broker-service-url-tls pulsar+ssl://pulsar-node1:6651,pulsar-node2:6651,pulsar-node3:6651
1.3 更改配置
环境变量
export JAVA_HOME=/opt/soft/java
export ZOOKEEPER_HOME=/opt/soft/zookeeper
export PULSAR_HOME=/opt/soft/pulsar
export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin:$PULSAR_HOME/bin
export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar
broker.conf
# 配置参数根据集群初始化命令提取
zookeeperServers = {{ zk_servers | join(':' + zookeeper_port|default("2181") + ',') }}:2181/pulsar-meta
configurationStoreServers={{ zk_servers | join(':' + zookeeper_port|default("2181") + ',') }}:2181/pulsar
clusterName={{ cluster_name }}
bookkeeper.conf
bookiePort={{ bookie_port }}
journalDirectory={{ journal_directory }}
ledgerDirectories={{ ledger_directories }}
zkServers={{ bookkeeper_zookeeper_servers }}{{ meta_chroot }}
zookeeper.conf
# 增加zookeeper多节点配置
{% for host in zk_servers -%}
server.{{loop.index}}={{host}}:2888:3888
{% endfor %}
client.conf
webServiceUrl=http://{{ pulsar_web_service_urls|join(":8080,") }}:8080
brokerServiceUrl=http://{{ pulsar_broker_service_urls|join(":6650,") }}:6650
1.4 启动服务
# 保证依赖环境完成后,首先启动bookie
pulsar-daemon start bookie # 守护进程启动,后台挂起
# 所有bookie节点启动后,启动broker节点
pulsar-daemon start broker
1.5 测试服务
# 执行测试命令
bookkeeper shell simpletest --ensemble 3 --writeQuorum 3 --ackQuorum 3 --numEntries 3
# 出现以下日志即成功
2022-08-22T09:21:47,831+0800 [bookkeeper-io-3-5] INFO org.apache.bookkeeper.proto.PerChannelBookieClient - connection [id: 0x53c3e05e, L:/10.xxx.xxx.xxx:45888 - R:10.xxx.xxx.xxx/10.xxx.xxx.xxx:3181] authenticated as BookKeeperPrincipal{ANONYMOUS}
2022-08-22T09:21:47,831+0800 [bookkeeper-io-3-4] INFO org.apache.bookkeeper.proto.PerChannelBookieClient - Successfully connected to bookie: 10.xxx.xxx.xxx:3181 [id: 0x27bc2a9e, L:/10.xxx.xxx.xxx:54690 - R:10.xxx.xxx.xxx/10.xxx.xxx.xxx:3181]
2022-08-22T09:21:47,832+0800 [bookkeeper-io-3-4] INFO org.apache.bookkeeper.proto.PerChannelBookieClient - connection [id: 0x27bc2a9e, L:/10.xxx.xxx.xxx:54690 - R:10.xxx.xxx.xxx/10.50.2.152:3181] authenticated as BookKeeperPrincipal{ANONYMOUS}
二、定义Pulsar RPM包
制作rpm依赖条件
yum install rpm-build rpmdevtools
# 在当前用户根目录生成rpm所需目录
rpmdev-setuptree
# 生成以下目录
rpmbuild
├── BUILD
├── RPMS
├── SOURCES # 存放源码包
├── SPECS # 存放spec文件
└── SRPMS
SPEC文件
参考:https://www.cnblogs.com/michael-xiang/p/10480809.html
Name: pulsar
Version: 2.9.3
# Avoid some silly dependencies and allow
# symlink in the init.d folder
AutoReqProv: no
Release: 0
Summary: Pulsar is a multi-tenant, high-performance solution for server-to-server messaging.
License: Apache 2.0
Group: Applications/Internet
Source0: pulsar-2.9.3.tar.gz
Prefix: /var
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-root
Provides: pulsar
Requires(post): /sbin/chkconfig, /sbin/service
Requires(preun): /sbin/chkconfig, /sbin/service
%description
%prep
%build
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/var/lib/pulsar
mkdir -p $RPM_BUILD_ROOT/etc/init.d
mkdir -p %{_localstatedir}/lib/pulsar
tar xfz $RPM_SOURCE_DIR/pulsar-%{version}.tar.gz
cp -r $RPM_BUILD_DIR/pulsar-%{version}/* $RPM_BUILD_ROOT/var/lib/pulsar
%clean
rm -rf $RPM_BUILD_ROOT
%post
# command link
ln -sf /var/lib/pulsar/bin/bookkeeper %{_sysconfdir}/init.d/bookkeeper
ln -sf /var/lib/pulsar/bin/pulsar %{_sysconfdir}/init.d/pulsar
ln -sf /var/lib/pulsar/bin/pulsar-admin %{_sysconfdir}/init.d/pulsar-admin
ln -sf /var/lib/pulsar/bin/pulsar-admin-common.sh %{_sysconfdir}/init.d/pulsar-admin-common
ln -sf /var/lib/pulsar/bin/pulsar-client %{_sysconfdir}/init.d/pulsar-client
ln -sf /var/lib/pulsar/bin/pulsar-daemon %{_sysconfdir}/init.d/pulsar-daemon
ln -sf /var/lib/pulsar/bin/pulsar-managed-ledger-admin %{_sysconfdir}/init.d/pulsar-managed-ledger-admin
ln -sf /var/lib/pulsar/bin/pulsar-perf %{_sysconfdir}/init.d/pulsar-perf
ln -sf /var/lib/pulsar/bin/function-localrunner %{_sysconfdir}/init.d/function-localrunner
%files
%defattr(-,root,root,-)
/var/lib/pulsar
%preun
unlink %{_sysconfdir}/init.d/bookkeeper
unlink %{_sysconfdir}/init.d/pulsar
unlink %{_sysconfdir}/init.d/pulsar-admin
unlink %{_sysconfdir}/init.d/pulsar-admin-common
unlink %{_sysconfdir}/init.d/pulsar-client
unlink %{_sysconfdir}/init.d/pulsar-daemon
unlink %{_sysconfdir}/init.d/pulsar-managed-ledger-admin
unlink %{_sysconfdir}/init.d/pulsar-perf
unlink %{_sysconfdir}/init.d/function-localrunner
%changelog
* Tue Aug 19 2014 - daniel.beneyto at abiquo dot com
- Initial release.
制作rpm
rpmbuild -ba pulsar.spec
# 生成RPM存放在RPMS目录下
三、定义Ambari metainfo.xml文件
3.1 确定服务安装包
根据上面制作的RPM包作为基础安装包,挂载资源的形式放在ambari-server节点
cd /var/www/html
mkdir pulsar
cp pulsar-2.9.3-0.noarch.rpm /var/www/html/pulsar
3.2 服务启停流程
服务启动依赖关系,在ambari中通过定义role_command_order.json进行维护
{
"general_deps" : {
"_comment" : "dependencies for PULSAR",
"BOOKKEEPER_SERVER-START" : ["ZOOKEEPER_SERVER-START"],
"BROKER_SERVER" : ["ZOOKEEPER_SERVER-START", "BOOKKEEPER_SERVER-START"],
"PULSAR_SERVICE_CHECK-SERVICE_CHECK": ["BOOKKEEPER_SERVER-START", "BROKER_SERVER-START"]
}
}
3.3 服务配置提取
模版文件(存放目录: PULSAR/templates)
bookkeeper.conf.j2
broker.conf.j2
client.conf.j2
zookeeper.conf.j2
涉及目录
serviceName (即存放在ambari-server节点)
/var/lib/ambari-server/resources/stacks/HDP/3.1/services
其中版本号根据当前HDP部署版本号进行选择,将自定义服务放入此目录下(名称一定要大写)
mkdir PULSAR
cd PULSAR
touch && metainfo.xml && mkdir {package,configuration,properties}
cd package
mkdir {templates,scripts}
目录说明:
PULSAR # 服务顶层目录
|——package # 默认读取template、script的上级目录
|————templates # 服务配置或者需要生成的配置文件模版(python j2模版文件)
|————scripts # 服务所需脚本
|——configuration # 配置文件定义,全部是标准的xml格式文件,即展示在界面上的配置项
|——properties # 在配置中引用的property文件
|——role_command_order.json # 服务角色启动依赖定义
3.4 涉及脚本
bookkeeper_server.py # bookkeeper服务相关操作
broker_server.py # broker服务相关操作
params.py # 全局参数定义
service_check.py # 服务检查脚本
setup_pulsar.py # 安装服务前配置服务脚本
bookkeeper_server.py
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/17
@file: bookkeeper_server.py.py
describe: pulsar service bookie role scripts
"""
from resource_management import *
from resource_management.core.logger import Logger
import os
Logger.initialize_logger()
class BookieServer(Script):
def install(self, env):
import params
env.set_params(params)
Logger.info("Start install pulsar package.")
ambari_server_host = params.ambari_server_host
ambari_download_port = params.ambari_download_port
# download pulsar rpm package
download_command = 'wget -O /tmp/pulsar-{0}-0.noarch.rpm http://{1}:{2}/pulsar/pulsar-{3}-0.noarch.rpm'.format(
params.pulsar_version, ambari_server_host, ambari_download_port, params.pulsar_version)
Logger.info("Install PULSAR service command ===> {0}".format(download_command))
Execute(download_command)
Execute(params.install_command)
Logger.info('Install the Pulsar success')
Execute(params.init_command)
conf_path = params.pulsar_conf_base_dir
Logger.info("Setup pulsar, conf_base_dir : " + conf_path)
configFile("bookkeeper.conf", template_name="bookkeeper.conf.j2")
configFile("broker.conf", template_name="broker.conf.j2")
configFile("zookeeper.conf", template_name="zookeeper.conf.j2")
configFile("client.conf", template_name="client.conf.j2")
Execute(params.clean_command)
def stop(self, env):
import params
env.set_params(params)
Logger.info('Stop the BooKieServer')
Execute('ps -ef | grep \'org.apache.bookkeeper.server.Main\' | grep -v grep | awk \'{print $2}\' |xargs kill -9')
Execute(format('rm -f {params.pulsar_base_dir}/bin/pulsar-bookie.pid'))
# Execute(params.broker_stop_command, timeout=30)
def start(self, env):
import params
Logger.info('Start BooKieServer')
Execute(params.bookie_start_command)
def status(self, env):
import params
env.set_params(params)
Logger.info('Status BooKieServer')
check_process_status(params.pulsar_base_dir + "/bin/pulsar-bookie.pid")
def configure(self, env):
import params
# from setup_pulsar import setup_pulsar
env.set_params(params)
setup_pulsar()
def setup_pulsar():
pass
def configFile(name, template_name=None, mode=None):
import params
File(os.path.join(params.pulsar_conf_base_dir, name),
content=Template(template_name),
mode=mode
)
if __name__ == '__main__':
BookieServer().execute()
broker_server.py
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/17
@file: broker_server.py.py
describe:
"""
# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/17
@file: bookkeeper_server.py.py
describe: pulsar service bookie role scripts
"""
from resource_management import *
class BrokerServer(Script):
def install(self, env):
Logger.info('Pass the BrokerServer install step.')
def stop(self, env):
import params
env.set_params(params)
Logger.info("Stop component broker server.")
Execute(
'ps -ef |grep \'org.apache.pulsar.PulsarBrokerStarter\' |grep -v grep |awk \'{print $2}\' |xargs kill -9')
Execute('rm -f {params.pulsar_base_dir}/bin/pulsar-broker.pid')
# Execute(params.broker_stop_command)
def start(self, env):
import params
env.set_params(params)
Logger.info('Start component broker server')
Execute(params.broker_start_command)
def status(self, env):
import params
env.set_params(params)
print 'Check BrokerServer status.'
check_process_status(params.pulsar_base_dir + "/bin/pulsar-broker.pid")
def configure(self, env):
import params
env.set_params(params)
def restart(self, env):
self.stop(env)
self.start(env)
if __name__ == '__main__':
BrokerServer().execute()
params.py
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/17
@file: params.py
describe:
"""
from resource_management import *
from resource_management.core.logger import Logger
config = Script.get_config()
Logger.initialize_logger()
Logger.info("Start load params config.")
ambari_server_host = config["ambariLevelParams"]["ambari_server_host"]
ambari_download_port = 1880
pulsar_version = config["serviceLevelParams"]["version"]
dfs_default = config["configurations"]["hdfs-site"]["dfs.namenode.rpc-address"]
##### pulsar templates conf #####
pulsar_bookkeeper_conf_content = config["configurations"]["bookkeeper-conf"]["content"]
pulsar_broker_conf_content = config["configurations"]["broker-conf"]["content"]
pulsar_client_conf_content = config["configurations"]["client-conf"]["content"]
pulsar_zookeeper_conf_content = config["configurations"]["zookeeper-conf"]["content"]
pulsar_base_dir = '/var/lib/pulsar'
bookie_start_command = format('{pulsar_base_dir}/bin/pulsar-daemon start bookie')
broker_start_command = format('{pulsar_base_dir}/bin/pulsar-daemon start broker')
bookie_stop_command = format('{pulsar_base_dir}/bin/pulsar-daemon stop bookie')
broker_stop_command = format('{pulsar_base_dir}/bin/pulsar-daemon stop broker')
##### pulsar global config #####
pulsar_conf_base_dir = format("{pulsar_base_dir}/conf")
global_base_path = "/configurations/pulsar-global-conf"
cluster_zookeeper = config["configurations"]["clusterHostInfo"]["zookeeper_server_hosts"]
zk_servers = str(config["configurations"]["pulsar-global-conf"]["zk_servers"]).split(",")
zookeeper_port = default(format("{global_base_path}/zookeeper_port"), "2181")
meta_chroot = default(format("{global_base_path}/meta_chroot"), "/pulsar-meta")
config_store_chroot = default(format("{global_base_path}/config_store_chroot"), "/pulsar")
##### pulsar bookie config #####
bookie_base_path = "/configurations/bookkeeper-conf"
bookie_port = default(format("{bookie_base_path}/bookie_port"), "3181")
journal_directory = default(format("{bookie_base_path}/journal_directory"), "/mnt/disk1/pulsar/data/bookkeeper/journal")
ledger_directories = default(format("{bookie_base_path}/ledger_directories"),
"/mnt/disk1/pulsar/data/bookkeeper/ledgers")
# znode = default(format("{bookie_base_path}/znode"), "/pulsar-meta")
bookkeeper_zookeeper_servers = ''
for idx, zkServer in enumerate(zk_servers):
if idx + 1 < len(zk_servers):
bookkeeper_zookeeper_servers += zkServer + ':' + str(zookeeper_port) + ","
else:
bookkeeper_zookeeper_servers += zkServer + ':' + str(zookeeper_port)
##### pulsar broker config #####
broker_base_path = "/configurations/broker-conf"
cluster_name = default(format("{broker_base_path}/cluster_name"), "pulsar-cluster")
##### pulsar client config #####
client_base_path = "/configurations/client-conf"
web_service_url_list = str(config["configurations"]["client-conf"]["web_service_url"]).split(",")
web_service_port = default(format("{client_base_path}/web_service_port"), "8080")
broker_service_url_list = str(config["configurations"]["client-conf"]["broker_service_url"]).split(",")
broker_service_port = default(format("{client_base_path}/broker_service_port"), "6650")
#### deal with config ####
# "/pulsar-meta"
pulsar_metadata_store = config["configurations"]["bookkeeper-conf"]["znode"]
# "/pulsar"
pulsar_configuration_metadata_store = config["configurations"]["broker-conf"]["config_store_chroot"]
# "pulsar-node1,pulsar-node2,pulsar-node3"
# pulsar_web_service_url = str(config["configurations"]["client-conf"]["web_service_url"]).split(",")
# "8080"
pulsar_web_service_port = config["configurations"]["client-conf"]["web_service_port"]
pulsar_web_service_urls = ''
pulsar_web_service_tls_urls = '' # tls
for idx, web_service_url in enumerate(web_service_url_list):
if idx + 1 < len(web_service_url_list):
pulsar_web_service_urls += web_service_url + ':' + str(pulsar_web_service_port) + ","
else:
pulsar_web_service_urls += web_service_url + ':' + str(pulsar_web_service_port)
# "pulsar-node1,pulsar-node2,pulsar-node3"
# pulsar_broker_service_url = str(config["configurations"]["client-conf"]["broker_service_url"]).split(",")
# "6650"
pulsar_broker_service_port = config["configurations"]["client-conf"]["broker_service_port"]
pulsar_broker_service_urls = ''
for idx, broker_service_url in enumerate(broker_service_url_list):
if idx + 1 < len(broker_service_url_list):
pulsar_broker_service_urls += broker_service_url + ':' + str(pulsar_broker_service_port) + ","
else:
pulsar_broker_service_urls += broker_service_url + ':' + str(pulsar_broker_service_port)
###### pulsar commands #####
install_command = 'rpm -Uvh --force /tmp/pulsar-{0}-0.noarch.rpm'.format(pulsar_version)
clean_command = format('rm -f /tmp/pulsar-{pulsar_version}-0.noarch.rpm')
init_command = format("""
{pulsar_base_dir}/bin/pulsar initialize-cluster-metadata \
--cluster {cluster_name} \
--zookeeper {bookkeeper_zookeeper_servers}{meta_chroot} \
--configuration-store {bookkeeper_zookeeper_servers}{config_store_chroot} \
--web-service-url http://{pulsar_web_service_urls} \
--broker-service-url pulsar://{pulsar_broker_service_urls}
""")
Logger.info("Load params config successful.")
service_check.py (测试)
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/17
@file: service_check.py.py
describe:
"""
from resource_management.libraries.script.script import Script
from resource_management.core.shell import as_user
from ambari_commons.os_family_impl import OsFamilyImpl
from ambari_commons import OSConst
from resource_management.libraries.functions.curl_krb_request import curl_krb_request
from resource_management.libraries import functions
from resource_management.libraries.functions.format import format
from resource_management.libraries.resources.execute_hadoop import ExecuteHadoop
from resource_management.core.logger import Logger
from resource_management.core.source import StaticFile
from resource_management.core.resources.system import Execute, File
class PulsarServiceCheck(Script):
pass
@OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
class PulsarServiceCheckDefault(PulsarServiceCheck):
def service_check(self, env):
Logger.warning(format("env =====> {0}", env))
Logger.info("Check Pulsar service...")
if __name__ == "__main__":
PulsarServiceCheck().execute()
setup_pulsar.py (当时定义后,使用未生效,原因未知)
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@time: 2022/08/19
@file: setup_pulsar.py
describe:
"""
from resource_management import *
from resource_management.core.logger import Logger
Logger.initialize_logger("pulsar-setup")
def setup_pulsar():
import params
conf_path = params.pulsar_conf_base_dir
Logger.info("Setup pulsar.")
Logger.info(format("conf_base_dir : {conf_path}"))
configFile("bookkeeper.conf", template_name="bookkeeper.conf.j2")
configFile("broker.conf", template_name="broker.conf.j2")
configFile("zookeeper.conf", template_name="zookeeper.conf.j2")
configFile("client.conf", template_name="client.conf.j2")
def configFile(name, template_name=None, mode=None):
import params
File(os.path.join(params.pulsar_conf_base_dir, name),
content=Template(template_name),
mode=mode
)
四、测试集成服务
将定义好的pulsar服务目录下所有文件全部拷贝到ambari-server节点/var/lib/ambari-server/resources/stacks/HDP/3.1/services/PULSAR
目录下,然后重启ambari-server节点,即可从Add Services
中看到自定义服务
五、FAQ
更改自定义服务相关配置文件后,需要重启ambari-server节点才能生效,ambari-server在启动时会生成对应的缓存文件,在services/CUSTOM_SERVICE/package目录下生成archive.zip
和.hash
文件,重启ambari-server后,server节点会重新下发相关文件到各个agent节点
六、参考
博客参考:
rpm构建 spec文件基础:https://www.cnblogs.com/michael-xiang/p/10480809.html
分布式pulsar搭建:https://segmentfault.com/a/1190000041486276
ambari自定义服务集成(很详细):https://www.cxyzjd.com/article/ZYC88888/116496591
官网参考:
https://cwiki.apache.org/confluence/display/AMBARI/Stacks+and+Services
https://cwiki.apache.org/confluence/display/AMBARI/Defining+a+Custom+Service
https://cwiki.apache.org/confluence/display/AMBARI/How-To+Define+Stacks+and+Services