Py学习  »  Elasticsearch

Q新闻丨MongoDB勒索软件已波及上万数据库!配置高性能Elasticsearch集群的9个小贴士

InfoQ • 7 年前 • 2058 次点击  
编辑|小智
本周要闻:MongoDB勒索软件已波及上万数据库!经验总结:配置高性能Elasticsearch集群的9个小贴士。
MongoDB勒索软件已波及上万数据库

无须身份验证的开放式MongoDB数据库实例正在遭受多个黑客组织的攻击,被攻破的数据库内容会被加密,受害者必须支付赎金才能找回自己的数据。

攻击者利用配置存在疏漏的开源MongoDB数据库展开了一系列勒索行为。此番针对MongoDB的勒索行为最早是由GDI Foundation的安全研究人员Victor Gevers在2016年12月27日发现的,在这之后影响陆续扩大,目前至少有五个不同黑客组织控制了上万个数据库实例。

截至目前,最后一个加入此次MongoDB勒索行动的黑客组织是由安全研究人员Nial Merrigan在1月6日发现的。目前,MongoDB攻击者的身份信息只有用于支付赎金的电子邮件地址,最新加入的黑客组织所用的邮件地址为3lix1r@mail2tor.com,该地址已攻陷至少17个MongoDB实例,要求受害者支付0.25个比特币才能找回数据。

目前在Google Docs上有一个列表,其中列出了参与此次攻击的黑客组织名单,具体数量还在增加中。攻击者所要求支付的金额各异,最低仅0.15个比特币,但也有高达1个比特币的赎金。2017年至今,比特币的价值上下波动,截止1月6日,具体金额约等于892美元。列表见:

https://docs.google.com/spreadsheets/d/1QonE9oeMOQHVh8heFIyeqrjfKEViL0poLnY8mAakKhM/edit#gid=0

此次针对MongoDB的攻击非常简单,利用了配置有误且可公开访问的数据库,无须具备相应的管理员凭据即可展开攻击。一旦攻击者登录到开放的数据库,随后会全面夺取控制权并窃取或加密数据库,被勒索的受害者必须支付赎金才能找回自己的数据。

很多MongoDB数据库处于开放状态,这种情况早已存在。2015年12月,安全研究人员Chris Vickery就曾使用Shodan搜索工具找到了很多端口开放的MongoDB服务器。当时Vickery甚至找到了一个被Mac OS X工具软件MacKeeper的开发者Kromtech使用的,配置存在疏漏的MongoDB数据库。

Shodan的创始人John Matherly跟进了Vickery的研究结果,并在2015年12月称,当时互联网上共有至少35,000个可公开访问,无须身份验证的MongoDB实例,一年过去了,直到2017年1月,开放式MongoDB数据库的数量不降反增,估计目前共有多达99,000个数据库处于风险中。

作为应对此次MongoDB安全隐患的有效措施,数据库管理员需要参考MongoDB网站上提供的安全清单进行排查。首先需要“启用访问控制并强制进行身份验证”。

安全研究人员对eWEEK表示,MongoDB被攻击者进行勒索完全在意料之中。

“考虑到MongoDB的流行度以及在生产环境中的普及率,以开源的数据库作为目标并不会让人惊讶。”Dome9共同创始人兼首席执行官Zohar Alon向eWEEK说到:“通常来说,数据库部署过程中的配置疏漏和疏忽就会导致可被攻击者利用的弱点。”

Alon还补充说,用户的人为错误与不够强的安全意识也会威胁到云环境中运行的工作负载。他建议在使用开源数据库等第三方软件之前,用户应该自学相关知识,掌握最佳实践和已知弱点等内容。

“有趣的是,大部分人认为数据库是足够安全的,因为可以受到防火墙和数据中心的保护,”Jean-François Dubé首席技术官RiskVision告诉eWEEK:“问题在于攻击者依然可以通过消费者所用的端点和第三方连接访问这些服务器并获取信息。”

Dubé建议总的来说,应当定期对数据库进行风险评估。

“使用风险评估工具对数据库进行近乎实时监视的企业,会在加密后的数据离开数据库时更清楚地发现这一切,”他说。

Mimecast公司网络安全战略师Matthew Gardiner评论说,此次MongoDB被攻击完全没有让他感到意外。

“一处开放的,无须身份验证的,存有宝贵数据的系统,或其他任何重要的系统,被互联网将规模放大上千倍后,最大的问题在于:攻击者为什么等到现在才开始下手?”Gardiner说。

本文翻译已获授权,原文链接:

http://www.eweek.com/security/mongodb-ransomware-impacts-over-10000-databases.html

本文译者:大愚若智

配置高性能Elasticsearch集群的9个小贴士

Loggly服务底层的很多核心功能都使用了Elasticsearch作为搜索引擎。就像Jon Gifford(译者注:Loggly博客作者之一)在他近期关于“Elasticsearch vs Solr”的文章中所述,日志管理在搜索技术方面产生了一些苛刻的需求,为满足这些需求,必须能够:

在超大规模数据集上可靠地进行准实时索引 - 在我们的案例中,每秒有超过100,000个日志事件

与此同时,在该索引上可靠高效地处理超大量的搜索请求

当时我们正在构建Gen2日志管理服务,想保证使用的所有Elasticsearch配置信息,可以获得最优的索引和搜索性能。悲剧的是,我们发现想在Elasticsearch文档里找到这样的信息非常困难,因为它们不只在一个地方。本文总结了我们的学习经验,可作为一个配置属性的参考检查单(checklist)用于优化你自己应用中的ES。

https://www.loggly.com/blog/nine-tips-configuring-elasticsearch-for-high-performance/

小贴士1:规划索引、分片 以及集群增长情况

ES使得创建大量索引和超大量分片非常地容易,但更重要的是理解每个索引和分片都是一笔开销。如果拥有太多的索引或分片,单单是管理负荷就会影响到ES集群的性能,潜在地也会影响到可用性方面。这里我们专注于管理负荷,但运行大量的索引/分片依然会非常显著地影响到索引和检索性能。

我们发现影响管理负荷的最大因素是集群状态数据的大小,因为它包含了集群中每个索引的所有mapping数据。我们曾经一度有单个集群拥有超过900MB的集群状态数据。该集群虽然在运行但并不可用。

让我们通过一些数据来了解到底发生了什么……

假如有一个索引包含50k的mapping数据(我们当时是有700个字段)。如果每小时生成一个索引,那么每天将增加24 x 50k的集群状态数据,或者1.2MB。如果需要在系统中保留一年的数据,那么集群状态数据将高达438MB(以及8670个索引,43800个分片)。如果与每天一个索引(18.25MB,365个索引,1825个分片)作比较,会看到每小时的索引策略将会是一个完全不同的境况。

幸运的是,一旦系统中有一些真实数据的话,实际上非常容易做这些预测。我们应当能够看到集群必须处理多少状态数据和多少索引/分片。在上到生产环境之前真的应该演练一下,以便防止凌晨3:00收到集群挂掉的电话告警。

在配置方面,我们完全可以控制系统中有多少索引(以及有多少分片),这将让我们远离危险地带。

小贴士2:在配置前了解集群的拓扑结构

Loggly通过独立的master节点和data节点来运行ES。这里不讨论太多的部署细节(请留意后续博文),但为了做出正确的配置选择,需要先确定部署的拓扑结构。

另外,我们为索引和搜索使用单独的ES client节点。这将减轻data节点的一些负载,更重要的是,这样我们的管道就可以和本地客户端通信,从而与集群的其他节点通信。

可通过设置以下两个属性的值为true或false来创建ES的data节点和master节点:

Master node: node.master:true node.data:false

Data node: node.master:false node.data:true

Client node: node.master:false node.data:false

以上是相对容易的部分,现在来看一些值得关注的ES高级属性。对大多数部署场景来说默认设置已经足够了,但如果你的ES使用情况和我们在log管理中遇到的一样难搞,你将会从下文的建议中受益良多。

小贴士3: 内存设置

Linux把它的物理RAM分成多个内存块,称之为分页。内存交换(swapping)是这样一个过程,它把内存分页复制到预先设定的叫做交换区的硬盘空间上,以此释放内存分页。物理内存和交换区加起来的大小就是虚拟内存的可用额度。

内存交换有个缺点,跟内存比起来硬盘非常慢。内存的读写速度以纳秒来计算,而硬盘是以毫秒来计算,所以访问硬盘比访问内存要慢几万倍。交换次数越多,进程就越慢,所以应该不惜一切代价避免内存交换的发生。

ES的mlockall属性允许ES节点不交换内存。(注意只有Linux/Unix系统可设置。)这个属性可以在yaml文件中设置:

bootstrap.mlockall: true

在5.x版本中,已经改成了bootstrap.memory_lock: true.

mlockall默认设置成false,即ES节点允许内存交换。一旦把这个值加到属性文件中,需要重启ES节点才可生效。可通过以下方式来确定该值是否设置正确:

curl http://localhost:9200/_nodes/process?pretty

如果你正在设置这个属性,请使用-DXmx选项或ES_HEAP_SIZE属性来确保ES节点分配了足够的内存。

小贴士4:discovery.zen属性控制ElasticSearch的发现协议

Elasticsearch默认使用服务发现(Zen discovery)作为集群节点间发现和通信的机制。Azure、EC2和GCE也有使用其他的发现机制。服务发现由discovery.zen.*开头的一系列属性控制。

在0.x和1.x版本中同时支持单播和多播,且默认是多播。所以要在这些版本的ES中使用单播,需要设置属性discovery.zen.ping.multicast.enabled为false。

从2.0开始往后服务发现就仅支持单播了。

首先需要使用属性discovery.zen.ping.unicast.hosts指定一组通信主机。方便起见,在集群中的所有主机上为该属性设置相同的值,使用集群节点的名称来定义主机列表。

属性discovery.zen.minimum_master_nodes决定了有资格作为master的节点的最小数量,即一个应当“看见”集群范围内运作的节点。如果集群中有2个以上节点,建议设置该值为大于1。一种计算方法是,假设集群中的节点数量为N,那么该属性应该设置为N/2+1。

Data和master节点以两种不同方式互相探测:

通过master节点ping集群中的其他节点以验证他们处于运行状态通过集群中的其他节点ping master节点以验证他们处于运行状态或者是否需要初始化一个选举过程

节点探测过程通过discover.zen.fd.ping_timeout属性控制,默认值是30s,决定了节点将会等待响应多久后超时。当运行一个较慢的或者拥堵的网络时,应该调整这个属性;如果在一个慢速网络中,将该属性调大;其值越大,探测失败的几率就越小。

Loggly的discovery.zen相关属性配置如下:

discovery.zen.fd.ping_timeout: 30s

discovery.zen.minimum_master_nodes: 2

discovery.zen.ping.unicast.hosts: [“esmaster01″,”esmaster02″,”esmaster03″]

以上属性配置表示节点探测将在30秒内发生,因为设置了discovery.zen.fd.ping_timeout属性。另外,其他节点应当探测到最少两个master节点(我们有3个master)。我们的单播主机是esmaster01、 esmaster02、esmaster03。

小贴士5:当心DELETE _all

必须要了解的一点是,ES的DELETE API允许用户仅仅通过一个请求来删除索引,支持使用通配符,甚至可以使用_all作为索引名来代表所有索引。例如:

curl -XDELETE ‘http://localhost:9200/*/’

这个特性非常有用,但也非常危险,特别是在生产环境中。在我们的所有集群中,已通过设置action.destructive_requires_name:true来禁用了它。

这项配置在1.0版本中开始引用,并取代了0.90版本中使用的配置属性disable_delete_all_indices。

小贴士6:使用Doc Values

2.0及以上版本默认开启Doc Values特性,但在更早的ES版本中必须显式地设置。当进行大规模的排序和聚合操作时,Doc Values相比普通属性有着明显的优势。本质上是将ES转换成一个列式存储,从而使ES的许多分析类特性在性能上远超预期。

为了一探究竟,我们可以在ES里比较一下Doc Values和普通属性。

当使用一个普通属性去排序或聚合时,该属性会被加载到属性数据缓存中。一个属性首次被缓存时,ES必须分配足够大的堆空间,以便能保存每一个值,然后使用每个文档的值逐步填充。这个过程可能会耗费一些时间,因为可能需要从磁盘读取他们的值。一旦这个过程完成,这些数据的任何相关操作都将使用这份缓存数据,并且会很快。

如果尝试填充太多的属性到缓存,一些属性将被回收,随后再次使用到这些属性时将会强制它们重新被加载到缓存,且同样有启动开销。为了更加高效,人们会想到最小化或淘汰,这意味着我们的属性数量将受限于此种方式下的缓存大小。

相比之下,Doc Values属性使用基于硬盘的数据结构,且能被内存映射到进程空间,因此不影响堆使用,同时提供实质上与属性数据缓存一样的性能。当这些属性首次从硬盘读取数据时仍然会有较小的启动开销,但这会由操作系统缓存去处理,所以只有真正需要的数据会被实际读取。

Doc Values因此最小化了堆的使用(因为垃圾收集),并发挥了操作系统文件缓存的优势,从而可进一步最小化磁盘读操作的压力。

小贴士7:Elasticsearch配额类属性设置指南

分片分配就是分配分片到节点的过程,可能会发生在初始化恢复、副本分配、或者集群再平衡的阶段,甚至发生在处理节点加入或退出的阶段。

cluster.routing.allocation.cluster_concurrent_rebalance决定了允许并发再平衡的分片数量。这个属性需要根据硬件使用情况去适当地配置,比如CPU个数、IO负载等。如果该属性设置不当,将会影响ES的索引性能。

cluster.routing.allocation.cluster_concurrent_rebalance:2

默认值是2,表示任意时刻只允许同时移动2个分片。最好将该属性设置得较小,以便压制分片再平衡,使其不影响索引。

另一个分片分配相关属性是cluster.routing.allocation.disk.threshold_enabled。如果该属性设备为true(默认值),在分配分片到一个节点时将会把可用的磁盘空间算入配额内。关闭该属性会导致ES可能分配分片到一个磁盘可用空间不足的节点,从而影响分片的增长。

当打开时,分片分配会将两个阀值属性加入配额:低水位和高水位。

低水位定义ES将不再分配新分片到该节点的磁盘使用百分比。(默认是85%)高水位定义分配将开始从该节点迁移走分片的磁盘使用百分比。(默认是90%)

这两个属性都可以被定义为磁盘使用的百分比(比如“80%”表示80%的磁盘空间已使用,或者说还有20%未使用),或者最小可用空间大小(比如“20GB”表示该节点还有20GB的可用空间)。

如果有很多的小分片,那么默认值就非常保守了。举个例子,如果有一个1TB的硬盘,分片是典型的10GB大小,那么理论上可以在该节点上分配100个分片。在默认设置的情况下,只能分配80个分片到该节点上,之后ES就认为这个节点已经满了。

为得到适合的配置参数,应该看看分片到底在变多大之后会结束他们的生命周期,然后从这里反推,确认包括一个安全系数。在上面的例子中,只有5个分片写入,所以需要一直确保有50GB的可用空间。对于一个1TB的硬盘,这个情形会变成95%的低水位线,并且没有安全系数。额外的,比如一个50%的安全系数,意味着应该确保有75GB的可以空间,或者一个92.5%的低水位线。

小贴士8:Recovery属性允许快速重启

ES有很多恢复相关的属性,可以提升集群恢复和重启的速度。最佳属性设置依赖于当前使用的硬件(硬盘和网络是最常见的瓶颈),我们能给出的最好建议是测试、测试、还是测试。

想控制多少个分片可以在单个节点上同时恢复,使用:

cluster.routing.allocation.node_concurrent_recoveries

恢复分片是一个IO非常密集的操作,所以应当谨慎调整该值。在5.x版本中,该属性分为了两个:

cluster.routing.allocation.node_concurrent_incoming_recoveries

cluster.routing.allocation.node_concurrent_outgoing_recoveries

想控制单个节点上的并发初始化主分片数量,使用:

cluster.routing.allocation.node_initial_primaries_recoveries

想控制恢复一个分片时打开的并行流数量,使用:

indices.recovery.concurrent_streams

与流数量密切相关的,是用于恢复的总可用网络带宽:

indices.recovery.max_bytes_per_sec

除了所有这些属性,最佳配置将依赖于所使用的硬件。如果有SSD硬盘以及万兆光纤网络,那么最佳配置将完全不同于使用普通磁盘和千兆网卡。

以上所有属性都将在集群重启后生效。

小贴士9:线程池属性防止数据丢失

Elasticsearch节点有很多的线程池,用于提升一个节点中的线程管理效率。

在Loggly,索引时使用了批量操作模式,并且我们发现通过threadpool.bulk.queue_size属性为批量操作的线程池设置正确的大小,对于防止因批量重试而可能引起的数据丢失是极其关键的。

threadpool.bulk.queue_size: 5000

这会告诉ES,当没有可用线程来执行一个批量请求时,可排队在该节点执行的分片请求的数量。该值应当根据批量请求的负载来设置。如果批量请求数量大于队列大小,就会得到一个下文展示的RemoteTransportException异常。

正如上文所述,一个分片包含一个批量操作队列,所以这个数字需要大于想发送的并发批量请求的数量与这些请求的分片数的乘积。例如,一个单一的批量请求可能包含10个分片的数据,所以即使只发送一个批量请求,队列大小也必须至少为10。这个值设置太高,将会吃掉很多JVM堆空间(并且表明正在推送更多集群无法轻松索引的数据),但确实能转移一些排队情况到ES,简化了客户端。

既要保持属性值高于可接受的负载,又要平滑地处理客户端代码的RemoteTransportException异常。如果不处理该异常,将会丢失数据。我们模拟使用一个大小为10的队列来发送大于10个的批处理请求,获得了以下所示异常。

RemoteTransportException[[][inet[/192.168.76.1:9300]][bulk/shard]]; nested: 
EsRejectedExecutionException[rejected execution (queue capacity 10) on 
org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction$AsyncShardOperationAction$1@13fe9be];

为2.0版本以前的用户再赠送一个小贴士:最小化Mapping刷新时间

如果你仍在使用2.0版本以前的ES,且经常会更新属性mapping,那么可能会发现集群的任务等待队列有一个较大的refresh_mappings请求数。对它自身来说,这并不坏,但可能会有滚雪球效应严重影响集群性能。

如果确实遇到这种情况,ES提供了一个可配置参数来帮助应对。可按下述方式使用该参数:

indices.cluster.send_refresh_mapping: false

那么,这是怎么个意思,为什么可以奏效?

当索引中出现一个新的属性时,添加该属性的数据节点会更新它自己的mapping,然后把新的mapping发送给主节点。如果这个新的mapping还在主节点的等待任务队列中,同时主节点发布了自己的下一个集群状态,那么数据节点将接收到一个过时的旧版本mapping。

通常这会让它发送一个更新mapping的请求到主节点,因为直到跟该数据节点有关,主节点一直都拥有错误的mapping信息。这是一个糟糕的默认行为——该节点应该有所行动来保证主节点上拥有正确的mapping信息,而重发新的mapping信息是一个不错的选择。

但是,当有很多的mapping更新发生,并且主节点无法持续坚持时,会有一个乱序聚集(stampeding horde)效应,数据节点发给主节点的刷新消息就可能泛滥。

参数indices.cluster.send_refresh_mapping可以禁用掉默认行为,因此消除这些从数据节点发送到主节点的refresh_mapping请求,可以让主节点保持最新。即时没有刷新请求,主节点也最终会看到最初的mapping变更,并会发布一个包含该变更的集群状态更新。

总结:Elasticsearch的可配置属性是其弹性的关键

对Loggly来讲Elasticsearch可深度配置的属性是一个巨大的优势,因为在我们的使用案例中已经最大限度发挥了Elasticsearch的参数威力(有时更甚)。如果在你自己应用进化的当前阶段ES默认配置工作得足够好了,请放心,随着应用的发展你还会有很大的优化空间。

今日荐文

点击下方图片即可阅读

2016互联网技术人薪资报告,这一年搬的砖都去哪儿了?



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/weixin/OazAIP1xCu
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/2082
 
2058 次点击