ansible自动化部署 Zookeeper 集群
Linux 9 自动化部署 Zookeeper 集群
Apache ZooKeeper 是一个开源服务,可以实现高度可靠的分布式协调。它常被应用于分布式系统中,管理配置信息、命名服务、分布式同步、法定人数和状态。此外,一些分布式系统依靠 ZooKeeper 来实现共识、leader 选举和组管理。
本文将通过以下主题,讨论在 Rocky Linux 9 上安装和配置满足生产环境高可用性及弹性要求的 Zookeeper 集群:
- 部署环境介绍
- 下载 Zookeeper 包
- 部署 JDK
- 部署 Zookeeper 集群
- 验证集群
- 自动化监控
- 总结
35.1 部署环境介绍
完成本教程需要四个节点:一个节点作为 Ansible 控制节点,三个节点部署 Zookeeper 集群。
35.1.1 节点信息
四个节点分别为 2 核 CPU、2 GB 内存的虚拟机。
ZooKeeper 将数据保存在内存中以实现高吞吐量和低延迟,因此生产环境要提供更高内存的主机,建议 8 GB 内存。低内存可能产生 JVM 交换,导致 ZooKeeper 服务延迟。高延迟可能会导致客户端会话超时等问题,影响系统稳定。
Ansilbe 节点信息:
# IP:10.211.55.18
# 主机名:automate-host.aiops.red
# 系统版本:Rocky Linux release 9.1
Ansible Inventory hosts:
[zookeeper]
zk1.server.aiops.red
zk2.server.aiops.red
zk3.server.aiops.red
[prometheus]
prometheus.server.aiops.red
Zookeeper 节点信息:
# zookeeper1
# IP:10.211.55.31
# 主机名:zk1.server.aiops.red
# 系统版本:Rocky Linux release 9.1
# zookeeper2
# IP:10.211.55.32
# 主机名:zk2.server.aiops.red
# 系统版本:Rocky Linux release 9.1
# zookeeper3
# IP:10.211.55.33
# 主机名:zk3.server.aiops.red
# 系统版本:Rocky Linux release 9.1
35.1.2 节点要求
为使安装过程顺利进行,节点应满足以下要求。
35.1.2.1 时钟同步
Zookeeper 集群节点时钟须保持同步。
要自动化实现时钟同步,可以参考 “Linux 9 自动化部署 NTP 服务”。
35.1.2.2 主机名解析
Ansible 控制节点能够解析 Zookeeper 节点的主机名,通过主机名访问 Zookeeper 节点。
要实现主机名称解析,可以在 Ansible 控制节点的 /etc/hosts
文件中指定 Zookeeper 节点的 IP、主机名条目,或者参考 “Linux 9 自动化部署 DNS 服务” 一文配置 DNS 服务。
35.1.2.3 账号权限
Ansible 控制节点可以免密登录 Zookeeper 节点,并能够免密执行 sudo。可以参考 “Linux 9 自动化部署 NTP 服务” 中的 “部署环境要求” 一节实现。
35.1.3 扩展知识
在本文的最后部分,演示了通过 Prometheus 自动化监控 Zookeeper 集群。如要完成此部分,需要准备好 Prometheus 监控系统。有关 Prometheus 监控系统的自动化部署,可以参考 ”Linux 9 自动化配置 Prometheus 监控系统“。
在满足以上要求后,开始 Zookeeper 集群的部署。
35.2 下载 Zookeeper 包
Linux 的 dnf 仓库没有提供 Zookeeper 的安装包,因此需要从 Apache Zookeeper 官网下载。应将下载包和安装配置 Zookeeper 分成两个 Ansible Role 实现。因为包下载一次即可,无需多次执行。
35.2.1 创建下载 Zookeeper 的角色
执行以下命令,创建 download_zookeeper
Role:
图 35.1 创建下载 Zookeeper 的角色ansible-galaxy role init --init-path ~/roles download_zookeeper
cd ~/roles/download_zookeeper
在 tasks/main.yml
文件中,编辑下载 Zookeeper 的任务:
---
# tasks file for download_zookeeper
- name: create download directory task
ansible.builtin.file:
path: "{{ download_path }}"
state: directory
- name: download and unarchive tarball task
ansible.builtin.unarchive:
src: "{{ download_url }}"
dest: "{{ download_path }}"
remote_src: true
extra_opts:
- --strip-components=1
35.2.2 创建下载 Zookeeper 的 Playbook
在 ~/playbooks/
目录下创建 deploy_zookeeper/
目录:
图 35.2 创建下载 Zookeeper 的 Playbookmkdir ~/playbooks/deploy_zookeeper
cd ~/playbooks/deploy_zookeeper
创建 download_zookeeper.yaml
Playbook 文件,内容如下:
---
- name: download zookeeper tarball play
hosts: localhost
become: false
gather_facts: false
vars_files:
- variables.yaml
roles:
- role: download_zookeeper
tags: download_zookeeper
...
创建变量文件:
mkdir vars
touch vars/variables.yaml
在 vars/variables.yaml
中添加需要的变量:
download_path: ~/software/zookeeper_tools/zookeeper
download_url: https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
35.2.3 下载安装包
执行 download_zookeeper.yaml
Playbook,下载安装包:
ansible-playbook download_zookeeper.yaml
图 35.3 下载 Zookeeper 安装包
使用 tree 命令查看下载文件的目录结构:
tree -L 1 ~/software/zookeeper_tools/zookeeper
图 35.4 Zookeeper 目录结构
下载的版本为当前稳定版,可以在 https://downloads.apache.org/zookeeper/stable/ 查看。
35.3 部署 JDK
Zookeeper 服务依赖 Java 环境才能运行,因此需要在运行 Zookeeper 的节点上部署 JDK。
有关 JDK 自动化部署的详细介绍,可以参考 ”Linux 9 自动化部署 JDK“。在 JDK 部署完成后,继续下面的步骤。
35.4 部署 Zookeeper 集群
在节点和安装包准备好后,本节讨论 Zookeeper 集群的安装。
35.4.1 设置 Local Facts 变量
Zookeeper 集群依赖 SID 进行快速选举,SID 的值必须写入数据目录的 myid
文件中。通过定义 Local Facts 变量,为节点设置 SID 值。
创建三个 Facts 文件:
for sid in $(seq 1 3); do echo -e "[var]\nsid=${sid}" > zk${sid}.fact; done
图 35.5 创建 Local Facts 变量文件
为 Zookeeper 节点创建 /etc/ansible/facts.d/
目录:
ansible zookeeper -m file -a "path=/etc/ansible/facts.d state=directory" -b
图 35.6 创建 facts.d 目录
将三个文件拷贝到对应节点的 /etc/ansible/facts.d/
:
图 35.7 拷贝 fact 文件到对应的托管节点ansible zk1.server.aiops.red -m copy -a "src=zk1.fact dest=/etc/ansible/facts.d/zk.fact" -b
ansible zk2.server.aiops.red -m copy -a "src=zk2.fact dest=/etc/ansible/facts.d/zk.fact" -b
ansible zk3.server.aiops.red -m copy -a "src=zk3.fact dest=/etc/ansible/facts.d/zk.fact" -b
35.4.2 创建部署 Zookeeper 的角色
使用以下命令创建 Role:
图 35.8 创建部署 Zookeeper 的角色ansible-galaxy role init --init-path ~/roles deploy_zookeeper
cd ~/roles/deploy_zookeeper
35.4.2.1 创建用户
使用独立用户运行服务,可以提高隔离性和安全性。因此,第一个任务是创建用于启动 Zookeeper 服务的用户。
编辑 tasks/main.yml
文件,添加创建用户的任务:
- name: "create {{ user_name }} user task"
ansible.builtin.user:
name: "{{ user_name }}"
home: "{{ home_dir }}"
shell: /sbin/nologin
需要为任务定义两个变量,user_name
表示创建的用户名;home_dir
用户家目录。Zookeeper 文件将被安装在 home_dir
目录。
变量可以在 defaults/main.yml
文件或 vars/main.yml
文件中定义,前者定义的变量,可以被 Playbook 中的变量覆盖。
35.4.2.2 创建数据目录
Zookeeper 将所有配置、状态数据持久化在磁盘上,这样即使重启后,服务仍能正常工作。
在 tasks/main.yml
中编写第二个任务,为 Zookeeper 创建数据目录:
- name: create data directory task
ansible.builtin.file:
path: "{{ home_dir }}/data/zookeeper"
state: directory
owner: "{{ user_name }}"
group: "{{ user_name }}"
mode: 0755
35.4.2.3 拷贝二进制文件
将下载好的 Zookeeper 安装文件,拷贝到 home_dir
下。编辑 tasks/main.yml
文件,添加以下两个任务:
- name: copy the installation file task
ansible.posix.synchronize:
src: "{{ download_path }}"
dest: "{{ home_dir }}"
- name: set the file owner task
ansible.builtin.shell: "chown {{ user_name }}.{{ user_name }} {{ home_dir }} -R"
ansible.posix.synchronize 模块在此处以 root 用户同步文件。因此,在文件同步结束后,使用 chown 修改目录的属主及属组。
35.4.2.4 配置文件模板
Zookeeper 集群中的节点应为奇数个,这样就能形成有效的法定人数。法定人数是指在提交事务前,需要同意的最小节点数。法定人数为奇数,才能形成多数。偶数个节点可能导致平局,这将意味着节点不会达成多数或共识。
在 templates/
目录下,创建 zoo.cfg.j2
文件,内容如下:
tickTime=2000
dataDir={{ home_dir }}/data/zookeeper
clientPort={{ client_port }}
maxClientCnxns=60
initLimit=10
syncLimit=5
{% for host in groups['zookeeper'] %}
server.{{ hostvars[host].ansible_local.zk.var['sid'] }}={{ host }}:{{ follower_port }}:{{ leader_port }}
{% endfor %}
模板配置文件解析:
- tickTime:单位毫秒。Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,每个 tickTime 时间都会发送一个心跳。
- dataDir:Zookeeper 保存数据的目录。
- clientPort:客户端连接 Zookeeper 服务器的端口,Zookeeper 监听该端口,接受客户端的访问请求。默认 TCP 2181。
- maxClientCnxns:单个客户端与单台服务器的连接数限制,是 ip 级别的,默认 60,如果设置为 0,表示不作任何限制。
- initLimit:Follower 在启动过程中,会从 Leader 同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader 允许 Follower 在 initLimit 时间内完成这个工作。
- syncLimit:在运行过程中,Leader 负责与 Zookeeper 集群中所有机器进行通信,例如通过一些心跳检测机制,检测机器的存活状态。如果 Leader 发出心跳包在 syncLimit 之后,还没有从 Follower 那里收到响应,那么就认为这个 Follower 已经下线。
- server.sid:sid 是一个数字,与
myid
文件中的值一致。右边可以配置两个端口,第一个端口用于 Follower 和 Leader 之间的数据同步和其它通信,第二个端口用于 Leader 选举过程中投票通信。
sid 的值来自于之前定义的 Local Facts 变量,通过 hostvars[host]
从对应主机获取 sid。
准备好了模板文件,接下来在 tasks/main.yml
中定义将模板配置文件渲染为 Zookeeper 配置文件的任务:
- name: render configuration file task
ansible.builtin.template:
src: zoo.cfg.j2
dest: "{{ home_dir }}/zookeeper/conf/zoo.cfg"
notify: restart zookeeper service handler
notify: restart zookeeper service handler 定义了当配置文件有变化时,执行 ”restart zookeeper service handler“,重启 Zookeeper 服务。
35.4.2.5 myid 模板
为 Zookeeper 生成 myid
文件,该文件的内容应与 sid 一致。创建 templates/myid.j2
文件,内容如下:
{{ ansible_local.zk.var['sid'] }}
在 tasks/main.yml
中定义将模板渲染为 myid
文件的任务:
- name: render myid file task
ansible.builtin.template:
src: myid.j2
dest: "{{ home_dir }}/data/zookeeper/myid"
myid
文件应存放在 Zookeeper 的 dataDir
目录下。
35.4.2.6 单元文件模板
创建启动 Zookeeper 服务的单元文件模板,templates/zookeeper.service.j2
内容如下:
[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target
[Service]
Type=forking
WorkingDirectory={{ home_dir }}/zookeeper
User={{ user_name }}
Group={{ user_name }}
ExecStart={{ home_dir }}/zookeeper/bin/zkServer.sh start {{ home_dir }}/zookeeper/conf/zoo.cfg
ExecStop={{ home_dir }}/zookeeper/bin/zkServer.sh stop {{ home_dir }}/zookeeper/conf/zoo.cfg
ExecReload={{ home_dir }}/zookeeper/bin/zkServer.sh restart {{ home_dir }}/zookeeper/conf/zoo.cfg
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=default.target
在 tasks/main.yml
中定义将模板文件渲染为 systemd 单元文件的任务:
- name: render systemd unit file task
ansible.builtin.template:
src: zookeeper.service.j2
dest: /usr/lib/systemd/system/zookeeper.service
35.4.2.7 设置防火墙
需要在 Firewalld 上开启 Zookeeper 服务的相关端口。编辑 tasks/main.yml
文件,添加以下任务:
- name: turn on zk ports in the firewalld task
ansible.builtin.firewalld:
port: "{{ item }}"
permanent: true
immediate: true
state: enabled
with_items:
- "{{ client_port }}/tcp"
- "{{ follower_port }}/tcp"
- "{{ leader_port }}/tcp"
35.4.2.8 设置 JAVA_HOME
Zookeeper 在启动时,需要为其指定 JAVA_HOME
变量。编辑 tasks/main.yml
文件,添加在 zkEnv.sh
文件中设置该变量的任务:
- name: set JAVA_HOME in zkEnv.sh file task
ansible.builtin.lineinfile:
path: "{{ home_dir }}/zookeeper/bin/zkEnv.sh"
line: "export JAVA_HOME=/opt/jdk19"
insertafter: "/usr/bin/env"
JAVA_HOME
变量的值要设置为真实值,通过 “Linux 9 自动化部署 JDK” 安装的 JDK,路径为 /opt/jdk19
。
35.4.2.9 启动 Zookeeper 集群
安装和配置已经进行完成,可以启动 Zookeeper 服务了。编辑 tasks/main.yml
文件,添加启动任务:
- name: enable and start the zk service task
ansible.builtin.systemd:
name: zookeeper.service
state: started
enabled: true
daemon_reload: true
在这个任务中,会重载单元文件,启动 zookeeper 服务,并把该服务设置为开机启动。
35.4.2.10 添加 Handlers
在 handlers/main.yml
文件中,添加名为 ”restart zookeeper service handler“ 的 Handlers:
---
# handlers file for deploy_zookeeper
- name: restart zookeeper service handler
ansible.builtin.systemd:
name: zookeeper.service
state: restarted
35.4.3 创建部署 Zookeeper 的 Playbook
创建 ~/playbooks/deploy_zookeeper/deploy.yaml
文件,内容如下:
---
- name: deploy zookeeper cluster play
hosts: zookeeper
become: true
gather_facts: true
vars_files:
- variables.yaml
roles:
- role: deploy_zookeeper
tags: deploy_zookeeper
...
Playbook 文件中用到了 variables.yaml
变量文件,在该文件中添加需要的变量。
35.4.4 提供变量
vars/variables.yaml
文件内容如下:
download_path: ~/software/zookeeper_tools/zookeeper
download_url: https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
home_dir: /opt/zk
user_name: zk
client_port: 2181
follower_port: 2888
leader_port: 3888
35.4.5 部署集群
执行 deploy.yaml
Playbook 文件,部署 Zookeeper 集群:
ansible-playbook deploy.yaml
图 35.9 部署 Zookeeper 集群
35.5 验证 Zookeeper
在集群成功部署后,可以对集群进行测试。
登录 Zookeeper 集群的某个节点,执行 zkCli.sh 命令:
ssh zk1.server.aiops.red
sudo su -
/opt/zk/zookeeper/bin/zkCli.sh -server zk2.server.aiops.red:2181
执行以下命令,创建、查看、删除 znode:
图 35.10 验证 Zookeeper 集群# 创建
create /hello "aiops"
# 查看
get /hello
# 删除
delete /hello
znodes 是 ZooKeeper 中的基本抽象,类似于文件系统上的文件和目录。ZooKeeper 将其数据维护在分层命名空间中,znodes 是该命名空间的数据寄存器。
成功测试了两个 ZooKeeper 节点之间的连接。还通过 create、get 和 delete znodes 学习了基本的 znode 管理。Zookeeper 集群已成功部署,可以使用 ZooKeeper 了。
35.6 自动化监控 Zookeeper
本节讨论 Zookeeper 的自动化监控。监控服务使用 Prometheus 完成,因此需要准备好 Prometheus 监控系统。可参考上一篇文章完成 Prometheus 的自动化部署。
35.6.1 启用 MetircsProvider
从 3.6.0 版本开始,Zookeeper 内置的指标系统提供了丰富的指标,方便用户对其监控。编辑 Zookeeper 模板配置文件 templates/zoo.cfg.j2
,添加 metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
:
tickTime=2000
dataDir={{ home_dir }}/data/zookeeper
clientPort={{ client_port }}
maxClientCnxns=60
initLimit=10
syncLimit=5
{% for host in groups['zookeeper'] %}
server.{{ hostvars[host].ansible_local.zk.var['sid'] }}={{ host }}:{{ follower_port }}:{{ leader_port }}
{% endfor %}
metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
该配置启用了 Prometheus MetricsProvider,Zookeeper 服务将新增对 TCP 7000 端口的监听。
编辑 Zookeeper Role tasks/main.yml
,在 firewalld 任务增加 7000 端口:
- name: turn on zk ports in the firewalld task
ansible.builtin.firewalld:
port: "{{ item }}"
permanent: true
immediate: true
state: enabled
with_items:
- "{{ client_port }}/tcp"
- "{{ follower_port }}/tcp"
- "{{ leader_port }}/tcp"
- "7000/tcp"
再次运行 Playbook 使配置文件生效:
ansible-playbook deploy.yaml
图 35.11 再次执行 Playbook,启用 Prometheus MetricsProvider
35.6.2 Prometheus 收集 Zookeeper 指标
创建名为 zk_monitor.yaml
Playbook 文件,添加以下任务向 Prometheus 的配置文件插入抓取 Zookeeper 目标的配置:
- name: zk monitor play
hosts: prometheus
become: true
gather_facts: false
tasks:
- name: insert scrape zk block task
ansible.builtin.blockinfile:
path: /opt/monitor/prometheus/prometheus.yaml
insertafter: EOF
marker: "# add zk scrape {mark}"
marker_begin: "begin ==>"
marker_end: "end ==>"
create: true
state: present
block: |2
- job_name: "zk"
static_configs:
- targets:
{% for host in groups["zookeeper"] %}
- "{{ host }}:7000"
{% endfor %}
notify: restart prometheus service handler
ansible.builtin.blockinfile 任务将在 promethues.yaml
文件末尾添加抓取 Zookeeper 指标的配置。
有了指标,接下来配置 Dashboard。
35.6.3 配置 Zookeeper Dashboard
在 zk_monitor.yaml
文件中,新增下载 Grafana Dashboard 的任务。因为 Grafana 与 Prometheus 是同一主机,因此该任务与 “insert scrape zk block task” 任务定义在同一 Play 中:
- name: downlaod zookeeper dashboard json file task
ansible.builtin.get_url:
url: https://grafana.com/api/dashboards/10465/revisions/4/download
dest: /var/lib/grafana/dashboard/zookeeper.json
35.6.4 配置报警规则
创建 files/
目录,并在该目录下创建规则文件 zk_rule.yml
,内容如下:
groups:
- name: zk-alert-example
rules:
- alert: ZooKeeper server is down
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} ZooKeeper server is down"
description: "{{ $labels.instance }} of job {{$labels.job}} ZooKeeper server is down: [{{ $value }}]."
- alert: create too many znodes
expr: znode_count > 1000000
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} create too many znodes"
description: "{{ $labels.instance }} of job {{$labels.job}} create too many znodes: [{{ $value }}]."
- alert: create too many connections
expr: num_alive_connections > 50 # suppose we use the default maxClientCnxns: 60
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} create too many connections"
description: "{{ $labels.instance }} of job {{$labels.job}} create too many connections: [{{ $value }}]."
- alert: znode total occupied memory is too big
expr: approximate_data_size /1024 /1024 > 1 * 1024 # more than 1024 MB(1 GB)
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} znode total occupied memory is too big"
description: "{{ $labels.instance }} of job {{$labels.job}} znode total occupied memory is too big: [{{ $value }}] MB."
- alert: set too many watch
expr: watch_count > 10000
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} set too many watch"
description: "{{ $labels.instance }} of job {{$labels.job}} set too many watch: [{{ $value }}]."
- alert: a leader election happens
expr: increase(election_time_count[5m]) > 0
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} a leader election happens"
description: "{{ $labels.instance }} of job {{$labels.job}} a leader election happens: [{{ $value }}]."
- alert: open too many files
expr: open_file_descriptor_count > 300
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} open too many files"
description: "{{ $labels.instance }} of job {{$labels.job}} open too many files: [{{ $value }}]."
- alert: fsync time is too long
expr: rate(fsynctime_sum[1m]) > 100
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} fsync time is too long"
description: "{{ $labels.instance }} of job {{$labels.job}} fsync time is too long: [{{ $value }}]."
- alert: take snapshot time is too long
expr: rate(snapshottime_sum[5m]) > 100
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} take snapshot time is too long"
description: "{{ $labels.instance }} of job {{$labels.job}} take snapshot time is too long: [{{ $value }}]."
- alert: avg latency is too high
expr: avg_latency > 100
for: 1m
labels:
severity: warning
annotations:
summary: "Instance {{ $labels.instance }} avg latency is too high"
description: "{{ $labels.instance }} of job {{$labels.job}} avg latency is too high: [{{ $value }}]."
- alert: JvmMemoryFillingUp
expr: jvm_memory_bytes_used / jvm_memory_bytes_max{area="heap"} > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "JVM memory filling up (instance {{ $labels.instance }})"
description: "JVM memory is filling up (> 80%)\n labels: {{ $labels }} value = {{ $value }}\n"
将 zk_rule.yml
文件拷贝至 Prometheus 安装目录下:
- name: copy rule file to prometheus task
ansible.builtin.copy:
src: zk_rule.yml
dest: /opt/monitor/prometheus/zk_rule.yml
owner: monitor
group: monitor
在 Prometheus 配置文件 prometheus.yaml
插入引用 zk_rule.yml
规则文件的行:
- name: insert line
lineinfile:
path: /opt/monitor/prometheus/prometheus.yaml
insertafter: "rule_files:"
line: " - zk_rule.yml"
notify: restart prometheus service handler
在 zk_monitor.yaml
中定义 Handlers:
handlers:
- name: restart prometheus service handler
ansible.builtin.systemd:
name: prometheus.service
state: restarted
最后执行 zk_monitor.yaml
Playbook 文件:
ansible-playbook zk_monitor.yaml
图 35.12 监控 Zookeeper
35.6.5 查看监控页面
登录 Grafana,查看 Dashboard,点击 “Zookeeper by Prometheus”,Cluster 选择 “zk”,浏览器将显示 Zookeeper 的监控页面:
图 35.13 Zookeeper 监控页面在 Prometheus 的 rules 页面,能够看到为 Zookeeper 配置的报警规则,如下图:
图 35.14 Zookeeper 报警规则35.7 总结
本教程演示了 Zookeeper 集群的自动化部署、简单的数据操作,以及通过 Prometheus 对 Zookeeper 集群进行监控。教程同样适用于其他基于 RPM 的 Linux 发行版。