并不是专业运维,如果有更好的想法欢迎讨论。
是的,最近我们对ZooKeeper
做了一些调整,而这一切都源自一次业务花里胡哨的操作。
当我们以为稳了的时候,往往就有业务从中作妖。
这不就来了吗。。
中间还涉及到ZK的升级、兼容性测试、压测等,之后会通过一篇新的文章来介绍。
背景
有一天运维突然收到告警,某个业务服务实例疯狂请求ZK,同时ZK节点总数飞快增长。
可以看到节点数已经快到80万了,立刻联系业务进行确认,最终定位到和业务定时任务有关。
- 根本原因
业务有个定时任务需要对海量用户进行推送,于是将用户分批拆成小任务交由不同的节点来处理,实现多个节点同时处理,其中拆分出来的小任务就是存在ZK里的。
而这个过程存在两个设计问题:
1、拆分的小任务在ZK中创建的是永久节点,并且小任务处理完后未删除节点;
2、当用户量快速膨胀,拆分出的小任务就会非常多,导致ZK中节点数快速增长。
日积月累,节点数快速增长,而业务实例也要不断的读取ZK拉取节点来获取小任务,容器Read流量突增。
- 引发的思考
从结果来看,对ZK的性能没有实际的影响。但是,这个过程也引发了我们的思考,过往我们对于基础组件的管理是粗放的,没有规则限制,也没有资源隔离,出了问题无法快速屏蔽影响,并且所有的业务都在使用同一个ZK集群,鸡蛋都在同一个篮子里。
因此是需要一定的控制、规则来对基础组件进行管理的,ZK本身也提供了一些默认的资源管理能力。
ZK资源管理能力
从ZK官方给出的配置及功能来看,对于资源的管理主要通过ACL
及quota
,其中ACL
实现基础的访问控制,quota
实现配额控制。
ACL
ZK通过ACL机制(访问控制列表)来实现对ZNode的访问控制,包含身份认证及权限两个部分。
- 身份认证
ZK提供了多种内置认证模式,包含world
、auth
、digest
、ip
和x509
,同时也提供自定义可插拔的鉴权插件入口。
认证模式 | 描述 |
---|---|
world | 新节点默认认证模式,代表任何人均可操作 |
auth | 使用当前会话中的认证用户 |
digest | 使用用户名:密码字符串生成MD5哈希,然后将其用作ACL标识 |
ip | 使用客户端主机IP作为ACL标识 |
x509 | 使用客户端X500主体作为ACL标识 |
看上去模棱两可,我们一会儿通过例子来理解会更简单。
- 访问控制权限
权限现类似Unix文件访问权限,分为一下几种类型:
Permission | Description |
---|---|
CREATE | 创建子节点 |
READ | 可以从节点获取数据并列出其子节点。 |
WRITE | 可以设置节点的数据 |
DELETE | 可以删除子节点 |
ADMIN | 可以设置权限 |
- ACL配置
ACL的配置通过get/setAcl
完成ZNode权限配置,当需要对具有权限的ZNode进行操作时,可以通过addauth
进行身份认证。
以比较常见前三种的认证模式为例,看看实际的例子。
- world模式
创建的新ZNode默认是这个认证模式,即所有人均可操作,同时权限包含全部crwda权限。
1 |
|
- auth模式
该模式下,会自动以当前会话认证的用户进行权限配置。
1 |
|
这里有一点需要特别注意,单个会话可以添加多个身份认证,如果此时使用auth
模式进行ACL配置,那么会为已认证的多个用户身份都添加上权限。
所以,在使用auth
模式时,建议先通过whoami
确认当前会话认证的用户身份,再进行ACL配置。
- digest模式
这种模式就比较简单了,直接为指定的用户设置节点权限。
1 |
|
其中,digest模式配置ACL时,需要配置编码的认证信息,方式如下:
1 |
|
注意事项!!!,子节点不会继承ACL配置,意味着新创建的子节点为所有人可操作
Quota
Quota
机制是ZK对ZNode
及其子节点的数量、大小进行控制的一种方法,从3.5.0
版本就开始支持,但是在旧版本中仅支持软规则Quota
,即当ZNode
及其子节点的数量、大小超过限制后,仅会在日志中打印异常,不会强行限制令操作失败,直到3.7.0
版本才支持硬规则Quota
。
1 |
|
quota参数取值 | 参数描述 |
---|---|
“n” | 节点下能够创建的最大子节点数量,软规则,超过阈值仅日志告警 |
“b” | 节点下能够创建的数据总大小的上限,单位字节,软规则 |
“N” | 节点下能够创建的最大子节点数量,硬规则,超过阈值则操作失败 |
“B” | 节点下能够创建的数据总大小的上限,单位字节,硬规则 |
其中,只有设置了Quota
后,才可以通过listquota
查看节点下的子节点数量、大小。
注意事项!!!,在新版本ZK中(3.8.1已测试)需要在ZK配置文件中,加入enforceQuota=true,才能使用硬规则Quota
当前节点也会占用
Quota
配额。[zk: 127.0.0.1:53412(CONNECTED) 18] set /test test_content # 无子节点,仅设置值 [zk: 127.0.0.1:53412(CONNECTED) 15] setquota -n 100 /test [zk: 127.0.0.1:53412(CONNECTED) 19] listquota /test absolute path is /zookeeper/quota/test/zookeeper_limits Output quota for /test count=100,bytes=-1=;byteHardLimit=-1;countHardLimit=-1 Output stat for /test count=1,bytes=12 # 节点数量占用1,节点大小占用12字节
SuperDigest
SuperDigest
是一种特殊的身份认证方式,以”超级用户”的身份访问任何ZNode
节点,对于该用户是不会进行ACL检查的,在3.2.0
版本后,该认证方式默认关闭。
若需要开启,则需要在ZK配置文件中进行设置:
1 |
|
配置后,在ZK中就可以通过该用户操作任意节点。
1 |
|
ZK资源管理规则
基于以上能力,我们整理了业务申请、使用ZK资源的管理规则。
业务侧
- 限制根目录访问,仅超管账号可操作,限制业务自行创建一级节点;
- 各业务需使用ZK时,申请一级节点作为业务独立节点,隔离不同业务,所有业务新建节点均在申请的一级节点下,例如用户中心服务,则申请
/usercenter
,业务新建节点为/usercenter/abc
; - 为业务分配身份认证信息,并为业务一级节点配置
ACL
,仅授权业务身份可访问(仅有cwrd权限); - 为业务一级节点配置
Quota
配额,限制业务节点资源使用,包含子节点数量及大小限制。
通过上面的方式,可以实现业务资源的隔离和限制。
运维侧
- 业务节点管理
当业务节点有了ACL
配置,那就面临一个问题,运维在必要时如何操作业务节点,例如之前提到业务新建大量节点,需要运维介入进行删除。
在通过一级节点资源隔离后,业务节点对应不同的身份认证,运维操作需要根据不同的业务使用不同的身份认证,这对运维来说并不友好。
这就使用上了SuperDigest
,我们为运维配置了”超级用户”,可操作所有节点,在必要时可以通过该用户进行运维行为。
- 监控和告警
同时还有一个运维需要面对的问题,就是监控和告警。Quota
配额决定的业务使用资源的上限,但是运维侧需要对业务资源的使用情况有感知,这就涉及到Quota
的监控。
我们的组件监控主要通过组件exporter
+Prometheus
+Grafana
来完成监控数据的采集、存储和展示。
在ZooKeeper
中,有对应的Quota Metrics
来反映当前的Quota
配额使用情况,从3.8.0
版本开始提供。
对,没错,3.8.0才有。。。 3.5.0 quota软规则 3.7.0 quota硬规则 3.8.0 quota metrics to prometheus
看了一下源码,暴露出来的指标包含一级节点的Quota
配额限制、使用量及异常数。
其中NAMESPACE
可以理解为一级子节点,有了Quota Metrics
就可以进行监控,当某个一级节点的配额使用超过一定比例时,就可以进行告警。
自动化资源申请
有了ZK资源管理规则,业务需要使用时就会找到运维进行申请,整个配置的过程还是比较繁琐且容易出错的,所以为了减轻运维同学的负担,同时避免人工误操作带来的错误或故障,我们提供了自动化的资源申请流程,业务可自行进行申请。
业务提供流水线申请ZK资源,技术经理审核完后自动执行申请操作,返回给业务对应的一级目录信息、身份认证信息。
总结
通过这次实践,我们整理了一些基础的ZooKeeper资源管理规则,以此来规范我们的资源申请和使用。
从基础资源和设施的管理角度上看,我们其实还有很多部分是空白的,更多都是提供资源,但是并不做管理,当没有规范约束时,就容易带来问题。
对于组件的管理和建设包含很多方面,未来的路还很长,需要一点点去弥补。