0


Hadoop 安全实践指南(二)

原文:Practical Hadoop security

协议:CC BY-NC-SA 4.0

六、Hadoop 日志:关联和解释

有一天,一位非常恼火的商业智能主管(在一个客户站点)冲进我的办公室,抱怨其中一个承包商从生产服务器上删除了一些分类账记录。她收到了一份每日摘要审计日志报告,显示有 300 个分类账记录(财务交易条目)被删除!首先,有问题的承包商不应该接触到它们。所以我进行了调查,结果发现客户使用的 ERP(企业资源规划)软件有一个缺陷,它通过“公共”角色提供访问。如果我没有启用审计日志记录,我就不会发现这个错误,这证明了审计日志记录从安全角度来看是多么重要。

HDFS 审计日志记录的目的是记录 Hadoop 内的所有 HDFS 访问活动。MapReduce 审核日志包含所有已提交作业的条目。此外,Hadoop 守护进程日志文件包含启动消息、内部诊断信息、错误、信息或警告消息、配置日志等。您可以过滤以后不需要的信息,但记录所有访问(包括授权访问)会很有帮助。即使授权用户也可以执行未授权的任务。例如,一名警察可能在没有适当批准的情况下对其女友的罚单记录进行了未经授权的更新。此外,对于被审核的应用程序或任何符合 SOX 的应用程序,必须审核对应用程序中数据对象(例如,表)的所有访问,以及审核更改被审核的应用程序中任何数据的所有作业活动。

在本章中,我将讨论如何为 Hadoop 启用审计,以及如何捕获审计数据。Log4j 是 Hadoop 日志记录的核心,无论是审计日志还是 Hadoop 守护进程日志。我将从对 Log4j API 以及如何使用它进行审计日志记录的高级讨论开始,然后讨论 Log4j 日志记录级别及其目的。在概述了守护进程日志及其捕获的信息之后,您将了解如何将审计与 Hadoop 守护进程日志关联起来,以有效地实现安全性。

使用 Log4j API

Apache Log4j 是一个基于 Java 的实用程序或框架,由 Ceki Gülcü创建,后来成为 Apache 软件基金会的一个项目。日志记录是任何开发周期的重要组成部分,在没有调试器的情况下(通常是这样),它是排除应用程序代码故障的唯一工具。使用正确的日志记录类型非常重要——可靠、快速、灵活的日志记录类型。Log4j 满足这些要求:

  • 可靠性 是对相关错误或状态信息显示无任何异常的期望。自定义日志记录例程容易出现错误,因为一些消息由于逻辑错误而无法显示。Log4j 没有这个问题。这个日志系统经过了很好的测试,并且已经流行了很长时间。Log4j 当然可以保证日志输出逻辑的可靠性。
  • 速度 指所使用的测井程序的响应时间。使用 Log4j,Logger类被实例化(创建一个实例),而不是与接口交互,从而产生超快的响应。决定记录什么(基于日志记录级别)只涉及基于记录器层次结构的决定,这很快。由于使用了使用布局和附录的预格式化,日志消息的输出很快;通常,实际的日志记录大约需要 100 到 300 微秒。使用 simple Layout(Log4j 最简单的布局选项,在“布局”一节中有解释),Log4j 可以像 print 语句一样快速地记录日志(它只是将输入文本打印到控制台或文件中)!
  • 灵活性 是指对日志记录系统进行更改的容易程度(无需修改使用它的应用程序二进制文件)以及使用修改后的日志记录的应用程序的易用性。例如,使用 Log4j,您可以使用多个日志目的地(也称为 Appenders)将输出定向到两个目的地,比如控制台和日志文件。只需修改 log4j.properties 配置文件来进行这一更改;不需要修改代码。

当然,包含状态或错误消息的最简单的方法是将它们直接插入到代码中。那么,与在应用程序代码中插入注释或使用自定义日志模块相比,使用 Log4j 进行日志记录有什么优势呢?嗯,插入注释和删除注释是一个乏味且耗时的过程,依赖于程序员的专业知识——他们可能会在测试后忘记删除注释。获得正确的评论百分比(有时太多,有时太少)是困难的,并且有选择地显示那些评论是不可能的。此外,对注释的任何更改都涉及到代码的重新编译。最后,一个定制的日志模块可能会有错误,或者可能没有 Log4j API 那样丰富的功能。

通过配置文件,Log4j 允许您在运行时设置日志行为,而无需修改应用程序二进制文件。日志记录的一个主要问题是它对性能的影响。任何日志记录本质上都降低了应用程序的速度,但是对于 Log4j,对性能的影响微乎其微。例如,对最新发布的 Log4j 2(版本 2)的独立测试显示,它每秒可以输出高达 1800 万条消息(完整结果请参见 Christian Grobmeier,“Log4j”:性能接近疯狂,”

www.javacodegeeks.com/2013/07/Log4j-2-performance-close-to-insane.html

)。对于 Log4j,影响被限制在纳秒到微秒的范围内,这取决于您的 Log4j 配置、日志记录级别和 Appenders。

Log4j 日志框架的主要组件是记录器、附加器、布局和过滤器。因此你可以更好地理解它们是如何一起工作的,图 6-1 说明了它们在框架中的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-1 。Log4j 框架及其主要组件

接下来的部分将详细讨论这些组件,并提供关于它们的作用以及它们在框架中的确切角色的信息。

记录器

记录器 是一个命名实体,它与一个配置(LoggerConfig)相关联,随后与一个日志记录级别相关联。为了让 Log4j 日志记录正常工作,您需要一个定义了相关配置的根日志记录器。根记录器定义默认配置(附加器、布局等。).那么,这些日志记录级别是什么,它们是如何相互关联的呢?

Log4j 的日志记录级别

Log4j API 有七个日志记录级别。它们按照严重性顺序记录信息,每个级别都包含所有更高的级别。例如,日志级别

INFO

包括信息性消息、警告(包括更高级别的

WARN

)、非致命错误(包括更高级别的

ERROR

)和致命错误(包括更高级别的

FATAL

)。类似地,日志级别

WARN

包括警告、非致命错误和致命错误。图 6-2 总结了这些内含物。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-2 。Log4j 测井级别和内含物

七个日志级别如下:

  • ALL :这是可能的最低日志级别,它记录包括更高级别的所有消息(例如,致命错误、非致命错误、信息性消息等。)
  • TRACE :顾名思义,这个级别比调试级别记录更细粒度的信息事件。
  • DEBUG :记录对调试应用程序最有用的细粒度信息事件。
  • INFO :记录信息性消息,以更粗粒度的级别突出应用程序的进度。
  • 警告:记录潜在的有害情况。
  • ERROR :记录可能仍然允许应用程序继续运行的错误事件。
  • FATAL :记录可能导致应用程序中止的非常严重的错误事件。

请注意,启用的

TRACE

DEBUG

级别可被视为生产系统中的严重安全缺陷,并可能被漏洞扫描器报告。因此,请仅在解决问题时使用这些日志级别,并确保在解决问题后立即禁用它们。

记录器继承

记录器名称区分大小写并分层命名。如果一个记录器的名字后面跟一个点是其后代记录器名字的前缀,那么这个记录器就是另一个记录器的祖先。如果一个日志记录器和它的后代日志记录器之间没有祖先,那么这个日志记录器就是子日志记录器的父代。举个例子,那个名叫 L1 的伐木工。L2 是名为 L1.L2.L3 的记录器的父亲,L1 也是 L1 的父亲。L2 和 L1.L2.L3 的祖先(认为是祖父母)。记录器位于记录器层次结构的顶端。

可以为记录器分配默认的日志级别。如果一个级别没有分配给记录器,那么它将从其最近的祖先那里继承一个已分配的级别。给定记录器 L1 的继承级别等于记录器层次结构中的第一个非空级别,从 L1 开始,在层次结构中向上朝着根记录器前进。为了确保所有记录器都继承一个级别,根记录器总是有一个指定的级别。图 6-3 包含了一个级别继承的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-3 。记录器级别继承

如你所见,伐木工 L1 和 L1。L2.L3 已经分配了日志记录级别。伐木工 L1。没有为 L2 分配日志记录级别,它从其母公司 L1 继承了 L1 日志记录级别。如果日志请求的级别高于或等于其记录器的级别,则称该日志请求已启用。否则,请求将被禁用。

大多数 Hadoop 发行版都在

/etc/Hadoop/conf

$HADOOP_INSTALL/hadoop/conf

目录下的

log4j.properties

中定义了五个标准记录器(图 6-4 )。为了使 Log4j 日志记录正常工作,必须定义一个日志记录器(带有相关配置)。安全记录器记录安全审计信息。审计记录器记录 HDFS 和 MapReduce 审计信息,而作业摘要记录器记录关于 MapReduce 作业的摘要信息。一些发行版还为 Hadoop metrics、JobTracker 或 TaskTracker 定义了记录器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-4 。记录器和默认日志级别

图 6-5 是来自

log4j.properties

的 HDFS 审计记录器的示例条目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-5 。HDFS 审计记录者

maxfilesize

设置是临界大小(此处为 256MB ),在此之后,日志文件将“滚动”并创建一个新的日志文件;

maxbackupindex

(本例中为 20)是要创建的日志文件的备份副本数量。在此示例中,当日志文件滚动 21 次时,最旧的文件将被擦除。其他记录器的属性在

log4j.properties

文件中以类似的方式指定。

附加器

对于 Log4j 框架,输出目的地被称为附加器。目前,附加器存在于控制台、文件、GUI 组件、远程套接字服务器、JMS、NT 事件记录器和远程 UNIX 系统日志守护进程中。换句话说,您可以将其中任何一个定义为日志记录的输出目的地。从 Log4j Version 2 开始,您还可以异步记录日志,将控制权从日志记录器传递回应用程序,同时 I/O 操作由单独的线程或进程在后台执行。异步日志记录可以提高应用程序的性能。

追加加法

一个记录器可以连接多个附加器。给定记录器的每个启用的日志记录请求将被转发给该记录器中的所有附加器以及层次结构中更高的附加器。这是一个默认的行为,称为追加器累加性,可以通过在

log4j.properties

配置文件中将累加性标志设置为

false

来轻松禁用。

考虑图 6-6 中的例子。如果将控制台 Appender 添加到根日志记录器,那么所有启用的日志记录请求都将显示在控制台上。此外,如果一个文件附加器被添加到记录器 L1,L1。L2 和 L1。L2。L3,然后记录 L1 L1 的请求。L2 和 L1。L2.L3 将被写入适当的文件并显示在控制台上。现在假设您将 Logger L4 的加法标志设置为

false

。这有效地断开了 L4 及其子节点与日志输出向上传播的连接。因为 Logger L4 的父。L5(在本例中是 L4)将其可加性标志设置为

false

,L4。L5 的输出将只指向 L4 中的 Appenders。L5(在这种情况下没有)及其祖先直到并包括 L4 (

File4

),但是不会传播到 L1、L2 或 L3。图 6-6 列出了结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-6 。Log4j 框架的附加器可加性

主要 Hadoop 发行版经常使用的附加器有:

  • 控制台追加器:在控制台上显示日志信息
  • 文件附加器:将日志信息写入一个特定的文件,该文件在log4j.properties中定义
  • 滚动文件追加器:将日志消息写入文件,并根据大小滚动
  • 每日滚动文件追加器:将日志消息写入文件并每日滚动

使用与 HDFS 审计记录器相同的条目(图 6-5 ),考虑图 6-7 中的附录部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-7 。HDFS 审计记录器的滚动文件附加器

在图 6-7 中,我将

RollingFileAppender

与 HDFS 审计记录器一起使用。输出按照布局(

PatternLayout

)和定义的转换模式格式化(我稍后将讨论布局和转换模式),如下所示:

2014-02-0916:00:00,683 INFO FSNamesystem.audit: allowed=true ugi=hdfs (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo src=/user/sqoop2/.Trash/Current dst=null perm=null

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意 HDFS 审计输出可能会产生一个大文件。因此,每天或按大小将它回滚到一个新文件是一个好主意。

布局

布局 是日志条目的输出格式。它可以与一个 Appender 相关联,并且可以在通过 Appender 传递请求之前,根据您的规范格式化日志记录请求。

以一种易于阅读和解释的方式组织和呈现信息是很重要的。通常有必要将日志信息传递给远程机器上运行的另一个错误处理程序。因此,决定记录信息的结构很重要。这就是

Layout

对象所提供的。

布局使用转换模式来格式化和输出日志消息。转换模式由格式修饰符和转换字符组成。例如,修饰符

t

输出生成日志事件的线程的名称,转换字符

%5p

使用五个字符显示(或写入)日志级别,在左边填充空格。因此,日志级别

INFO

显示(或写入)为

"INFO"

可以在

log4j.properties

文件中为一个追加器指定一个布局。例如,我在图 6-8 的中指定了 PatternLayout 作为一个布局(用于我们的 HDFS 审计日志附录)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-8 。HDFS 审计记录器的模式布局

图 6-8 中的转换图形

%d{ISO8601} %p %c{2}: %m%n

输出为:

2014-01-2720:34:55,508 INFO FSNamesystem.audit: allowed=true ugi=mapred (auth:SIMPLE) ip=/127.0.0.1 cmd=setPermission src=/tmp/mapred/system/jobtracker.info dst=null perm=mapred:supergroup:rw-------

第一个字段是 ISO8601 (YYYY-MM-DD HH:mm:ss,SSS)格式的日期/时间。第二个字段是日志语句的级别或优先级。第三个是类别,第四个字段是消息本身,第五个字段是行分隔符(newline 或

/n

)。

Apache Log4j 提供了几个

Layout

对象:

  • 简单布局 : org.apache.log4j.SimpleLayout为日志消息提供了非常基本的结构。它只包括日志信息的级别和日志消息本身。如果使用简单布局而不是 PatternLayout:INFO allowed=true ugi=hdfs (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo src=/user/sqoop2/.Trash/Current dst=null perm=null,这就是 HDFS 审计记录器的日志消息(来自图 6-8 )的输出方式
  • Thread-Time-Category-Context Layout(TTCCLayout): This Layout outputs the invoking thread, time (in milliseconds since application started), the category or Logger used to create this logging event, and nested diagnostic context. All these properties are optional and if they are all disabled, the Layout will still write out the logging level and the message itself, just like Simple Layout. If you specify the following options in log4j.properties:#configuring the Appender CONSOLElog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout=org.apache.log4j.TTCCLayout#configuring the Layout TTCCLayoutlog4j.appender.CONSOLE.layout.ThreadPrinting=falselog4j.appender.CONSOLE.layout.ContextPrinting=falselog4j.appender.CONSOLE.layout.CategoryPrefixing=falselog4j.appender.CONSOLE.layout.DateFormat= ISO8601您将获得以下输出:INFO allowed=true ugi=hdfs (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo src=/user/sqoop2/.Trash/Current dst=null perm=null
  • DateLayout :顾名思义,这种布局提供了 NULL(不显示日期/时间)、RELATIVE(显示应用程序启动后经过的时间)、DATE (dd MMM YYYY HH:mm:ss、SSS 模式;最终 SSS 是应用程序启动后经过的时间)、绝对时间(HH:mm:ss,SSS 模式)和 ISO8601 (yyyy-MM-dd HH:mm:ss,SSS 模式)。
  • HTMLLayout :您的应用程序可能需要在一个美观的 HTML 格式文件中呈现日志信息。org.apache.log4j.HTMLLayout是相关对象。使用 HTML 格式的日志文件的一个很大的优点是,它可以作为网页发布,以便远程查看。
  • XMLLayout :为了以可移植(跨多个应用程序模块)的格式呈现日志信息,Log4j 提供了org.apache.log4j.xml.XMLLayout对象。需要注意的是,最终输出是而不是一个格式良好的 XML 文件。这个Layout对象产生大量的<log4j:event>元素形式的日志信息。
  • PatternLayout :您可以使用这种布局,使用一致的模式来“格式化”或输出日志消息,以便于外部实体使用它们。相关的布局对象是org.apache.log4j.PatternLayout格式由格式修饰符指定(如m写日志信息,p写日志级别信息),转换模式如%d{ISO8601} %p %c{2}: %m%n。显示(或写入)信息由转换字符指定。例如,%10c指示记录器名称必须是 10 个字符,如果它更短,就在左边添加空格填充。指定%-10c表示应该向右添加空格填充。有关 PatternLayout 类和转换字符的更多详细信息,请参见:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

过滤

过滤器评估日志事件,并允许或不允许它们被发布。有几种类型的过滤器,它们根据事件数量(BurstFilter)等标准筛选出事件;匹配正则表达式(RegexFilter)的日志事件消息;或者事件 ID、类型和消息(StructuredDataFilter)。过滤器的类型决定了您需要指定它的位置:

  • 上下文范围的过滤器作为配置(LoggerConfig)的一部分进行配置,并在将事件传递给记录器进行进一步处理之前对其进行评估。
  • 记录器过滤器是为记录器配置的,并在记录器的上下文范围过滤器和日志级别之后进行评估。
  • Appender 过滤器是为 Appender 配置的,它确定特定的 Appender 是否应该发布事件。
  • Appender 引用过滤器是为记录器配置的,它确定记录器是否应该将事件路由到 Appender。

请注意,所有这些过滤器都需要在您的

log4j.properties

文件中的适当部分(针对记录器或附加器)指定。例如,图 6-9 显示了来自

log4j.properties

的一个部分,它定义了一个 RegexFilter 来捕获仅用于登录根的 HDFS 审计事件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-9 。HDFS 审核记录器的 RegexFilter

同样,您可以使用其他类型的过滤器来防止捕获不需要的事件,这将有助于保持较小的审计日志大小,并使关注特定问题变得更加容易。

查看 Hadoop 审计日志和守护程序日志

正如您已经了解到的,您可以使用 Log4j 组件为许多目的生成日志输出(例如,调试、操作统计、审计)。Log4j 输出的日志数据依次由系统守护进程生成,特定类型的数据可能存在于多个位置。如何连接和分析来自不同来源的数据,以获得系统操作、历史和状态的总体视图?关键是 Hadoop 的审计日志。本节将讨论哪些守护进程生成哪些数据,审计捕获哪些类型的数据,以及如何使用 Hadoop 审计日志来提出安全建议。

为了获得完整的系统图片,您需要了解 Hadoop 守护进程或进程(生成日志)记录了什么类型的数据,以及这些日志文件驻留在哪里。您还需要了解捕获的数据与配置的日志记录级别有何不同。例如,来自 HDFS 的审计数据没有执行的作业的细节。该数据存在于其他地方,因此将职务与 HDFS 访问审计关联起来需要一些工作。您必须知道 JobTracker、TaskTracker (MapReduce V1)和 ResourceManager (MapReduce V2)的日志在哪里,或者任务尝试的日志数据存储在哪里。您将需要它来对数据访问(谁/什么/哪里)进行完整的审计,并且在出现安全漏洞时,您肯定会需要它。

Hadoop 审计的一个主要问题是,没有直接或简单的方法将审计数据与作业数据关联起来。例如,JobTracker 和 TaskTracker 日志(以及任务尝试日志数据)可以提供已执行作业的详细信息以及与作业相关的所有统计信息。但是,如何将这些数据与只有所有 HDFS 访问细节的审计数据联系起来呢?在本章的后面,你将会学到几种可能的方法。

审计日志

Hadoop 中的审计是使用 Log4j API 实现的,但默认情况下是不启用的。Hadoop 提供了一个 HDFS 审计日志,用于捕获对 HDFS 的所有访问,以及 MapReduce 审计日志,用于捕获关于 Hadoop 集群的所有已提交作业的信息。使用位于

$HADOOP_INSTALL/hadoop/conf directory

(

$HADOOP_INSTALL

是 Hadoop 的安装目录)的

hadoop-env.sh

配置文件中定义的环境变量

HADOOP_LOG_DIR

来指定审计日志的位置。审计日志文件名在

log4j.properties

文件中定义,默认为

hdfs-audit.log

(针对 HDFS 审计日志)和

mapred-audit.log

(针对 MapReduce 审计日志)。您还不能使用

log4j.properties

为纱线定义审计日志;这仍在进行中(参见“将 YARN 审计日志添加到 log4j.properties”,

https://issues.apache.org/jira/browse/HADOOP-8392

)。

要启用审计,您需要修改

log4j.properties

配置文件,将适当记录器的记录级别从

WARN

更改为

INFO

。您将在

/etc/Hadoop/conf

目录或

$HADOOP_INSTALL/hadoop/conf

目录中找到该文件,其中

$HADOOP_INSTALL

是 Hadoop 的安装目录。

log4j.properties

定义 NameNode 和其他 Hadoop 守护进程(JobTracker、TaskTracker、NodeManager 和 ResourceManager)的日志配置。例如,要启用 HDFS 审计,请在

log4j.properties

文件中查找这一行:

log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=WARN

WARN

替换为

INFO

以启用 HDFS 审计,并确保为每个 HDFS 事件在 HDFS 审计日志中写入一个日志行。

同样,要启用 MapReduce 审计,请将其记录器设置为 INFO 级别:

log4j.logger.org.apache.hadoop.mapred.AuditLogger=INFO

图 6-10 显示了

log4j.properties

中定义 HDFS 审计配置的部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-10 。HDFS 审计日志记录配置

Hadoop 守护进程日志

Hadoop 守护进程日志是由 Hadoop 守护进程(NameNode、DataNode、JobTracker 等)生成的日志。)并位于

/var/log/hadoop

下;实际目录可能会因所使用的 Hadoop 发行版而异。可用日志如下:

  • NameNode 日志(hadoop-hdfs-namenode-xxx.log)包含有关文件打开和创建、元数据操作(如重命名、mkdir 等)的信息。
  • DataNode 日志(hadoop-hdfs-datanode-xxx.log),包含有关 DataNode 访问和数据块修改的信息。
  • 二级 NameNode 日志(hadoop-hdfs-secondarynamenode-xxx.log),包含有关 FSimage 编辑应用、新 FSimage 生成和 NameNode 传输的信息。
  • JobTracker 日志(hadoop-xxx-mapreduce1-jobtracker-xxx.log),包含有关已执行作业的信息。JobTracker 为集群上运行的每个作业创建一个 xml 文件(job_xxx_conf.xml)。XML 文件包含作业配置。此外,JobTracker 为作业创建运行时统计信息。统计数据包括任务尝试、任务尝试的开始时间和其他信息。
  • TaskTracker 日志(hadoop-xxx-mapreduce1-tasktracker-xxx.log),包含有关已执行任务的信息。TaskTracker 为任务尝试创建日志,包括标准错误日志、标准输出日志和 Log4j 日志。
  • ResourceManager ( yarn-xxx-resourcemanager-xxx.log)和作业历史服务器日志(mapred-xxx-historyserver-xxx.log),包含有关作业提交、视图或修改的信息。这些仅在使用 MapReduce V2 或 YARN 时可用。

与审计日志一样,您可以在配置文件

log4j.properties

中指定 Hadoop 守护进程的日志记录级别,如果需要,每个守护进程可以有不同的日志记录级别。例如,您可以将 HDFS 的审计日志记录器设置为

INFO

级别,并指示 TaskTracker 在

TRACE

级别记录日志:

log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=INFO
log4j.logger.org.apache.hadoop.mapred.TaskTracker=TRACE

请注意,其他组件(例如,蜂巢、HBase、猪、Oozie 等。)在自己的配置目录中有对应的

log4j.properties

文件。

任何可运行的 Hadoop 集群都有许多在不同时间执行的计划(和未计划的或临时的)作业,由任何批准的用户提交。如上所述,将作业日志与通过审核捕获的 HDFS 访问日志相关联是一项挑战。例如,考虑审计记录中的典型行:

2013-10-0708:17:53,438 INFO FSNamesystem.audit: allowed=true ugi=hdfs (auth:SIMPLE) ip=/127.0.0.1 cmd=setOwner src=/var/lib/hadoop-hdfs/cache/mapred/mapred/staging dst=null perm=mapred:supergroup:rwxrwxrwt

这一行只说了一个命令(在本例中为

setOwner

)是在源文件上执行的,但没有指出它是否是作为作业的一部分执行的。

您需要参考相应的 JobTracker 或 TaskTracker 日志来查看当时是否有任何作业正在执行,或者假设这是使用 Hadoop 客户端执行的特定操作。因此,除了审计日志之外,您还需要维护其他 Hadoop 守护进程或进程的日志,并将它们关联起来,以便进行有效的故障排除。

关联和解释日志文件

Hadoop 会生成大量日志。有审计日志和守护进程日志,它们分别提供关于在收集它们的源上完成的处理的大量信息。然而,它们并没有形成在您的 Hadoop 集群上执行的所有处理的连贯、完整的画面。这就是为什么在解决问题或调查安全漏洞时,您需要关联这些日志。

将 Hadoop 审计数据与 Hadoop 守护进程生成的日志关联起来并不简单,确实需要一点努力,但是结果非常值得。使用用户名或作业号以及 Linux 过滤器(例如 sed 或流编辑器实用程序),您可以关联数据并识别安全漏洞。

关联什么?

Hadoop 守护进程记录了许多有用的信息,您还可以启用和收集审计日志。假设您有所有这些可用的日志,您应该关联什么?嗯,这取决于你要调查的事件。

在第三章的票务系统例子中考虑一个可能的安全漏洞。如您所知,所有警察局每晚都会向警察总部的中央存储库发送票务数据。中央存储库将票据数据保存在一个 Hive 表中,该表包含每天的分区。每天,IT 专业人员都会使用收到的数据运行自动流程来添加新分区。

一天,一名 IT 专业人员决定帮助他的女朋友删除超速罚单记录。由于使用相关日志进行分析,他被捕了。他从传票表中删除了传票条目,但忘记了从司法相关的表中删除相应的条目,当案件要进行听证时,系统标记了错误。随后,进行了彻底的调查。让我们跟随它展开的轨迹;不专业的 IT 专业人员使用用户名

RogueITGuy

检测到错误时,系统管理员使用以下命令检查对 HDFS 的访问:

  • HDFS 审计日志 :该日志提供了用户在集群上执行的所有命令的详细信息。因为Ticket_details是丢失记录的表,调查人员将注意力集中在它上面,过滤掉用户root和 HDFS 超级用户hdfs(因为两者都是密码受控的系统用户)的访问,以获得访问过Ticket_details的用户列表。为了过滤,调查人员(包括系统管理员在内的团队)使用了以下 shell 命令:grep Ticket_details hdfs-audit.log | grep -v 'ugi=root'| grep -v 'ugi=hdfs'
  • (The -v option for command grep filters records with the keyword specified after the option.) The results included normal user activity plus the following suspicious activity by a user RogueITGuy:2014-03-0622:26:08,280 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfosrc=/Ticketing/Ticket_details_20140220 dst=null perm=null2014-03-0622:26:08,296 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=rename src=/Ticketing/Ticket_details_20140220 dst=/Ticketing/Ticket_stg/Ticket_details_20140220 perm=RogueITGuy:supergroup:rw-r--r—2014-03-0622:27:02,666 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy(auth:SIMPLE) ip=/127.0.0.1 cmd=opensrc=/Ticketing/Ticket_stg/Ticket_details_20140220 dst=null perm=null调查人员得出以下结论:- 用户RogueITGuy ( ugi=RogueITGuy)加载了新版本的每日登台文件Ticket_details_20140220 ( cmd=rename src=/Ticketing/Ticket_details_20140220 dst=/Ticketing/Ticket_stg/Ticket_details_20140220)。- 文件被加载到指向外部登台表Ticket_details_stg的 HDFS 位置,该表用于通过创建和覆盖特定日期的分区将数据加载到Ticket_details表。- 第一个条目(cmd=getfileinfo src=/Ticketing/Ticket_details_20140220)是确保他从自己的 PC 上传了正确的(修改后删除了他女朋友的机票条目)文件。- 第三个条目是确保修改后的文件被正确地上传到暂存位置。
  • Hive log: If this user overwrote a partition with the modified file, he would have done that using Hive. So, investigators looked at the Hive logs next (in /var/log/hive for Cloudera CDH4; may vary as per your distribution and configuration):grep 'ugi=RogueITGuy' hadoop-cmf-hive1-HIVEMETASTORE-localhost.localdomain.log.out | grep 'ticket_details'| grep -v 'get_partition'他们通过表Ticket_details中的RogueITGuy搜索活动,并在查看输出后,过滤掉'get_partition'条目,因为该命令不会修改分区。以下是他们看到的情况:2014-03-0622:42:36,948 INFOorg.apache.hadoop.hive.metastore.HiveMetaStore.audit: ugi=RogueITGuyip=/127.0.0.1 cmd=source:/127.0.0.1 get_table : db=default tbl=ticket_details2014-03-0622:42:37,184 INFOorg.apache.hadoop.hive.metastore.HiveMetaStore.audit: ugi=RogueITGuyip=/127.0.0.1 cmd=source:/127.0.0.1 append_partition: db=defaulttbl=ticket_details[2014,2,20]调查人员得出以下结论:
  • 2/20/14的分区被RogueITGuy覆盖了Ticket_details表的ugi=RogueITGuy ip=/127.0.0.1 cmd=source:/127.0.0.1 append_partition: db=default tbl=ticket_details[2014,2,20]
  • 文件Ticket_details_20140220于 2014 年 3 月 6 日 22:26 上传,配置单元分区于 2014 年 3 月 6 日 22:42 被同一用户RogueITGuy覆盖。结案了。

最后,调查人员检查了

RogueITGuy

提交的工作。几个任务相关日志提供了用户执行任务的细节。调查人员从审查 *MapReduce 审计日志**开始,其中包含所有用户、日期/时间和提交作业的结果细节。对于 Cloudera,它们的位置是

/var/log/hadoop-0.20-mapreduce/mapred-audit.log

。调查人员接下来发布了以下命令:*

grep 'RogueITGuy' mapred-audit.log

它创造了几个工作机会:

2014-03-0622:28:01,590 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0008 RESULT=SUCCESS
2014-03-0622:42:07,415 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0009 RESULT=SUCCESS
2014-03-0622:45:55,399 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0010 RESULT=SUCCESS
2014-03-0622:47:39,380 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0011 RESULT=SUCCESS
2014-03-0622:48:46,991 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0012 RESULT=SUCCESS

调查人员在

http://JobTrackerHost:50030/JobTracker.jsp

使用 JobTracker 的 web 界面检查了 JobTracker 和 TaskTracker 日志。乔布斯

job_201403042158_00010

job_201403042158_0011

job_201403042158_0012

是没有修改任何数据的精选语句,但是乔布斯

job_201403042158_0008

job_201403042158_0009

导致了确凿的证据!调查人员检查了这些作业的

job.xml

文件中的

hive.query.string

属性,并检索了执行的查询,它是:

FROM Ticket_details_stg INSERT OVERWRITE TABLE Ticket_details PARTITION (Yr=2014,Mo=2,Dy=20) SELECT TicketId,DriverSSN,Offense,IssuingOfficer

该查询使用来自

Ticket_details_stg

表(每日分段表)的数据来覆盖表

Ticket_details

的日期为 2/20/14 的分区。HDFS 审计日志已经确定

RogueITGuy

已经将一个临时数据文件加载到暂存表中。

这些日志一起明确了

RogueITGuy

编辑了每日临时数据文件,并删除了包含其女友门票条目的记录。然后,他将这个新文件上传到 staging 表,并使用 staging 表来覆盖

Ticket_details

表的一个分区,以确保 ticket 条目被删除。通过使用 HDFS 审计日志、Hive 日志、MapReduce 审计日志和

job.xml

文件,调查人员获得了

RogueITGuy

进行未授权活动的确凿证据,并能够成功结束调查。

结果,

RogueITGuy

丢了工作,女朋友要付机票钱。然而,她被他的忠诚所感动,同意嫁给他。所以,最后连

RogueITGuy

都感谢了相关日志!

如何使用工作名称进行关联?

有几种方法可以关联日志。最简单的方法是使用登录名或作业名,因为日志消息包含这些信息。您看到了

RogueITGuy

用户名如何关联各种日志文件来调查未授权的活动。使用作业名关联日志也是重要的一步。为了追踪安全漏洞,调查人员必须从日志中提取相关信息,并使用作业名称来关联多个日志,以获得特定作业所执行活动的详细信息。

我现在将带你完成这个过程,从 MapReduce 审计日志(

mapred-audit.log

)开始,它有如图 6-11 所示的条目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-11 。MapReduce 审核日志

注意带有作业名称

job_201403042158_0008

的高亮条目。HDFS 审核日志对此作业有多个条目。你如何过滤掉它们?

如果您查看这个作业的第一个条目(在

hdfs-audit.log

中),您会发现它具有模式

cmd=getfileinfo

以及作业名称

job_201403042158_0008

。这适用于 Cloudera 的 Hadoop 发行版(CDH4 ),如果您使用不同的发行版,您将需要为特定作业的第一次和最后一次出现确定一个唯一的模式。好消息是,对于 Hadoop 发行版,您只需执行这个练习一次。您只需为作业名称的第一次和最后一次出现建立一个唯一的模式,将它与随后的出现区分开来;然后你可以用它进行所有的搜索。

随后,您可以使用 Linux 实用程序 awk 来获取该模式第一次出现的行号:

awk '/cmd\=getfileinfo/ && /job_201403042158_0008\t/ { print NR }' hdfs-audit.log

awk 实用程序寻找匹配模式

cmd=getfileinfo

job_201403042158_0008

的第一行,并使用内置变量

NR

输出行号。

此外,您可以通过使用模式

cmd=delete

/src=/tmp/mapred/system/ job_201403042158_0008

获得作业名称最后出现的行号,如下所示:

awk '/cmd\=delete/ && /src=\/tmp\/mapred\/system\/job_201403042158_0008/ { print NR }' hdfs-audit.log

之后,您可以使用流编辑器,比如 sed,打印以第一个模式开始,以第二个模式结束的行。例如,

sed –n 1,20p hdfs-audit.log

将在屏幕上显示文件

hdfs-audit.log

的第 1 至 20 行。

sed -n `awk '/cmd\=getfileinfo/ && /job_201403042158_0008\t/ { print NR }' hdfs-audit.log`,`*awk '/cmd\=delete/* && */src=\/tmp\/mapred\/system\/ job_201403042158_0008/ { print NR }' hdfs-audit.log*`p hdfs-audit.log
sed

命令使用之前步骤中获得的行号(用粗体和斜体标记)作为开始和结束,打印中间的所有行。您可以将命令

sed

的输出重定向到一个文件,并查看 HDFS 审计记录,而不是在屏幕上查看它们(正如最后一个

sed

命令所暗示的)。您可以使用这个

sed

命令从

hdfs-audit.log

中提取任何作业(对于 CDH4)的作业细节——只需替换作业名称!

现在,在这种情况下,您没有从

hdfs-audit.log

条目中获得太多信息,除了这个作业进行了与 Hive 相关的处理,并且还显示了

job.xml

的位置:

2014-03-0622:27:59,817 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=create src=/user/RogueITGuy/.staging/job_201403042158_0008/libjars/hive-builtins-0.10.0-cdh4.4.0.jar dst=null perm=RogueITGuy:supergroup:rw-r--r—

2014-03-0622:28:02,184 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo src=/user/RogueITGuy/.staging/job_201403042158_0008/job.xml dst=null perm=null2014-03-0622:28:02,324 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo src=/tmp/hive-RogueITGuy/hive_2014-03-06_22-27-55_562_981696949097457901-1/-mr-10004/164c8515-a032-4b6f-a551-9bc285ce37c4 dst=null perm=null

为什么不直接使用

grep

命令来检索

hdfs-audit.log

中作业

job_201403042158_0008

的作业细节呢?原因是与作业

job_201403042158_0008

相关的所有行可能不包含作业名称模式,并且您希望确保不会遗漏日志文件

hdfs-audit.log

中的任何相关行。

使用作业名称检索作业详细信息

您可以使用查找第一次出现的唯一模式的相同技术,从 JobTracker 或 TaskTracker 日志中检索与作业相关的记录。例如,要在 JobTracker 日志文件中查找模式,并获得作业第一次出现的行号,如

job_201403042158_0008

,请使用:

awk '/job_201403042158_0008/ && /nMaps/ && /nReduces/ { print NR }' hadoop-cmf-mapreduce1-JOBTRACKER-localhost.localdomain.log.out

要检索“job_201403042158_0008”最后一次出现的行号,请使用:

awk '/job_201403042158_0008/ && /completed successfully/ { print NR }' hadoop-cmf-mapreduce1-JOBTRACKER-localhost.localdomain.log.out

您可以使用命令

sed

通过指定作业名从 CDH4 的 JobTracker 日志文件中获取详细信息。例如,打印出

job_201403042158_0008

的所有记录的

sed

命令是:

sed -n `awk '/job_201403042158_0008/ && /nMaps/ && /nReduces/ { print NR }' hadoop-cmf-mapreduce1-JOBTRACKER-localhost.localdomain.log.out*`,`awk '/job_201403042158_0008/* && */completed successfully/ { print NR }' hadoop-cmf-mapreduce1-JOBTRACKER-localhost.localdomain.log.out*`p hadoop-cmf-mapreduce1-JOBTRACKER-localhost.localdomain.log.out

该命令的输出提供了有价值的详细信息,如执行任务的节点或任务输出的位置:

2014-03-0622:28:01,394 INFO org.apache.hadoop.mapred.JobInProgress: job_201403042158_0008: nMaps=1 nReduces=0 max=-12014-03-0622:28:01,764 INFO org.apache.hadoop.mapred.JobInProgress: Input size for job job_201403042158_0008 =74\. Number of splits =12014-03-0622:28:01,765 INFO org.apache.hadoop.mapred.JobInProgress: tip:task_201403042158_0008_m_000000 has split on node:/default/localhost.localdomain

2014-03-0622:28:01,765 INFO org.apache.hadoop.mapred.JobInProgress: Job job_201403042158_0008 initialized successfully with1 map tasks and 0 reduce tasks.2014-03-0622:28:02,089 INFO org.apache.hadoop.mapred.JobTracker: Adding task (JOB_SETUP)'attempt_201403042158_0008_m_000002_0' to tip task_201403042158_0008_m_000002,for tracker 'tracker_localhost.localdomain:localhost.localdomain/127.0.0.1:47799'

使用 Web 浏览器检索工作详细信息

您还可以使用浏览器界面轻松查看 JobTracker 和 TaskTracker 日志记录。最好使用浏览器界面查看作业的运行时统计信息或作业的 XML 文件。记录的 URL 由跟踪者的姓名和 web 访问端口组成。例如,如果您的 JobTracker 主机名为

'MyJobHost'

,并使用端口 50030 进行 web 访问,那么可以在

http://MyJobHost:50030/logs/

查看 JobTracker 日志。同样,在主机

'MyTaskHost'

上运行并使用端口 50060 的 TaskTracker 的日志可以在

http://MyTaskHost:50060/logs/

查看。检查您的配置文件(

mapred-site.xml

)以了解运行特定守护程序和端口的主机的详细信息。文件名可能因发行版而异,但日志文件的名称中会有

TaskTracker

JobTracker

,使它们易于识别。

图 6-12 显示了使用 MapReduce 1.0 的集群的日志目录和各种 MapReduce 日志文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-12 。MapReduce 版本 1 的 MapReduce 日志文件

如果使用 YARN,那么对应的守护进程是 ResourceManager(而不是 JobTracker)和 NodeManager(而不是 TaskTracker)。请检查纱线配置文件(

yarn-site.xml

)中的网络访问端口(

mapreduce.johistory.webapp.address

yarn.resourcemanager.webapp.address

的值)。例如,在图 6-13 的中,资源管理器使用端口 8088。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-13 。纱线资源管理器 web 界面

节点管理器使用端口 8042,如图图 6-14 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-14 。YARN 的节点管理器 web 界面

最后,历史服务器使用端口 19888 ( 图 6-15 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-15 。纱线的历史服务器 web 界面

当使用 YARN 时,应该使用 NodeManager 和 ResourceManager 的 YARN 日志来获取作业细节。Historyserver 保存已存档或“退役”作业的日志。因此,如果您需要访问旧的工作详细信息,这就是您需要检查的内容。定位第一行和最后一行的模式可能稍有变化,可能需要调整;但是您可以轻松地浏览日志文件来进行这些调整。找出纱线日志文件位置的一个简单方法是参考位于

/etc/hadoop/conf

中的

log4j.properties

文件,并查看合适的附件指向哪里。

在我结束这一章之前的一个想法。您已经看到了如何为一个作业关联日志,但是如果您想要跟踪一个用户的所有活动或者想要跟踪一整天的活动,该怎么办呢?定义和使用 awk 模式会很麻烦、困难,并且容易出错。相反,可以尝试为 appender 定义 Log4j 过滤器,并定义额外的 appender 来将相关输出定向到一个问题的单独文件,并合并一个问题的所有文件。为此,您可以使用 Flume,也可以简单地让 shell 脚本为您进行整合。

日志记录的重要注意事项

一些额外的因素将帮助您有效地使用日志记录。虽然它们与安全性没有直接关系,但我将在本节中简要介绍它们,您可以决定它们与您的具体环境有多大关系。

时间同步

Hadoop 是一个具有多个节点的分布式系统,通常有大量节点。因此,Hadoop 日志也分布在集群中的各个节点上。各个日志消息都有时间戳,在进行故障排除时,您需要确保一个节点上的 12:00 PM 与另一个节点上指定的 12:00 PM 是同一时刻。

对于一个网络,时钟偏差是网络上不同节点时钟的时间差。通常,以毫秒为单位的时间差是可以接受的;但是需要避免更大的时钟偏移。许多协议(例如,网络时间协议,

http://en.wikipedia.org/wiki/Network_Time_Protocol

)可用于确保存在可忽略的时间偏差。确保为集群生成的日志是时间同步的,这一点当然很重要。

Hadoop 分析

在“关联和解释日志文件”一节中,我讨论了如何结合使用 Linux 流编辑器 sed 和功能强大的文本处理器 awk 来搜索模式并打印适当的行。您可以很容易地将这种方法扩展到计算匹配模式的行数。您可以对日志文件进行多次检查,并聚合匹配项来分析使用模式。如此生成的分析可能对安全调查没有用处,但它们肯定能为您的 Hadoop 集群提供有用的统计数据。

例如,下面的命令可以告诉您自 Hadoop 集群启动以来用户

RogueITGuy

访问了它多少次(当然您也可以轻松地提取访问的日期范围):

grep 'ugi=RogueITGuy' hdfs-audit.log | wc -l

以下命令告诉您自从集群重新启动以来,

RogueITGuy

执行了多少个作业:

grep 'USER=RogueITGuy' mapred-audit.log | wc -l

以下脚本提取作业

job_201403042158_0008

的开始和结束日期/时间(然后您可以计算作业持续时间):

awk –F ',''/cmd\=getfileinfo/ && /job_201403042158_0008\t/ { print $1 }' hdfs-audit.log
awk –F ',''/cmd\=delete/ && /src=\/tmp\/mapred\/system\/job_201403042158_0008/ { print $1 }' hdfs-audit.log

您可以开发自动化脚本,将所有日常作业分析或 HDFS 访问分析写入文件,并将它们作为分区添加到适当的配置单元表中。然后,您可以在自己的分析系统中对这些数据执行聚合或使用其他统计函数。

当然,与你更相关的分析可能会有所不同,但我相信你理解它们背后的方法。

通过定义变化阈值,该历史数据(存储为 Hive 表)也可用于生成安全警报。例如,您可以编写一个 Hive 查询来生成一个警报(通过 Nagios ),如果一个用户执行的作业数量是他的月平均值的两倍(或更多)。安全警报的历史数据的使用总是依赖于使用中的突然变化,您可以使用适用于您的环境的概念。

软体

Splunk 是一个非常强大的分析 Hadoop 数据的工具。使用 Splunk 的 Hadoop Connect 模块,您可以导入任何 HDFS 数据,并使用 Splunk 的索引功能进一步搜索、报告、分析和可视化您的数据。您还可以导入 Hadoop 日志,对其进行索引和分析。

Splunk 为搜索和分析实时和历史数据提供了强大的搜索处理语言(SPL)。它还可以提供实时监控日志数据(模式/阈值)的功能,并在特定模式出现时(在您的数据中)生成警报。例如,如果您正在使用 Hive,您想知道一个分区(对于您的一个生产表)何时被覆盖或添加。当其中一个用户连接到您的集群时,您可能还希望提醒您的系统管理员。

Splunk 最重要的功能(从安全日志的角度来看)是关联数据的能力。Splunk 支持以下关联数据的方式:

  • 基于时间和地理位置的:您可以关联在特定日期或时间段以及特定位置发生的事件的数据。因此,如果我使用 Splunk 对RogueITGuy进行调查,我可以要求 Splunk 向我提供 2014 年 3 月 16 日(问题发生的具体日期)的所有日志数据。
  • 基于事务的:您可以关联一个业务流程(或一系列业务流程)的所有数据,并将其标识为单个事件。尽管它不能用于安全性,但它可以为作业或业务流程提供分析(如持续时间、消耗的 CPU 和 RAM 资源等。).
  • 子搜索:允许你使用一次搜索的结果,并在另一次搜索中使用。因此,如果我使用 Splunk 对RogueITGuy进行调查,那么我可以将我的子搜索定义为 HDFS、MapReduce 或 Hive access,以便于分析。
  • 查找:允许您关联来自外部来源的数据。例如,我可以检查来自 Nagios 的所有 Hive 警报,看看RogueITGuy是否涉及任何其他问题。
  • Joins :允许您基于用户名或事件 ID 字段将两个完全不同的数据集链接在一起。使用 Splunk,我可以使用用户名RogueITGuy链接 Ganglia 的监控数据和 Hadoop 日志数据,并调查他在执行已知的非法活动时还访问了什么。

最后,Splunk 提供了 Hunk,这是一款专门为 Hadoop 和 NoSQL 数据设计的分析工具。它允许您探索、分析和可视化原始的非结构化数据。Hunk 还提供基于角色的访问,以限制对敏感数据的访问(更多信息见

www.splunk.com/hunk

)。看一看,是不是对你的需求更有用!

摘要

在本章中,我讨论了 Hadoop 日志如何有效地用于安全目的。高级方法是使用 Linux 实用程序和流编辑器来处理日志文件中的文本,并获取必要的信息,但是这当然是非常过时和困难的工作。通过使用 Splunk 等第三方解决方案,有更简单的方法来实现类似的结果。

大量第三方产品可用于减少排除故障或调查安全漏洞的工作量。缺点是,在关联或分析日志时,您将没有足够的控制力或灵活性。首选项是您的,而且大多数时候是由您的环境和需求决定的。无论采用哪种方法,在依赖生成的日志之前,都要确保同步所有需要考虑的节点上的时间。

最后,探索使用 Hadoop 日志进行分析是值得的——无论是否与安全相关。您可以购买昂贵的软件来执行分析,或者开发您自己的脚本,如果您确定您的需求——如果它们的数量很少!*

七、Hadoop 中的监控

任何系统管理员都会告诉你,监控是找到性能问题根源的理想方法。例如,监视可以帮助您了解系统 CPU 或 RAM 资源不足的原因,并在 CPU 或 RAM 使用率接近指定百分比时通知您。您的系统管理员可能不知道(但您可以在阅读本章后解释)的是,监视同样非常适合于找出安全问题。

考虑一个场景:您管理一个 Hadoop 集群(作为系统管理员),并且关注两个特定的用户:Bob,一个公认的黑客,和 Steve,他喜欢运行访问大量他不应该访问的数据的查询!为了防止密码丢失和避免服务器崩溃,您希望在 Bob 试图读取

/etc/password

文件和 Steve 运行检索整个数据库的大型查询时得到通知。Hadoop 监控可以提供你需要的信息。具体来说,Hadoop 提供了许多指标来获取有用的安全细节,领先的监控系统可以使用这些指标来提醒您注意问题。此外,这些监控系统允许您基于特定指标值定义阈值(用于生成警报),还允许您定义适当的操作(如果达到阈值)。因此,Hadoop 监控提供了许多功能,您可以使用这些功能进行性能监控和故障排除。

在本章对监控的详细概述中,我将讨论监控系统需要的特性,重点是监控分布式集群。此后,我将讨论可以用于安全目的的 Hadoop 指标,并介绍 Ganglia 和 Nagios,这是两个最流行的 Hadoop 监控应用程序。最后,我将讨论一些对 Ganglia 和 Nagios 有用的插件,它们提供了这两个程序之间的集成,以及提供安全相关功能的插件。

监控系统概述

监控分布式系统总是具有挑战性。不仅多个进程与用户交互,而且还相互交互,您必须在不影响这些进程性能的情况下监视系统。像 Hadoop 这样的系统提出了更大的挑战,因为监控软件必须监控单个主机,然后在整个系统的上下文中整合数据。它还需要考虑整个系统中各种组件的作用。例如,DataNode 上的 CPU 使用率不如 NameNode 上的 CPU 使用率重要。那么,系统将如何处理 CPU 消耗警报,或者为分布式系统中具有不同角色的主机确定单独的阈值级别呢?此外,在考虑 datanode 的 CPU 或存储使用情况时,监视系统必须考虑群集中所有 datanode 的组合使用情况。随后,监控系统还需要能够按角色汇总监控阈值。

除了复杂的资源监控能力之外,用于分布式系统的监控系统还需要随时访问正在执行的进程的细节。这是生成警报(例如,导致 90% CPU 使用率的用户进程)或执行任何预防措施(例如,用户正在访问关键系统文件)所必需的。

在有效应对监控 Hadoop 系统的挑战之前,您需要了解一个简单监控系统的架构。在下一节中,我将讨论有效监控分布式系统所需的组件、处理和特性,以及如何调整这个简单的架构以更好地监控 Hadoop 集群。

简单监控系统

一个简单的监控系统需要四个关键组件:一个服务器或协调器进程,轮询分布式系统主机并收集必要信息的连接,一个存储收集信息的存储库,以及一个作为前端的图形用户界面(图 7-1 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-1 。简单监控系统

如您所见,监控服务器整合了通过轮询分布式系统主机接收到的输入,并将详细的(以及汇总的)输出写入存储库。控制台为收集的数据提供显示选项,这些数据可以使用各种参数进行汇总,如监视事件、服务器、警报类型等。

不幸的是,像这样简单的监控系统架构不能很好地扩展。考虑一下,如果图 7-1 的系统必须监控数千台主机而不是三台,会发生什么。监控服务器必须管理一千个连接的轮询,处理和整合输出,并在几秒钟内将其呈现在控制台上!随着每台主机添加到监控系统,监控服务器上的负载也会增加。达到一定数量的主机后,您将无法再添加任何主机,因为服务器根本无法支持它们。此外,大量轮询会增加网络流量并影响整体系统性能。

除此之外,Hadoop 集群的复杂性还在于,您需要在整合数据时考虑节点的角色,以及汇总具有相同角色的多个节点的数据。简单的设计是不够的,但它可以用于监控 Hadoop 集群。

Hadoop 监控系统

一个简单的监控系统遵循与传统的客户端-服务器设计相同的处理安排:一个单一的集中式监控服务器完成所有的处理,并且随着主机数量的增加,处理负载也会增加。网络流量也会降低负载,因为来自主机的轮询数据会整合到监控服务器上。

正如 Hadoop 的分布式架构在效率上比传统的客户端-服务器处理有了显著提高一样,分布式处理模型也可以改进简单的监控系统。例如,如果本地化的监控流程为 Hadoop 集群中的每个节点捕获和存储监控数据,那么就不会再有集中式服务器成为处理瓶颈或单点故障。每个节点都是并行执行部分处理的主动参与者。然后,这些本地化进程中的每一个都可以将数据传输到群集中的其他节点,并且还可以从群集中的其他节点接收数据的副本。轮询过程可以以任何预定的频率从集群内的任何节点轮询整个集群的监控数据。数据可被写入储存库并存储以供进一步处理,或由基于图形或网络的前端显示。图 7-2 显示了一种可能的设计。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-2 。Hadoop 监控系统

使用这种体系结构,即使添加 1000 台主机进行监控也不会对性能产生负面影响。任何现有节点或轮询进程都没有额外的负载负担,因为轮询进程仍然可以从任何节点进行轮询,而不必进行多次轮询。集群节点将数据传输到公共信道,所有其他节点接收该数据。因此,增加节点数量不会以任何方式影响轮询过程或系统性能,从而使体系结构具有高度可伸缩性。与传统的监控系统相比,您需要做的唯一额外工作是将监控流程配置应用于所有节点。

仔细查看图 7-2 ,注意各个节点上的监控进程计算“本地监控数据”监控数据需要在本地计算;由于 Hadoop 是一个多节点分布式系统,数据分布在众多的 datanode 上,根据 Hadoop“对数据进行处理”的理念,数据在本地进行处理(数据驻留在 datanode 上)。这个“本地监控数据”实际上是各个节点的度量输出;它可以告诉你很多关于你的系统的安全性和性能的信息,这一点你接下来会学到。

Hadoop 指标

Hadoop 指标是关于系统内发生的事情的简单信息,例如内存使用情况、打开的连接数或节点上的剩余容量。您可以配置每个 Hadoop 守护进程 定期收集指标,然后使用插件输出数据。收集的数据可以包含关于 Hadoop 守护进程(例如,它们使用的资源)、事件(例如,MapReduce 作业执行)和测量(例如,为 NameNode 创建的文件数量)的信息。您使用的输出插件决定了指标的目的地。例如,FileContext 将指标写入文件,GangliaContext 将传递给 Ganglia 监控系统的指标进行显示和整合,而 NullContext 则丢弃该指标。

根据它们包含的信息,度量被分为四个上下文 : jvm、dfs、rpc 和 mapred。jvm 的度量包含 JVM (Java 虚拟机)的基本统计数据,如内存使用或线程计数等。这个上下文适用于所有 Hadoop 守护进程。dfs (分布式文件系统)上下文适用于 NameNode 和 DataNode。该上下文的一些指标输出诸如容量或文件数量(对于 NameNode)、故障磁盘卷数量、特定工作节点上的剩余容量(对于 DataNode)等信息。JobTracker 和 TaskTracker 为它们的计数器使用 mapred 上下文。这些度量包含作业前计数器数据、作业计数器和作业后计数器。rpc 上下文用于远程过程调用(rpc)指标,如处理 RPC 所需的平均时间、打开的连接数等,适用于所有 Hadoop 守护进程。表 7-1 总结了上下文。

表 7-1 。Hadoop 指标的上下文

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

早期版本的 Hadoop 通过一个名为 Metrics 的系统来管理指标,而当前版本的 Hadoop 使用 Metrics2 。管理系统有两个主要的区别。度量依赖于每个插件一个上下文的一对一关系,而 Metrics2 使您能够将度量输出到多个插件。Metrics2 系统也使用稍微不同的术语;Hadoop 守护进程输出的指标数据被称为,插件被称为接收器。源产生数据,接收器消费或输出数据。让我讨论一下每种环境的一些指标。

jvm 上下文

jvm 度量关注基本的 JVM 统计数据。表 7-2 列出了其中的一些指标。

表 7-2 。jvm 上下文的度量
|

公制的

|

描述

|
| — | — |
| 账户 | 为 JVM 执行的垃圾收集(从不使用的对象中自动释放堆内存)的数量 |
| GcTimeMillis | JVM 的所有垃圾收集的总时间(毫秒) |
| 日志致命 | 错误级别为致命的日志行数(使用 Log4j) |
| MemHeapCommittedM | 提交的堆内存,或者保证可供 JVM 使用的内存量(MB) |
| MemHeapUsedM | JVM 当前使用的堆内存(包括所有对象占用的内存)(MB) |
| 线程等待 | 处于等待状态(即等待另一个线程完成操作)的线程数 |

您可以通过查看 GcCountGcTimeMillis 指标来推断 JVM 进程的动态性;较大的数字表示大量基于内存的活动。大量致命错误表明您的系统或应用程序有问题,您需要立即查阅日志。内存计数器 MemHeapUsedM 告诉你总的内存使用情况,如果你看到大量的线程等待,你就知道你需要更多的内存。

dfs 上下文

dfs(分布式文件系统)指标侧重于基本文件操作(创建、删除)或容量、事务等。表 7-3 列出了其中一些指标。

表 7-3 。dfs 上下文的度量
|

公制的

|

说明

|
| — | — |
| 容量维护 | HDFS 的总可用磁盘空间(GB) |
| 创建的文件 | 群集中创建的文件数量 |
| 删除的文件 | 群集中删除的文件数 |
| 文件重命名 | 群集中重命名的文件数 |
| 剩余百分比 | 剩余 HDFS 容量的百分比(GB) |
| 总块数 | 簇中的总块数 |
| 事务 _ 平均 _ 时间 | 交易的平均时间 |
| 交易数量操作 | 交易数量 |

dfs 指标可用于安全目的。您可以使用它们来发现集群中不寻常的活动或活动的突然变化。您可以存储每天的度量值(在一个 Hive 表中),并计算过去 30 天的平均值。然后,如果某个指标的每日值与平均值相差 50%,您就可以生成一个警报。您还可以将指标输出定向到 Ganglia,使用 Ganglia 进行聚合和平均,然后使用 Nagios 生成基于 50%变化阈值的警报。

rpc 上下文

rpc(远程过程调用)度量关注远程过程的过程细节。表 7-4 列出了一些重要的 RPC 矩阵。

表 7-4 。rpc 上下文的度量
|

公制的

|

说明

|
| — | — |
| RpcProcessingTimeNumOps | 已处理的 RPC 请求数 |
| rpcauthentaicationfailures | 失败的 RPC 认证调用数 |
| RpcAuthorizationFailures | 失败的 RPC 授权调用数 |

rpc 度量也可以用于安全目的。您可以使用它们来发现集群中不寻常的 RPC 活动或 RPC 活动的突然变化。同样,您可以将每日指标值存储在一个 Hive 表中(或使用 Ganglia ),并维护过去 30 天的平均值。然后,如果某个指标的每日值与平均值相差某个百分比,如 50%,您可以生成一个警报。从安全的角度来看,像RpcAuthenticationFailuresRpcAuthorizationFailures 这样的指标尤其重要。

映射的上下文

mapred (MapReduce)上下文的度量提供与作业相关的详细信息(针对 JobTracker/TaskTracker)。表 7-5 列出了一些重要的 mapred 指标。

表 7-5 。映射上下文的度量
|

公制的

|

说明

|
| — | — |
| 作业 _ 已完成 | 成功完成的作业数 |
| 作业 _ 失败 | 失败的作业数 |
| 地图 _ 已完成 | 成功完成的映射数 |
| 地图 _ 失败 | 失败的映射数 |
| memNonHeapCommittedM | 提交的非堆内存(MB) |
| memNonHeapUsedM | 使用的非堆内存(MB) |
| 已占用 _ 地图 _ 插槽 | 使用的地图槽数 |
| 地图 _ 插槽 | 地图位置的数量 |
| 已占用 _ 减少 _ 插槽 | 使用的缩减插槽数量 |
| 减少 _ 插槽 | 缩减插槽的数量 |
| 减少 _ 完成 | 成功完成的缩减器数量 |
| 减少 _ 失败 | 失败的减速器数量 |
| 跑步 _1440 | 长期运行的作业数(超过 24 小时) |
| 追踪者 | 可用于群集的 TaskTrackers 数量 |

mapred 上下文的度量提供了有关在集群上执行的作业的有价值的信息。它们可以帮助您确定集群是否有任何性能问题(从作业执行的角度来看)。您可以使用一个监控系统(比如 Ganglia)来确保您有足够的 map 和 reduce 插槽随时可用。此外,你可以确保你没有任何长时间运行的作业——除非你事先知道它们!您可以在 Ganglia 中使用 Nagios 来生成适当的警报。就像其他上下文一样,还可以监视 mapred 度量的异常作业活动(相对于平均作业活动)。

您可以在附录 D“Hadoop 指标及其与安全性的相关性”中找到 Hadoop 指标附录 D 还包含了一个例子,解释了使用特定的度量和模式搜索来实现安全性(我也包含了那个例子的特定于安全性的配置)。

指标和安全性

一些指标可以提供有用的安全信息,包括:

  • NameNode 的活动统计:监控 NameNode 上的活动很重要,因为它可以提供大量信息,提醒您注意安全问题。作为 Hadoop 集群的“大脑”, NameNode 是所有文件创建活动的中枢。如果新创建的文件数量急剧变化,或者权限被更改的文件数量急剧增加,这些指标会触发警报,以便您进行调查。
  • 活动统计对于一个****DataNode: 对于一个 DataNode,如果一个本地客户端的读写次数突然增加,你肯定需要调查。此外,如果添加或删除的块数发生较大百分比的变化,则指标会触发警报向您发出警告。
  • RPC 相关处理的活动统计:** 对于 NameNode(或 DataNode),您需要密切监视 RPC 统计,例如处理的 RPC 请求的数量、失败的 RPC 认证调用的数量或失败的 RPC 授权调用的数量。您可以将每天的数字与每周的平均值进行比较,如果数字相差阈值百分比,则生成警报。例如,如果一天中失败的 RPC 授权调用次数为 50 次,每周平均次数为 30 次,那么如果警报阈值为每周平均次数的 50%或更多,将会生成警报(30 的 50%为 15,每天的次数(50)大于 45)。**
  • 系统突然变化的活动统计****资源: 监视任何主要系统资源(如可用内存、CPU 或存储)的突然变化都是有益的。Hadoop 提供了监控这些资源的指标,您可以定义一个特定的百分比(用于生成警报)或监控与每周或每月平均值的百分比偏差。后一种方法更加精确,因为即使受到恶意攻击,一些集群也可能永远达不到目标警报百分比(例如,如果集群的平均内存使用率为 20%,而恶意攻击导致使用率跃升至 60%)。如果您定义了 80%或 90%的警报阈值,那么您将永远不会收到警报。或者,如果您将警报阈值定义为 50%或更多(平均使用率),那么您肯定会收到警报。

您可以结合使用 Ganglia 和 Nagios 来监控任何 Hadoop 守护进程的任何系统资源或指标值的突然变化。同样,附录 D 有一个描述这种方法的例子。

如果您不想使用监控系统,而想采用将指标数据写入文件并使用 Hive 或 HBase 将数据加载到表中的“老式”方法,这也是可行的。当然,您需要开发 will 脚本来调度您的数据加载、执行聚合、生成摘要报告以及生成适当的警报。

指标过滤

当您对安全漏洞或可能的性能问题进行故障排除时,查看大量指标数据可能会花费时间,并且会分散注意力和容易出错。过滤指标数据有助于您关注可能的问题并节省宝贵的时间。Hadoop 允许您通过源、上下文、记录和指标来配置指标过滤器。最高级别的筛选是按源(例如,DataNode5),最低级别的筛选是按指标名称(例如,文件创建)。可以组合过滤器以优化过滤效率。

例如,以下文件接收器仅接受来自上下文 dfs 的指标:

bcl.sink.file0.class=org.apache.hadoop.metrics2.sink.FileSink
bcl.sink.file0.context=dfs

要设置过滤器,您首先需要在您的

$HADOOP_INSTALL/hadoop/conf/

Hadoop-metrics 2 . properties文件中添加如下代码片段:

# Syntax:<prefix>.(source|sink).<instance>.<option>*.sink.file.class=org.apache.hadoop.metrics2.sink.FileSink
*.source.filter.class=org.apache.hadoop.metrics2.filter.GlobFilter
*.record.filter.class=${*.source.filter.class}*.metric.filter.class=${*.source.filter.class}

此后,您可以包括以下任何配置选项,这些选项将在不同级别设置过滤器:

# This will filter out sources withnames starting with Cluster2

jobtracker.*.source.filter.exclude=Cluster2*

# This will filter out records withnames that match localhost in the source dfs

jobtracker.source.dfs.record.filter.exclude=localhost*

# This will filter out Metrics withnames that match cpu*for sink instance file only

jobtracker.sink.file.metric.filter.exclude=cpu*
jobtracker.sink.file.filename=MyJT-metrics.out

因此,总的来说,您可以根据源、源中的模式或者接收的输出文件中的指标名称或模式来过滤指标数据。

请记住,当您仅指定“包括”模式时,过滤器仅包括与过滤条件匹配的数据。此外,当您仅指定“排除”模式时,匹配的数据将被排除。最重要的是,当您指定这两种模式时,不匹配任何一种模式的源也包括在内!最后,包含模式优先于排除模式。

将指标输出捕获到文件

如何将 NameNode 或 DataNode 指标输出到文件中?使用 Metrics2,您可以定义一个接收器(输出文件),通过向目录

/etc/Hadoop/conf

$HADOOP_INSTALL/hadoop/conf

中的

hadoop-metrics2.properties

配置文件添加几行,将来自您的度量源的输出定向到该接收器中。在下面的示例中,我将 NameNode 和 DataNode 指标重定向到单独的输出文件以及 Ganglia 监控系统(请记住,Metrics2 可以支持同时输出到两个接收器):

# Following are entries from configuration file hadoop-metrics2.properties
# collectively they output Metrics from sources NameNode and DataNode to
# a sink named 'tfile'(output to file) and also to a sink named 'ganglia'
# (output to Ganglia)

# Defining sink for file output
*.sink.tfile.class=org.apache.hadoop.metrics2.sink.FileSink

# Filename for NameNode output

namenode.sink.tfile.filename = namenode-metrics.log

# Output the DataNode Metrics to a separate file
datanode.sink.tfile.filename = datanode-metrics.log

# Defining sink for Ganglia 3.1*.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31

# Default polling period for GangliaSink
*.sink.ganglia.period=10

# Directing output to ganglia servers
namenode.sink.ganglia.servers=gangliahost_1:8649,gangliahost_2:8649
datanode.sink.ganglia.servers=gangliahost_1:8649,gangliahost_2:8649

现在您已经将所有的度量数据保存在文件中,您需要有效地利用它。如果您不打算使用监控系统,您将不得不为所有 Hadoop 守护进程定义文件接收器(作为输出),并手动分析巨大的输出文件或根据需要聚合它们!最多,您可以定义 Hive 外部表并简化处理。或者,您可以将指标输出定向到 JMX 控制台进行检查。

请注意,无论使用哪种方法,您都无法以图形方式显示指标数据或聚合以进行快速查看。此外,您还需要通过 shellscripts(访问配置单元数据)设置带有警报机制的接口,并设置用于寻呼系统管理员的接口(如果发生关键事件)。

但是,如果您计划使用 Ganglia,那么将您的指标发送到 Ganglia 监控系统就像将它们发送到一个文件一样简单,并且提供了更多的优势,您将在下一节中了解到。

使用 Ganglia 和 Nagios 进行安全监控

最适合您的 Hadoop 集群的安全监控系统是一个符合您的环境和需求的系统。在某些情况下,确保只有授权用户才能访问可能是最重要的,而在其他情况下,您可能需要监控系统资源,并在资源使用发生突然变化时立即发出警报。一些集群管理员只想监控失败的认证请求。Hadoop 安全监控领域的领导者 Ganglia (

http://ganglia.sourceforge.net

)和 Nagios (

www.nagios.org

)通过提供灵活性和各种监控系统资源、连接以及技术上可能监控的 Hadoop 集群的任何其他部分的方法来应对这一挑战。

两者都是开源工具,具有不同的优势,可以很好地互补。Ganglia 非常擅长收集指标,随着时间的推移跟踪它们,并汇总结果;而 Nagios 更侧重于提供一种警报机制。由于收集指标和发出警报都是监控的重要方面,Ganglia 和 Nagios 配合得最好。这两种工具都有在集群的所有主机上运行的代理,并通过轮询过程收集信息,轮询过程可以轮询任何主机以获取必要的信息。

神经节

Ganglia 是在加州大学伯克利分校设计的,最初是一个开源监控项目,旨在用于大型分布式系统。Ganglia 的开放式架构使其易于与其他应用程序集成,并收集有关其操作的统计数据。这就是 Ganglia 能够轻松接收和处理来自 Hadoop 指标的输出数据并有效使用它的原因。

对于受监控的集群,每个主机运行一个名为 gmond 的守护进程,该进程收集并广播本地指标数据(如 CPU 使用率、内存使用率等。)发送到集群中的所有主机。然后,轮询进程( gmetad )可以查询任何主机,读取所有指标数据,并将其路由到中央监控服务器。中央主机可以显示指标、汇总指标或汇总指标以备将来使用。 Gmond 开销很小,因此可以很容易地在集群中的每台机器上运行,而不会影响用户性能。Ganglia 的 web 界面可以根据您的需要轻松显示过去一小时、一天、一周或一个月的使用情况摘要。此外,您可以根据需要获得这些资源使用的详细信息。

神经节架构

概括地说,Ganglia 有四个主要组件:gmond、gmetad、rrdtool 和 gweb。gmond 在集群中的所有节点上运行并收集指标数据, gmetad 轮询来自 gmond 的数据, rrdtool 存储轮询的数据, gweb 是为存储的数据提供可视化和分析的接口。图 7-3 展示了 Ganglia 的组件如何适应图 7-2 所示的基本 Hadoop 分布式监控系统。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-3 。适用于 Hadoop 的 Ganglia 监控系统

仔细看看每个 Ganglia 组件的功能:

  • gmond: gmond needs to be installed on every host you want monitored. It interacts with the host operating system to acquire Metrics such as load Metrics (e.g., average cluster load), process Metrics (e.g., total running processes) or rpc Metrics (e.g., RpcAuthenticationFailures). It is modular and uses operating system–specific plugins to take measurements. Since only the necessary plugins are installed at compile time, gmond has a very small footprint and negligible overhead.gmond 不是根据来自外部轮询引擎的请求被调用的(用于测量),而是根据本地配置文件定义的时间表进行轮询。通过在同一组播地址广播的简单监听/通告协议,与其他主机(来自集群)共享测量结果。每个 gmond 主机还记录它从集群中的其他主机接收到的指标。因此,Ganglia 集群中的每个主机都知道同一个集群中每个其他主机记录的每个指标的当前值。这就是为什么每个集群只需要轮询一台主机来获取整个集群的指标,任何单个主机故障都不会影响系统!此外,这种设计减少了需要以指数方式轮询的主机数量,因此很容易扩展到大型集群。
  • gmetad: gmetad 是 Ganglia 监控系统中的轮询过程。它需要一个主机名列表,为每个集群指定至少一台主机。gmetad 可以通过端口 8649 从集群中的任何主机请求集群指标的 XML 格式转储,这就是 gmetad 获取集群指标数据的方式。
  • RRDtool: RRDtool 是 Ganglia 组件,用于存储 gmetad 从任何集群主机轮询的度量数据。指标以“循环”方式存储;当没有剩余空间来存储新值时,旧值将被覆盖。根据指定的数据保留需求, RRDtool 聚集数据值或“汇总它们”这种数据存储方式允许我们快速分析最近的数据,并使用少量的磁盘空间维护多年的历史数据。此外,因为所有需要的磁盘空间都是预先分配的,所以容量规划非常容易。
  • gweb: gweb is the visualization interface for Ganglia. It provides instant access to any Metric from any host in the cluster without specifying any configuration details. It visually summarizes the entire grid using graphs that combine Metrics by cluster and provides drop-downs for additional details. If you need details of a specific host or Metric, you can specify the details and create a custom graph of exactly what you want to see.gweb 允许您更改图表中的时间段,支持以各种文本格式(CSV、JSON 等)提取数据,并提供了一个功能齐全的 URL 接口,以便您可以通过特定的 URL 将必要的图表嵌入到其他程序中。此外,gweb 是一个 PHP 程序,运行在 Apache web 服务器下,通常安装在与 gmetad 相同的物理硬件上,因为它需要访问 gmetad 创建的 RRD 数据库。

配置和使用 Ganglia

对 Ganglia 的主要组件有了更清晰的理解后,您就可以设置它并让它为安全相关的监控和输出特定的 Hadoop 指标而工作了。

要在想要监控的 Hadoop 集群上安装 Ganglia,请执行以下步骤:

  1. 在一个集群节点或主机上安装 Ganglia 组件 gmetad、gmond 和 gweb。(以我为例,我调用了主机 GMaster)。
  2. 在所有其他集群节点上安装 Ganglia 组件 gmond。

确切的命令语法或安装方式会因您使用的操作系统而异。具体请参考 Ganglia 安装说明。然而,在所有情况下,您都需要修改配置文件,以使 Ganglia 正常工作,并使 Hadoop 按照预期通过 Ganglia 输出指标(需要修改配置文件

gmond.conf

gmetad.conf

hadoop-metrics2.properties

)。

首先,将

gmond.conf

(具有以下配置)复制到所有集群节点:

/* the values closely match ./gmond/metric.h definitions in 2.5.x */
globals {
  daemonize = yes
  setuid = yes
  user = nobody
  debug_level =0
  max_udp_msg_len =1472
  mute = no
  deaf = no
  allow_extra_data = yes
  host_dmax =86400/*secs. Expires hosts in 1 day */
  host_tmax =20/*secs */
  cleanup_threshold =300/*secs */
  gexec = no
  send_metadata_interval =0/*secs */}/*
 * The cluster attributes specified will be used as part of the <CLUSTER>
 * tag that will wrap all hosts collected by this instance.
 */
cluster {
  name ="pract_hdp_sec"
  owner ="Apress"
  latlong ="N43.47 E112.34"
  url ="http://www.apress.com/9781430265443"}/* The host section describes attributes of the host, like the location */
host {
  location ="Chicago"}/* Feel free to specify as many udp_send_channels as you like */
udp_send_channel {
  bind_hostname = yes #soon to be default
  mcast_join =239.2.11.71
  port =8649
  ttl =1}/* You can specify as many udp_recv_channels as you like as well. */
udp_recv_channel {
  mcast_join =239.2.11.71
  port =8649
  bind =239.2.11.71
  retry_bind =true}/* You can specify as many tcp_accept_channels as you like to share
   an xml description of the state of the cluster */
tcp_accept_channel {
  port =8649}/* Each Metrics module that is referenced by gmond must be specified and
   loaded. If the module has been statically linked with gmond, it does
   not require a load path. However all dynamically loadable modules must
   include a load path. */
modules {
  module {name ="core_metrics"}
  module {name ="cpu_module" path ="modcpu.so"}
  module {name ="disk_module" path ="moddisk.so"}
  module {name ="load_module" path ="modload.so"}
  module {name ="mem_module" path ="modmem.so"}
  module {name ="net_module" path ="modnet.so"}
  module {name ="proc_module" path ="modproc.so"}
  module {name ="sys_module" path ="modsys.so"}}

在 Globals 部分,

daemonize

属性,当

true

时,将使 gmond 作为后台进程运行。大于 0 的

debug_level

将导致 gmond 在前台运行并输出调试信息。当

true

时,

mute

属性将阻止 gmond 发送任何数据,当

true

时,

deaf

属性将阻止 gmond 接收任何数据。如果

host_dmax

设置为正数,那么 gmond 将在

host_dmax

秒内没有收到主机消息后刷新主机。

cleanup_threshold

是 gmond 清除任何带有过期数据的主机或指标之前的最短时间。

send_metadata_interval

设置为 0 意味着 gmond 将只在启动时以及在收到远程运行的其他 gmond 节点的请求时发送元数据包。

几个 Ganglia 指标可以检测系统资源的突然变化,非常适合安全监控:

  • cpu_aidle(自上次启动以来 cpu 周期空闲的百分比;对 Linux 有效)
  • cpu_user(执行用户进程所花费的 cpu 周期百分比)
  • load_five(报告的系统负载,五分钟内的平均值)
  • mem_shared(系统和用户进程占用的内存量)
  • proc_run(运行的进程总数)
  • mem_free(可用内存量)
  • disk_free(总可用磁盘空间)
  • bytes_in(从所有非环回接口读取的字节数)
  • bytes_out(写入所有非环回接口的字节数)

您可以将它们添加到您的

gmond.conf

文件中,格式如下:

collection_group {
  collect_every =40
  time_threshold =300
  metric {
    name ="bytes_out"
    value_threshold =4096
    title ="Bytes Sent"}}

正如您在示例中看到的,需要以相同的时间间隔收集和发送的指标可以被分组到同一个

collection_group

下。在本例中,

collect_every

指定采样间隔,

time_threshold

指定最大数据发送间隔(即,数据以该间隔发送),而

value_threshold

是度量方差阈值(即,如果值超过

value_threshold

值,则发送该值)。

第二个配置文件是

gmetad.conf

,它只需要驻留在主机(GMaster)上。请记住,下面的代码只是一个示例,您可以根据需要设置自己的数据源或更改设置以进行循环归档:

# Format:
# data_source "my cluster"[polling interval] address1:port addreses2:port ...
#
data_source "HDPTaskTracker"50 localhost:8658
data_source "HDPDataNode"50 localhost:8659
data_source "HDPNameNode"50 localhost:8661
data_source "HDPJobTracker"50 localhost:8662
data_source "HDPResourceManager"50 localhost:8664
data_source "HDPHistoryServer"50 localhost:8666
#
# Round-Robin Archives
# You can specify custom Round-Robin archives here
#
RRAs "RRA:AVERAGE:0.5:1:244""RRA:AVERAGE:0.5:24:244" RRA:AVERAGE:0.5:168:244" "RRA:AVERAGE:0.5:672:244" "RRA:AVERAGE:0.5:5760:374"
#
# The name of this Grid. All the data sources above will be wrapped in a GRID
# tag withthis name.
# default: unspecified
gridname "HDP_GRID"
#
# In earlier versions of gmetad, hostnames were handled in a case
# sensitive manner. If your hostname directories have been renamed to lower
# case, set this option to 0 to disable backward compatibility.
# From version 3.2, backwards compatibility will be disabled by default.
# default:1(for gmetad <3.2)
# default:0(for gmetad >=3.2)
case_sensitive_hostnames 1

最后,您需要定制目录

/etc/Hadoop/conf

$HADOOP_INSTALL/hadoop/conf

中的

hadoop-metrics2.properties

配置文件。您可以定义适当的源(在本例中,可以是 dfs、jvm、rpc 或 mapred 指标)、接收器(只是 Ganglia 或 Ganglia 和输出文件的组合)和过滤器(过滤掉您不需要的指标数据)。

要设置源和接收器,请使用类似如下的代码:

# syntax:[prefix].[source|sink|jmx].[instance].[options]
# See package.html for org.apache.hadoop.metrics2 for details

*.period=60*.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31
*.sink.ganglia.period=10

# default for supportsparse is false*.sink.ganglia.supportsparse=true.sink.ganglia.slope=jvm.metrics.gcCount=zero,jvm.metrics.memHeapUsedM=both
.sink.ganglia.dmax=jvm.metrics.threadsBlocked=70,jvm.metrics.memHeapUsedM=40

# Associate sinks withserver and ports
namenode.sink.ganglia.servers=localhost:8661
datanode.sink.ganglia.servers=localhost:8659
jobtracker.sink.ganglia.servers=localhost:8662
tasktracker.sink.ganglia.servers=localhost:8658
maptask.sink.ganglia.servers=localhost:8660
reducetask.sink.ganglia.servers=localhost:8660
resourcemanager.sink.ganglia.servers=localhost:8664
nodemanager.sink.ganglia.servers=localhost:8657
historyserver.sink.ganglia.servers=localhost:8666
resourcemanager.sink.ganglia.tagsForPrefix.yarn=Queue

supportsparse

设置为

true

有助于减少带宽使用。否则,每次发布指标时都会更新指标缓存,这可能会占用大量 CPU/网络资源。Ganglia

slope

可以有值

zero

(度量值始终保持不变)、

positive

(度量值只能增加)、

negative

(度量值只能减少)或

both

(度量值可以增加或减少)。

dmax

值表示特定值将保留多长时间。例如,JVM 指标

threadsBlocked

(来自前面的配置)的值将只保留 70 秒。

正如我在前面的“指标过滤”一节中所讨论的,过滤器在您进行故障排除或需要关注已知问题并且只需要特定指标数据的情况下非常有用。当然,您可以通过

gmond.conf

中的设置来限制您正在捕获的指标数据(正如您在本节前面所学的那样),但是当您需要临时限制(或捕获)指标数据时,过滤器会很有用——而且要快!

使用 Ganglia 监控 HBase

Ganglia 可用于监控 HBase,就像您看到的它用于监控 Hadoop 一样。在目录

$HBASE_HOME/conf

中有一个名为

hadoop-metrics.properties

的配置文件(其中

$HBASE_HOME

是 HBase 安装目录)。您需要为 HBase 配置所有“上下文”,以便将 Ganglia 用作输出:

# Configuration of the "hbase" context for Ganglia
hbase.class=org.apache.hadoop.metrics.ganglia.GangliaContext
hbase.period=60
hbase.servers=localhost:8649

# Configuration of the "jvm" context for Ganglia
jvm.class=org.apache.hadoop.metrics.ganglia.GangliaContext
jvm.period=60
hbase.servers=localhost:8649

# Configuration of the "rpc" context for Ganglia
rpc.class=org.apache.hadoop.metrics.ganglia.GangliaContext
rpc.period=60
hbase.servers=localhost:8649

对于

hbase

上下文,您可以在 HBase 主服务器上看到 averageLoad(每个区域服务器服务的平均区域数)或 numRegionServers(在线区域服务器数)等指标的值。

另外,对于

jvm

上下文,您可以看到 MemHeapUsedM(使用的堆内存,以 MB 为单位)和 MemHeapCommittedM(提交的堆内存,以 MB 为单位)这样的指标。如果不止一个 jvm 正在运行(即不止一个 HBase 进程), Ganglia 会聚合指标值,而不是针对每个实例报告它们。

HBase 监控部分到此结束。我在附录 D 中列出了所有 HBase 指标,供您参考。

在结束关于 Ganglia 的讨论之前,我想让您快速浏览一下 Ganglia web 界面。请回顾图 7-4 。它显示了 Ganglia 仪表板,其中显示了上个月的摘要图。您可以看到平均和最大负载、CPU 使用率、内存使用率和网络使用率。从控制面板中,您可以选择任何这些资源的详细图表,或者为您需要的特定指标创建自定义图表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-4 。神经节仪表盘

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传神经节在

http://ganglia.sourceforge.net/

可用。神经节的插件在

https://github.com/ganglia/

可用。Ganglia 的用户社区 URL 是:

http://ganglia.info/?page_id=67

Nagios〔??〕

Nagios 是一个专门的调度和通知引擎。它不监控任何进程或资源,而是调度插件(可执行程序——Nagios 插件与 Hadoop Metrics 插件不同)的执行,并根据执行状态采取行动。例如,状态 0 表示成功,1 表示警告,2 表示严重,3 表示未知。您可以配置 Nagios 服务,为配置文件中定义的所有插件的每个输出映射特定的动作。此外,您可以定义自己的插件,并定义监视它们的频率以及映射到每个可能输出的操作。

除了代码之外,插件还可以返回文本消息,该消息可以写入日志,也可以显示在 web 界面上。如果文本消息包含管道字符,则其后的文本将被视为性能数据。性能数据包含来自被监控主机的指标,可以传递给外部系统(如 Ganglia)使用。

大多数时候,Nagios 与 Ganglia 一起用于监控。原因是这两种开源工具很好地互补,因为它们有不同的优势。例如,Ganglia 更侧重于收集指标并在一段时间内跟踪它们,而 Nagios 更侧重于作为一种警报机制。因为收集指标和发出警报都是监控的重要方面,所以它们最好结合使用。Ganglia 和 Nagios 都在集群的所有主机上运行代理,并收集信息。

回到 Nagios,让我从 Nagios 体系结构开始。

架构

Nagios 守护进程或服务运行在一台主机上,并在所有需要监控的远程主机上运行插件。(要将 Nagios 与 Ganglia 集成,请确保 Ganglia 进程 gmond 正在运行 Nagios 插件的每台主机上运行)。远程 Nagios 插件向 Nagios 服务发送信息和更新,Nagios web 界面显示这些信息。当检测到问题时,Nagios 守护程序使用电子邮件或页面(发送到手机的文本消息)通知预定义的管理联系人。配置文件中定义的日志文件中提供了历史日志数据。正如你在图 7-5 中看到的,Nagios 监控系统有三个主要组件:

  • **服务器:**服务器负责管理和调度插件。服务器定期检查插件状态,并根据状态执行操作。出现警报时,会通知已配置的管理资源。
  • 插件: Nagios 提供了一组标准的用户可配置插件,您还可以根据需要添加更多插件。插件是可执行程序(大多用 C、Java、Python 等编写)。它执行特定的任务并将结果返回给 Nagios 服务器。
  • Nagios 的浏览器界面:这些是由 CGI 生成的网页,显示关于被监控资源的概要信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-5 。Nagios 架构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意 Nagios 在

http://www.nagios.org

免费提供。你可以在

http://nagiosplug.sourceforge.net

从 Nagios 插件开发团队下载 Nagios 官方插件。此外,Nagios 社区正在不断开发新的插件,您可以在

http://exchange.nagios.org

找到。

尽管结合使用 Ganglia 和 Nagios 是一种有效的安全监控方法,但是在默认情况下,这些应用程序并没有集成。正如下一节所解释的,您需要通过插件来集成它们。

Nagios 与 Ganglia 的集成

Nagios 没有内置的指标。Nagios 执行远程或本地插件,并将它们的状态与用户指定的状态/通知映射进行比较,以执行任何必要的通知任务。像 NRPE (Nagios 远程插件执行器)或 NSCA (Nagios 服务检查接收器)这样的服务被用于远程执行。但是,如果使用 Ganglia 进行监控,Nagios 需要的所有指标(CPU、内存、磁盘 I/O 等。)已经有了。您只需将 Nagios 指向 Ganglia 来收集这些指标!为了帮助您,从版本 2.2.0 开始,Ganglia 项目开始在其 gweb 版本中包含许多官方 Nagios 插件(有关详细信息,请参见

https://github.com/ganglia/ganglia-web/wiki/Nagios-Integration

)。在 Nagios 中,您可以使用这些插件创建命令和服务,将 Ganglia 捕获(或生成)的指标与 Nagios 中定义的警报阈值进行比较。

最初,有五个 Ganglia 插件可用:

  • check_heartbeat(检查心跳以验证主机是否可用)
  • check_metric(检查特定主机上的单个指标)
  • check_multiple_metrics(检查特定主机上的多个指标)
  • check_host_regex(检查 regex 定义的主机范围内的多个指标)
  • check_value_same_everywhere(检查一组主机上的值是否相同)

现在,当前的 Ganglia web tarball(版本 3.6.2)包含 10 个用于 Nagios 集成的插件!你可以在

http://sourceforge.net/projects/ganglia/files/ganglia-web/3.6.2/

下载它来检查五个新插件。

使用 Ganglia 的 Nagios 插件

解压缩后,Ganglia web tarball 包含一个名为

nagios

的子目录,其中包含 well 脚本以及每个插件的 PHP 脚本。插件的 shellscript 接受参数值,并将它们传递给相应的 PHP 脚本。PHP 脚本处理这些值,并使用网格状态的 XML 转储(包含所有指标细节的集群状态;由 gmetad 获得)以按照请求获取当前度量值。一个返回代码(指示请求的状态)被传递回 Nagios。图 7-6 说明了这个过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-6 。Ganglia-Nagios 集成处理

记得在使用服务器端 PHP 脚本功能之前启用它,并验证配置文件

conf.php

(由 gweb 使用)中的以下参数值:

$conf['nagios_cache_enabled']=1;
$conf['nagios_cache_file']= $conf['conf_dir']."/nagios_ganglia.cache";
$conf['nagios_cache_time']=45;
conf.php

的位置因操作系统、Hadoop 发行版和其他因素而异。您的最佳选择是使用

find

命令:

find /-name conf.php –print

使用 Nagios 作为五个 Ganglia 插件中任何一个的调度和警报机制的步骤都非常相似。因此,我将用两个插件来演示这个过程:

check_heartbeat

check_multiple_metrics

。我还假设您已经安装了 Ganglia、PHP 和 Nagios,并且正在使用 Hortonworks Hadoop 发行版。

check_heartbeat

插件是 Ganglia 用来确保主机正常运行的心跳计数器。每当主机收到新的度量数据包时,此计数器都会重置。要在 Nagios 中使用这个插件,首先将 Ganglia web tarball(在我的例子中是

/var/www/html/ganglia/nagios

)中 Nagios 子目录下的

check_heartbeat.sh

脚本复制到您的 Nagios 插件目录下(在我的例子中是

/usr/lib64/nagios/plugins

)。确保脚本中的

GANGLIA_URL

是正确的。替换您的本地主机名,并检查

http://localhost/ganglia

是否会将您带到 Ganglia 主页进行安装。然后检查这是否是

check_heartbeat.sh

中的设置:

GANGLIA_URL=http://*<localhost>*/ganglia/nagios/check_heartbeat.php

此时,您可能还想验证 Nagios 服务器上的 PHP 命令行安装是否正常工作;你可以通过运行

php –version

命令来实现。您应该会看到类似以下内容的响应:

PHP 5.3.3(cli)(built: Aug 6201405:54:27)
Copyright (c)1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c)1998-2010 Zend Technologies

运行插件脚本,并验证它是否正确提供了心跳状态:

>./check_heartbeat.sh host=pract_hdp_sec threshold=75

OK Last beacon received 0 days,0:00:07

接下来,将这个插件定义为 Nagios 的一个命令(详见侧栏“Nagios 命令和宏”)。阈值是自上次报告心跳以来的时间量;也就是说,如果收到的最后一个数据包是在 50 秒之前,您应该将阈值指定为 50:

define command {
command_name check_ganglia_heartbeat
command_line $USER1$/check_heartbeat.sh host=$HOSTADDRESS$ threshold=$ARG1$
}

请注意宏

$HOSTADDRESS$

(替换为主机的 IPaddress)、

$USER1$

(在资源文件中定义的用户自定义宏)和

$ARG1$

(命令的第一个参数)的使用。使用宏会将宏中包含的信息自动提供给命令(因为引用的值是可用的)。因此,命令

check_ganglia_heartbeat

可以用于检查集群中任何主机的心跳。类似地,传递给该命令的参数值允许您在运行时更改该参数。请参考侧栏“Nagios 命令和宏”,了解关于宏的更多细节。

NAGIOS 命令和宏

对于 Nagios,可以将命令定义为包括服务检查、服务通知、服务事件处理程序、主机检查、主机通知和主机事件处理程序。命令定义可以包含在运行时替换的宏;这是使 Nagios 灵活的主要特性之一(关于宏的更多信息,请参考

http://nagios.sourceforge.net/docs/3_0/macros.html

)。

宏可以提供来自主机、服务和其他来源的信息。例如,

$HOSTNAME$

$HOSTADDRESS$

是经常使用的宏。宏也可以使用

     A 
    
   
     R 
    
   
     G 
    
   
     n 
    
   
  
    ARGn 
   
  
ARGn传递参数(第 n 个参数传递给命令*)。Nagios 支持多达 32 个参数宏(
$ARG1$

$ARG32$

)。定义命令的语法如下:*

define command{
command_name
command_line
}

其中

<command_name>

是命令的名称,而

<command_line>

是 Nagios 在使用命令时实际执行的内容。

您可以在名为

nagios.cfg

的 Nagios 主配置文件中定义命令。大多数情况下,该文件驻留在

/etc/nagios

中,但是对于您的安装,位置可能会有所不同。主配置文件为命令、服务、联系人、模板等定义了单独的对象配置文件。此外,可能会有一个针对 Hadoop 服务器的特定部分。例如,Hortonworks

nagios.cfg

有以下部分:

# Definitions for hadoop servers
cfg_file=/etc/nagios/objects/hadoop-hosts.cfg
cfg_file=/etc/nagios/objects/hadoop-hostgroups.cfg
cfg_file=/etc/nagios/objects/hadoop-servicegroups.cfg
cfg_file=/etc/nagios/objects/hadoop-services.cfg
cfg_file=/etc/nagios/objects/hadoop-commands.cfg

我将在配置文件

/etc/nagios/objects/hadoop-commands.cfg

中定义命令

check_ganglia_heartbeat

。最后一步是为 Nagios 定义一个服务。在 Nagios 中,术语服务的使用非常通用或者不明确。它可以指示主机上运行的实际服务(例如,POP、SMTP、HTTP 等)。)或与主机相关联的某种其他类型的度量(空闲磁盘空间、CPU 使用率等)。).服务在配置文件

/etc/nagios/objects/hadoop-services.cfg

中定义,其语法如下:

define service {
        host_name localhost
        use hadoop-service
        service_description GANGLIA::Ganglia Check Heartbeat
        servicegroups GANGLIA
        check_command check_ganglia_heartbeat!50
        normal_check_interval 0.25
        retry_check_interval 0.25
        max_check_attempts 4}

请注意,

check_command

表示将在指定主机上执行的实际命令。参数

normal_check_interval

指示在安排服务的下一次检查之前要等待的时间单位数。一个时间单位是 60 秒(这是默认值),因此 0.25 表示 15 秒。

retry_check_interval

定义了当服务变为非正常状态时,在安排重新检查服务之前等待的时间单位数,而

max_check_attempts

表示在这种情况下重试的次数。

命令

check_multiple_metrics

检查多个 Ganglia 指标并生成一个警报。要使用它,请将 Ganglia web tarball 中 Nagios 子目录下的

check_multiple_metrics.sh

脚本复制到您的 Nagios 插件目录中。确保脚本中的

GANGLIA_URL

被设置为

http://localhost/ganglia/nagios/check_heartbeat.php

,还记得用适当的主机名替换

localhost

在配置文件

/etc/nagios/objects/hadoop-commands.cfg

中定义相应的命令

check_ganglia_multiple_metrics

:

define command {
command_name check_ganglia_multiple_metrics
command_line $USER1$/check_multiple_metrics.sh host=$HOSTADDRESS$ checks='$ARG1$'}

您可以添加用冒号分隔的检查列表。每次检查由

Metric_name,operator,critical_value

组成。接下来,在配置文件

/etc/nagios/objects/hadoop-services.cfg

中定义相应的服务:

define service {
        host_name localhost
        use hadoop-service
        service_description GANGLIA::Ganglia check Multiple Metric service
        servicegroups GANGLIA
        check_command check_ganglia_multiple_metrics!disk_free,less,10:load_one,more,5
        normal_check_interval 0.25
        retry_check_interval 0.25
        max_check_attempts 4}

注意定义要执行的命令的

check_command

部分:

check_ganglia_multiple_metrics!disk_free,less,10:load_one,more,5.

这表示如果(主机的)可用磁盘空间低于 10GB,或者如果 1 分钟平均负载超过 5,将会生成警报。

成功定义 Ganglia 插件后,您可以使用 Nagios web 界面来检查和管理这些插件。正如您在图 7-7 中看到的,新的

check_heartbeat

check_multiple_metrics

插件已经就位,并由 Nagios 管理。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-7 。带插件的 Nagios web 界面

如果您想要更多的练习,您可以遵循相同的步骤并添加其他三个插件。

Nagios 社区

Nagios 的真正优势在于其活跃的用户社区,该社区一直致力于更有效地使用 Nagios,并添加插件来增强其功能。要查看其他用户开发的最新插件,请访问位于

http://exchange.nagios.org/directory/Plugins

的社区页面。出于安全目的,您会发现许多可以有效使用的插件,例如:

  • check_ssh_faillogin :监控ssh次失败的登录尝试;在http://exchange.nagios.org/directory/Plugins/Security/check_ssh_faillogin/details有售。
  • 显示 _ 用户: 显示已登录的用户。可以使用白名单、黑名单或两者同时使用,对登录的特定用户发出警报。详情请见:http://exchange.nagios.org/directory/Plugins/System-Metrics/Users/Show-Users/details
  • **check _ long _ running _ procs . sh:**检查长时间运行的流程;在http://exchange.nagios.org/directory/Plugins/System-Metrics/Processes/Check-long-running-processes/details可用。

您可以使用与使用 Ganglia 插件相同的过程来使用任何新插件。您需要将它复制到 Nagios 插件目录,然后定义一个命令和服务。当然,请遵循各个插件的任何特定安装说明,或者安装它们运行所需的任何附加包。

摘要

在本章中,我讨论了 Hadoop 的监控以及流行的开源监控工具。请记住,监视需要对需要监视的资源和您计划监视的环境有很好的了解。虽然我可以告诉您 Hadoop 集群需要监控什么,但是您最了解您的环境的具体需求。我已经尝试提供一些一般性的提示,但是从我的经验来看,监视总是比您自己的系统管理员对您的环境的了解和理解要好。

“相关性”(一个系统的“最新”或“最先进”程度)也是一个非常有效的考虑因素。您必须每天关注您感兴趣领域的所有创新(包括恶意攻击),并根据它们调整您的监控。请记住,最好的系统管理员是那些最警觉、反应最敏捷的人。

最后,请试着透过特定的工具和版本号来理解本章中描述的监控技术背后的原理和意图。您可能无法使用相同的工具进行监控,但是如果您遵循这些原则,您将能够建立有效的监控系统——最终,这是我们的共同目标。

八、Hadoop 中的加密

最近,我和一个朋友谈论可能使用 Hadoop 来加速对他公司的 4TB“海量”数据仓库的报告。(他是芝加哥地区最大的房地产公司之一的 IT 部门主管。)虽然他勉强同意了一个可能的性能收益,但是他非常自信地问道,“但是加密我们的 HR(人力资源)数据呢?对于基于 MS SQL Server 的 HR 数据,我们使用对称密钥加密和证书,并辅以 C#代码。你如何用 Hadoop 实现这一点?”

随着 Hadoop 越来越多地在企业环境中使用,越来越多的人会问同样的问题。答案并不简单。大多数 Hadoop 发行版现在已经安装和/或实现了 Kerberos,并且包括实现授权和传输加密的简单选项,但是对于 Hadoop 的静态加密,您的选项是有限的,尤其是文件级粒度。

当数据处于静止状态并存储在磁盘上时,为什么需要对其进行加密?当黑客完全访问您的数据时,加密是最后一道防线。知道你的数据仍然是安全的,这是一种令人欣慰的感觉,因为没有加密它的密钥,它就不能被解密和使用。但是,请记住,加密是用于对抗未授权的访问,因此不能被认证或授权所取代(这两者都控制授权的访问)。

在本章中,我将讨论静态加密,以及如何在 Hadoop 中实现它。首先,我将简要概述 DES 和 AES 算法使用的对称(密钥)加密、RSA 算法使用的非对称(公钥)加密、密钥交换协议和证书、数字签名以及加密哈希函数。然后,我将解释 Hadoop 中需要加密的内容以及如何加密,并讨论英特尔 Hadoop 发行版,该发行版现在计划部分随 Cloudera 的发行版提供,也可通过 Project Rhino 开源获得。最后,我将讨论如何使用 Amazon Web Services 的 Elastic MapReduce(或预装 Hadoop 的虚拟机)来实现静态加密。

数据加密简介

密码学 可以非常有效地用来对抗多种安全威胁。无论您将数据称为加扰的、伪装的还是加密的,它都不容易被读取、修改或操纵。幸运的是,即使密码学起源于高等数学,你也不需要理解它的数学基础来使用它。简单理解一下,一种常见的方法是将加密建立在一个密钥(一种用作加密和解密基础的独特字符模式)和一个算法(根据需要使用密钥对数据进行加扰或解扰的逻辑)的基础上。参见“加密的基本原理”侧栏,了解更多关于加密的构建模块

加密的基本原理

小时候,我和我的朋友们开发了我们自己的特殊代码语言,以便在学校里交流。任何需要在课堂上传递的信息都包含像“4 21 8 0 27 18 24 0 6 18 16 12 17 10”这样的数字序列,如果我们被抓住了,就会让老师感到困惑。

我们的代码是一个简单的替换密码的例子,其中数字(表示字母表中的位置)被替换为字母,然后每个数字加一个 3;0 被用作单词分隔符。于是,上面的序列简单的问了对方一句“你来吗”?虽然我们的代码非常简单,但实际应用中的数据加密使用复杂的密码,这些密码依赖于复杂的逻辑来替换字符。在某些情况下,一个键,如一个单词或数学表达式,被用来调换字母。因此,例如,使用“myword”作为密钥,ABCDEFGHIJKLMNOPQRSTUVWXYZ 可以映射到my wordabcefghijklnpqstuvwxyz,这意味着短语“Hello world”的密码文本将是“Brggj ujngo”。为了增加复杂度,可以用字母在字母表中的位置代替表达式 2 x + 5

£

26 中的 x 来映射 ABCDEFGHIJKLMNOPQRSTUVWXYZ 到 gikmoqsuwyabcdefhjlnprtvxz。复杂的替代密码可用于增强安全性,但一个大问题是加密和解密它们所需的时间。

另一种加密方法是转置(也称为重新排序、重新排列或置换)。换位是一种加密,其中原始文本的字母被重新排列以生成加密文本。通过在信息中传播信息,换位使信息难以理解。这种加密的一个非常简单的例子是列转置,它涉及到将文本行转置为列。例如,要将短语“你现在能读这个吗”转置为六列转置,我可以将字符写成六行,并一行接一行地排列:

C A N Y O U
R E A D T H

然后,生成的密码文本将按列读取:“cri aes nan ydo otw uh”。由于所需的存储空间和解密密文所涉及的延迟,当时间至关重要时,这种算法并不特别适合于长消息。

虽然替换和转置密码并不单独用于现实世界的数据加密,但它们的组合构成了一些广泛使用的商业级加密算法的基础。

流行的加密算法

有两种基本的基于密钥的加密:对称的和非对称的。对称算法通常被称为秘密密钥 ,使用相同的密钥进行加密和解密。两个用户共享一个密钥,他们都用这个密钥来加密和发送信息给对方,以及解密来自对方的信息——就像我童年的朋友和我用相同的数字替换密钥来编码我们在课堂上传递的笔记一样。因为每对计划使用它的用户都需要一个单独的密钥,所以密钥分发是使用对称加密的一个主要问题。数学上, n 需要成对通信的用户需要n×(n–1)/2 个密钥。因此,随着用户数量的增加,密钥的数量几乎呈指数增长。使用对称密钥的两种流行算法是 DES 和 AES(稍后将详细介绍)。

非对称或公钥系统不存在密钥分配和密钥指数的问题。公钥可以通过电子邮件消息分发,或者复制到共享目录中。使用它加密的消息可以使用相应的私钥解密,该私钥只有授权用户拥有。由于一个用户(在一个系统内)可以使用任何其他用户的公钥来加密发给他的消息(该用户有相应的私钥来解密),密钥的数量仍然很少——是用户数量的两倍。流行的加密算法 RSA 使用公钥。然而,公钥加密通常比对称密钥加密慢 10,000 倍,因为公钥加密使用的模幂运算涉及乘法和除法,比对称算法使用的位操作(加法、异或、替换、移位)慢。因此,对称加密更常用,而公钥加密则保留给速度不是限制因素的特殊应用。公钥加密变得非常有用的一个地方是对称密钥交换:它允许对称密钥的受保护交换,然后可以用它来保护进一步的通信。

对称和非对称加密,尤其是 DES、AES 和 RSA,被用作执行诸如签署文档、检测更改和交换敏感数据等计算任务的构建模块,您将在“加密的应用”一节中了解到这一点。现在,让我们仔细看看这些流行的算法。

数据加密标准(DES)

由 IBM 在其 Lucifer 算法的基础上开发的数据加密标准 ( DES )于 1976 年 11 月被正式采纳为美国联邦标准,用于所有公共和私营部门的非机密通信。DES 算法是加密的两个基本原理的复杂组合:替换和换位。该算法的稳健性是由于在总共 16 个循环中重复应用这两种技术。DES 算法是一种块算法,这意味着它使用 64 位数据块而不是字符流。它将输入数据块分成两半,分别对每一半执行替换,将密钥与其中一半融合,最后交换这两半。这个过程执行 16 次,详见“DES 算法”侧栏。

DES 算法

对于 DES 算法,当最初的 64 个数据位通过初始置换进行转置时,第一个加密周期开始。首先,64 个转置数据位被分成左半部分和右半部分,每部分 32 位。64 位密钥(56 位用作密钥;其余的是奇偶校验位)用于变换数据位。接下来,密钥左移预定数量的位并被转置。产生的密钥与右半部分组合(替换),并且在一轮排列之后,结果与左半部分组合。这成为新的右半边。旧的右半部分(与键和左半部分结合之前的部分)成为新的左半部分。该循环(图 8-1 )执行 16 次。在最后一个循环完成后,执行最终的转置(与初始置换相反)以完成算法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-1 。DES 算法的循环

因为 DES 将其算术和逻辑运算限制为 64 位数字,所以它可以在当前大多数 64 位操作系统上与软件一起用于加密。

这种算法的真正弱点是抵御一种称为差分密码分析的攻击,在差分密码分析中,可以在 258 次搜索中从选择的密文中确定密钥。密码分析攻击没有暴露 DES 中任何重大的、可利用的漏洞,但是随着计算能力的容易获得,使用 56 位密钥的风险正在增加。尽管破解 DES 所需的计算能力或时间仍然很重要,但一个有决心的黑客肯定能解密用 DES 加密的文本。如果使用三重 DES 方法(使用序列调用 DES 三次进行加密:通过 Key1 加密,使用 Key2 解密,使用 Key3 加密),则有效密钥长度变为 112(如果三个密钥中只有两个是唯一的)或 168 位(如果 Key1、Key2 和 Key3 都是唯一的),攻击难度成倍增加。DES 可以在短期内使用,但肯定会寿终正寝,需要被更健壮的算法所取代。

高级加密标准(AES)

1997 年,美国国家标准与技术研究所呼吁采用新的加密算法;随后,高级加密标准 ( AES )成为 2001 年的新标准。最初被称为 Rijndael ,AES 也是一种分组密码,使用多个循环或回合,使用 128 的输入数据块大小来加密数据。128、192 和 256 位的加密密钥分别需要 10、12 或 14 个加密周期。AES 的循环很简单,包括一个替换、两个置换函数和一个键控函数(更多细节见侧栏“AES 算法”)。AES 没有已知的弱点,并且在商业上广泛使用。

AES 算法

为了帮助您直观地了解 AES 的操作,我先假设输入数据长度为 9 个字节,并将 AES 矩阵表示为一个 3 × 3 数组,数据字节为 b0 至 b8。

如图 8-2 所示,AES 算法的每一轮由以下四个步骤组成:

  1. 替换:为了扩散数据,使用替换表替换 128 位数据块的每个字节。
  2. 移位行:通过左循环移位对数据行进行置换;行 n 的第一个(最左边,高位) n 元素被移至末尾(最右边,低位)。因此,行 n 向左循环移位(n–1)字节。
  3. 混合列:为了转换列,每列的三个元素乘以一个多项式。对于每个元素,比特被左移并与它们自身进行异或运算,以将该列的每个元素扩散到该列的所有三个元素上。
  4. 添加循环密钥:最后,对这个循环唯一的密钥(子密钥)的一部分进行异或运算或添加到每个数据列。子密钥是通过对密钥进行一系列置换、替换和异或运算而从密钥中得到的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-2 。AES 算法的周期

里维斯特-沙米尔-阿德尔曼加密

对于 DES、AES 和其他对称密钥算法,每对用户都需要一个单独的密钥。每增加一个用户( n + 1), n 就需要更多的密钥,这使得很难跟踪你需要与之通信的每个额外用户的密钥。确定和分发这些密钥可能是一个问题,维护分发的密钥的安全性也是一个问题,因为它们不可能都被记住。然而,非对称或公钥加密有助于避免对称密钥加密遇到的这一问题和许多其他问题。使用公钥加密的最著名的算法是Rivest-sha mir-Adelman(RSA)算法。RSA 于 1978 年推出,并以其三位发明者(Rivest、Shamir 和 Adelman)的名字命名,至今仍然安全,没有发现严重的缺陷。要了解 RSA 如何工作,请参见“Rivest-Shamir-Adelman (RSA)加密”侧栏。

RIVEST-SHAMIR-ADELMAN (RSA)加密

RSA 加密算法将数论的结果与确定给定数字的质因数的难度结合起来。RSA 算法用算术模 n 运算;对于一个数 P 的模 n 是你用 P 除以 n 的余数。

RSA 中用于解密和加密的两个密钥是可以互换的;可以选择任一个作为公钥,另一个可以用作私钥。任何明文块 P 都被加密为Pemodn。因为是求幂运算,mod ne 以及 n 都是非常大的数( e 一般是 100 位, n 一般是 200 位),因式分解 Pe 来解密加密的明文几乎是不可能的。选择解密密钥 d 使得(Pe)dmodn=P。因此,知道 d 的合法接收者可以简单地确定(Pe)dmodn=P,从而恢复 P ,而不需要因式分解 Pe 。加密算法基于分解大数的基本问题,该问题没有简单或快速的解决方案。

如何确定加密密钥?如果你的明文是 P ,你在计算Pemodn,那么加密密钥将是数字 en ,解密密钥将是 dn 。作为两个质数 pq 的乘积, n 的值应该非常大,通常大约 100 位或大约 200 个十进制数(或 512 位)长。如果需要, n 可以是 768 位甚至 1024 位。 n 的值越大,因式分解 n 以确定 pq 的难度就越大。

下一步,选择一个数 e ,使得 e 与(p-1)×(q-1)没有共同的因子。确保这一点的一种方法是选择 e 作为大于( p - 1)以及( q - 1)的素数。

最后,选择这样一个数字 d ,数学上:

e × d = 1 mod (p - 1) × (q - 1)

如你所见,即使已知 n 是两个素数的乘积,但如果它们很大,从 e 中确定素数 pq 或私钥 d 是不可行的。因此,该方案为 d 提供了足够的安全性。这也是 RSA 安全并在商业上使用的原因。不过,值得注意的是,由于改进的算法和增强的计算能力,多达 1024 位的 RSA 密钥已经被破解(尽管无论如何都不是微不足道的)。因此,被认为对大多数应用足够安全的密钥大小是 2048 位;对于更敏感的数据,应该使用 4096 位。

数字签名算法加密

另一种使用公钥加密的流行算法是 DSA ( 数字签名算法)。尽管这个算法的最初目的是签名,但它也可以用于加密。DSA 安全性具有基于离散对数问题的理论数学基础,并且是使用离散对数问题没有快速或有效解决方案的假设来设计的。表 8-1 比较了 DSA 和 RSA。

表 8-1 。DSA 与 RSA

|

属性

|

目录系统代理(Directory System Agent)

|

南非共和国(Republic of South Africa)

|
| — | — | — |
| 密钥生成 | 更快的 | |
| 加密 | | 更快的 |
| [通信]解密 | 更快 ** | |
| 数字签名生成 | 更快的 | |
| 数字签名验证 | | 更快的 |
| 较慢的客户端 | | 更好的 |
| 较慢的服务器 | 更好的 | |

** 请注意,“更快”也意味着使用更少的计算资源

总而言之,DSA 和 RSA 具有几乎相同的加密强度,尽管它们各有自己的性能优势。在出现性能问题的情况下,评估问题出在哪里(客户端还是服务器)并以此为基础选择关键算法可能是个好主意。

加密的应用

在许多情况下,一种类型的加密比另一种更适合您的需要,或者您可能需要多种加密方法的组合来满足您的需要。您将遇到的加密算法的四种常见应用是加密散列函数、密钥交换、数字签名和证书。对于 HDFS,客户端数据访问使用 TCP/IP 协议,该协议反过来使用 SASL 和数据加密密钥。Hadoop web 控制台和 MapReduce shuffle 使用使用公钥证书的安全 HTTP。英特尔的 Hadoop 发行版(现在的 Project Rhino)使用对称密钥进行静态加密,使用证书通过 MapReduce 作业进行加密数据处理。为了更好地理解 Hadoop 和其他应用程序如何使用这些应用程序,您需要了解每个应用程序是如何工作的。

哈希函数

在某些情况下,诚信比保密更重要。例如,在存储法律文档或管理贷款的文档管理系统中,知道文档没有被更改是很重要的。因此,加密也可以用来提供完整性。

在大多数文件中,内容的组件没有以任何方式绑定在一起。换句话说,文件中的每个字符都是独立的,即使更改一个值会影响文件的完整性,也很容易被检测到。加密可以用来“密封”文件,这样任何更改都可以很容易地被检测到。提供这种密封的一种方法是计算一个加密函数,称为文件的散列校验和,或消息摘要。因为散列函数依赖于被密封文件的所有位,所以改变一位将改变校验和结果。每次访问或使用文件时,哈希函数都会重新计算校验和,只要计算出的校验和与存储的值匹配,就可以知道文件没有被更改。

DES 和 AES 非常适合于密封值,因为需要一个密钥来修改存储的值(以匹配修改的数据)。分组密码也使用一种叫做链接的技术:通过使用异或将加密的前一个块与当前块的加密相结合,一个块链接到前一个块的值,从而链接到文件中所有前一个块,就像一个链。随后,文件的加密校验和可能是文件的链式加密的最后一个块,因为该块依赖于所有其他块。常见的哈希函数有 MD4MD5 (MD 意为消息摘要)、以及 SHA / SHS (安全哈希算法或标准)。事实上,当具有 Hadoop 令牌凭证的 Hadoop 客户端连接到 Hadoop 守护程序(例如,读取/写入 HDFS 的 MapReduce 任务)时,Hadoop 使用 SASL MD5-DIGEST 机制进行认证。

密钥交换

假设你需要与一个陌生人(他也不认识你)交换信息,同时确保没有其他人可以访问这些信息。解决方案是公钥加密。因为非对称密钥是成对的,所以一对密钥中的一半可以公开,而另一半不会受到影响。私钥可以用来加密,接收方只需要有公钥就可以解密。为了理解这一点的重要性,考虑一个示例密钥交换。

假设萨姆和罗伊需要交换一个共享的对称密钥,并且两人都有一个通用加密算法的公钥(称这些为 K PUB-S 和 K PUB-R )以及私钥(称这些为 K PRIV-S 和 K PRIV-R )。最简单的解决方案是 Sam 选择任意对称密钥 K,并使用他的私钥(K PRIV-S )对其进行加密,然后将其发送给 Roy,Roy 可以使用 Sam 的公钥来解除加密并获得 K。不幸的是,任何能够访问 Sam 的公钥的人也可以获得仅对 Roy 有用的对称密钥 K。因此,更安全的解决方案是 Sam 首先使用他自己的私钥加密对称密钥 K,然后使用 Roy 的公钥再次加密它。然后,罗伊可以用他的私钥解密第一级加密(外部加密)——这是只有他能做的事情——然后用萨姆的公钥解密“内部加密”(证明通信来自萨姆)。因此,总之,对称密钥可以在不损害安全性的情况下进行交换。

数字签名和证书

今天,我们的大部分日常交易都是在数字世界中进行的,因此用于批准的签名的概念已经发展成一种依赖于数字签名的相互认证的模型。一个数字**签名 是一个像真实签名一样工作的协议:它可以为发送者提供一个唯一的标记,并使其他人能够从该标记中识别发送者,从而确认一个协议。数字签名需要以下属性:

  • 不可复制
  • 唯一可追溯的来源真实性(仅来自预期来源)
  • 与信息不可分割
  • 传输后不可变
  • 最近使用过一次,不应允许重复使用

公钥加密系统非常适合数字签名。例如,出版公司可以先用自己的私钥加密合同,然后再用作者的公钥加密。作者可以使用他的私钥解密第一级加密,然后使用发布者的公钥解密内部加密以获得合同。之后,作者可以通过创建合同的哈希值,然后用自己的私钥加密合同和哈希值来“签名”。最后,他可以通过使用发布者的公钥再次加密来增加一层加密,然后将加密的合同通过电子邮件发送回发布者。因为只有作者和出版商有权访问他们的私钥,所以交换显然是不可伪造的,并且是唯一可信的。哈希函数和校验和确认了不变性(假设计算并保存了合同的初始校验和以供比较),而电子邮件的频率和时间戳确保了最近的一次性使用。图 8-3 总结了该过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-3 。使用数字签名进行加密通信

在图 8-3 中,E(C,K PRIV-P 表示契约 C 是用 KPRIV-P加密的,同样,D(E(E(C,K PRIV-P ,K PUB-A ,K PRIV-A 表示发送给作者的双重加密契约的第一级是用 KPRIV-A解密的)

数字证书建立在各方之间通过一个共同的受尊重的个人的信任基础上,它在多方之间的作用类似于数字签名对两个人的作用。公钥和用户的身份在一个证书中相关联,然后由一个认证机构进行“签名”,证明关联的准确性并认证身份。

例如,一家出版公司可能会建立一个证书方案,以下列方式对作者、他们的代理和公司编辑进行认证。首先,发布者选择一个公钥对,将公钥公布在公司中每个人都可以访问的地方,并保留私钥。然后,每个编辑创建一个公钥对,将公钥和他或她的身份一起放入消息中,并将消息安全地传递给发布者。发布者通过创建消息的哈希值对其进行签名,然后用他或她的私钥对消息和哈希值进行加密。通过签署消息,发布者确认消息中的公钥(编辑者的)和身份(也是编辑者的)是同一个人的。这条消息被称为编辑证书。作者可以用他的公钥创建一个消息,作者的代理可以签名、散列并返回它。那将是作者的证明。因此,作者和编辑的证书可以建立和用于验证他们的身份。任何人都可以通过从发布者的公钥开始并解密编辑者的证书以检索他或她的公钥和身份来验证编辑者的证书。可以通过从代理从发布者处获得的公钥开始验证作者的证书,并使用该公钥解密证书以检索作者的公钥和身份。

因为 Hadoop 为其各种组件使用不同类型的加密,所以我将在下一节中简要讨论这些加密在哪里使用。

Hadoop 加密选项概述

当考虑 Hadoop 中敏感数据的加密时,您需要考虑存储在集群节点内磁盘上的“静态”数据,以及传输中的数据,这些数据在不同节点之间以及节点和客户端之间的通信过程中会移动。第四章解释了保护节点和应用程序之间传输的数据的细节;您可以为加密配置单个 Hadoop 生态系统组件(使用组件的配置文件),就像您为加密配置 Hadoop 的 RPC 通信一样。例如,要为 Hive 配置 SSL 加密,您需要在

hive-site.xml

中更改配置(需要将

hive-site.xml

中的属性

hive.server2.use.SSL

设置为

true

,并且需要使用属性

hive.server2.keystore.path

hive.server2.keystore.password

来指定密钥库)。因此,本章重点介绍静态配置 Hadoop 数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意加密是一项 CPU 密集型活动,会加重硬件负担,降低处理速度。仔细权衡使用加密的决定。如果您确定加密是必要的,则对存储在集群中的所有数据以及与该数据相关的处理实现加密。

对于 Hadoop 集群,静态数据是分布在所有 DataNodes 上的数据。需要加密可能是因为数据是敏感的,信息需要得到保护,或者加密对于遵守法律法规(如保险业的 HIPAA 或金融业的 SOX)是必要的。

尽管目前没有 Hadoop 发行版提供静态加密,但 Cloudera 和 Hortonworks 等主要供应商提供了第三方解决方案。例如,Cloudera 与 Gazzang 的 zNcrypt 合作,为数据块和文件提供静态加密。为了提供额外的保护,zNcrypt 使用基于进程的 ACL 和密钥。此外,亚马逊 Web 服务(AWS) 通过其弹性 MapReduce web 服务和 S3 存储提供静态加密(您将很快了解到更多信息),英特尔的 Hadoop 发行版也提供静态加密。但所有这些解决方案要么是专有的,要么将您限制在 Hadoop 的特定发行版上。

对于加密静态 Hadoop 数据的开源解决方案,您可以使用 Project Rhino。2013 年,英特尔启动了一个开源项目,通过向 Apache 贡献代码来提高 Hadoop 和 Hadoop 生态系统的安全能力。该代码尚未在 Apache Foundation 的 Hadoop 发行版中实现,但它包含了一些增强功能,包括分布式密钥管理和静态加密功能。这个开源项目的总体目标如下:

  • 支持加密和密钥管理
  • 通用授权框架(超越 ACL)
  • 一个通用的基于令牌的认证框架
  • HBase 的安全性改进
  • 改进的安全审计

你可以在

https://github.com/intel-hadoop/project-rhino

查看 Project Rhino 的进度,在下一节了解更多。

使用英特尔的 Hadoop 发行版进行加密

2013 年,英特尔宣布了自己的 Hadoop 发行版——对于一家硬件制造公司来说,这是一个奇怪的决定,通过 Hadoop 发行版姗姗来迟地进入大数据领域。然而,英特尔向 Hadoop 世界保证,它的意图只是为 Hadoop 生态系统(Apache 基金会)做出贡献,并帮助解决 Hadoop 安全问题。英特尔声称其 Hadoop 发行版与特定的英特尔芯片(用作 CPU)完美协调,加密和解密速度比当前的替代产品快 10 至 15 倍。

大约在同一时间,我有机会与英特尔团队合作,为一个需要加密存储在 HDFS 的数据的客户进行试点项目,我了解了英特尔的加密技术是如何工作的。客户使用 Hive 进行查询和报告,英特尔提供涵盖 HDFS 和 Hive 的加密。虽然我所使用的发行版(它构成了本节所介绍信息的基础)还没有上市,但它所提供的大部分功能都可以通过 Project Rhino 和 Cloudera 的 Hadoop 发行版获得(现在英特尔已经投资了该发行版)。

具体来说,英特尔发行版使用编解码器来实现加密(稍后将详细介绍),并提供可用于 Hive 或 HBase 的文件级加密。它将对称和非对称密钥与 Java 密钥库结合使用(更多信息请参见侧栏“密钥库和信任库”)。我使用的实现细节将让您对 Project Rhino 的潜力有所了解。

密钥库和信任库

密钥库是用于各种目的的密钥或可信证书的数据库或储存库,包括认证、加密和数据完整性。密钥条目包含所有者的身份和私钥,而可信证书条目除了实体的身份之外,只包含公钥。为了更好的管理和安全性,您可以使用两个密钥库:一个包含您的密钥条目,另一个包含您的可信证书条目(包括证书颁发机构的证书)。使用您的私钥可以限制对密钥库的访问,而可信证书驻留在更容易公开访问的信任库中。

在决定信任什么时使用,信任库 包含来自您希望与之通信的某人的证书,或者来自您信任以识别其他方的证书颁发机构的证书。仅当您信任潜在条目的来源实体时,才将条目添加到信任库。

有各种类型的密钥库可用,如 PKCS12 或 JKS。JKS 是 Java 世界中最常用的。PKCS12 不是特定于 Java 的,但是对于具有从浏览器备份的私钥或者来自基于 OpenSSL 的工具的私钥的证书来说,使用起来很方便。PKCS12 主要用作密钥库,但对信任库来说用处不大,因为它需要一个与证书相关联的私钥。JKS 不要求每个条目都是私钥条目,因此您可以将它用作您信任但不需要私钥的证书的信任库。

逐步实现

该客户的要求是对存储在 HDFS 并使用 Hive 访问的敏感财务数据进行静态加密。因此,我必须确保从 SQL Server 作为文本文件推送的数据文件在存储于 HDFS 时是加密的,并且只能由授权用户通过 Hive 正常访问(应用解密)。图 8-4 提供了加密过程的概述。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-4 。英特尔 Hadoop 发行版的数据加密

实现我的目标的第一步是用命令创建一个秘密(对称)密钥和密钥库(我在我的主目录下创建了一个目录/密钥,并在那里创建了所有与加密相关的文件):

> keytool -genseckey -alias BCLKey -keypass bcl2601 -storepass bcl2601 -keyalg AES -keysize 256-KeyStore BCLKeyStore.keystore -storetype JCEKS

这个

keytool

命令生成密钥

BCLKey

,并将其存储在新创建的名为

BCLKeyStore

的密钥库中。

keyalg

参数指定用于生成密钥的算法

AES

,而

keysize 256

指定要生成的密钥的大小。最后,

keypass

是用于保护密钥的密码,

storepass

对密钥库也是如此。您可以使用以下命令调整密钥库的权限:

> chmod 600 BCLKeyStore.keystore

接下来,我用以下命令创建了一个密钥对(私钥/公钥)和密钥库:

> keytool -genkey -alias KEYCLUSTERPRIVATEASYM -keyalg RSA -keystore clusterprivate.keystore -storepass 123456-keypass 123456-dname "CN= JohnDoe, OU=Development, O=Intel, L=Chicago, S=IL, C=US"-storetype JKS -keysize 1024

这将生成一个密钥对(一个公钥和相关的私钥)和单元素证书链,作为条目

KEYCLUSTERPRIVATEASYM

存储在密钥库

clusterprivate.keystore

中。注意使用算法

RSA

进行公钥加密和密钥长度

1024

。参数

dname

指定与

alias

关联的名称,作为自签名证书中的颁发者和主体。

我使用英特尔管理器(admin) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传配置外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传安全外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传密钥管理在集群中分发创建的密钥库

clusterprivate.keystore

为了创建信任库,我接下来采取了以下步骤:

  1. Extract the certificate from the newly created KeyStore with the command:> keytool -export -alias KEYCLUSTERPRIVATEASYM -keystore clusterprivate.keystore -rfc -file hivepublic.cert -storepass 123456该命令从 KeyStore clusterprivate.keystore中读取与alias KEYCLUSTERPRIVATEASYM相关联的证书,并将其存储在文件hivepublic.cert中。证书将以可打印的编码格式输出(如-rfc选项所示)。
  2. Create a TrustStore containing the public certificate:> keytool -import-alias HIVEKEYCLUSTERPUBLICASYM -file hivepublic.cert -keystore clusterpublic.TrustStore -storepass 123456该命令从文件hivepublic.cert中读取证书(或证书链),并将其存储在由HIVEKEYCLUSTERPUBLICASYM标识的密钥库(用作信任库)条目中。信任库clusterpublic.TrustStore被创建,导入的证书被添加到可信证书列表中。
  3. > chmod 644 clusterpublic.TrustStore> chown root:hadoop clusterpublic.TrustStore命令将clusterpublic.TrustStore所有权改为root,组改为hadoop,权限改为"644" (read/write for root and read for members of all groups)
  4. 创建一个文件TrustStore.passwords 将其权限设置为644,并在文件中添加以下内容:keystore.password=123456
  5. /keys目录及其所有文件复制到集群中的所有其他节点。在每个节点上,密钥库目录必须在/usr/lib/hadoop/中。

准备好信任库后,我随后创建了一个文本文件(

bcl.txt

)用于测试加密,并将其复制到 HDFS:

> hadoop fs -mkdir /tmp/bcl.....> hadoop fs -put bcl.txt /tmp/bcl

启动 Pig

(> pig)

,被带到

grunt>

提示。我在 Pig 中执行了以下命令来设置所有需要的环境变量

:
set KEY_PROVIDER_PARAMETERS 'keyStoreUrl=file:root/bcl/BCLKeyStore.keystore&keyStoreType-JCEKS&password=bcl2601';
set AGENT_SECRETS_PROTECTOR 'com.intel.hadoop.mapreduce.crypto.KeyStoreKeyProvider';

set AGENT_PUBLIC_KEY_PROVIDER 'org.apache.hadoop.io.crypto.KeyStoreKeyProvider';

set AGENT_PUBLIC_KEY_PROVIDER_PARAMETERS 'keyStoreUrl=file:keys/clusterpublic.TrustStore&keyStoreType=JKS&password=123456';
set AGENT_PUBLIC_KEY_NAME 'HIVEKEYCLUSTERPUBLICASYM';
set pig.encrypt.keyProviderParameters 'keyStoreUrl=file:root/bcl/BCLKeyStore.keystore&keyStoreType-JCEKS&password=bcl2601';

接下来,为了从 HDFS 读取

bcl.txt

文件,对其进行加密,并将其存储到名为

bcl_encrypted

的目录中的相同位置,我发出了以下命令:

raw = LOAD '/tmp/bcl/bcl.txt' AS (name:chararray,age:int,country:chararray);
STORE raw INTO '/tmp/bcl/bcl_encrypted' USING PigStorage('\t','-keyName BCLKey');

退出 Pig 后,我通过发出以下命令检查加密文件的内容:

> hadoop fs -cat /tmp/bcl/bcl_encrypted/part-m-00000.aes

控制字符似乎确认了加密。我使用以下步骤创建了一个 Hive 外部表并将其指向加密文件:

  1. 启动蜂巢。
  2. 设置环境变量:set hive.encrypt.master.keyName=BCLKey;set hive.encrypt.master.keyProviderParameters=keyStoreUrl=file:////root/bcl/BCLKeyStore.keystore&keyStoreType=JCEKS&password=bcl2601;set hive.encrypt.keyProviderParameters=keyStoreUrl=file:////root/bcl/BCLKeyStore.keystore&keyStoreType=JCEKS&password=bcl2601;set mapred.crypto.secrets.protector.class=com.intel.hadoop.mapreduce.cryptocontext.provider.AgentSecretsProtector;set mapred.agent.encryption.key.provider=org.apache.hadoop.io.crypto.KeyStoreKeyProvider;set mapred.agent.encryption.key.provider.parameters=keyStoreUrl=file:////keys/clusterpublic.TrustStore&keyStoreType=JKS&password=123456;set mapred.agent.encryption.keyname=HIVEKEYCLUSTERPUBLICASYM;
  3. 创建一个指向 Pig 创建的加密数据文件的加密外部表:create external table bcl_encrypted_pig_data(name STRING, age INT, country STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION '/tmp/bcl/bcl_encrypted/' TBLPROPERTIES("hive.encrypt.enable"="true","hive.encrypt.keyName"="BCLKey");
  4. 一旦创建了表,任何授权的客户端(在/usr/lib/hadoop/keys 目录中有适当的密钥和证书文件)都可以在 Hive 提示符下使用select查询(在 Hive 语法中):> select * from bcl_encrypted_pig_data;

总之,为了实现用于 Hive 的 Intel 发行版,我设置了用于加密的密钥、密钥库和证书。然后,我从密钥库中提取证书,并将其导入信任库。注意,虽然我在示例中为用户

JohnDoe

创建了密钥对和证书,但是对于多用户环境,您需要为所有授权用户创建密钥对和证书。

对称密钥用于加密 HDFS(和 Hive)内的数据。MapReduce 使用公钥和证书,因为配置单元内的客户端通信使用 MapReduce。这也是 Hive 的授权用户(被授权访问加密数据的用户)需要密钥对和证书的原因。

英特尔发行版使用的特殊类

静态加密的预期功能需要实现特殊的编解码器、类和逻辑。尽管有许多类和编码解码器可用,但它们不能在提供加密功能的公共逻辑支持下协调工作。英特尔在其发行版中添加了底层逻辑。

例如,

org.apache.hadoop.io.crypto.KeyStoreKeyProvider

是类

org.apache.hadoop.io.crypto.KeyProvider.

的实现,HBase 对应的 Apache 类是

org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider

,它是

org.apache.hadoop.hbase.io.crypto.KeyProvider

的实现。此类用于解析本地文件系统上受保护的密钥库文件中的密钥。英特尔使用这个类来管理存储在密钥库(和信任库)文件中的密钥。使用的其他 Hbase 类有:

org.apache.hadoop.hbase.io.crypto.Cipher
org.apache.hadoop.hbase.io.crypto.Decryptor
org.apache.hadoop.hbase.io.crypto.Encryptor

这些类是如何使用的?例如,用 Java 术语来说,类

org.apache.hadoop.hbase.io.crypto.Cipher

的方法

Encryption.decryptWithSubjectKey

使用提供的对称密钥解密加密数据块;而方法

Encryption.encryptWithSubjectKey

使用提供的对称密钥加密数据块。总之,这个类使用对称密钥提供加密/解密。

英特尔定制类

com.intel.hadoop.mapreduce.crypto.KeyStoreKeyProvider

专为加密 MapReduce 处理而设计,其工作方式类似于 Apache Hadoop 加密类

mapred.crypto.KeyStoreKeyProvider

。它适用于 MapReduce 作业,能够处理证书和密钥。

这些类中的大多数都是由 Apache 基金会开发和使用的。唯一的区别是 Apache Foundation 的 Hadoop 发行版不使用这些类来提供静态加密的累积功能,其他商业发行版也不使用这些类。Project Rhino 正在尝试补救这种情况,由于甚至英特尔定制类和编解码器也可供他们使用,因此您可以期待很快 Project Rhino 将提供静态加密功能。

使用亚马逊网络服务 来加密你的数据

正如你所看到的,安装和使用加密可能是一项艰巨的任务,但 Amazon 有意识地努力让它变得简单。AWS 提供了简单的选项,消除了安装、配置、管理和使用 Hadoop 加密所需的大部分工作和时间。有了 AWS,您可以选择不做、做部分或全部工作,这取决于您租用的配置服务。例如,如果您需要关注项目的其他部分(例如设计从 RDBMS(关系数据库管理系统)向 HDFS 或分析系统批量加载数据的 ETL),您可以让 AWS 负责为您的数据全面实现静态加密。

决定数据加密和存储的模式

AWS 为加密使用提供了几种配置或型号。第一个模型,模型 A,让你控制加密方法以及 KMI(密钥管理基础设施 ) 。它为您提供了最大的灵活性和控制力,但是所有的工作都由您来做。模型 B 让您在 AWS 存储密钥时控制加密方法。;你仍然可以管理你的钥匙。最严格的选择是模型 C,它不能控制 KMI 或加密方法,尽管它是最容易实现的,因为 AWS 为您完成了所有工作。要实现模型 C,您需要使用支持服务器端加密的 AWS 服务,如亚马逊 S3、亚马逊 EMR、亚马逊红移或亚马逊冰川。

为了演示,我将使用 Amazon 的模型 C 实现静态加密。基本步骤很容易理解,您可以使用您获得的理解来实现模型 A,为此您需要实现所有的任务(我已经提供了实现模型 A 的步骤,可以在 Apress 网站上下载)。我将使用亚马逊 EMR(或 Elastic MapReduce,它提供了一个易于使用的 Hadoop 实现,运行在亚马逊弹性计算云、EC2 上)以及亚马逊 S3 进行存储。请注意:租用 EMR 服务的一个警告是,AWS 按“正常”小时收费,而不是实际小时,因为该计划使用多个 AWS“设备”和至少两个 EC2 实例。

如果你不熟悉 AWS 的产品,EC2 是 AWS 的焦点。EC2 允许您租用一个虚拟服务器(或虚拟机),这是一个预配置的 Amazon 机器映像,带有所需的操作系统和虚拟硬件资源选择(CPU、RAM、磁盘存储等)。).您可以引导(或启动)这个虚拟机或实例,并根据需要运行您自己的应用程序。术语弹性指的是灵活的、按小时付费的模型,适用于你创建和使用的任何实例。图 8-5 显示 AWS 管理控制台 。这就是你需要开始“租用”各种 AWS 组件的地方(假设你已经先创建了一个 AWS 账户):

http://aws.amazon.com

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-5 。AWS 管理控制台

回到使用模型 C 的实现,如果您在获取 EMR 集群时指定了服务器端加密(选择 AWS 控制台中的弹性 MapReduce 选项,如图 8-5 所示),EMR 模型将为您的数据提供服务器端加密,并透明地管理加密方法和密钥。图 8-6 描绘了 AWS 用于服务器端加密的 方法“信封加密”。基本步骤如下:

  1. 当您请求加密数据时,AWS 服务会生成一个数据密钥。
  2. AWS 使用数据密钥来加密您的数据。
  3. 使用 S3 存储来存储加密的数据密钥和加密的数据
  4. AWS 使用密钥加密密钥(在这种情况下是 S3 独有的)来加密数据密钥,并将其与数据密钥和加密数据分开存储。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-6 。AWS 的信封加密

对于数据检索和解密,这个过程是相反的。首先,使用密钥加密密钥对加密的数据密钥进行解密,然后用它来解密您的数据。

从图 8-6 可以看出,S3 存储服务支持服务器端加密。亚马逊 S3 服务器端加密使用 256 位 AES 对称密钥作为数据密钥和主(密钥加密)密钥。

使用所选模型加密数据文件

在这一节中,我将讨论基于 EMR 的 model C 的逐步实现,其中 AWS 透明地管理您的加密方法和密钥。如前所述,您可以在 Apress 网站上找到实现模型 A 的步骤。

通过 AWS 创建 S3 存储

您需要首先创建存储,因为您的 EMR 集群将需要它。只需登录 AWS 管理控制台,选择服务 S3,并在(图 8-7 )中创建一个名为

htestbucket

的存储桶和一个文件夹

test

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-7 。创建 S3 存储桶和文件夹

为您创建的文件夹

test

指定服务器端加密(图 8-8 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-8 。激活文件夹的服务器端加密

根据需要调整先前创建的存储桶

htestbucket

的权限(图 8-9 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-9 。调整 S3 存储桶的权限

创建一个密钥对(

bclkey

)用于认证

.pem

文件保存到您的客户端。使用 PuTTYgen 创建一个

.ppk

(私有密钥文件),可以使用 PuTTY 进行认证,以连接到 EMR 集群(主节点)。有关使用 PuTTY 和 PuTTYgen 的详细信息,请参见第四章和附录 b。图 8-10 显示了创建密钥对的 AWS 屏幕。要访问它,请在 AWS 管理控制台上选择 service EC2,然后选择 option Key Pairs。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-10 。在 AWS 中创建密钥对

创建访问密钥 ID 和秘密访问密钥

这些密钥用作加密的凭证,并与用户相关联。如果您没有创建任何用户,并且正在使用 AWS 的

root

帐户,那么您需要为

root

创建这些密钥。从身份和访问管理(IAM)管理控制台 ( 图 8-11 ),选择 Dashboard,然后点击第一个选项,删除您的根访问密钥。(如果你没有为

root

创建这些键,你不会看到这个警告)。要访问 IAM 控制台,请在 AWS 管理控制台上选择服务“身份&访问管理”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-11 。AWS 的 IAM 控制台

点击管理安全凭证 按钮,忽略警告“继续安全凭证”(图 8-12 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-12 。安全凭证的创建

你的 AWS

root

账户就像一个 UNIX

root

账户,AWS 不建议使用它。相反,根据需要创建具有角色、权限和访问密钥的用户帐户。如果这样做,您可以更容易地自定义权限,而不会影响安全性。关于使用

root

账户,另一件要记住的事情是,如果你丢失了访问密钥 ID 或秘密访问密钥,你将无法找回它们!因此,我创建了一个用户

Bhushan

,用于我的 EMR 集群(图 8-13 )。我使用身份和访问管理(IAM)管理控制台中的“用户”选项和“创建新用户”按钮(图 8-11 )来创建这个新用户。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-13 。创建用于 EMR 集群的用户

要为用户设置密钥,请再次从 IAM 管理控制台开始,选择“用户”选项,然后选择特定用户(或创建用户)。接下来,打开安全凭证区域,为所选用户创建访问密钥 ID 和秘密访问密钥(图 8-13 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意当您创建访问密钥 ID 和秘密访问密钥时,您可以下载它们并将其保存在安全的地方作为备份。采取这种预防措施肯定比在丢失钥匙的情况下重新创建一套钥匙容易。

创建 AWS EMR 集群,指定服务器端加密

完成准备步骤后,您就可以创建 EMR 集群了。登录到 AWS 管理控制台,选择 Elastic MapReduce 服务,然后单击 Create Cluster 按钮。选择“服务器端加密”和“一致视图”配置选项,保留其他选项的默认值(图 8-14 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-14 。创建 EMR 集群

在硬件配置部分(图 8-15 ,请求一个主 EC2 实例运行 JobTracker 和 NameNode,请求一个核心 EC2 实例运行 TaskTrackers 和 DataNodes。(这只是为了测试;在现实世界中,根据您所需的处理能力,您需要获得多个主实例或核心实例。)在 Security Access 部分,指定前面创建的密钥对之一(

bclkey

),而在 IAM Roles 部分,为 EMR 角色设置

EMR_DefaultRole

EMR_EC2_DefaultRole

。确保这些角色有权访问 S3 存储(存储桶和文件夹)以及您需要使用的任何其他资源。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-15 。EMR 集群的硬件配置

检查完所有要求的配置选项后,单击屏幕底部的“创建集群”按钮,根据您的要求创建一个 EMR 集群。

几分钟后,您将收到类似于图 8-16 的集群创建确认。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-16 。EMR 集群已创建

测试加密

最后一步,测试 EMR 和 S3 之间的“静态”加密是否正常工作。根据 AWS 和 EMR 文档,任何将数据从 HDFS 传输到 S3 存储(或从 S3 传输到 HDFS)的 MapReduce 作业都应该对写入永久存储的数据进行加密。

您可以使用 Amazon utility S3DistCp 来验证这一点,该工具旨在亚马逊 S3 和 HDFS 之间移动大量数据(来自 EMR 集群)。S3DistCp 支持请求亚马逊 S3 在将 EMR 数据写入您管理的亚马逊 S3 桶时使用服务器端加密。然而,在使用它之前,您需要将以下配置添加到您的

core-site.xml

(我已经清空了我的访问键):

<property><name>fs.s3.awsSecretAccessKey</name><value>xxxxxxxxxxxxxxxxxxxx</value></property><property><name>fs.s3.awsAccessKeyId</name><value>yyyyyyyyyyyyyyyyyyyy</value></property><property><name>fs.s3n.awsSecretAccessKey</name><value>xxxxxxxxxxxxxxxxxxxx</value></property><property><name>fs.s3n.awsAccessKeyId</name><value>yyyyyyyyyyyyyyyyyyyy</value></property>

记住用值替换您自己的访问密钥 ID 和秘密访问密钥。不需要重启任何 Hadoop 守护进程。

接下来,确保以下 jar 存在于您的

/home/hadoop/lib

(my Hadoop 安装目录下的

/lib

)中。如果没有,找到并复制到以下位置:

/home/hadoop/lib/emr-s3distcp-1.0.jar
/home/hadoop/lib/gson-2.1.jar
/home/hadoop/lib/emr-s3distcp-1.0.jar
/home/hadoop/lib/EmrMetrics-1.0.jar
/home/hadoop/lib/httpcore-4.1.jar
/home/hadoop/lib/httpclient-4.1.1.jar

现在,您已经准备好运行 S3DistCp 实用程序,并将文件

test1

从 HDFS 复制到文件夹

test

中,用于 S3 桶

htestbucket

:

> hadoop jar /home/hadoop/lib/emr-s3distcp-1.0.jar -libjars /home/hadoop/lib/gson-2.1.jar,/home/hadoop/lib/emr-s3distcp-1.0.jar,/home/hadoop/lib/EmrMetrics-1.0.jar,/home/hadoop/lib/httpcore-4.1.jar,/home/hadoop/lib/httpclient-4.1.1.jar --src /tmp/test1 --dest s3://htestbucket/test/--disableMultipartUpload --s3ServerSideEncryption

我的示例在几秒钟内产生了以下响应:

14/10/1003:27:47 INFO s3distcp.S3DistCp: Running withargs:-libjars /home/hadoop/lib/gson-2.1.jar,/home/hadoop/lib/emr-s3distcp-1.0.jar,/home/hadoop/lib/EmrMetrics-1.0.jar,/home/hadoop/lib/httpcore-4.1.jar,/home/hadoop/lib/httpclient-4.1.1.jar --src /tmp/test1 --dest s3://htestbucket/test/--disableMultipartUpload --s3ServerSideEncryption
........14/10/1003:27:51 INFO client.RMProxy: Connecting to ResourceManager at
14/10/1003:27:54 INFO mapreduce.Job: The url to track the job: http://10.232.45.82:9046/proxy/application_1412889867251_0001/14/10/1003:27:54 INFO mapreduce.Job: Running job: job_1412889867251_0001
14/10/1003:28:12 INFO mapreduce.Job: map 0% reduce 0%........14/10/1003:30:17 INFO mapreduce.Job: map 100% reduce 100%14/10/1003:30:18 INFO mapreduce.Job: Job job_1412889867251_0001 completed successfully

显然,MapReduce 作业成功地将文件复制到了 S3 存储。现在,您需要验证文件是否加密存储在 S3。为此,使用 S3 管理控制台并检查存储桶

htestbucket

中文件夹

test

内文件

test1

的属性(图 8-17 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-17 。验证 MapReduce 作业的服务器端加密

如您所见,属性服务器端加密被设置为

AES-256

,这意味着来自 EMR 集群的 MapReduce 作业成功地将数据复制到具有服务器端加密的 S3 存储中!

您可以尝试调用 MapReduce 作业的其他方式(例如,Hive 查询或 Pig 脚本),并写入 S3 存储以验证存储的数据确实是加密的。您还可以使用 S3DistCp 将数据从您自己的本地 Hadoop 集群传输到亚马逊 S3 存储。只需确保在本地集群的所有节点上复制了

core-site.xml

中的 AWS 凭证,并且之前列出的六个

.jar

文件位于 Hadoop 安装目录的

/lib

子目录中。

如果您想比较使用 AWS EMR 的加密实现与更实用的模型 A 的实现(在模型 A 中,您管理加密和密钥,另外您需要在 EC2 实例上安装特定的软件来实现加密),请记住您可以从 Apress 网站下载并查看这些步骤。

现在,您已经看到了使用 Hadoop 提供静态加密的两种选择(使用英特尔的 Hadoop 发行版和使用 AWS)。如果你仔细回顾,你会发现它们在实现加密方面确实有共性。图 8-18 总结了通用步骤。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-18 。DataNode 使用对称密钥(来自客户端)来解密数据块,如果成功,则检索数据块。各个数据节点检索并传回后续数据块

摘要

Hadoop 的静态加密仍然是一项正在进行的工作,特别是对于开源世界。也许当 Hadoop 在企业界得到更广泛的应用时,我们的选择会有所改善。现在,你必须求助于付费的第三方解决方案。这些第三方解决方案的缺点是,即使他们声称可以使用特定的发行版,他们的声明也很难得到验证。此外,不清楚他们给你的 Hadoop 安装添加了多少定制代码,以及你实际上为加密/解密获得了什么样的性能。最后,这些解决方案不是由训练有素的密码学家或密码分析师开发或测试的。因此,没有可靠性或保证它们是(并将是)“牢不可破的”。

英特尔以大量宣传和炒作进入 Hadoop 和静态加密领域,但很快退出并投资了 Cloudera。现在,Rhino 项目的未来以及该代码与 Cloudera 发行版的可能集成似乎还不太明朗。有一些零星的开源应用程序,但是还没有一个健壮的、集成的解决方案可以满足一个严肃的 Hadoop 实践者的实际加密需求。

现在,让我们希望这个 Hadoop 领域在用户中产生足够的兴趣,以便在未来使用开源解决方案实现加密的更多选择。

无论未来如何,就目前而言,这是最后一章。我真诚地希望这本书能够促进您对 Hadoop 安全选项的理解,并帮助您确保环境的安全!

九、附录 A:Pageant 使用和实现

Pageant 是一个 SSH 认证代理,它可以与 PuTTY 或 WinSCP 一起使用,用于在内存中保存您的解密密钥,这样您就不需要在每次使用密钥对向服务器进行认证时输入密码来解密您的密钥(第四章详细讨论了基于密钥的认证)。如果您使用多个密钥对来认证多个服务器,Pageant 甚至更有用。您可以使用 Pageant 将所有解密的密钥保存在内存中,这意味着您只需在启动 Windows 会话时输入一次相应的密码。当您注销您的 Windows 会话时,Pageant 会退出,而不会将解密的密钥保存在磁盘上,这就是您需要在启动您的 Windows 会话时再次输入密码短语的原因。

因为 Pageant 是 PuTTY 安装包的一部分,所以可以从同一个 URL (

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

)下载。当你运行可执行文件 Pageant.exe 开始 Pageant,一个图标,看起来像一个戴着帽子的电脑会出现在你的系统托盘。右键单击图标以调用 Pageant 菜单,然后选择所需的菜单选项:新建会话、保存的会话、查看密钥、添加密钥、关于或退出。但是,如果在添加键之前选择查看键,您将只会看到一个空的列表框。

使用 Pageant

要使用 Pageant,首先需要生成一个密钥对,并将公钥复制到需要连接的服务器上。例如,我生成了一个密钥对,并将密钥保存为

keytest.ppk

(私钥)和

keytest.pub

(公钥)。然后,我使用一个密码对私钥进行了加密。因为我想连接到主机

pract_hdp_sec

,所以我将我的公钥粘贴到。ssh 目录(正如在第四章中讨论的)。接下来,我将把解密的私钥存储在 Pageant 中。图 A-1 说明了选择和添加密钥。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-1 。为 Pageant 比赛添加关键点

当您选择一个密钥时(此处为

testkey.ppk

,系统会提示您输入密码短语(图 A-2 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-2 。使用 Pageant 存储密钥的密码短语

输入正确的密码短语后,Pageant 解密您的私钥,并将其保存在内存中,直到您注销 Windows 会话。您可以看到您的密钥在 Pageant 中列出,如图 A-3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-3 。列出 Pageant 比赛中存储的密钥

现在,您只需要在 PuTTY ( 图 A-4 )中指定您的私钥作为授权方式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-4 。在 PuTTY 中指定基于密钥的认证

下次您想连接到服务器

pract_hdp_sec

时,只需打开一个 PuTTY 会话,它会提示您输入登录名。一旦你输入登录名,PuTTY 会直接将你连接到服务器,正如你在图 A-5 中看到的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-5 。使用来自 Pageant 比赛的解密密钥执行基于密钥的认证

PuTTY 识别出 Pageant 正在运行,自动检索解密的密钥,并使用它进行认证。您可以根据需要为同一台服务器打开任意多个 PuTTY 会话,而无需再次键入密码。

此外,Pageant 可以在启动时自动加载多个私钥。例如,假设您每天需要连接十台服务器。每天手动将密钥添加到 Pageant 比赛中既困难又容易出错。要自动加载多个键,请使用类似下面的 Pageant 命令行;当然,目录路径取决于您的

Pageant.exe

或您的私钥文件(。ppk 文件)位于:

C:\Users\Administrator\Desktop>pageant.exe c:\bhushan\keytest.ppk c:\bhushan\bhushan.ppk

您可以添加多个由空格分隔的键。如果密钥是加密的,Pageant 会在启动时提示输入密码。如果 Pageant 已经在运行,并且您执行了这个命令,它会将密钥加载到现有的 Pageant 中。

你也可以创建一个快捷方式,并在那里指定命令行,如图图 A-6 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 A-6 。为多个键指定起始(默认)目录

如果您只有一个私钥,请在目标字段中指定其完整路径:

C:\Users\Administrator\Desktop>pageant.exe c:\bhushan\keytest.ppk

如果您有多个键并且路径很长,您可以只指定一个起始目录,而不是为每个键指定路径。例如,要为我之前的多键示例指定一个起点,在目标字段中输入

C:\Users\Administrator\Desktop>pageant.exe keytest.ppk

,在起点字段中输入

C:\Bhushan

在 Pageant 初始化并加载命令行上指定的键之后,您可以命令 Pageant 启动另一个程序。此程序(例如 WinSCP 或 PuTTY 等。)然后可以使用 Pageant 加载的密钥。语法如下:

C:\Users\Administrator\Desktop>pageant.exe c:\bhushan\keytest.ppk -c C:\PuTTY\putty.exe

安全考虑

在 Pageant 中保存解密的私钥比在本地磁盘驱动器上存储密钥文件更安全,但是仍然存在一些已知的安全问题。

例如,Windows 不以任何方式保护“交换”数据(写入系统交换文件的内存数据)。因此,如果您长时间使用 Pageant,解密的密钥数据可能会被交换并写入磁盘。获得您硬盘访问权限的恶意攻击者也可以获得您的密钥。当然,这比将未加密的文件存储在本地磁盘驱动器上要安全得多,但仍然存在漏洞。

Windows 只有防止可执行代码写入另一个可执行程序的内存空间的安全措施;但是仍然提供对它的读访问。换句话说,程序可以访问彼此的内存空间,这是一种帮助调试的方式。不幸的是,恶意程序可以利用这一特性,并可以访问 Pageant 的内存来提取解密的密钥,并将它们用于非法目的。

然而,通过确保您的网络基础设施是安全的并且安装了防火墙,这些风险可以很容易地被减轻。

十、附录 B:基于 Linux 的客户端的 PuTTY 和 SSH 实现

在第四章的“使用 PuTTY 进行基于密钥的认证”一节中,您回顾了 PuTTY 如何有效地用于基于 Windows 的客户端的基于密钥的认证。对于基于 Linux 的客户端,基于密钥的认证怎么样?答案又是油灰。

您可以从各种来源下载基于 Linux 的 PuTTY 版本。对于 CentOS 6.2 的最新 PuTTY 版本(0.63),我使用了 rpm (Red Hat Package Manager,一种用于 Linux 域软件分发的包管理系统);文件是

putty-0.63-1.el6.rf.x86_64.rpm

。您可以从各种来源下载 rpm 你只需要搜索你的操作系统。下载文件后,安装 rpm:

rpm -Uvh putty-0.63-1.el6.rf.x86_64.rpm

要在 PuTTY 的 Linux 版本中生成一对私有和公共密钥,您需要使用一个名为 PuTTYgen 的命令行实用程序,它会在您通过 rpm 安装 PuTTY 时自动安装。要生成密钥对,请使用以下命令:

puttygen -t rsa -C "my key pair"-o bcl.ppk

然后,PuTTYgen 会提示您输入一个密码短语。请记下来,因为每次使用密钥对连接到主机时,您都需要指定相同的密码。

您可以将密钥保存在您的主目录中(容易记住位置),然后使用以下命令将公钥导出到

authorized_keys

文件:

puttygen -L bcl.ppk >> $HOME/.ssh/authorized_keys

接下来,将

authorized_keys

文件复制到需要连接的主机上(使用 PuTTY)。注意,如果您的主机在

$HOME/.ssh

目录中已经有一个

authorized_keys

文件,那么使用不同的名称复制您新创建的文件,并将其内容附加到现有的

authorized_keys

文件中。

接下来,通过在命令提示符下键入 putty 来调用 PuTTY。该界面看起来与基于 Windows 的界面完全相同(图 B-1 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 B-1 。具有基于密钥的认证的 Linux PuTTY

要连接到服务器,请单击选项 SSH 以打开下拉列表,然后单击该列表下的选项 Auth(授权)。在 PuTTY 界面的右侧,单击 Browse 并选择您之前保存的私钥文件(在本例中为

/root/bcl.ppk

)。单击“打开”打开一个新会话。

就是这样!现在,您已经准备好使用 PuTTY 进行基于密钥的认证了!图 B-2 显示了登录提示和密码提示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 B-2 。使用带有密码短语的 Linux PuTTY

使用 SSH 进行远程访问

您还可以使用 SSH 远程连接到主机。如果您想使用一个密钥对通过 SSH 进行认证,首先需要使用一个名为 ssh-keygen 的实用程序来生成密钥。默认情况下,密钥以文件

id_rsa

(私钥)和

id_rsa.pub

(公钥)的形式保存在

$HOME/.ssh

目录中。图 B-3 显示了在默认位置生成的不带密码短语的密钥对(您可以指定一个密码短语以增加安全性)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 B-3 。使用 ssh-keygen 为远程访问生成密钥对

可以将公钥复制到适当的主机,并附加到

$HOME/.ssh

目录中现有的

authorized_keys

文件中。要使用私钥文件连接到主机,请使用以下语法:

ssh -i ~/.ssh/id_rsa root@Master

这里,

root

是用户,

Master

是您试图连接的服务器。

如果您有多个主机,并且您想要组织连接到它们的过程,您可以在目录

$HOME/.ssh

中的一个名为

config

的文件中创建主机条目。使用以下格式创建条目:

Host Master
User root
HostName Master
IdentityFile ~/.ssh/id_rsa

然后,您可以简单地连接为:

ssh -f -N Master
标签: VKDoc

本文转载自: https://blog.csdn.net/wizardforcel/article/details/141190570
版权归原作者 绝不原创的飞龙 所有, 如有侵权,请联系我们删除。

“Hadoop 安全实践指南(二)”的评论:

还没有评论