因此,碰巧我们在SaaS版本的LogSentinel上遇到了生产问题–我们的Elasticsearch停止了对新数据编制索引。 由于Elasticsearch只是辅助存储,因此没有数据丢失,但这给我们的客户带来了一些问题(他们无法在其仪表板上看到实时数据)。 以下是事后分析–发生了什么事情,发生了什么原因,我们如何处理它以及如何防止它。
让我从系统如何运行的背景开始–我们通过RESTful API(或syslog)接受审核跟踪条目(日志),并将其推送到Kafka主题。 然后使用Kafka主题将数据存储在主存储(Cassandra)中并对其进行索引,以便在Elasticsearch中更好地进行可视化和分析。 选择托管的AWS Elasticsearch服务是因为它节省了集群管理的所有开销,并且作为一家启动公司,我们希望最大程度地减少基础架构管理工作。 就像下面将要看到的那样,这是一种祝福和诅咒。
我们在许多元素上启用了警报,包括Elasticsearch存储空间和日志文件中的应用程序错误数。 这使我们能够快速响应问题。 因此触发了“大量应用程序错误”警报。 索引由于FORBIDDEN/8/index write
而被阻止。 我们有一个启用它的系统调用,因此我尝试运行它,但是不到一分钟后,它再次被阻止。 这意味着我们的Kafka使用者无法处理消息,这很好,因为我们在Kafka中有足够的消息保留期限,因此不会丢失任何数据。
我调查了这种阻止的可能原因。 根据Amazon的说法,其中有两个 -JVM内存压力增加和磁盘空间不足。 我检查了指标,一切看起来都很好– JVM内存压力几乎没有达到70%(阈值是75%),并且有超过200GiB的免费存储。 Elasticsearch应用程序日志中只有一个WARN(这是“节点故障”,但此后未报告任何问题)
这个问题还有另一个奇怪的方面–节点的数量是配置的两倍。 这通常在升级期间发生,因为AWS正在为Elasticsearch使用蓝色/绿色部署,但是我们最近没有进行任何升级。 这些额外的节点通常会在很短的一段时间后消失(在重新部署/升级准备就绪之后),但是在这种情况下它们不会消失。
无法通过SSH连接到实际机器,无法通过Elasticsearch手段取消阻止索引,无法关闭或重新启动节点,我提出了支持请求。 经过我们几次和几次交流后,问题已经明确并得到解决。
此问题的主要原因是2倍。 首先,我们有一个无法反映集群状态的配置–我们假设有更多的节点,而共享和副本配置意味着我们没有分配副本( 此处和此处的 碎片和副本更多 )。 最佳实践是使节点>副本数,以便每个节点获得一个副本(加上主分片)。 拥有未分配的分片副本本身并不坏,并且有合理的理由。 我们可能被认为是配置错误,但不是立即造成负面影响的一种。 我们之所以选择这些设置,部分原因是创建集群后无法在AWS中更改某些设置。 并且不支持打开和关闭索引。
第二个问题是AWS Elasticsearch逻辑,用于计算其断路器中阻止索引编制的可用存储。 因此,即使每个现有节点上都有200+ GiB可用空间,AWS Elasticsearch仍认为我们空间不足并阻止了索引编制。 我们无法看到这一点,因为我们只能看到可用的存储,而没有看到AWS认为可用的存储。 因此,计算将获得分片+副本的总数,然后将其乘以每个共享存储。 这意味着未分配副本不会占用实际空间,就好像它们已占用空间一样。 这种逻辑是违反直觉的(如果不是完全错误的话),几乎没有办法预测它。
发生蓝/绿部署时,将触发此逻辑–因此,在正常操作中,将检查实际的剩余存储空间,但是在升级期间,将触发基于分片的检查。 那已经阻塞了整个集群。 但是,什么触发了蓝绿色部署过程?
我们有时需要访问Kibana,并且由于严格的安全规则,默认情况下任何人都无法访问它。 因此,我们临时更改了访问策略,以允许从我们的办公室IP进行访问。 预计此更改不会触发新的部署,也永远不会导致这种变化。 但是,AWS文档指出:
在大多数情况下,以下操作不会导致蓝绿色部署:更改访问策略,更改自动快照时间,如果您的域具有专用主节点,则更改数据实例计数。
有一些例外。 例如,如果自从启动三个可用区支持以来就没有重新配置域,则Amazon ES可能会执行一次蓝/绿部署,以在可用区中重新分配专用主节点。
显然还有其他例外,其中之一发生在我们身上。 这就导致了蓝/绿部署,由于我们的配置有缺陷,这又触发了基于奇数逻辑的索引块,以假定未分配的副本占用了存储空间。
我们如何修复它-我们用更少的副本创建了索引,并开始了重新索引(它从主要来源获取数据并成批索引)。 这减小了占用空间,AWS手动干预以“取消”蓝/绿部署。 一旦知道了问题,修复就很容易了(由于其他索引配置的更改,我们仍然必须重新创建索引)。 (再次)说一下在解决问题和沟通方面,AWS支持有多好。
正如我在开始时所说的,这并不意味着有数据丢失,因为我们让Kafka将消息保留了足够的时间。 但是,一旦索引可写,我们就希望使用者继续使用上一条成功的消息–我们专门编写了事务行为,该行为仅在成功存储到主存储器中并成功建立索引之后才提交偏移量。 不幸的是,我们正在使用的kafka客户端打开了我们忽略的自动提交功能。 因此,消费者跳过了失败的消息。 它们仍然在Kafka中,我们正在使用单独的工具对其进行处理,但这向我们表明了我们的假设是错误的,并且代码调用了“ commit”这一事实,但这实际上并不意味着什么。
因此,故事的寓意是:
- 监视一切。 发生坏事,快速了解它们是一件好事。
- 检查您的生产配置,并确保它足以满足当前需求。 它是副本,JVM大小,磁盘空间,重试次数,自动缩放规则等。
- 请注意托管云服务。 他们节省了很多精力,但也使您失去了控制权。 他们可能遇到的问题是您唯一的选择就是联系支持部门。
- 如果提供托管服务,请确保显示有关潜在边缘情况的足够信息。 错误控制台,活动控制台或诸如此类,使客户可以了解发生了什么。
- 验证关于库默认设置的假设。 (理想情况下,如果您在当前的配置状态下执行了某些意外操作,则库应该警告您)
- 确保您的应用程序是容错的,即,一个组件中的故障不会停止整个世界,也不会导致数据丢失。
因此,总的来说,一个罕见的事件意外触发了蓝绿色部署,其中有缺陷的配置和有缺陷的可用空间计算的结合导致了不可写的集群。 幸运的是,没有数据丢失,至少我学到了一些东西。
翻译自: https://www.javacodegeeks.com/2020/03/an-aws-elasticsearch-post-mortem.html