Hadoop-安全实践指南-全-

Hadoop 安全实践指南(全)

原文:Practical Hadoop security

协议:CC BY-NC-SA 4.0

零、简介

去年,我为一个客户设计安全性,他正在寻找一本关于 Hadoop 领域安全性实现的参考书,这样他就可以避免已知的问题和陷阱。令我懊恼的是,我找不到一本详细介绍 Hadoop 安全方面的书,也找不到一本为打算保护存储敏感数据的集群的人提供选择的书。我既失望又惊讶。每个计划保护其 Hadoop 集群的人肯定都经历过类似的挫折。所以我决定将我的安全设计经验应用到更广泛的领域,并自己写这本书。

随着 Hadoop 日益获得更多的公司支持和使用,我们都需要认识并关注 Hadoop 的安全方面。企业实现还涉及遵循数据保护和机密性的法规和法律,这些安全问题是使 Hadoop“企业就绪”的驱动力

开源软件通常缺乏有组织的文档和关于独特执行特定功能任务的共识,Hadoop 在这方面也不例外。过去几年中涌现的各种发行版在实现各种 Hadoop 功能方面有所不同,有些功能,如授权或加密,甚至不是所有的供应商发行版都提供的。所以,在这方面,Hadoop 就像 80 年代或 90 年代的 Unix:开源开发导致了大量的变化,在某些情况下偏离了功能。由于这些变化,设计一个通用策略来保护您的 Hadoop 安装是很困难的。在本书中,我试图提供一个适用于大多数情况的策略和解决方案(可能的话是开源解决方案),但也可能存在例外,尤其是如果您使用的是不太知名的 Hadoop 发行版。

开发这本书是一个伟大而激动人心的旅程,我故意说“开发”,因为我相信创作一本技术书籍非常类似于从事一个软件项目。有挑战,有回报,有令人兴奋的发展,当然,还有不可预见的障碍——更不用说最后期限了!

这本书是给谁的

对于计划生产 Hadoop 环境的 IT 经理或想要保护其环境的 Hadoop 管理员来说,这本书是一个极好的资源。这本书也适用于希望在其环境中实现安全性的 Hadoop 开发人员,以及希望了解 Hadoop 安全性的学生。本书假设读者对 Hadoop(尽管第一章回顾了许多基本概念)、Kerberos、关系数据库和 Hive 有基本的了解,并对 Linux 有中级的了解。

这本书的结构

本书分为五个部分:第一部分,“Hadoop 及其安全性介绍”,包含第一章、第二章和第三章;第二部分“在您的 Hadoop 集群中进行认证和授权”,横跨第四章和第五章;第三部分“审计日志和安全监控”,包含第六章和第七章;第四部分,“Hadoop 加密”,包含第八章;第五部分包含四个附录。

以下是每一章更详细的预览:

  • 第一章“理解安全概念”概述了安全、安全工程框架、安全协议(包括 Kerberos)和可能的安全攻击。本章还解释了如何保护分布式系统,并以 Microsoft SQL Server 为例讨论了安全系统。
  • 第二章“Hadoop 简介”,介绍了 Hadoop 架构和 Hadoop 分布式文件系统(HDFS),并解释了 HDFS 固有的安全问题以及为什么很容易侵入 HDFS 安装。还介绍了 Hadoop 的 MapReduce 框架,并讨论了它的安全性缺点。最后,它讨论了 Hadoop 堆栈。
  • 第三章“Hadoop 安全性简介”是为 Hadoop 设计和实现安全性的技术路线图。它引入了认证(使用 Kerberos)来提供安全的访问、授权来指定访问级别,以及监控未授权的访问或不可预见的恶意攻击(使用 Ganglia 或 Nagios 等工具)。您还将了解记录对 Hadoop 守护进程的所有访问的重要性(使用 Log4j 日志记录系统)以及数据加密的重要性(传输中和静态)。
  • 第四章“Hadoop 中的开源认证”,讨论如何使用开源解决方案保护您的 Hadoop 集群。它从使用 PuTTY 保护客户端开始,然后描述 Kerberos 架构,并一步一步地详细介绍 Hadoop 的 Kerberos 实现。此外,您将学习如何保护使用 RPC(远程过程调用)协议的进程间通信,如何加密 HTTP 通信,以及如何保护使用 DTP(数据传输协议)的数据通信。
  • 第五章“实现细粒度授权”,从确定安全需求的方法(基于应用程序)开始,然后研究为应用程序设计细粒度授权的方法。目录级和文件级权限用一个真实的例子来演示,然后用 HDFS 访问控制列表和 Apache Sentry with Hive 来重新实现同一个例子。
  • 第六章“Hadoop 日志:关联和解释”,讨论了日志记录的安全性使用。在对 Log4j API 以及如何使用它进行审计日志记录进行了高级讨论之后,本章将研究 Log4j 日志记录级别及其用途。您将了解如何关联 Hadoop 日志以有效实现安全性,了解 Hadoop 分析以及使用 Splunk 的可能实现。
  • 第七章“Hadoop 中的监控”讨论了安全监控。它首先讨论监控系统需要的特性,重点是监控分布式集群。此后,本文讨论了可以用于安全目的的 Hadoop 指标,并研究了 Ganglia 和 Nagios 的使用,这是两个最流行的 Hadoop 监控应用程序。本文最后讨论了一些对 Ganglia 和 Nagios 有用的插件,这些插件提供了与安全性相关的功能,还讨论了 Ganglia 与 Nagios 的集成。
  • 第八章“Hadoop 中的加密”从一些数据加密基础知识开始,讨论了流行的加密算法及其应用(证书、密钥、哈希函数、数字签名),定义了 Hadoop 集群可以加密的内容,并列出了一些流行的加密供应商选项。下面是 HDFS 和 Hive 静态数据的详细实现,展示了英特尔的实际分布。本章以使用 Amazon Web Services 的 Elastic MapReduce VM (EMR)逐步实现静态加密作为结束。

下载代码

这本书的源代码可以在 Apress 网站的下载部分获得。

联系作者

您可以在blakhe@aol.combclakhe@gmail.com到达 Bhushan Lakhe。

一、理解安全概念

在当今技术驱动的世界中,计算机已经渗透到我们生活的各个方面,我们的个人和公司数据比以往任何时候都更容易通过电子方式获得。不幸的是,提供如此多好处的同一技术也可能被用于破坏性目的。近年来,以前主要为个人利益而工作的个人黑客组织成了为经济利益而工作的团体,使得个人或公司数据被窃取用于非法目的的威胁变得更加严重和真实。恶意软件侵扰我们的计算机,并根据我们的浏览环境将我们的浏览器重定向到特定的广告网站。网络钓鱼邮件诱使我们登录看似真实但旨在窃取我们密码的网站。病毒或直接攻击破坏我们的网络,窃取密码和数据。随着大数据、分析和机器学习进入现代企业,暴露关键数据和造成伤害的机会呈指数级增长。

如果您想应对这些针对您个人财产(是的,您的数据是您的个人财产)或公司财产的攻击,您必须彻底了解这些威胁以及您自己的漏洞。只有这样,您才能设计一种策略来保护您的数据,无论是个人数据还是公司数据。

想象一下这样一个场景,您银行的投资部门使用 Hadoop 来分析万亿字节的数据,而您银行的竞争对手可以访问结果。或者,如果您的保险公司基于对数百万份索赔的大数据分析决定停止提供房主保险,而他们的竞争对手已经(秘密地)访问了这些数据,并发现用作分析基础的大部分索赔都是欺诈性的,情况会如何?你能想象这些安全漏洞会给受影响的公司带来多大的损失吗?不幸的是,只有这些漏洞凸显了安全的重要性。对于用户来说,一个好的安全设置——无论是个人的还是公司的——总是透明的。

本章为您开始构建安全策略奠定了基础。我首先定义一个安全工程框架。然后,我讨论了安全的一些心理学方面(人的因素),并介绍了安全协议。最后,我介绍了对程序安全性的常见潜在威胁,并解释了如何应对这些威胁,提供了一个安全分布式系统的详细示例。首先,让我向您介绍一下安全工程的概念。

安全工程简介

安全工程是关于设计和实现不泄露私人信息的系统,并且能够可靠地抵御恶意攻击、错误或灾难。作为一门科学,它专注于设计和实现完整系统以及改造现有系统所需的工具、过程和方法。

安全工程需要跨不同学科的专业知识,如密码学、计算机安全、计算机网络、经济学、应用心理学和法律。软件工程技能(从业务流程分析到实现和测试)也是必要的,但主要是为了应对错误和“灾难”——而不是恶意攻击。设计对抗恶意的系统需要专门的技能,当然也需要专门的经验。

安全要求因系统而异。通常您需要用户认证、授权、策略定义、审计、集成事务、容错、加密和隔离的平衡组合。许多系统失败是因为他们的设计者关注了错误的事情,忽略了其中的一些因素,或者关注了正确的事情但做得不充分。保护包含许多组件和接口的大数据系统尤其具有挑战性。传统的数据库只有一个目录和一个接口:SQL 连接。一个 Hadoop 系统有许多“目录”和许多接口(Hadoop 分布式文件系统或 HDFS、Hive、HBase)。这种日益增加的复杂性,以及此类系统中各种各样的海量数据,给安全工程师带来了许多挑战。

因此,保护系统取决于几种类型的过程。首先,您需要确定您的安全需求,然后如何实现它们。此外,您必须记住,安全系统除了技术组件之外,还有一个非常重要的组件:人的因素!这就是为什么你必须确保负责保护和维护系统的人有适当的动力。在下一节中,我定义了一个考虑所有这些因素的框架。

安全工程框架

良好的安全工程依赖于以下五个在系统概念化时需要考虑的因素:

  • 策略:你的策略围绕着你的目标。一个具体的目标是为您的系统定义认证、授权、整体事务、容错、加密和隔离的良好起点。您还需要考虑可能的错误条件或恶意攻击场景。
  • 实现:实现您的战略包括采购必要的硬件和软件组件,设计和开发满足您所有目标的系统,定义访问控制,并彻底测试您的系统以匹配您的战略。
  • 可靠性:可靠性是你对你的每个系统组件以及整个系统的依赖程度。可靠性是根据故障和失灵来衡量的。
  • 相关性:相关性决定系统抵御最新威胁的能力。为了保持相关性,尤其是对于安全系统,定期更新它以保持其应对新威胁的能力也是极其重要的。
  • 动机:动机与负责管理和维护您的系统的人员正确完成工作的动力或奉献精神有关,也指攻击者试图挫败您的策略的诱惑。

图 1-1 说明了这五个因素是如何相互作用的。

9781430265443_Fig01-01.jpg

图 1-1 。设计安全框架前需要考虑的五个因素

注意这些关系,比如相关性的策略、策略的实现、相关性的实现、动机的可靠性等等。

通过一个真实世界的例子来考虑图 1-1 的框架。假设我正在设计一个存储高中生成绩的系统。这五个关键因素是如何发挥作用的?

带着我的目标——创建一个学生评分系统——我首先概述了这个系统的策略。首先,我必须定义学生、员工和学校管理员所需的认证和授权级别(访问策略)。显然,学生只需要对他们的个人成绩有读取权限,工作人员需要对他们学生的成绩有读写权限,学校管理员需要对所有学生记录有读取权限。任何数据更新都需要是一个整体事务,这意味着要么它应该完成所有相关的更改,要么如果它在进行中中止,那么所有的更改都应该恢复。因为数据是敏感的,所以应该加密——学生应该只能看到自己的成绩。应该使用内部防火墙将评分系统隔离在学校内部网中,并且当任何人试图使用该系统时,应该提示进行认证。

我的策略需要通过首先采购必要的硬件(服务器、网卡)和软件组件(SQL Server、C#)来实现。NET 组件、Java)。接下来是通过使用 SQL Server 设计过程流、数据流、逻辑数据模型、物理数据模型以及使用 Java 设计图形用户界面来设计和开发系统以满足目标。我还需要定义访问控制,以确定谁可以访问系统以及拥有什么权限(基于授权需求的角色)。例如,我将School_Admin角色定义为具有所有等级的读取权限,将Staff角色定义为具有读写权限,以此类推。最后,在构建系统之前,我需要对我的硬件和软件组件进行安全实践审查。

在彻底测试系统时,我可以通过确保没有人可以访问他们不应该访问的数据,以及确保所有用户都可以访问他们被允许访问的数据来测量可靠性。任何偏离这一功能的情况都会使系统不可靠。此外,系统需要全天候可用。如果不是,那也会降低系统的可靠性。这个系统的相关性将取决于它的固若金汤。换句话说,任何学生(或外部黑客)都不能使用任何最新的技术侵入它。

负责管理该系统(硬件、数据库等)的系统管理员。)应该是可靠的并且有动力有良好的职业操守。既然他们可以接触到所有的敏感数据,他们就不应该向任何未经授权的人透露(例如在该高中学习的朋友或亲戚,任何无良的招生人员,甚至媒体)。在这种情况下,禁止任何此类披露的法律可能是一个很好的动机;但是职业操守同样重要。

安全工程的心理学方面

为什么需要了解安全工程的心理学方面?对你的网络安全最大的威胁是欺骗:利用心理学和技术的恶意攻击。我们都收到过网络钓鱼电子邮件,警告我们支票、信用卡或 PayPal 账户存在一些“问题”,并敦促我们通过登录一个巧妙伪装的网站来“修复”它,该网站旨在出于非法目的捕获我们的用户名、密码或账号。借口是私家侦探或骗子窃取信息的另一种常见方式,无论是个人信息还是公司信息。它包括以虚假的借口给某人(掌握信息的受害者)打电话,并获取机密信息(通常是通过伪装成有权获得该信息的人)。开发人员或系统管理员接到“安全管理员”打来的电话,被要求提供密码信息,据说是为了验证或安全目的,这种情况有很多。你可能会认为这在今天是行不通的,但是这些情况即使在现在也很常见!最好通过电子邮件或书面形式请求披露任何机密或敏感信息。

公司使用许多对策来打击网络钓鱼:

  • 密码加扰器:许多浏览器插件通过散列(使用秘密密钥)和被访问网站的域名,将你的密码加密成一个强大的、特定域的密码。即使您总是使用相同的密码,您访问的每个网站都会有一个不同的、唯一的密码。因此,如果你在一个钓鱼网站上错误地输入了你的美国银行密码,黑客就会得到你真实密码的一个不可用的变体。
  • 客户证书或定制应用:一些银行提供自己的笔记本电脑和 VPN 接入,以便使用他们的定制应用连接到他们的系统。他们验证客户端是否使用了他们自己的硬件(例如,通过媒体访问控制或 MAC 地址),并在允许用户连接到他们的系统之前使用 VPN 凭证来验证用户。一些银行还向他们的用户提供由他们的服务器认证的客户证书;因为它们驻留在客户端电脑上,黑客无法访问或使用它们。
  • 两阶段认证:在该系统中,登录需要令牌密码和保存密码。安全令牌生成密码(一次性使用或基于时间)以响应您要访问的系统发送的质询。例如,每隔几秒钟,安全令牌就会显示一个与中央服务器同步的新的八位密码。输入令牌密码后,系统会提示您输入之前设置的已保存密码。这使得黑客无法使用您的密码,因为令牌密码变化太快,黑客无法使用。两阶段认证仍然容易受到实时“中间人”攻击(有关更多详细信息,请参见“中间人攻击”侧栏)。

中间人攻击

中间人攻击的工作原理是,黑客成为合法用户和验证者之间的隐形中继(中间人),以获取非法使用的信息。黑客(或“网络钓鱼者”)捕获用户响应,并将它们转发给验证者。然后,他或她将来自认证者的任何质询转发给用户,并将任何后续的用户响应转发给认证者。因为所有的响应都通过黑客,所以他被认证为一个用户,而不是真正的用户,因此可以冒充合法用户自由地执行任何非法活动!

例如,假设一个用户想要登录他的支票账户,但是被一个网络钓鱼计划引诱而登录到一个网络钓鱼站点。网络钓鱼网站同时开启与用户银行的登录会话。当银行发送挑战时;钓鱼者将此转发给用户,用户使用他的设备对其进行响应;网络钓鱼者将此响应转发给银行,并且现在作为用户向银行进行了认证!当然,在那之后,他可以在那个支票账户上进行任何非法活动,比如把所有的钱转到他自己的账户上。

一些银行通过使用基于最后提取金额、收款人账号或交易序列号的认证代码作为响应,而不是简单的响应,来应对这种情况。

  • 可信计算:这种方法包括在 PC 主板上安装 TPM(可信平台模块)安全芯片。TPM 是一个专用的微处理器,它生成密钥并使用它们进行加密/解密。因为本地化的硬件用于加密,所以它比软件解决方案更安全。为了防止任何恶意代码获取和使用密钥,您需要确保整个加密/解密过程都在 TPM 内完成,而不是由 TPM 生成密钥并将它们传递给外部程序。将这种硬件交易支持集成到 PC 中将使黑客更难侵入系统。例如,OpenSSL 中最近出现的 Heartbleed 错误将被 TPM 击败,因为密钥不会暴露在系统内存中,因此不会被泄漏。
  • 强密码协议:史蒂夫·贝洛文和迈克尔·梅里特提出了一系列用于加密密钥交换的协议,通过这种方式,密钥交换与共享密码结合在一起,使得中间人(phisherman)无法猜出密码。其他各种研究人员提出了类似的协议,这项技术是我们今天使用的“安全”(HTTPS)协议的前身。因为使用 HTTPS 更方便,所以它被广泛地实现,而不是现在的浏览器都没有实现的强密码协议。
  • 双通道认证:这包括通过单独的通道或设备(如用户的手机)向用户发送一次性访问码。此访问码与常规用户密码一起用作附加密码。这种认证类似于两阶段认证,也容易受到实时中间人攻击。

安全协议简介

安全系统由用户、公司和服务器等组件组成,这些组件使用包括电话、卫星链路和网络在内的多种渠道进行通信,同时还使用物理设备,如笔记本电脑、便携式 USB 驱动器等。安全协议是管理这些通信的规则,旨在有效对抗恶意攻击。

由于实际上不可能设计一个协议来对抗所有类型的威胁(除了昂贵之外),协议被设计成仅对抗某些类型的威胁。例如,用于认证的 Kerberos 协议假设用户在输入用户名和密码时连接到了正确的服务器(而不是钓鱼网站)。

对协议进行评估时,通常会考虑它们所要应对的威胁出现的可能性,以及它们消除这种威胁的有效性。

在一个庞大而复杂的系统中,多种协议常常必须协同工作;因此,您需要注意这种组合不会暴露任何漏洞。在接下来的几节中,我将向您介绍一些常用的协议。

Needham-Schroeder 对称密钥协议

Needham-Schroeder 对称密钥协议在请求者和认证者之间建立了一个会话密钥,并在整个会话中使用该密钥来确保通信的安全。让我用一个简单的例子来解释一下。

用户需要从安全文件系统访问文件。作为第一步,用户通过提供她的 nonce (用于保证消息新鲜的随机数或序列号)和她需要访问的安全文件系统的名称,向认证服务器请求会话密钥(图 1-2 中的步骤 1)。服务器提供会话密钥,使用服务器和用户之间共享的密钥进行加密。会话密钥还包含用户的 nonce,只是为了确认它不是重播。最后,服务器向用户提供使用服务器和安全文件系统之间共享的密钥加密的会话密钥的副本(步骤 2)。用户将密钥转发给安全文件系统,安全文件系统可以使用与服务器共享的密钥对其进行解密,从而认证会话密钥(步骤 3)。安全文件系统向用户发送使用会话密钥加密的随机数,以表明它拥有该密钥(步骤 4)。用户在 nonce 上执行一个简单的操作,重新加密它,并将其发送回来,验证她仍然活着,并且她持有密钥。因此,在用户和安全文件系统之间建立了安全通信。

这个协议的问题是,安全文件系统必须假设它从认证服务器(通过用户)接收的密钥是新的。这可能不是真的。此外,如果黑客得到了用户的密钥,他可以用它与许多其他主体建立会话密钥。最后,如果用户通过使用日志发现冒名顶替或不当使用,她不可能撤销会话密钥。

总之,Needham-Schroeder 协议容易受到重放攻击,因为不可能确定会话密钥是新的还是最近的。

9781430265443_Fig01-02.jpg

图 1-2 。Needham-Schroeder 对称密钥协议

麻省理工学院开发的安全认证系统

Kerberos 是 Needham-Schroeder 协议的衍生物,起源于麻省理工学院,现在被用作 Linux 和 Windows 的标准认证工具。Kerberos 不是使用单个可信服务器,而是使用两个服务器:一个认证服务器,对用户登录进行认证;以及提供票证的票证授予服务器,允许访问各种资源(例如,文件或安全进程)。这提供了更具可伸缩性的访问管理。

如果用户需要访问使用 Kerberos 的安全文件系统,该怎么办?首先,用户使用密码登录到认证服务器。用户 PC 上的客户端软件从该服务器获取票证,该票证根据用户的密码进行加密,并包含会话密钥(仅在预定的持续时间内有效,如一小时或一天)。假设用户已经过认证,他现在使用会话密钥来访问由票据授予服务器控制的安全文件系统。

接下来,用户从票据授予服务器请求访问安全文件系统。如果访问是允许的(取决于用户的权限),则创建一个包含合适密钥的票证并提供给用户。用户还可以获得在会话密钥下加密的密钥的副本。现在,用户通过向安全文件系统发送时间戳来验证票据,安全文件系统通过发回加 1 的时间戳来确认票据是否有效(这表明它能够正确解密票据并提取密钥)。之后,用户可以与安全文件系统通信。

Kerberos 通过用时间戳替换随机随机数来修复 Needham–Schroeder 的漏洞。当然,现在有一个基于时间戳的新漏洞,在这个漏洞中,作为更复杂攻击的一部分,各种客户端和服务器上的时钟可能会故意失去同步。

Kerberos 被广泛使用,并作为其认证机制被集成到 Windows Active Directory 服务器中。实际上,Kerberos 是使用最广泛的安全协议,其他协议只具有历史重要性。您将在后面的章节中了解更多关于 Kerberos 的内容,因为它是当今 Hadoop 使用的主要认证。

布伦斯-阿巴迪-李约瑟逻辑

burrows-Abadi-Needham(BAN)逻辑提供了定义和分析敏感信息的框架。基本原则是,如果消息满足三个标准,则它是可信的:它用相关密钥加密,它来自可信的来源,并且它还是新的(即,在协议的当前运行期间生成)。通常遵循的验证步骤是

  1. 检查来源是否可信,
  2. 检查加密密钥是否有效,以及
  3. 检查时间戳以确保它是最近生成的。

一些银行使用 BAN 逻辑的变体(例如,Visa International 使用的 COPAC 系统)。BAN 逻辑是一个非常广泛的协议,因为它有多步验证过程;但这也是它不太受欢迎的确切原因。它实现起来很复杂,也容易受到时间戳操作的影响(就像 Kerberos 一样)。

考虑 BAN 逻辑的实际实现。假设 Mindy 从网络零售商处购买了一个昂贵的钱包,并授权通过她的信用卡向零售商支付 400 美元。Mindy 的信用卡公司必须能够核实和证明该请求确实来自 Mindy,如果她后来否认发送它。信用卡公司还想知道这个请求完全是 Mindy 的,并且没有被修改过。此外,该公司必须能够验证 Mindy 输入的加密密钥(来自信用卡的三位数安全码)。最后,公司希望确保消息是新的,而不是重复使用以前的消息。所以,查看需求,您可以得出结论,信用卡公司需要实现 BAN 逻辑。

现在,在回顾了这些协议以及它们可以用来对抗恶意攻击的方式之后,您认为使用一个强大的安全协议(来保护程序)足以克服软件中的任何“缺陷”(这些缺陷会使程序容易受到安全攻击)吗?还是像用一把昂贵的锁锁住房子的前门,而让窗户开着?要回答这个问题,您首先需要知道缺陷是什么,或者它们如何导致安全问题。

保护程序安全

在保护程序之前,您需要了解是什么因素使程序不安全。首先,使用安全协议只能保护程序的入口。一旦程序开始执行,它需要具有健壮的逻辑,只提供对必要资源的访问,而不为恶意攻击提供任何途径来修改系统资源或获得对系统的控制。那么,这就是一个程序没有缺陷的方式吗?好吧,我将简单地讨论一下,但是首先让我定义一些重要的术语,这将帮助你理解缺陷以及如何应对它们。

先说术语程序??。程序是任何可执行的代码。甚至操作系统或者数据库系统都是程序。我认为一个程序是安全的,如果它确切地(并且仅仅)做了它应该做的事情——没有别的!安全性评估也可以基于程序对规范的符合性来决定——如果代码满足安全性要求,那么它就是安全的。为什么这很重要?因为当一个程序执行时,它有能力修改你的环境,你必须确保它只修改你想让它修改的。

因此,您需要考虑会阻止程序满足安全性要求的因素。这些因素有可能被称为程序中的缺陷。瑕疵可以是错误,也可以是失败

故障是由于人为错误在系统中引入的异常。在设计阶段,由于设计者误解了分析师的需求,或者在实现阶段,由于程序员没有理解设计者的意图并且编码不正确,可能会引入错误。一个错误可以产生许多错误。综上所述,故障是系统的设计者或开发者在开发之后注意到的逻辑问题或矛盾。

一个失败是对系统所需功能的偏离。故障可以在软件开发生命周期(SDLC)的任何阶段被发现,例如测试或运行。单个故障可能导致多个故障(例如,如果没有输入,设计故障会导致程序退出)。如果功能需求文档包含错误,失败将表明系统没有按要求执行(即使它可能按指定执行)。因此,失败是故障的明显后果:用户可以看到的问题。

幸运的是,不是每个错误都会导致失败。例如,如果代码的错误部分从未被执行,或者逻辑的错误部分从未被输入,那么该错误将永远不会导致代码失败——尽管您永远无法确定失败何时会暴露该错误!

概括地说,这些缺陷可以分为:

  • 非恶意(缓冲区溢出、验证错误等。)和
  • 恶意(病毒/蠕虫攻击、恶意软件等。).

在接下来的几节中,我们将更仔细地研究这些缺陷、它们可能产生的安全漏洞的种类,以及如何设计一种策略来更好地保护您的软件免受此类漏洞的侵害。

非恶意缺陷

非恶意缺陷源于无意的、疏忽的人为错误。大多数这些缺陷只会导致程序故障。然而,最近几年,一些类别已经导致了许多安全漏洞。

缓冲区溢出

一个缓冲区(或数组字符串)是一个分配的内存(或 RAM)量,数据在这里被临时保存以供处理。如果写入缓冲区的程序数据超过缓冲区先前定义的最大大小,则该程序数据基本上溢出缓冲区。一些编译器检测到缓冲区溢出并停止程序,而另一些则简单地认为溢出是附加指令并继续执行。如果继续执行,程序数据可能会覆盖系统数据(因为所有程序和数据元素在执行期间都与操作系统和其他代码共享内存空间)。黑客可能会发现溢出并在系统空间中插入代码,从而以更高的权限控制操作系统。 1

有几种编程技术用于防止缓冲区溢出,例如

  • 强制检查缓冲区溢出;
  • 系统堆栈区和用户代码区的分离;
  • 使内存页面可写或可执行,但不能两者都写;和
  • 监视器在系统堆栈被覆盖时发出警报。

不完全调解

当程序未经验证或确认就接受用户数据时,就会发生不完全中介。程序需要检查用户数据是否在指定的范围内,或者是否遵循预定义的格式。如果没有做到这一点,黑客就可以出于非法目的操纵数据。例如,如果一个网络商店不传递用户数据,黑客可能会关闭任何客户端 JavaScript(用于验证)或只编写一个脚本来与网络服务器交互(而不是使用网络浏览器),并向服务器发送任意(非中介)值来操纵销售。在某些情况下,这种性质的漏洞是由于未能检查组件的默认配置造成的;默认情况下为 XML 数据启用 shell 转义的 web 服务器就是一个很好的例子。

不完全中介的另一个例子是 SQL 注入,攻击者能够插入(和提交)由 web 应用程序执行的数据库 SQL 命令(代替或与参数值一起),操纵后端数据库。当 web 应用程序未经彻底验证就接受用户提供的输入数据时,就会发生 SQL 注入攻击。巧妙格式化的用户数据欺骗应用程序执行非预期的命令或修改敏感数据的权限。黑客可以访问敏感信息,如社会安全号、信用卡号或其他财务数据。

SQL 注入的一个例子是一个 web 应用程序,它接受登录名作为输入数据,并为用户显示所有信息,但不验证输入。假设 web 应用程序使用以下查询:

"SELECT * FROM logins WHERE name ='" + LoginName + "';"

恶意用户可以使用“' or '1'='1”LoginName值,这将导致 web 应用程序将所有用户的登录信息(带密码)返回给恶意用户。

如果用户输入根据一组定义的长度、类型和语法规则进行验证,就可以防止 SQL 注入。此外,重要的是要确保用户权限(数据库访问)应限制在尽可能低的权限内(仅在相关数据库内),并且系统管理员帐户(如sa)不应用于 web 应用程序。不使用的存储过程应该删除,因为它们很容易成为数据操作的目标。

应该采取两个关键步骤进行防御:

  • 必须执行基于服务器的中介。所有客户端输入在被处理之前都需要经过程序(位于服务器上)的验证。
  • 需要检查客户端输入的范围有效性(例如,月份在一月和十二月之间)以及允许的大小(文本数据的字符数或数字数据的数值等)。).

检验时间到使用时间误差

当系统状态(或用户控制的数据)在特定任务的授权检查和任务执行之间发生变化时,检查时间到使用时间的错误就会发生。也就是说,在任务的授权和执行之间缺乏同步或串行化。例如,用户可以请求对无害日志文件的修改权限,并且在检查授权(针对此操作)和实际授予修改权限之间,可以将日志文件切换为关键系统文件(例如,/etc/password针对 Linux 操作系统)。

有几种方法可以消除这些错误:

  • 将所请求的用户数据(对于请求)复制到系统区域,使修改变得不可能。
  • 锁定请求数据,直到请求的操作完成。
  • 对请求的数据执行校验和(使用验证程序)以检测修改。

恶意缺陷

恶意缺陷会在程序中产生意想不到的或不希望的影响,并且是故意设计来造成损害(数据损坏、系统崩溃等)的代码的结果。).恶意缺陷是由病毒、蠕虫、兔子、特洛伊木马、陷阱门和恶意软件引起的:

  • 病毒是一种自我复制程序,它可以通过将恶意代码的副本附加到未被感染的程序上来修改这些程序。被感染的程序自己变成病毒,并进一步复制以感染整个系统。一个短暂病毒依赖于它的宿主程序(它是其中的一部分的可执行程序),并且当它的宿主执行时运行,传播它自己并且执行它被设计的恶意活动。一个常驻病毒驻留在系统内存中,可以作为独立程序执行,甚至在其宿主程序完成执行之后。
  • 一个蠕虫不同于使用其他程序作为媒介来传播自己的病毒,它是一个独立的程序,通过网络进行复制。
    *** 一只兔子是一种病毒或蠕虫,它可以无限制地自我复制,耗尽计算资源。例如,一只兔子可能会无限次地将自己复制到一个磁盘上,并填满整个磁盘。* 一个特洛伊木马是代码,除了它的主要目的之外,还有隐藏的恶意目的。* 一个逻辑触发器是在特定条件发生时执行的恶意代码(例如,当文件被访问时)。时间触发器是以特定时间或日期为激活条件的逻辑触发器。* 一个陷阱门是一个程序的秘密入口点,它可以让某人绕过正常的认证并获得访问权。活板门一直被程序员用于合法的目的,比如故障排除、调试或测试程序;但是,当不道德的程序员使用它们来获得未经授权的访问或执行恶意活动时,它们就会成为威胁。恶意软件可以在联网的电脑上安装恶意程序或陷阱门。一旦安装,陷阱门就可以打开互联网端口,进行匿名、恶意的数据收集,推销产品(广告软件),或执行创建者设计的任何其他破坏性任务。**

**我们如何防止恶意代码的感染?

  • 仅安装从可靠、知名的供应商处获得的商业软件。
  • 跟踪所有已安装的开源组件的版本和漏洞,并维护开源组件安全修补策略。
  • 仔细检查任何已安装软件的所有默认配置;不要假定默认值是为安全操作而设置的。
  • 孤立地测试任何新软件。
  • 只打开来自已知来源的“安全”附件。此外,避免打开来自已知来源的包含奇怪或特殊邮件的附件。
  • 每天或每周维护一个可恢复的系统映像(根据需要)。
  • 制作并保留可执行系统文件以及可能包含“可感染”代码的重要个人数据的备份副本。
  • 使用防病毒程序并根据需要安排每日或每周扫描。不要忘记更新病毒定义文件,因为每天都有大量新病毒产生!

保护分布式系统

到目前为止,我们已经检查了对 程序的安全性的潜在威胁,但是记住——分布式系统也是一个程序。上一节讨论的所有威胁和解决方案不仅适用于分布式系统,而且这些程序的特殊性质也使它们在其他方面容易受到攻击。这导致分布式系统需要多级安全性。

当我想到一个安全的分布式系统时,我会想到 SAP 或 PeopleSoft 等 ERP(企业资源)系统。此外,Oracle、Microsoft SQL Server 或 Sybase 等关系数据库系统是安全系统的良好范例。所有这些系统都配备了多层安全措施,并且已经运行了很长时间。随后,他们发现了许多针对存储数据的恶意攻击,并设计了有效的对策。为了更好地理解是什么使这些系统安全,我将讨论 Microsoft SQL Server 如何保护敏感的雇员工资数据。

对于一个安全的分布式系统,数据隐藏在多层防御之后(图 1-3 )。存在诸如认证(使用登录名/密码)、授权(具有一组权限的角色)、加密(使用密钥对数据进行加密)等级别。对于 SQL Server,第一层是用户认证层。其次是授权检查,以确保用户拥有通过数据库角色访问数据库的必要授权。具体来说,任何到 SQL Server 的连接都由服务器根据存储的凭据进行认证。如果认证成功,服务器会传递连接。连接后,客户端将继承系统管理员分配给已连接登录的授权。这种授权包括使用分配的角色(对于每个数据库)访问任何系统或用户数据库。也就是说,用户只能访问他有权访问的数据库——并且只能访问分配了权限的表。在数据库级别,安全性进一步划分为表级和列级安全性。必要时,视图被设计成进一步隔离数据并提供更详细的安全级别。数据库角色用于对一组表的安全设置进行分组。

9781430265443_Fig01-03.jpg

图 1-3 。SQL Server 通过多种安全级别保护数据

在图 1-3 中,经过认证并被允许连接的用户被授权查看 DB1 数据库中的员工数据,但工资数据除外(因为他不属于 HR 角色,只有人力资源部的用户被分配了 HR 角色)。因此,使用 SQL Server 中的角色可以很容易地限制对敏感数据的访问。虽然图中没有说明它们,但是更多的安全层是可能的,您将在接下来的几节中了解到。

证明

第一层安全是认证。 SQL Server 使用登录/密码对来验证存储的凭据元数据。您还可以将集成安全性用于 Windows,并且可以使用 Windows 登录来连接到 SQL Server(假设系统管理员已经提供了对该登录的访问权限)。最后,证书或一对非对称密钥可用于认证。提供了一些有用的功能,如密码策略实现(强密码)、登录的日期有效性、阻止登录的能力等,以增加便利性。

批准

第二层是授权。根据需要在各种数据库(服务器上)内创建第一层登录对应的用户来实现。如果用户不存在于数据库中,他或她就不能访问它。

在数据库中,有各种对象,如表(保存数据)、视图(对可能分布在多个表中的过滤数据库访问的定义)、存储过程(使用数据库脚本语言的脚本)和触发器(在事件发生时执行的脚本,如更新表中的列或插入表中的数据行),用户可能具有对这些对象的读取、修改或执行权限。此外,对于表或视图,可以向用户提供部分数据访问权限(仅针对某些列)。这在配置访问时提供了灵活性和非常高的粒度。

加密

第三个安全层是加密。SQL Server 提供了两种加密数据的方法:对称密钥/证书和透明数据库加密(TDE)。这两种方法都是对存储在数据库中的“静态”数据进行加密。通过在服务器和客户端上配置相应的公共和私有证书以使用加密连接,SQL Server 还能够对从客户端传输到服务器的数据进行加密。仔细看看:

  • 使用对称密钥/证书加密:一个对称密钥是一个二进制或十六进制字符序列,它与加密算法一起用来加密数据。服务器和客户端必须使用相同的密钥进行加密和解密。为了进一步增强安全性,可能需要包含公钥和私钥对的证书。客户端应用程序必须有这个对可用于解密。使用证书和对称密钥进行加密的真正优势是它提供的粒度。例如,你可以只加密单个表中的单个列(图 1-4)——不需要加密整个表或数据库(如 TDE)。加密和解密是 CPU 密集型操作,会占用宝贵的处理资源。这也使得加密数据的检索速度比未加密数据慢。最后,加密数据需要更多的存储空间。因此,如果数据库中只有一小部分包含敏感数据,那么使用该选项是有意义的。

9781430265443_Fig01-04.jpg

图 1-4 。使用对称密钥和证书创建列级加密

  • TDE: TDE 是 SQL Server 提供的使用对称密钥和证书对数据库进行完全加密的机制。一旦启用了数据库加密,数据库中的所有数据在存储到磁盘上时都会被加密。这种加密对请求数据的任何客户端都是透明的,因为数据在从磁盘传输到缓冲区时会自动解密。图 1-5 详细描述了为数据库实现 TDE 的步骤。

9781430265443_Fig01-05.jpg

图 1-5 。为 SQL Server 数据库实现 TDE 的过程

  • 使用加密连接:该选项包括加密客户端到 SQL 服务器的连接,并确保传输中的数据是加密的。在服务器端,您必须将服务器配置为接受加密连接,创建证书,并将其导出到需要使用加密的客户端。然后,客户端的用户必须在客户端上安装导出的证书,配置客户端以请求加密连接,并打开到服务器的加密连接。

图 1-6 描绘了 SQL Server 安全的各个级别。如您所见,可以在访问的每个阶段过滤数据(根据需要),为用户授权提供粒度。

9781430265443_Fig01-06.jpg

图 1-6 。包含详细信息的 SQL Server 安全层

Hadoop 也是一个分布式系统,可以从您在这里学到的许多原则中受益。在接下来的两章中,我将介绍 Hadoop,并概述 Hadoop 的安全架构(或者说缺乏安全架构)。

摘要

本章介绍了一般的安全概念,以帮助您更好地理解和欣赏将用于保护 Hadoop 的各种技术。但是,请记住,理解安全的心理因素和技术一样重要。如果你轻易地将你的密码提供给黑客,没有任何安全协议可以帮助你!

保护一个程序需要了解潜在的缺陷,这样你才能应对它们。通过在 SDLC 的每个阶段进行质量控制,并在实现阶段进行大量测试,可以减少或消除非恶意缺陷。专门的反病毒软件和程序纪律是解决形式化缺陷的唯一方法。

分布式系统由于其体系结构而需要多级安全性,这种体系结构将数据分布在多个主机上,并通过在多个位置执行的多个进程来修改数据。因此,重要的是设计能够在多个级别上工作的安全性,并根据主机的角色来保护系统中的各种主机(例如,中央主机或主控主机所需的安全性与其他主机不同)。大多数情况下,这些级别是认证、授权和加密。

最后,计算世界正在快速变化,新的威胁每天都在演变。设计一个安全的系统很重要,但保持系统的更新也同样重要。昨天还是最好的安全系统现在已经不够好了。今天必须是最好的,明天也可能是最好的!


1 请参考 Jonathan Pincus 和 Brandon Baker 撰写的 IEEE 论文“超越堆栈粉碎:利用缓冲区溢出的最新进展”,了解关于这类攻击的更多详细信息。该文章的 PDF 可在http://classes.soe.ucsc.edu/cmps223/Spring09/Pincus%2004.pdf获得。**

二、Hadoop 简介

我参加了一个数据仓库会议,与一家领先银行的高管谈论 Hadoop。当我告诉他这项技术时,他插话道:“但是它对我们有什么用处吗?我们没有任何互联网使用情况可以分析!”他只是表达了一个普遍的误解。Hadoop 不仅仅是一种用于分析网络使用或日志文件的技术;它在 Pb(每个 1,000)的世界中有真正的用途。这是一项超级智能的技术,可以帮助您高效快速地管理大量数据,而无需在硬件上花费大量资金。

Hadoop 可能始于实验室,一些真正聪明的人使用它来分析数据以实现行为目的,但它今天在企业界越来越受到支持。为了在这种新环境中生存,it 需要进行一些改变(例如增加安全性),但随着这些改变的出现,越来越多的公司开始意识到它为管理和处理大量数据带来的好处。

例如,福特汽车公司使用大数据技术处理他们的混合动力汽车产生的大量数据(每小时约 25GB),分析、总结并通过移动应用程序呈现给司机,该应用程序提供有关汽车性能、最近的充电站等信息。使用大数据解决方案,福特还通过消费者对其汽车的反馈和评论来分析社交媒体上的可用数据。使用传统的数据管理和分析工具来分析如此大量的不同数据是不可能的。

社交网站 LinkedIn 使用 Hadoop 以及定制开发的分布式数据库 Voldemort 和 Espresso 来增强其海量数据,使其能够快速提供热门功能,如“你可能认识的人”列表或 LinkedIn 社交图,只需点击一下。这对于传统的数据库或存储来说是不可能的。

Hadoop 使用低成本商用硬件和内置冗余,这是它吸引大多数将其用于存储或归档的公司的主要因素。此外,分布式处理等功能可以将您的处理能力乘以节点数,轻松处理数 Pb 的数据;无需停机即可扩展容量;高度的容错能力使得 Hadoop 对越来越多的企业用户具有吸引力。

在接下来的几节中,您将了解 Hadoop 架构、Hadoop 堆栈,以及 Hadoop 架构固有的安全问题。请注意,在本章中,我将只简要讨论这些安全问题;第四章包含了关于这些问题的更详细的讨论,以及可能的解决方案。

Hadoop 架构

网站将 Hadoop 定义为“一个框架,允许使用简单的编程模型在计算机集群上分布式处理大型数据集。”很简单,这就是哲学:提供一个易于使用、易于扩展的框架,并为生产使用提供容错和高可用性。

这个想法是利用现有的低成本硬件来建立一个强大的系统,可以非常高效和快速地处理数 Pb 的数据。Hadoop 通过将数据本地存储在其 DataNodes 上并在本地进行处理来实现这一点。所有这些都由 Hadoop 系统的大脑 NameNode 高效管理。所有客户端应用程序都通过 NameNode 读取/写入数据,正如您在图 2-1 的简单 Hadoop 集群中看到的。

9781430265443_Fig02-01.jpg

图 2-1 。使用 NameNode(大脑)和 DataNodes 进行数据存储的简单 Hadoop 集群

Hadoop 有两个主要组件:Hadoop 分布式文件系统(HDFS)和一个使用 MapReduce 范式并行处理大量数据的框架。让我先把你介绍给 HDFS。

HDFS

HDFS 是一个分布式文件系统层,位于操作系统的原生文件系统之上。例如,对于 Ubuntu 操作系统,HDFS 可以安装在 ext3、ext4 或 XFS 文件系统之上。它使用廉价、不可靠的硬件为大量数据提供冗余存储。在加载时,数据分布在所有节点上。这有助于高效的 MapReduce 处理。与大量小文件相比,HDFS 处理少量大文件(数千兆字节)的性能更好,这是其设计方式决定的。

文件是“写一次,读多次”新版本的文件现在提供了追加支持,但 HDFS 是针对大型流读取的,而不是随机访问。高持续吞吐量比低延迟更受青睐。

HDFS 中的文件存储为,并为冗余或可靠性进行复制。默认情况下,数据块会跨 DataNodes 复制三次;所以每个文件都有三份拷贝。此外,块大小比其他文件系统大得多。例如,NTFS(用于 Windows)的最大块大小为 4KB,Linux ext3 的默认值为 4KB。与 HDFS 使用的默认块大小 64MB 相比!

NameNode

NameNode(或“大脑”)存储元数据并协调对 HDFS 的访问。元数据存储在 NameNode 的 RAM 中,以便快速检索并减少响应时间(对于 NameNode ),同时提供数据块的地址。这种配置提供了简单的集中式管理,同时也为 HDFS 提供了单点故障(SPOF)。在以前的版本中,辅助 NameNode 提供从 NameNode 故障中恢复的功能;但当前版本提供了在主动/被动配置中群集热备用(备用节点接管 NameNode 的所有功能,无需任何用户干预)节点的能力,以消除 NameNode 的 SPOF,并提供 NameNode 冗余。

由于元数据存储在 NameNode 的 RAM 中,并且文件的每个条目(及其块位置)都会占用一些空间,因此大量的小文件会产生大量的条目,并且会比大文件的少量条目占用更多的 RAM。此外,小于块大小(最小块大小为 64 MB)的文件仍将被映射到单个块,保留它们不需要的空间;这就是为什么大文件比小文件更适合使用 HDFS 的原因。

图 2-2 展示了 HDFS 集群各组成部分之间的关系。

9781430265443_Fig02-02.jpg

图 2-2 。HDFS 集群及其组件

HDFS 文件存储和数据块复制

HDFS 文件存储和复制系统的重要之处在于其内置的块放置智能,这提供了更好的节点故障恢复能力。当 NameNode 处理文件存储请求(来自客户端)时,它会在客户端本地存储块的第一个副本—如果它是群集的一部分。如果没有,NameNode 会将它存储在一个不太满或不太忙的 DataNode 上。它将数据块的第二个副本存储在位于同一机架上的不同 DataNode 上(是的,HDFS 在决定数据块放置时会考虑 DataNode 的机架使用情况),并将第三个副本存储在位于不同机架上的 DataNode 上,只是为了降低由于机架故障而丢失全部数据的风险。图 2-2 展示了两个文件的两个副本(每个块的)是如何分布在可用的数据节点上的。

DataNode 向 NameNode 发送心跳,如果 DataNode 在特定时间内没有发送心跳,则认为它“丢失”NameNode 找到其他 DataNode(该 DataNode 上有数据块的副本),并指示它们将丢失的数据块复制到另一个 DataNode。这样,所有数据块的副本总数将始终与配置的复制因子相匹配(该因子决定将维护文件的多少个副本)。

添加或删除 DataNodes

在 HDFS 集群中添加或删除 DataNodes 非常容易。您只需要将新的 DataNode 的主机名添加到一个配置文件(一个名为slaves的文本文件)中,并运行一个管理实用程序来告诉 NameNode 这个添加。之后,在新的 DataNode 上启动 DataNode 进程,并且您的 HDFS 集群有了一个额外的 DataNode。

删除 DataNode 同样简单,只需要一个相反的过程——从slaves中删除主机名条目,然后运行管理实用程序让 NameNode 知道这一删除。此后,可以关闭该节点上的 DataNode 进程,并将其从 HDFS 集群中删除。NameNode 悄悄地将块(从退役的 DataNode)复制到其他 DataNode,生活继续进行。

集群重新平衡

添加或删除 DataNodes 很容易,但这可能会导致您的 HDFS 集群不平衡。在你的 HDFS 集群中,还有其他可能造成不平衡的活动。Hadoop 提供了一个实用程序(Hadoop Balancer ),可以再次平衡您的集群。平衡器将数据块从过度利用的数据节点移动到未充分利用的数据节点,同时仍然遵循 Hadoop 的存储和复制策略,即不将数据节点上的所有副本放在一个机架上。

数据块移动将持续进行,直到所有数据节点的利用率(已用空间与总容量的比率)都在彼此的阈值百分比范围内。例如,5%的阈值意味着所有 DataNodes 的利用率都在 5%以内。平衡器在后台以低带宽运行,不会加重集群负担。

磁盘存储器

HDFS 为 NameNode、辅助 NameNode 和 DataNodes 使用本地存储,因此使用正确的存储类型非常重要。作为集群的大脑,NameNode 需要冗余和容错存储。强烈建议使用 RAID 10(在至少两个磁盘上对数据进行条带化和镜像)。辅助 NameNode 需要 RAID 10 存储。就 DataNodes 而言,它们可以使用本地 JBOD(只是一堆磁盘)存储。请记住,这些节点上的数据已经复制了三次(或者无论复制因子是什么),因此没有使用 RAID 驱动器的实际需要。

辅助 NameNode

现在让我们考虑一下辅助 NameNode 如何维护 NameNode 元数据的备用副本。NameNode 使用一个名为fsimage的图像文件来存储 HDFS 的当前状态(存储在文件系统中的所有文件及其对应块的位置的地图),并使用一个名为edits的文件来存储对 HDFS 的修改。随着时间的推移,edits文件会变得非常大;因此,fsimage不会有正确反映 HDFS 状态的最新图像。在这种情况下,如果 NameNode 崩溃,HDFS 的当前状态将会丢失,数据将不可用。

为了避免这种情况,辅助 NameNode 执行检查点(默认情况下每小时一次),在本地合并 NameNode 的fsimageedits文件,并将结果复制回 NameNode。因此,在最坏的情况下,只有对 HDFS 的编辑或修改会丢失——因为辅助 NameNode 在本地存储了最新的fsimage副本。图 2-3 提供了对这一过程的更多了解。

9781430265443_Fig02-03.jpg

图 2-3 。由辅助 NameNode 执行的检查点

所有这些对您的数据意味着什么?考虑一下 HDFS 是如何处理请求的。图 2-4 显示了 NameNode 如何处理数据请求,以及如何从相应的 DataNodes 中检索数据。

9781430265443_Fig02-04.jpg

图 2-4 。Hadoop 数据访问请求剖析

NameNode 高可用性

正如您在名称节点一节中所记得的,名称节点是一个 SPOF。但是,如果将 Hadoop 集群用作生产系统,就需要有一种方法来消除这种依赖性,并确保集群即使在 NameNode 失败的情况下也能正常工作。应对 NameNode 故障的方法之一是使用 NameNode 高可用性(或 HA ),其中一个集群部署有一对主动/被动的 NameNode。edits预写日志需要对两个 NameNodes(主动/被动)都可用,因此位于共享的 NFS 目录中。活动 NameNode 写入edits日志,备用 NameNode 重放相同的事务,以确保它是最新的(准备好在出现故障时接管)。DataNodes 向两个节点发送数据块报告。

您可以为手动或自动故障转移配置 HA 命名节点对(主动和被动节点互换角色)。对于手动故障转移,需要执行一个命令,让备用 NameNode 接管主 NameNode 或活动 NameNode。对于自动故障转移,每个 NameNode 需要运行一个称为故障转移控制器的额外进程,用于监控 NameNode 进程并根据需要协调状态转换。ZooKeeper 应用程序通常用于管理故障转移。

在故障转移的情况下,无法确定活动 NameNode 是否不可用,或者是否无法从备用 NameNode 访问它。如果两个 NameNode 进程并行运行,它们都可以写入共享状态并破坏文件系统元数据。这构成了裂脑场景,为了避免这种情况,您需要确保失败的 NameNode 被停止或“隔离”越来越严格的技术被用来实现击剑;从通过 RPC(远程过程调用)向 STONITH (或“击中另一个节点的头部”)发出停止请求开始,通过发出远程重启或(以编程方式)短时间切断机器电源来实现。

使用 HA 时,由于备用 NameNode 接管了辅助 NameNode 的角色,因此不需要单独的辅助 NameNode 进程。

hdfs 架构的互联网安全问题

回顾 HDFS 架构后,您会发现这不是我们都习惯的处理数据的传统客户端/服务器模型。没有服务器来处理数据、验证用户或管理锁定。在最初的 Hadoop 设计中,没有安全网关或认证机制。尽管 Hadoop 现在内置了强大的认证(您将在后面看到),但与现有企业系统和基于角色的授权集成的复杂性仍然带来了挑战。

任何能够访问运行 NameNode 进程的服务器并对 Hadoop 二进制文件拥有执行权限的用户都有可能从 NameNode 请求数据并请求删除这些数据!访问权限仅受 Hadoop 目录和文件权限的限制;但是很容易模仿另一个用户(在这种情况下是 Hadoop 超级用户)并访问一切。此外,Hadoop 不支持基于角色的访问或对象级访问,也不支持足够粒度的属性级访问(针对特定对象)。例如,它不提供能够运行特定 Hadoop 守护进程(或服务)的特殊角色。管理员角色中有一个全能的 Hadoop 超级用户,但是其他人都是凡人。除非为特定所有者或组指定了文件访问权限,否则用户只需连接到 HDFS 并访问所有文件。

因此,Hadoop 架构提供的灵活性也因缺乏中央认证机制而产生了漏洞。由于数据分布在大量的 datanode 上,再加上分布式存储和处理的优势,datanode 也是潜在的攻击入口,需要很好地保护。

Hadoop 客户端使用 RPC 协议在 NameNode 执行元数据操作,如创建文件打开文件,并使用称为数据传输协议的流套接字协议直接从 DataNodes 读取/写入文件数据。通过 Hadoop 配置文件可以轻松加密通过 RPC 协议完成的通信,但加密 DataNodes 和客户端之间的数据流量需要使用 Kerberos 或 SASL(简单认证和安全层)框架。

web 控制台和 Hadoop 守护进程(NameNode、辅助 NameNode、DataNode 等)之间的 HTTP 通信。)是不加密和不安全的(默认情况下,它允许在没有任何形式的认证的情况下访问),如图 2-5 所示。因此,访问所有集群元数据非常容易。总而言之,HDFS 因其建筑而面临以下威胁:

  • 未经授权的客户端可以通过 RPC 或 HTTP 协议访问 HDFS 文件或群集元数据(因为默认情况下通信是不加密和不安全的)。
  • 未经授权的客户端可以通过管道流数据传输协议(同样,未加密的通信)在 DataNode 读取/写入文件的数据块。
  • 任务或节点可能伪装成 Hadoop 服务组件(如 DataNode ),并修改元数据或执行破坏性活动。
  • 具有网络访问权限的恶意用户可以截获未加密的节点间通信。
  • 如果处理不当,大型 Hadoop 集群中故障磁盘上的数据可能会泄露私人信息。

9781430265443_Fig02-05.jpg

图 2-5 。Hadoop 通信协议和漏洞

当 Hadoop 守护进程(或服务)相互通信时,它们不会验证另一个服务是否真的是它所声称的那样。因此,很容易启动一个流氓 TaskTracker 来访问数据块。有一些方法可以让 Hadoop 服务执行相互认证;但是 Hadoop 在默认情况下不会实现它们,它们需要配置更改以及一些额外的组件来安装。图 2-5 总结了这些威胁。

我们将在第四章和第五章(涵盖认证和授权)以及第八章(重点是加密)中更详细地讨论安全问题(以及相关的解决方案)。现在,将注意力转向 Hadoop 的另一个主要组件:使用 MapReduce 范式并行处理大量数据的框架。

使用 MapReduce 的 Hadoop 作业框架

在前面的章节中,我们回顾了 Hadoop 的一个方面:HDFS,它负责跨多个 DataNodes 分发(和存储)数据。另一方面是数据的分布式处理;这是由 Hadoop 的作业框架处理的,它使用 MapReduce。

MapReduce 是一种跨多个节点分配任务的方法。每个节点处理存储在该节点上的数据(如果可能)。它由两个阶段组成:映射和还原。Map 任务处理一个分割或部分输入数据(一个键-值对),转换它,并输出转换后的中间数据。然后在一个洗牌(排序)过程中节点之间有数据交换,同一个 key 的中间数据到同一个 Reducer

Reducer 从不同的映射器接收输出时,它使用键(键-值对)对输入的数据进行排序,并将同一键的所有值组合在一起。然后 reduce 方法被 reduce 调用。它通过迭代与给定键相关联的值来生成一个键-值对列表(可能为空),并将输出写入输出文件。

MapReduce 框架利用两个 Hadoop 守护进程(JobTracker 和 TaskTracker)来调度和处理 MapReduce 作业。 JobTracker 在主节点(通常是运行 NameNode 的同一个节点)上运行,并管理为 Hadoop 集群提交的所有作业。JobTracker 使用从属节点(DataNodes)上的多个task tracker根据需要处理部分作业。

一个任务尝试是在一个从(TaskTracker)节点上运行的一个任务的实例。任务尝试可能会失败,在这种情况下,它们将被重新启动。因此,至少会有与需要执行的任务一样多的任务尝试。

随后,MapReduce 程序导致以下步骤:

  1. 客户端程序向 Hadoop 提交一个作业(数据请求)。
  2. 该作业由一个映射器、一个缩减器和一个输入列表组成。
  3. 作业被发送到主节点上的 JobTracker 进程。
  4. 每个从节点运行一个名为 TaskTracker 的进程。
  5. JobTracker 指示 TaskTrackers 运行和监视任务(输入数据的映射或简化任务)。

图 2-6 说明了 Hadoop 的 MapReduce 框架以及它如何处理一个任务。

9781430265443_Fig02-06.jpg

图 2-6 。MapReduce 框架和作业处理

任务进程向 TaskTracker 发送心跳。TaskTrackers 向 JobTracker 发送心跳。任何未能在 10 分钟内报告的任务都将被视为失败,并被 TaskTracker 终止。此外,任何抛出异常的任务都被认为是失败的。

任务跟踪者将失败的任务报告给任务跟踪者。JobTracker 重新计划任何失败的任务,并试图避免在先前失败的同一 TaskTracker 上重新计划任务。如果一项任务失败超过四次,则整个作业都会失败。任何未能在 10 分钟内报告的 TaskTracker 被认为已经崩溃,所有分配的任务在另一个 TaskTracker 节点上重新开始。

任何报告大量失败任务的 TaskTracker 都被列入黑名单(以防止节点阻塞整个作业)。还有一个针对多个任务失败的 TaskTrackers 的全局黑名单。JobTracker 管理每个作业的状态,失败任务的部分结果将被忽略。

图 2-7 显示了 MapReduce 范式如何为输入键值对工作,并导致输出减少。

9781430265443_Fig02-07.jpg

图 2-7 。作业的 MapReduce 处理

对 MapReduce 的详细介绍超出了本书的范围;感兴趣的读者可以参考 Jason Venner 的Pro Hadoop(a press,2009)。Jason 在的第二章中介绍了 MapReduce,并在的第五章中详细讨论了 MapReduce 程序的结构。MapReduce 的每个组件都被详细讨论,提供了一个深入的理解。

Apache Hadoop 纱线

Hadoop 早期版本使用的 MapReduce 算法在许多情况下不足以满足需要定制资源处理的场景。有了 YARN,Hadoop 现在有了一个通用的分布式数据处理框架(带有内置的调度程序),可以用来定义自己的资源处理。Hadoop MapReduce 现在只是可以与 YARN 一起使用的分布式数据处理应用程序之一。

YARN 将 JobTracker 的两个主要功能(资源管理和作业调度/监控)分配给单独的守护进程:一个全局资源管理器和一个基于应用程序的 ApplicationMaster。ResourceManager 和 NodeManager(运行在每个“从属”节点上)与 ApplicationMaster 一起构成了一个通用的分布式数据处理系统。

ResourceManager 是为集群中所有分布式数据处理应用程序分配资源的总权威。ResourceManager 使用一个可插拔的调度器(由您选择,例如,公平或先进先出[FIFO]调度器),负责根据应用程序的需求为其分配资源。此计划程序不执行监控、跟踪状态或重新启动失败的任务。

每个应用程序的 ApplicationMaster 与 ResourceManager 协商资源,与 NodeManager 一起执行组件任务,跟踪它们的状态,并监视它们的进度。这项功能先前是由 TaskTracker 执行的(当然还有调度)。

NodeManager 负责启动应用程序的容器,监视它们的资源使用情况(CPU、内存、磁盘、网络),并将其报告给 ResourceManager。

那么,MapReduce 和 YARN 有什么区别呢?如前所述,YARN 将 JobTracker 的功能分为 ResourceManager(调度)和 Application Master(资源管理)。有趣的是,这也将所有特定于应用程序框架的代码移动到 ApplicationMaster,使系统通用化,以便支持多种分布式处理框架,如 MapReduce、MPI(消息传递接口,一种用于并行计算机的消息传递系统,用于开发许多可扩展的大规模并行应用程序)和图形处理。

Hadoop 作业框架的固有安全问题

MapReduce 框架的安全问题围绕着 Hadoop 中缺乏认证、Hadoop 守护程序之间的通信不安全以及 Hadoop 守护程序不相互进行认证这一事实。主要的安全问题如下:

  • 未经授权的用户可能会向队列提交作业,或者删除或更改作业的优先级(因为 Hadoop 不进行认证或授权,并且很容易冒充用户)。
  • 未经授权的客户端可能会通过其 TaskTracker 的 HTTP shuffle 协议(未加密且不安全)访问地图作业的中间数据。
  • 正在执行的任务可以使用主机操作系统接口来访问其他任务和本地数据,包括中间映射输出或在同一物理节点上运行的 DataNode 的本地存储(静态数据是未加密的)。
  • 任务或节点可能伪装成 Hadoop 服务组件,如 DataNode、NameNode、JobTracker、TaskTracker 等。(无主机进程认证)。
  • 一个用户可能作为另一个用户提交一个工作流(使用像 Oozie 这样的工作流包)(很容易模拟一个用户)。

正如你所记得的,图 2-6 展示了 MapReduce 框架如何处理一个任务。比较图 2-6 和图 2-8 会让你更好地了解 MapReduce 框架的安全问题。图 2-8 详细描述了相同上下文中的安全问题:作业执行。

9781430265443_Fig02-08.jpg

图 2-8 。MapReduce 框架漏洞

Hadoop 的运营安全困境

到目前为止,我们讨论的安全问题源于 Hadoop 的架构,而不是我们每天都要处理的运营问题。一些问题源于 Hadoop 相对较新,起源于隔离的安全环境中的隔离实验室。曾经有一段时间,通过严格限制对 Hadoop 集群的网络访问,Hadoop 是“安全的”。任何访问请求都必须附有安全部门和请求者自己的管理层的几份弃权书!

此外,一些现有技术还没有时间构建接口或提供网关来与 Hadoop 集成。例如,当你读到这篇文章的时候,一些现在缺失的特性可能已经被添加了。像过去的 Unix 一样,Hadoop 仍然是一项正在进行的工作,每天都有新功能和新技术加入。考虑到这一点,请考虑 Hadoop 目前面临的一些运营安全挑战。

无法使用现有的用户凭据和策略

假设您的组织使用单点登录或 active directory 域帐户连接到所使用的各种应用程序。如何在 Hadoop 中使用它们?嗯,Hadoop 确实提供了 LDAP(轻量级目录访问协议)集成,但配置它并不容易,因为这个接口仍处于萌芽阶段,文档也非常粗略(在某些情况下甚至没有文档)。这种情况由于 Hadoop 在各种 Linux 版本上的使用而变得更加复杂,并且问题因所使用的操作系统及其版本而异。因此,向 active directory 用户分配选择性 Hadoop 资源并不总是可行的。

此外,您如何实现现有的访问控制策略,例如应用程序用户的读权限、开发人员的读/写权限等等?答案是不能。最简单的方法是为 Hadoop 访问创建单独的凭据,并遵循组织策略手动重新建立访问控制。Hadoop 遵循自己的安全模型,它(在外观上)类似于 Linux,让很多人感到困惑。Hadoop 和 Hadoop 生态系统结合了许多具有不同配置端点和各种授权方法(基于 POSIX 文件、类似 SQL 数据库)的组件,这可能会给开发和维护安全授权策略带来巨大挑战。社区有解决这些问题的项目(例如 Apache Sentry 和 Argus),但在撰写本文时还没有全面的解决方案。

难以与企业安全集成

大多数组织使用企业安全解决方案来实现各种目标。有时是为了降低网络攻击的风险,为了安全合规,或者仅仅是为了建立客户信任。然而,Hadoop 无法与这些安全解决方案集成。也许可以写一个自定义插件来适应 Hadoop 但是让 Hadoop 遵守所有的安全政策可能是不可能的。

传输中的未加密数据

Hadoop 是一个分布式系统,因此由多个节点(如 NameNode 和多个 DataNodes)组成,它们之间进行数据通信。这意味着数据通过网络传输,但没有加密。这可能是敏感的财务数据,如帐户信息或个人数据(如社会安全号码),并且容易受到攻击。

Hadoop 中的节点间通信使用 RPC、TCP/IP 和 HTTP 等协议。目前,只有 RPC 通信可以轻松加密(即 NameNode、JobTracker、datanode 和 Hadoop 客户端之间的通信),从而使客户端和 datanode(TCP/IP)之间的文件数据的实际读/写以及 HTTP 通信(web 控制台、NameNode/辅助 NameNode 和 MapReduce shuffle 数据之间的通信)容易受到攻击。

可以加密 TCP/IP 或 HTTP 通信;但这需要使用 Kerberos 或 SASL(简单认证和安全层)框架。还有,Hadoop 的内置加密对性能有非常负面的影响,没有被广泛使用。

静态无数据加密

静止时,数据存储在磁盘上。Hadoop 不加密存储在磁盘上的数据,这可能会将敏感数据暴露给恶意攻击。目前,没有为此目的提供编解码器或框架。由于 Hadoop 架构的性质,这尤其是一个大问题,它将数据分布在大量节点上,在所有这些不安全的入口点暴露数据块。

使用 Hadoop 实现静态加密有多种选择;但是它们是由不同的供应商提供的,并且依赖于它们的发行版来实现加密。最值得注意的是英特尔 Hadoop 发行版,它为存储在磁盘上的数据提供加密,并使用 Apache 和自定义编解码器来加密数据。其中一些功能被提议通过 Project Rhino(一个 Apache 开源项目)提供。

您必须了解,由于 Hadoop 通常处理大量数据,加密/解密需要时间,因此所用框架足够快地执行加密/解密非常重要,这样才不会影响性能。英特尔发行版声称能够以极高的速度执行这些操作——前提是英特尔 CPU 与英特尔磁盘驱动器和所有其他相关硬件一起使用。

Hadoop 不跟踪数据来源

存在多步骤 MapReduce 作业在中间步骤失败的情况,并且由于执行通常是面向批处理的,因此很难调试失败,因为输出数据集是所有可用的。

数据起源 是一个捕捉数据如何通过工作流处理的过程,并通过启用回溯来帮助调试——查找导致任何给定步骤的输出的输入数据。如果输出不寻常(或者不是预期的),可以使用反向跟踪来确定被处理的输入。

Hadoop 不提供任何数据起源(或回溯)的工具;如果需要数据来源,需要使用 RAMP 等第三方工具。这使得排除作业故障变得非常困难和耗时。

我们对 Hadoop 架构和相关安全问题的讨论到此结束。接下来我们将讨论 Hadoop 堆栈。

Hadoop 堆栈

Hadoop 核心模块和主要组件被称为 Hadoop 堆栈。Hadoop核心模块共同为 Hadoop 集群提供基本的工作功能。Hadoop 公共模块提供共享库,HDFS 提供分布式存储和容错文件系统的功能。MapReduce 或 YARN 提供了分布式数据处理功能。因此,没有所有的华而不实,这是一个功能性的 Hadoop 集群。您可以将一个节点配置为 NameNode,并为一个基本的、正常工作的 Hadoop 集群添加几个 DataNodes。

下面是对每个核心模块的简要介绍:

  • Hadoop Common :这些是支持其他 Hadoop 模块功能的公共库或实用程序。由于其他模块大量使用这些库,这是 Hadoop 的主干,对其工作是绝对必要的。

  • Hadoop 分布式文件系统(HDFS) : HDFS 是 Hadoop 集群的核心。它是一个分布式的文件系统,具有容错能力,易于扩展,并在数据节点上使用本地处理和本地数据存储来提供高吞吐量。(我已经在“HDFS”一节中非常详细地讨论了 HDFS)。

  • Hadoop YARN: YARN is a framework for job scheduling and cluster resource management. It uses a global resource manager process to effectively manage data processing resources for a Hadoop cluster in conjunction with Node Manager on each data node.

    资源管理器还有一个可插拔调度器(可以使用任何调度器,如 FIFO 或 Fair 调度器),它可以调度作业并与 DataNodes 上的应用程序主进程一起工作。默认情况下,它使用 MapReduce 作为分布式数据处理算法,但也可以根据需要使用任何其他分布式处理应用程序。

  • Hadoop MapReduce :基于 YARN 的大数据集并行处理系统。MapReduce 是“处理数据”的算法所有数据节点都可以本地、独立和并行地处理映射(输入到所需输出的转换)和归约(输出的排序和合并),以提供超大型数据集所需的高吞吐量。我在前面的“使用 MapReduce 的 Hadoop 作业框架”一节中详细讨论了 MapReduce。

那么,你现在知道 Hadoop 核心模块是什么了,但是它们是如何相互关联以形成具有预期功能的内聚系统的呢?图 2-9 说明了相互连接。

9781430265443_Fig02-09.jpg

图 2-9 。Hadoop 核心模块及其相互关系

如您所见,Hadoop 的两个主要方面是分布式存储和分布式数据处理。您还可以清楚地看到这两个方面对 Hadoop 公共库和操作系统的依赖性。Hadoop 就像运行在操作系统环境中的任何其他应用程序一样。但是安全系统会怎么样呢?是从操作系统继承来的吗?这就是问题所在。安全性不是从操作系统继承的,Hadoop 的安全性虽然有所提高,但仍不成熟,难以配置。因此,您必须找到在 Hadoop 集群中对数据进行认证、授权和加密的方法。你将在第四章、第五章、第八章和第九章中学习这些技巧。

最后,请注意在现实世界中,在同一个节点上运行 NameNode(管理 HDFS 处理)和 JobTracker(管理作业处理)是很常见的。因此,图 2-9 仅表示加工的逻辑划分;在物理实现的情况下不一定如此。

Hadoop 的主要组件

正如您在上一节中看到的,Hadoop 核心模块提供了基本的 Hadoop 集群功能,但主要组件并不局限于核心模块。毕竟一个基本的 Hadoop 集群是不能作为生产环境的。任何数据存储和管理系统都需要额外的功能,例如 ETL 和从其他(非 Hadoop)数据源的批量加载功能、调度、快速基于键的检索和查询功能(针对数据)。Hadoop 的主要组件也提供了这些缺失的功能。

例如,Pig 组件提供了一种用于设计 ETL 的数据流语言。Sqoop 提供了一种在 HDFS 和关系数据库之间传输数据的方法。Hive 使用类似 SQL 的语言提供查询功能。Oozie 提供了调度功能,HBase 为海量数据存储和基于键的快速检索添加了列存储。表 2-1 列出了一些流行的组件及其用法。

表 2-1 。流行的 Hadoop 组件

|

成分

|

描述

|

笔记

|
| --- | --- | --- |
| 巴什 | HBase 是一个开源、分布式、版本化、面向列的数据存储。 | 它可用于存储大量结构化和非结构化数据。它提供基于键的数据访问,因此可以非常快速地检索数据。它高度可扩展,并使用 HDFS 进行数据存储。HBase 的真正优势在于它能够存储非结构化的无模式数据,并使用行键快速检索这些数据。 |
| 储备 | Hive 提供了一种类似 SQL 的查询语言(HiveQL ),可用于查询 HDFS 数据。 | Hive 将查询转换为 MapReduce 作业,运行它们,并显示结果。Hive“表格”实际上是 HDFS 内部的文件。Hive 适合用于数据仓库,因为它不支持行级的插入、更新或删除。现在,脸书超过 95%的 Hadoop 工作都是由 Hive 前端驱动的。 |
| 猪 | Pig 是一种数据流语言,可以有效地用作仓库环境的 ETL 系统。 | 就像几乎什么都吃的真正的猪一样,猪编程语言被设计成处理任何类型的数据——因此得名。使用 Pig,您可以加载想要操作的 HDFS 数据,通过一组转换运行数据(在后台,这些数据被转换为 MapReduce 任务),并在屏幕上显示结果或将结果写入文件。 |
| Sqoop | Sqoop 提供与关系数据库(微软 SQL Server、Oracle、MySQL 等)的连接。),数据仓库,以及 NoSQL 数据库(Cassandra,HBase,MongoDB 等。). | 使用 Sqoop“连接器”可以很容易地在 HDFS(或 Hive/HBase 表)和这些数据源之间传输数据 Sqoop 与 Oozie 集成,以调度数据传输任务。Sqoop 的第一个版本是命令行客户端;但是 Sqoop2 有一个 GUI 前端和一个可以与多个 Sqoop 客户端一起使用的服务器。 |
| 驭象者 | Oozie 是一个工作流调度器,这意味着它基于工作流运行作业。在这个上下文中,工作流是安排在控制依赖 DAG(直接非循环图)中的动作的集合。 | 动作之间的控制依赖关系简单地定义了动作的顺序;比如第一个动作完成后,第二个动作才能开始。DAG 指的是一个无环图,它有一个起点和一个终点,并且沿一个方向前进,从不反转。总而言之,Oozie 只是按照预定义的顺序执行动作或作业(考虑到依赖性)。除非 Oozie 收到来自执行当前步骤或作业的远程系统的完成响应,否则不会启动序列中的下一个步骤。Oozie 通常用于调度 Pig 或 Sqoop 工作流,并与它们很好地集成。 |
| 水道 | Flume 是一个分布式系统,用于将大量数据从多个来源(同时根据需要转换或聚合数据)移动到一个集中的目的地或数据存储。 | Flume 有源、装饰器和接收器。是数据源,如日志文件、进程输出、TCP/IP 端口的流量等。,而且 Flume 有许多预定义的源以便于使用。装饰器是对源数据流的操作(如压缩或解压缩数据,从数据流中添加或删除某些字符,对数字数据进行分组和平均等。).接收器是文本文件、控制台显示或 HDFS 文件等目标。Flume 的一个常见用途是将诊断或作业日志文件移动到一个中心位置,并使用关键字(例如,“错误”或“失败”)进行分析。 |
| 象夫 | Mahout 是一个机器学习工具 | 还记得当你访问亚马逊或网飞网站时,它们是如何根据你的浏览历史或之前的购买记录推荐产品的吗?这是 Mahout 或类似的机器学习工具在发挥作用,使用所谓的协作过滤来提出建议,这是 Mahout 使用的机器学习任务之一,它基于用户的点击、评级或过去的购买来生成建议。Mahout 使用其他几种技术来“学习”或理解数据,它提供了开发高度可伸缩的机器学习或数据挖掘库的优秀方法(即,在数据量发生巨大变化的情况下,它们仍然可以使用)。 |

您可能已经注意到没有组件专门用于提供安全性。您将需要使用开源产品,如 Kerberos 和 Sentry,来补充这一功能。你将在第四章和第五章中了解更多。

对主要组件的简要介绍非常重要,因为在讨论安全实现以及监控(第七章)、日志记录(第六章)或加密(第八章和 9)的使用时,我假设整本书都使用“扩展的”Hadoop 集群(核心模块和主要组件)。

摘要

本章介绍了 Hadoop 的架构、核心模块、主要组件和固有的安全问题。

Hadoop 不是一个完美的安全系统,但什么是呢?以及 Hadoop 与之相比如何?为了使 Hadoop 成为一个安全的系统,你需要对它做哪些修改?第一章简要概述了一个模型安全系统(SQL Server),我将在第四章到第八章中讨论如何使用各种技术保护 Hadoop。

在后面的章节中,您还将了解 Hadoop 集群如何使用这里介绍的 Hadoop 堆栈(Hadoop 核心模块和主要组件)。了解 Hadoop 堆栈的工作方式也将使您更容易理解我提出的补充安全性的解决方案。下一章概述了我将在整本书中讨论的解决方案。第三章还将帮助你决定你想要关注的具体解决方案,并指引你找到所需细节的章节。

三、Hadoop 安全性简介

我们生活在一个非常不安全的世界。从你家前门的钥匙到所有重要的虚拟钥匙,你的密码,所有的东西都需要被保护好。在处理、转换和存储海量数据的大数据世界中,保护您的数据更加重要。

几年前,伦敦警方逮捕了一群年轻人,他们涉嫌欺诈和盗窃价值 3000 万美元的数字资产。他们 20 岁的头目使用宙斯木马,从他的笔记本电脑上窃取银行信息的软件来实现犯罪。由于即使在进行简单的业务交易时,也会涉及大量的信息和无数的系统,因此像这样的事件很常见。在过去,可能只有成千上万的人有可能访问你的数据来对你犯罪;现在,随着互联网的出现,可能有数十亿人!同样,在大数据出现之前,只有直接访问特定系统上的特定数据才是危险的;现在,大数据成倍增加了此类信息的存储位置,因此提供了更多方式来泄露您的隐私,甚至更糟。在新技术驱动、互联网驱动的世界中,一切都被扩大和缩小了——包括犯罪和潜在的犯罪。

想象一下,如果您的公司花费数百万美元安装 Hadoop 集群,使用大数据解决方案收集和分析客户对某个产品类别的消费习惯。由于该解决方案不安全,您的竞争对手获得了该数据,您的该产品类别的销售额下降了 20%。系统是如何允许未经授权访问数据的?没有任何认证机制吗?为什么没有警报?这个场景应该让您思考安全性的重要性,尤其是涉及敏感数据的时候。

尽管 Hadoop 由于其分布式架构而存在固有的安全性问题(正如您在第二章中看到的那样),但所描述的情况极不可能发生在安全管理的 Hadoop 安装上。Hadoop 安装明确定义了用户角色和敏感数据的多级认证(和加密),不会让任何未经授权的访问通过。

这一章是本书其余部分的路线图。它简要概述了确保 Hadoop 安装安全所需的每项技术;后面的章节将会更详细地介绍这些主题。目的是提供安全选项的快速概述,并帮助您根据需要快速找到相关技术。我从认证(使用 Kerberos)开始,接着讨论授权(使用 Hadoop ACLs 和 Apache Sentry),然后讨论安全管理(审计日志和监控)。最后,本章研究了 Hadoop 的加密和可用选项。我尽可能使用开源软件,因此您可以轻松构建自己的 Hadoop 集群来尝试本书中描述的一些技术。

然而,作为这一切的基础,您需要了解 Hadoop 的开发方式,并对 Hadoop 架构有所了解。有了这些背景信息,您将更好地理解本章后面讨论的认证和授权技术。

从 Hadoop 安全性开始

当谈到 Hadoop 安全性时,您必须考虑 Hadoop 是如何被概念化的。当 Doug Cutting 和 Mike Cafarella 开始开发 Hadoop 时,安全性并不是他们的首要任务。我确信这甚至不是最初设计的一部分。Hadoop 旨在处理公共领域的大量 web 数据,因此安全性不是开发的重点。这就是为什么它缺乏一个安全模型,只为 HDFS 提供基本的认证——这不是很有用,因为假冒另一个用户非常容易。

另一个问题是 Hadoop 不是作为一个具有预定义模块的内聚系统来设计和开发的,而是作为一个模块的拼贴来开发的,这些模块要么对应于各种开源项目,要么对应于由各种供应商开发的一组(专有)扩展,以补充 Hadoop 生态系统中缺乏的功能。

因此,Hadoop 为其集群的运行假设了一个可信环境的隔离(或茧),而没有任何安全违规——这在大多数情况下是缺乏的。目前,Hadoop 正从实验或新兴技术阶段过渡到企业级和公司使用。这些新用户需要一种方法来保护敏感的业务数据。

目前,社区支持的保护 Hadoop 集群的标准方法是使用 Kerberos 安全性。Hadoop 及其主要组件现在完全支持 Kerberos 认证。不过,这只是增加了一层认证。仅仅添加了 Kerberos,仍然没有一致的内置方法来定义用户角色以更好地控制组件,没有方法来保护对 Hadoop 进程(或守护程序)的访问或加密传输中的数据(甚至静态数据)。一个安全的系统需要解决所有这些问题,还需要提供更多的特性和方法来定制满足特定需求的安全性。在整本书中,您将学习如何在 Hadoop 中使用这些技术。现在,让我们先简单看一下解决 Hadoop 认证问题的流行解决方案。

HDFS 认证授权介绍

安全性的第一个也是最重要的考虑是认证。用户在被允许访问 Hadoop 集群之前需要进行认证。由于 Hadoop 不做任何安全认证,Kerberos 通常与 Hadoop 一起使用来提供认证。

当为了安全而实现 Kerberos 时,一个客户端(试图访问 Hadoop 集群)联系 KDC(托管凭证数据库的中央 Kerberos 服务器)并请求访问。如果提供的凭据有效,KDC 将提供请求的访问权限。我们可以将 Kerberos 认证过程分为三个主要步骤:

  1. TGT 代,其中认证服务器(AS)授予客户端一张票据授予票(TGT) 作为认证令牌。一个客户端可以对多个 TGS 请求使用同一个 TGT(直到 TGT 过期)。
  2. TGS 会话票证生成,客户端使用凭证解密 TGT,然后使用 TGT 从票证授予服务器(TGS) 获取服务票证,该服务器授予服务器对 Hadoop 集群的访问权限。
  3. 服务访问,客户端使用服务票认证并访问 Hadoop 集群。

第四章讨论了 Kerberos 架构的细节,以及如何配置 Kerberos 以用于 Hadoop。此外,您将找到一个分步指南,帮助您设置 Kerberos 为您的 Hadoop 集群提供认证。

授权

实现安全性时,下一步是授权。具体来说,如何在 Hadoop 中实现细粒度的授权和角色?最大的问题是所有信息都存储在文件中,就像在 Linux 主机上一样(毕竟,HDFS 是一个文件系统)。没有表的概念(像关系数据库一样),这使得授权用户对存储的数据进行部分访问变得更加困难。

无论您称之为定义授权细节、设计细粒度授权还是“微调”安全性,这都是一个多步骤的过程。这些步骤是:

  1. 分析你的环境,
  2. 对数据进行分类以便访问,
  3. 确定谁需要访问什么数据,
  4. 确定必要的访问级别,以及
  5. 实现您设计的安全模型。

但是,您必须记住,Hadoop(及其分布式文件系统)将其所有数据存储在文件中,因此您可以设计的安全性粒度是有限的。像 Unix 或 Linux 一样, Hadoop 有一个非常类似于基于 POSIX(可移植操作系统接口)模型的权限模型——很容易将这些权限与 Linux 权限混淆——因此权限粒度仅限于对文件或目录的读或写权限。你可能会说,“有什么问题?我的 Oracle 或 PostgreSQL 数据库在磁盘上以文件形式存储数据,为什么 Hadoop 不一样?”在传统的数据库安全模型中,所有的访问都是通过明确定义的角色来管理的,并通过一个中央服务器进程来引导。相比之下,数据文件存储在 HDFS,没有这样的中央进程和多个服务,如 Hive 或 HBase 可以直接访问 HDFS 文件。

为了让您详细了解使用基于文件/目录的权限可能实现的授权,第五章讨论了相关概念,解释了逻辑过程,并提供了一个详细的实际例子。现在,另一个真实世界的例子,即授权,将帮助您更好地理解这个概念。

设计 Hadoop 授权的真实示例

假设您正在为一家保险公司的索赔管理系统设计安全性,您必须为访问这些数据的所有部门分配角色并设计细粒度的访问。对于这个例子,考虑两个部门的功能需求:呼叫中心和理赔员。

呼叫中心代表接听客户来电,然后在他们满足所有规定条件的情况下提出或记录索赔(例如,由“天灾”造成的损坏不符合索赔条件,因此不能为他们提出索赔)。

索赔调解人查看提交的索赔,并拒绝违反任何监管条件的索赔。然后,该理赔员提交剩余的索赔进行调查,将它们分配给专业理赔员。这些调整人员根据公司规定和他们的具体职能知识评估索赔,以决定最终结果。

自动报告程序挑选最终状态为“已调整”的索赔,并生成适当的信件邮寄给客户,通知他们索赔结果。图 3-1 总结了该系统。

9781430265443_Fig03-01.jpg

图 3-1 。各部门所需的索赔数据和访问权限

如您所见,呼叫中心代表需要追加索赔数据,而调解人需要修改数据。因为 HDFS 没有更新或删除的规定,所以 adjustors 只需要添加一个新的记录或行(针对索赔及其数据),其中包含更新的数据和新的版本号。一个预定的流程将需要生成一份报告来查找调整后的索赔,并将最终索赔结果邮寄给客户。因此,该流程将需要对索赔数据的读取权限。

在 Hadoop 中,请记住,数据存储在文件中。对于本例,数据存储在名为Claims的文件中。每日数据临时存储在名为Claims_today的文件中,并在每晚追加到Claims文件中。呼叫中心人员使用组ccenter,而理赔员使用组claims,这意味着ClaimsClaims_today上的 HDFS 权限看起来像图 3-2 中的所示。

9781430265443_Fig03-02.jpg

图 3-2 。HDFS 文件权限

第一个文件Claims_today,拥有所有者和组ccuser的写权限。因此,属于该组的所有代表都可以写入或附加到该文件。

第二个文件Claims,拥有所有者和组claims的读写权限。因此,所有的索赔调整人员都可以读取Claims数据,并为他们已经完成工作并提供最终结果的索赔添加新行。另外,请注意,您需要在组claims中创建一个名为Reports的用户,用于访问报告数据。

Image 注意示例中讨论的权限是 HDFS 权限,而不是操作系统权限。Hadoop 遵循一个独立的权限模型,该模型看起来与 Linux 相同,但是前面的权限存在于 HDFS 中,而不是 Linux 中。

那么,这些权限满足这个系统的所有功能需求吗?你可以很容易地验证他们这样做。当然,用户Reports拥有他不需要的写权限;但是除此之外,所有的功能需求都得到了满足。

我们将在第五章中用一个更详细的例子来讨论这个话题。正如您所观察到的,您分配的权限仅限于完整的数据文件。然而,在现实世界中,您可能需要足够细粒度的权限来访问部分数据文件。你是怎么做到的?下一节将预览如何操作。

Hadoop 的细粒度授权

有时,数据的必要权限与组织的现有组结构不匹配。例如,一家银行可能需要一个备用主管拥有与主管相同的权限集,以防主管休假或生病。因为备份监督者可能只需要监督者权限的子集,所以为他或她设计一个新的组是不实际的。另外,考虑另一种情况,公司帐户被转移到不同的部门,负责迁移的组需要临时访问权限。

HDFS 的新版本支持 ACL(访问控制列表)功能,这在这种情况下将非常有用。使用 ACL,您可以根据需要为特定用户或组指定读/写权限。在银行示例中,如果备份管理员需要对特定“个人帐户”文件的写权限,则可以使用 HDFS ACL 功能来提供必要的写权限,而无需对文件权限进行任何其他更改。对于迁移场景,可以使用 HDFS ACL 为执行迁移的组分配读/写权限。如果您熟悉 POSIX ACLs,HDFS ACL 的工作方式完全相同。第五章在“HDFS 的访问控制列表”一节中再次详细讨论了 Hadoop ACLs。

最后,如何只为数据文件的一部分或数据的某一部分配置权限?也许用户只需要访问非敏感信息。可以进一步配置粒度(用于授权)的唯一方法是使用 NoSQL 数据库(如 Hive)和专用软件(如 Apache Sentry)。您可以将部分文件数据定义为 Hive 中的,然后使用 Sentry 来配置权限。Sentry 与用户和用户组(称为)一起工作,并让您定义规则 (对表的可能操作,如读或写)和角色(一组规则)。一个用户或组可以分配一个或多个角色。第五章提供了一个使用 Hive 和 Sentry 的真实示例,解释了如何为 Hadoop 定义微调授权。第五章的中的也有 Apache Sentry 的架构细节。

安全管理 HDFS

第四章和第五章将带你了解各种认证和授权技术,这些技术有助于保护你的系统,但不是一个完整的解决方案。如果授权用户访问他们未被授权使用的资源,或者未经授权的用户使用不可预见的方法访问 Hadoop 集群上的资源(阅读:黑客攻击),该怎么办?安全管理通过监控或审计所有对集群的访问来帮助您处理这些情况。如果您不能阻止这种类型的访问,您至少需要知道它发生了!Hadoop 为其所有进程提供了广泛的日志记录(也称为守护进程),一些开源工具可以帮助监控集群。(第六章和第七章详细讨论了审计日志记录和监控。)

由于 HDFS 的设计和构建方式,安全管理 HDFS 面临诸多挑战。监控可以提醒您对任何 Hadoop 集群资源的未授权访问,从而有助于提高安全性。然后,您可以根据这些警报的严重性设计针对恶意攻击的对策。虽然 Hadoop 为这种监控提供了指标,但是使用起来很麻烦。当您使用 Nagios 或 Ganglia 等专用软件时,监控会容易得多。此外,Cloudera 和 Hortonworks 的标准 Hadoop 发行版提供了自己的监控模块。最后,您可以捕获和监控 MapReduce 计数器。

审计日志通过记录流向 Hadoop 集群的所有访问来补充安全性。您可以决定日志记录的级别(如仅记录错误,或记录错误和警告等。),而 Log4j 等模块提供的高级日志管理为日志记录过程提供了很多控制和灵活性。第六章提供了 Hadoop 可用的审计日志记录的详细概述(带示例)。作为预览,下一节将简要概述 Hadoop 日志记录。

使用 Hadoop 日志实现安全性

当安全问题发生时,拥有大量可用的活动日志可以帮助您调查问题。因此,在违规发生之前,您应该启用审计日志记录来跟踪对系统的所有访问。你总是可以过滤掉不需要的信息。即使您已经启用了认证和授权,审计集群活动仍然有好处。毕竟,即使是授权用户也可能执行他们无权执行的任务;例如,具有更新权限的用户可以在没有适当批准的情况下更新条目。但是,您必须记住,Hadoop 日志是原始输出。因此,为了使它们对安全管理员有用,需要接收和处理这些日志的工具(注意,一些安装使用 Hadoop 本身来分析审计日志,因此您可以使用 Hadoop 来保护 Hadoop!).

仅仅捕获审计数据是不够的。您还需要捕获 Hadoop 守护进程数据。受联邦监管法律约束的企业,如健康信息携带和责任法案(HIPAA) 和萨班斯-奥克斯利法案(SOX) 就是这种需求的例子。例如,美国法律要求 HIPAA 涵盖的所有企业防止未经授权访问“受保护的健康信息”(患者姓名、地址以及与患者健康和支付记录相关的所有信息)或审计该信息的应用程序。必须遵守 SOX(2002 年美国联邦法律,要求任何美国上市公司的最高管理层单独证明其公司财务信息的准确性)的企业必须审核对应用程序中任何数据对象(如表)的所有访问。他们还必须监控谁提交、管理或查看了可以更改被审核应用程序中任何数据的作业。对于这样的业务案例,您需要捕捉:

  • HDFS 审计日志(记录 Hadoop 内的所有 HDFS 访问活动),
  • MapReduce 审核日志(记录所有提交的作业活动),以及
  • NameNode、DataNode、JobTracker 和 TaskTracker 的 Hadoop 守护进程日志文件。

Log4j API 是 Hadoop 日志记录的核心,无论是审计日志还是 Hadoop 守护进程日志。Log4j 模块提供了广泛的日志记录功能,并包含几个日志记录级别,您可以使用这些级别来按类别限制消息的输出,以及按类别限制(或抑制)消息。例如,如果 Log4j 日志记录级别被定义为 NameNode 日志记录的信息,则对于 NameNode 接收的任何文件访问请求,事件将被写入 NameNode 日志(即,所有信息性消息将被写入 NameNode 日志文件)。

您可以在 Hadoop 守护进程的 URL 上轻松地更改其日志记录级别。例如,http://jobtracker-host:50030/logLevel将在此守护程序运行时更改日志记录级别,但当它重新启动时将被重置。如果遇到问题,可以临时更改相应守护进程的日志记录级别,以便于调试。问题解决后,您可以重置日志记录级别。对于守护进程日志级别的永久更改,您需要在 Log4j 配置文件(log4j.properties)中更改相应的属性。

Log4j 架构使用一个日志记录器(一个用于日志事件的命名通道,如 NameNode、JobTracker 等。)、一个附加器(日志事件被转发到该附加器,并负责将其写入控制台或文件)和一个布局(日志事件的格式化程序)。日志记录级别(致命、错误、警告、信息、调试和跟踪)以降序显示事件的严重性。最低日志级别用作过滤器;接受日志级别大于或等于指定级别的日志事件,而忽略不太严重的事件。

图 3-3 展示了级别过滤的工作原理。列显示日志记录级别,而行显示与适当的记录器配置相关联的级别。交集标识事件是被允许通过进一步处理(是)还是被丢弃(否)。使用图 3-3 您可以根据配置的日志记录级别,轻松确定日志中将包含的事件类别。例如,如果 NameNode 的日志记录级别设置为 INFO,则属于 INFO、WARN、ERROR 和 FATAL 类别的所有消息都将被写入 NameNode 日志文件。通过查看列信息并观察标记为 YES 的事件级别,您可以很容易地识别出这一点。“跟踪”和“调试”级别被标记为“否”,将被过滤掉。如果 JobTracker 的日志记录级别设置为致命,则只记录致命错误,这从“致命”列中的值可以明显看出。

9781430265443_Fig03-03.jpg

图 3-3 。Log4j 基于事件级别的日志记录级别和包含内容

第六章将全面介绍 Hadoop 日志(以及它在调查安全问题中的用途)。在下一节中,您将了解监控的主要特性。

安全监控

当您想到监控时,您可能会想到需要进行故障排除的可能的性能问题,或者,如果系统资源(如 CPU、内存、磁盘空间)达到阈值,可能会生成警报。但是,您也可以出于安全目的使用监控。例如,如果用户试图访问群集元数据或读取/写入包含敏感数据的文件,或者某个作业试图访问不应该访问的数据,您可以生成警报。更重要的是,您可以监控许多指标来获得有用的安全信息。

监控像 Hadoop 这样的分布式系统更具挑战性,因为监控软件必须监控单个主机,然后在整个系统的上下文中整合数据。例如,DataNode 上的 CPU 消耗没有 NameNode 上的 CPU 消耗重要。那么,系统将如何处理 CPU 消耗警报,或者能够为分布式系统中具有不同角色的主机识别单独的阈值级别?第七章详细回答了这些问题,但现在让我们来看看可以用于安全目的的 Hadoop 指标:

  • NameNode 上的活动统计信息
  • DataNode 的活动统计信息
  • 服务的详细 RPC 信息
  • 针对系统资源突然变化的健康监控

贸易工具

领先的监控工具是 Ganglia ( http://ganglia.sourceforge.net)和 Nagios ( www.nagios.org)。这些流行的开源工具互为补充,各有千秋。Ganglia 侧重于收集指标并在一段时间内跟踪它们,而 Nagios 更侧重于作为一种警报机制。因为收集指标和发出警报都是监控的重要方面,所以它们最好结合使用。Ganglia 和 Nagios 都在集群的所有主机上运行代理,并收集信息。

神经中枢

Ganglia 的概念来自加州大学伯克利分校,是一个开源监控项目,旨在用于大型分布式系统。作为集群一部分的每个主机都运行一个名为 gmond 的守护进程,该进程收集并发送指标(如 CPU 使用率、内存使用率等。)从操作系统到中央主机。收到所有指标后,中央主机可以显示、汇总或总结这些指标以备将来使用。

Ganglia 旨在与其他应用程序轻松集成,并收集有关其操作的统计信息。例如,Ganglia 可以轻松地从 Hadoop metrics 接收输出数据,并有效地使用它。gmond(Ganglia 在每台主机上都运行它)占用空间很小,因此可以很容易地在集群中的每台机器上运行,而不会影响用户性能。

Ganglia 的 web 界面(图 3-4 )向您展示了集群使用的硬件、最近一个小时的集群负载、CPU 和内存资源消耗等等。您可以根据需要查看过去一小时、一天、一周或一个月的使用情况摘要。此外,您可以根据需要获得这些资源使用的详细信息。第七章将更详细地讨论神经节。

9781430265443_Fig03-04.jpg

图 3-4 。Ganglia 监控系统:集群概述

纳吉奥斯

Nagios 提供了一个非常好的警报机制,可以使用 Ganglia 收集的指标。Nagios 的早期版本从其目标主机轮询信息,但目前它使用在主机(集群的一部分)上运行代理的插件。Nagios 有一个优秀的内置通知系统,可以用于通过页面或电子邮件发送某些事件的警报(例如,NameNode 故障或磁盘已满)。Nagios 可以监控应用程序、服务、服务器和网络基础设施。图 3-5 显示了 Nagios web 界面,它可以方便地管理状态(被监控的资源)、警报(在资源上定义)、通知、历史等等。

9781430265443_Fig03-05.jpg

图 3-5 。用于监控的 Nagios web 界面

Nagios 的真正优势在于数百个用户开发的插件可以免费使用。插件在所有类别中都可用。例如,“系统度量”类别包含子类别“用户”,其中包含诸如“显示用户”之类的插件,这些插件可以在某些用户登录或未登录时向您发出警报。使用这些插件可以减少宝贵的定制时间,这是所有开源(和非开源)软件的主要问题。第七章讨论了设置 Nagios 的细节。

加密:Hadoop 的相关性和实现

作为一个分布式系统,Hadoop 将数据分布在大量主机上,并存储在本地。这些主机之间有大量的数据通信;因此,数据在传输过程中以及在静止和存储在本地存储时都容易受到攻击。Hadoop 最初是一个数据存储库,用于收集 web 使用数据以及其他形式的不敏感的大量数据。这就是为什么 Hadoop 没有任何内置的数据加密功能。

如今,情况正在发生变化,Hadoop 越来越多地被用于在企业中存储敏感的仓库数据。这就产生了对传输中和静态数据进行加密的需求。现在有许多替代方案可以帮助您加密数据。

传输中的数据加密

Hadoop 中的节间通信使用 RPC、TCP/IP、HTTP 等协议。RPC 通信可以使用简单的 Hadoop 配置选项进行加密,并用于 NameNode、JobTracker、DataNodes 和 Hadoop 客户端之间的通信。这使得客户端和 datanode(TCP/IP)之间的文件数据的实际读/写以及 HTTP 通信(web 控制台、NameNode/辅助 NameNode 之间的通信以及 MapReduce shuffle 数据)未加密。

加密 TCP/IP 或 HTTP 通信是可能的,但这需要使用 Kerberos 或 SASL 框架。Hadoop 的当前版本通过在配置文件core-site.xmlhdfs-site.xml中设置显式值来允许网络加密(结合 Kerberos)。第四章将重温这个详细的设置,并详细讨论网络加密。

静态数据加密

使用 Hadoop 实现静态加密有许多选择,但它们由不同的供应商提供,并且依赖于他们的发行版来实现加密。最值得注意的是英特尔项目 Rhino(致力于 Apache 软件基金会和开源)和 AWS(亚马逊网络服务)产品,它们为存储在磁盘上的数据提供加密。

因为 Hadoop 通常处理大量数据,加密/解密需要时间,所以所用框架执行加密/解密的速度要足够快,以免影响性能,这一点很重要。英特尔解决方案(即将通过 Cloudera 发行版提供)声称能够以极高的速度执行这些操作——前提是英特尔 CPU 与英特尔磁盘驱动器和所有其他相关硬件配合使用。让我们快速了解一下亚马逊加密“静态”选项的一些细节。

AWS 对存储在 HDFS 中的数据进行加密,并且还支持由其他组件(如 Hive 或 HBase)对加密数据进行操作。这种加密对用户可以是透明的(如果必要的密码存储在配置文件中),或者可以在允许访问敏感数据之前提示用户输入密码,可以逐个文件地应用,并且可以与外部密钥管理应用程序结合使用。这种加密可以使用对称密钥和非对称密钥。要使用这种加密,敏感文件在存储到 HDFS 之前必须使用对称或非对称密钥进行加密。

当加密文件存储在 HDFS 时,它仍然是加密的。根据处理需要对其进行解密,并在移回存储之前重新加密。分析结果也被加密,包括中间结果。数据和结果不会以未加密的形式存储或传输。图 3-6 提供了该过程的概述。存储在 HDFS 的数据使用对称密钥加密,而 MapReduce 作业使用对称密钥(带证书)传输加密数据。

9781430265443_Fig03-06.jpg

图 3-6 。英特尔 Hadoop 发行版(现为 Project Rhino)提供的静态加密的详细信息

第八章将更详细地介绍加密。它概述了加密概念和协议,然后简要讨论了实现加密的两个选项:使用英特尔的发行版(现在作为 Project Rhino 提供)和使用 AWS 提供透明加密。

摘要

有了路线图,找到你想去的地方并计划如何到达那里就容易多了。本章是您设计和实现 Hadoop 安全性的技术路线图。在概述了 Hadoop 架构之后,您研究了使用 Kerberos 提供安全访问的认证。然后,您学习了如何使用授权来指定访问级别,以及您需要遵循分析数据的多步骤过程,并需要定义有效的授权策略。

为了通过认证和授权来补充您的安全性,您需要持续监控未经授权的访问或不可预见的恶意攻击;Ganglia 或 Nagios 之类的工具会有所帮助。您还了解了使用 Log4j 日志记录系统和 Hadoop 守护进程日志以及审计日志记录对 Hadoop 守护进程的所有访问的重要性。

最后,您了解了传输中(以及静态)的数据加密,以及它作为附加安全级别的重要性,因为这是阻止黑客绕过认证和授权层进行未授权访问的唯一方法。要为 Hadoop 实现加密,可以使用 AWS(亚马逊网络服务)或英特尔的 Project Rhino 的解决方案。

在本书的其余部分,你将遵循这个路线图,深入探讨本章中出现的每个主题。我们将在第四章中从认证开始。

四、Hadoop 中的开源认证

在前面的章节中,您了解了什么是安全系统,以及与业界认为的安全系统 Microsoft SQL Server(关系数据库系统)相比,Hadoop 安全性缺失了什么。本章将着重于实现安全系统的一些特性,以保护您的 Hadoop 集群免受所有大灰狼的攻击。微调安全性与其说是科学,不如说是艺术。对于一个环境来说,没有什么规则是“刚刚好”的,但是你可以依靠一些基本的约定来帮助你更接近——如果不是“刚刚好”的话例如,由于 Hadoop 是一个分布式系统,主要通过 Windows PC 上的客户端软件进行访问,因此从保护客户端开始是有意义的。接下来,您可以考虑通过添加强身份认证来保护 Hadoop 集群,等等。

然而,在你衡量成功之前,你需要一个标准。在这种情况下,您需要一个理想的 Hadoop 安全设置的愿景。您将在下一节中找到详细信息。

安全拼图的碎片

图 4-1 显示了一个 Hadoop 广泛安全设置的例子。它始于一个安全的客户端。SSH 协议使用密钥对保护客户端;服务器使用公钥,客户端使用私钥。这是为了对抗欺骗(拦截并重定向到攻击者系统的连接)以及黑客攻击或泄露的密码。在接下来的“建立安全的客户端访问”一节中,您将更深入地研究安全客户端设置的细节。在 Hadoop 系统允许访问之前,它使用 Kerberos(一种用于认证的开源应用程序)对客户端进行认证。在“构建安全的用户认证”一节中,您将了解如何设置 Kerberos 并使其与 Hadoop 一起工作。

一旦用户被连接,重点是根据用户的角色限制权限。图 4-1 中的用户可以访问除敏感的薪资数据之外的所有用户数据。通过将数据分成多个文件并为它们分配适当的权限,可以很容易地实现这一点。第五章关注这些授权问题及更多。

9781430265443_Fig04-01.jpg

图 4-1 。理想的 Hadoop 安全性,具备所有必需的组件

您还将观察到各种 Hadoop 进程之间(例如 NameNode 和 DataNodes 之间)的进程间通信是安全的,这对于分布式计算环境是至关重要的。这样的环境涉及各种主机之间的大量通信,并且不安全的数据容易受到各种类型的恶意攻击。本章的最后一节探讨了如何保护或加密 Hadoop 中的进程间流量。

这些是 Hadoop 安全难题的主要部分。缺少的一部分是静态数据的加密,但是您将在第八章中了解更多。

建立安全的客户端访问

对 Hadoop 集群的访问从您使用的客户端开始,因此从保护客户端开始。不安全的数据容易受到恶意攻击,这可能导致数据被破坏或窃取用于非法用途。对于数据块分布在大量节点上的分布式系统(如 Hadoop ),这种危险更大。客户端就像是实际数据的网关。在你考虑保护房子之前,你需要保护大门。

OpenSSH 或 SSH 协议通常用于通过使用登录/密码或访问密钥来保护客户端。密钥是更好的选择,因为密码可能被泄露、破解或伪造。对于基于 Windows 和基于 Linux 的客户端来说,PuTTY ( www.chiark.greenend.org.uk/~sgtatham/putty)都是支持 SSH 协议的优秀开源客户端。除了免费之外,PuTTY 的一个主要优势是它允许使用密钥和密码短语而不是密码进行访问的能力。PuTTY 有一个不太明显但同样重要的额外好处,那就是帮助对抗欺骗,这值得你关注。

用 PuTTY 的主机密钥对抗欺骗

正如您所记得的,欺骗是一种用于提取您的个人信息(如密码)以备滥用的技术,通过将您的连接重定向到攻击者的计算机(而不是您认为您所连接的计算机),从而将您的密码发送到攻击者的计算机。利用这种技术,攻击者可以访问您的密码、登录并使用您的帐户来达到他们自己的恶意目的。

为了对抗欺骗,一个独特的代码(称为主机密钥 ) 被分配给每个服务器。创建这些密钥的方式是,一个服务器不可能伪造另一个服务器的密钥。因此,如果您连接到一个服务器,它向您发送了一个不同的主机密钥(与您预期的不同),SSH(或者像 PuTTY 这样使用 SSH 的安全客户端)可以警告您您连接到了一个不同的服务器,这可能意味着正在进行欺骗攻击!

PuTTY 通过 Windows 注册表中的条目存储主机密钥(对于您成功连接的服务器)。然后,下次连接到以前连接过的服务器时,PuTTY 会将服务器提供的主机密钥与上次存储在注册表中的密钥进行比较。如果不匹配,您将看到一个警告,然后有机会在您提供密码或任何其他私人信息之前放弃您的连接。

然而,当您第一次连接到服务器时,PuTTY 无法检查主机密钥是否正确。因此它会发出一个警告,询问您是否想要信任这个主机密钥:

The server's host key is not cached in the registry. You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 1024 5c:d4:6f:b7:f8:e9:57:32:3d:a3:3f:cf:6b:47:2c:2a
If you trust this host, hit Yes to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, hit No.
If you do not trust this host, hit Cancel to abandon the
connection.

如果您不知道该主机,或者您对该主机是否是您想要连接的主机有任何疑问,您可以取消连接,以避免成为欺骗的受害者。

使用 PuTTY 的基于密钥的认证

假设一个超级黑客进入了您的网络,并获得了从您的客户端到您希望连接的服务器的通信。假设这个黑客捕获了真实主机发送给你的客户端的主机认证字符串,并把它作为自己的字符串返回,让你连接到他的服务器,而不是真实的服务器。现在,他可以很容易地获得您的密码,并使用该密码访问敏感数据。

你如何能阻止这样的攻击?答案是用 基于密钥的认证代替密码。没有公钥,黑客就无法访问!

实现认证密钥的一种方法是使用 SSH,SSH 是一种用于通过公共通道或公共的不安全网络进行安全通信的协议。通信的安全性依赖于用于数据加密和解密的密钥对。SSH 可以以多种方式使用(或实现)。您可以自动生成公钥/私钥对来加密网络连接,然后使用密码验证来登录。使用 SSH 的另一种方法是手动生成一个公钥/私钥对来执行认证,这将允许用户或程序在不指定密码的情况下登录。

对于基于 Windows 的客户端,可以使用 PuTTYgen 生成密钥对,PuTTYgen 是开源的,可以免费获得。密钥对由复制到服务器的公钥和位于安全客户端的私钥组成。

私钥可以用来生成新的签名。没有私钥的任何人都无法伪造用私钥生成的签名。然而,拥有相应公钥的人可以检查特定签名是否真实。

当使用密钥对进行认证时,PuTTY 可以使用您的私钥(使用密钥文件指定)生成签名。服务器可以检查签名是否真实(使用您的公钥),并允许您登录。如果您的客户端被欺骗,攻击者截获的只是一个无法重用的签名,但您的私钥或密码不会被泄露。图 4-2 说明了认证过程。

9781430265443_Fig04-02.jpg

图 4-2 。使用 PuTTY 的基于密钥的认证

要使用 PuTTY 设置基于密钥的认证,您必须首先选择所需的密钥类型。例如,我将使用 RSA 并设置一个可以用于 Hadoop 集群的密钥对。要设置密钥对,打开 PuTTY 密钥生成器(PuTTYgen.exe)。在窗口底部,在生成密钥之前选择参数。例如,要生成用于 SSH-2 协议的 RSA 密钥,选择密钥类型下的 SSH-2 RSA 以生成。生成的密钥中的位数的值决定了密钥的大小或强度。对于这个例子,1024 就足够了,但是在现实世界中,为了更好的安全性,您可能需要一个更长的密钥,比如 2048。需要记住的重要一点是,密钥越长越安全,但是加密/解密处理时间会随着密钥长度的增加而增加。输入一个密钥密码(为了保护您的私钥而加密)并记下它,因为您稍后需要使用它来解密。

Image 注意可用于 PuTTY 的最常见的公钥算法是 RSA 和 DSA。PuTTY 开发者强烈推荐你使用 RSADSA(也称为 DSS,美国的联邦数字签名标准)有一个固有的弱点,即可以轻松创建包含足够信息的签名,从而泄露私有密钥。(为了更好的理解为什么 RSA 几乎不可能被破解,参见第八章。)

接下来,点击生成按钮。作为回应,PuTTYgen 让你四处移动鼠标来产生随机性(那是 PuTTYgen 开发者在跟我们开玩笑!).在“关键点”窗口的空白区域上绕圈移动鼠标;进度条会随着 PuTTYgen 收集到足够的随机性并生成密钥而逐渐填满,如图图 4-3 所示。

9781430265443_Fig04-03.jpg

图 4-3 。生成用于实现安全客户端的密钥对

生成密钥后,点击保存公钥保存私钥按钮保存密钥。

接下来,您需要将公钥复制到位于您试图连接的服务器上的home目录下的.ssh目录中的文件authorized_keys。为此,请参见图 4-3 中公钥粘贴到打开的 SSH authorized_keys 文件部分。将光标移动到该部分并复制所有文本(如图所示)。然后,打开一个 PuTTY 会话,使用您的登录名和密码进行连接。转到目录.ssh,用你选择的编辑器打开authorized_keys文件。将使用 PuTTYgen 创建的公钥文本粘贴到文件中,并保存文件(图 4-4 )。

9781430265443_Fig04-04.jpg

图 4-4 。在authorized_keys文件中粘贴公钥

使用密码短语

如果有人进入了你的电脑会怎么样?他们可以像您一样生成签名。然后,他们可以使用您的凭据轻松连接到您的 Hadoop 集群!这当然可以通过使用您选择的的密码在存储到您的本地机器之前加密您的私钥来轻松避免。然后,为了生成签名,PuTTY 将需要解密密钥,这将需要您的密码,从而防止任何未经授权的访问。

现在,无论何时登录都需要输入密码短语,这很不方便。因此,Putty 提供了 Pageant,这是一个认证代理,它存储解密的私钥,并根据请求使用它们来生成签名。你所需要做的就是开始 Pageant 并输入你的私钥和密码。然后,您可以任意次数调用 PuTTY Pageant 会自动生成签名。这种安排将一直有效,直到您重新启动 Windows 客户端。Pageant 的另一个很好的特性是,当它关闭时,它永远不会将您解密的私钥存储在您的本地磁盘上。

因此,作为最后一步,配置您的 PuTTY 客户端使用私钥文件而不是密码进行认证(图 4-5 )。点击选项 SSH 旁边的 + 打开下钻,然后点击该选项下的选项 Auth (授权)。浏览并选择您之前保存的私钥文件(通过 PuTTYgen 生成)。点击打开打开新的会话。

9781430265443_Fig04-05.jpg

图 4-5 。使用 PuTTY 进行私钥认证的配置选项

现在你已经准备好通过服务器使用登录和密码进行认证,如图 4-6 中的所示。在登录提示符下输入登录名(本例中为root),并输入密码进行连接!

9781430265443_Fig04-06.jpg

图 4-6 。使用登录名和密码进行安全认证

在某些情况下(例如,预定的批处理),不可能键入密码短语;在这种情况下,你可以输入一次密码,启动 Pageant 并加载你的私钥。请参考附录 A 中关于 Pageant 使用和实现的示例,以及附录 B 中关于基于 Linux 的客户端的 PuTTY 实现。

构建安全的用户认证

安全的客户端连接至关重要,但这只是一个好的起点。当这个安全客户端连接到您的 Hadoop 集群时,您需要保护它。用户安全过程从认证用户开始。虽然 Hadoop 本身没有认证用户的方法,但是目前所有主要的 Hadoop 发行版都可以安装 Kerberos,并且 Kerberos 提供了认证。

对于早期版本的 Hadoop,当用户试图访问 Hadoop 集群时,Hadoop 只需检查 ACL 以确保底层操作系统用户被允许访问,然后提供这种访问。这不是一个非常安全的选项,也没有限制用户的访问(因为用户可以很容易地模拟 Hadoop 超级用户)。然后,用户可以访问 Hadoop 集群中的所有数据,并可以根据需要修改或删除这些数据。因此,您需要配置 Kerberos 或另一个类似的应用程序,在允许访问数据之前对用户进行认证——当然,还要限制访问!

Kerberos 是 Hadoop 用于认证的最流行的选项之一。Kerberos 是由麻省理工学院开发的,自 20 世纪 80 年代以来一直存在,并经过多次增强。目前的版本 Kerberos 是在 1993 年设计的,可以作为开源下载免费获得。Kerberos 最常用于保护 Hadoop 集群和提供安全的用户认证。在本节中,您将了解 Kerberos 是如何工作的,它的主要组件是什么,以及如何安装它。安装之后,我将讨论 Hadoop 的一个简单的 Kerberos 实现。

Kerberos 概述

Kerberos 是一种用于“不可信网络上的可信主机”的认证协议这仅仅意味着 Kerberos 假设它与之通信的所有主机都是可信的,并且不涉及欺骗或者它使用的密钥没有被泄露。为了更有效地使用 Keberos,请考虑其他几个关键事实:

  • Kerberos 一直依赖于中央服务器。如果中央服务器不可用,任何人都无法登录。可以使用多个“中央”服务器(以降低风险)或额外的认证机制(作为后备)。
  • Kerberos 非常依赖于时间,因此所有受控主机的时钟必须在配置的限制范围内保持同步(默认为 5 分钟)。大多数情况下,网络时间协议守护程序有助于保持受控主机的时钟同步。
  • Kerberos 提供了单点登录方法。客户只需要在每次会话中提供一次密码,然后就可以透明地访问所有授权服务。
  • 密码不应保存在客户端或任何中间应用服务器上。Kerberos 将它们集中存储,没有任何冗余。

图 4-7 提供了 Kerberos 认证架构的概述。如图所示,认证服务器和票据授予服务器是 Kerberos 密钥分发中心的主要组件。

9781430265443_Fig04-07.jpg

图 4-7 。Kerberos 密钥分发中心及其主要组件(TGT =票证授予票证)

客户端使用 Kerberos 客户端库请求访问启用 Kerberos 的服务。Kerberos 客户端联系 Kerberos 分发中心或 KDC(托管凭证数据库的中央 Kerberos 服务器)并请求访问。如果提供的凭据有效,KDC 将提供请求的访问权限。KDC 使用一个内部数据库来存储凭证,以及两个主要组件:认证服务器(AS)和票据授予服务器(TGS)。

证明

Kerberos 认证过程包含三个主要步骤:

  1. AS 向用户(和主机)授予票据授予票据(TGT)作为认证令牌。TGT 仅在特定时间内有效(有效性由管理员通过配置文件进行配置)。在服务原则(用于运行服务或后台进程的登录)请求 TGT 的情况下,凭证通过名为 keytabs 的特殊文件提供给 AS。
  2. 客户端使用凭证解密 TGT,然后使用 TGT 从票证授予服务器获取服务票证,以访问“Kerberos 化”的服务。一个客户端可以对多个 TGS 请求使用同一个 TGT(直到 TGT 过期)。
  3. 用户(和主机)使用服务票来验证和访问特定的支持 Kerberos 的服务。

重要术语

要完全理解 Kerberos,您需要使用它的领域、主体、票据和数据库语言。举一个 Kerberos 实现的例子,您正在名为pract_hdp_sec的单个节点集群上实现 Kerberos,并且您正在使用名为EXAMPLE.COM的虚拟域或领域。

术语表示用于认证的管理域(类似于 Windows 域)。其目的是建立虚拟边界,供 AS 用来对用户、主机或服务进行认证。这并不意味着用户和服务之间的认证强制他们在同一个领域中!如果两个对象属于不同的领域,但它们之间有信任关系,那么认证仍然可以进行(称为交叉认证 )。对于我们的实现,我创建了一个名为EXAMPLE.COM的领域(注意,按照惯例,一个领域通常使用大写字母)。

主体是与领域相关联的用户、主机或服务,并作为条目存储在通常位于 KDC 的 as 数据库中。Kerberos 5 中的主体使用以下格式定义:Name[/Instance]@REALM 用户常用的用法是用户名 @ 领域用户名 / 角色 @ 领域(例如alex/admin@REALMalex@REALM可能是两个不同的主体)。对于服务主体,常见的格式是服务 / 主机名 @ 领域(例如hdfs/host1.myco.com)。注意,Hadoop 期望它的服务主体有一个特定的格式。对于我们的实现,我定义了一些原则,比如hdfs/pract_hdp_sec@EXAMPLE.COM(NameNode 和 DataNode 的hdfs),mapred/pract_hdp_sec@EXAMPLE.COM(JobTracker 和 TaskTracker 的mapred)等等。

是客户端请求认证时由 AS 生成的令牌。票证中的信息包括:请求用户的主体(通常是用户名)、服务的主体、客户端的 IP 地址、有效日期和时间(以时间戳格式)、票证的最大生命周期和会话密钥(这具有基本的作用)。每个票证通常在 24 小时后过期,尽管这对于给定的 Kerberos 安装是可配置的。

此外,票据可以由用户请求更新,直到从发行开始的可配置的时间段(例如,从发行开始的 7 天)。如果系统管理员已经将登录客户端(例如 SSH)配置为在登录时自动获得票据,则用户可以明确地使用 Kerberos 客户端来获得票据,或者被自动提供一个票据。服务通常使用 keytab 文件(包含服务密码的受保护文件)来运行后台线程,这些线程根据需要获取和更新服务的 TGT。所有 Hadoop 服务都需要一个 keytab 文件放在各自的主机上,这个文件的位置在服务站点 XML 中定义。

Kerberos 使用一个加密的数据库 来存储所有与用户和服务相关的主体条目。每个条目包含以下信息:主体名称、加密密钥、与主体相关联的票证的最大有效期、与主体相关联的票证的最大续订时间、密码到期日期以及主体的到期日期(在此之后将不会颁发任何票证)。

还有更多与 Kerberos 架构相关的细节,但是因为本章主要关注为 Hadoop 安装和配置 Kerberos,所以对 Kerberos 架构的基本理解将满足我们的目的。所以让我们从 Kerberos 安装开始。

安装和配置 Kerberos

安装 Kerberos 的第一步是为您的新 KDC 安装所有 Kerberos 服务。对于 Red Hat Enterprise Linux (RHEL)或 CentOS 操作系统,使用以下命令:

yum install krb5-server krb5-libs krb5-auth-dialog krb5-workstation

安装服务器后,您必须编辑两个主要配置文件,缺省情况下,它们位于以下目录中(如果没有,请使用 Linux 实用程序“find”找到它们):

  • /etc/krb5.conf
  • /var/kerberos/krb5kdc/kdc.conf

下一步是指定您的领域(例如EXAMPLE.COM),并将 KDC 值更改为完全合格的 Kerberos 服务器主机的名称(这里是pract_hdp_sec)。您还必须将/etc/krb5.conf的更新版本复制到集群中的每个节点。下面是我们的例子中的/etc/krb5.conf:

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

[kdc]
profile = /var/kerberos/krb5kdc/kdc.conf

[realms]
 EXAMPLE.COM = {
  kdc = pract_hdp_sec
  admin_server = pract_hdp_sec
 }

[domain_realm]
 .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM

请注意领域名称和 KDC 名称的更改值。示例票证在创建后的 24 小时内有效,因此ticket_lifetime被设置为24h。7 天后这些票可以续签,因为renew_lifetime被设置为7d。以下是我正在使用的/var/kerberos/krb5kdc/kdc.conf:

[kdcdefaults]
 kdc_ports = 88
 kdc_tcp_ports = 88

[realms]
 EXAMPLE.COM = {
  profile = /etc/krb5.conf
  supported_enctypes = aes128-cts:normal des3-hmac-sha1:normal
arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
allow-null-ticket-addresses = true
database_name = /var/Kerberos/krb5kdc/principal
#master_key_type = aes256-cts
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  dict_file = /usr/share/dict/words
  max_life = 2d 0h 0m 0s
  max_renewable_life = 7d 0h 0m 0s
  admin_database_lockfile = /var/kerberos/krb5kdc/kadm5_adb.lock
  key_stash_file = /var/kerberos/krb5kdc/.k5stash
  kdc_ports = 88
  kadmind_port = 749
  default_principle_flags = +renewable
}

在领域EXAMPLE.COM的设置中,acl_file参数指定 ACL(RHEL 或 CentOS 中的文件/var/kerberos/krb5kdc/kadm5.acl),用于定义对 Kerberos 数据库具有管理(修改)访问权限的主体。该文件可以简单到只有一个条目:

*/admin@EXAMPLE.COM *

这个条目指定所有具有/admin 实例扩展的主体对数据库具有完全访问权限。Kerberos 服务kadmin需要重新启动才能使更改生效。

此外,请注意max_life(最长票证寿命)设置对于领域EXAMPLE.COM2d (2 天)。您可以覆盖特定领域的配置设置。您也可以为主体指定这些值。

注意,在前面代码的[realms]部分,我已经禁用了 256 位加密。如果要使用 256 位加密,必须下载 Java Cryptography Extension(JCE),并按照说明将其安装在任何运行使用 Kerberos 的 Java 进程的节点上(对于 Hadoop,所有集群节点)。如果您想跳过这一步,只使用 128 位加密,在生成您的 KDC 主密钥之前,删除行#master_key_type = aes256-cts并删除对aes-256的引用,如“创建数据库”一节所述

这包括安装和设置 Kerberos。请注意,不可能涵盖所有可能的选项(操作系统、版本等。)和 Kerberos 安装的细微差别。关于 Kerberos 安装的更多讨论,请参考麻省理工学院的 Kerberos 安装指南。奥莱利的 Kerberos:权威指南也是一个很好的参考。

回到 Kerberos 实现,让我创建一个数据库并设置主体(用于 Hadoop)。

为 Kerberos 实现做准备

Kerberos 使用内部数据库(存储为文件)来保存为使用而设置的主体的详细信息。该数据库包含用户(主体)及其私钥。主体包括 Kerberos 使用的内部用户以及您定义的用户。数据库文件存储在配置文件kdc.conf文件中定义的位置;对于这个例子,/var/kerberos/krb5kdc/principal.

创建数据库

要设置数据库,请使用实用程序 kdb5_util:

kdb5_util create -r EXAMPLE.COM –s

您将会看到类似这样的响应:

Loading random data
Initializing database '/var/kerberos/krb5kdc/principal' for realm 'EXAMPLE.COM',
master key name 'K/M@EXAMPLE.COM'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key:
Re-enter KDC database master key to verify:

请记下万能钥匙。另外,请注意-s选项允许您将数据库的主服务器密钥保存在隐藏文件中(使用kdc.conf中的参数key_stash_file定义)。如果 stash 文件不存在,您需要在每次启动时使用主密码(在安装过程中指定)登录 KDC。这将自动重新生成主服务器密钥。

既然已经创建了数据库,那么就创建第一个用户主体。这必须在 KDC 服务器上完成,同时您以root身份登录:

/usr/sbin/kadmin.local -q "addprinc root/admin"

系统将提示您输入密码。请记下委托人root/admin@EXAMPLE.COM的密码。您可以稍后创建其他主体;现在,是时候开始 Kerberos 了。要为 RHEL 或 CentOS 操作系统执行此操作,请发出以下命令来启动 Kerberos 服务(对于其他操作系统,请参考相应的命令参考):

/sbin/service kadmin start
/sbin/service krb5kdc start

创建服务主体

接下来,我将使用 kadmin 实用程序创建用于 Hadoop 的服务主体。主要名称hdfs将用于 HDFS;mapred将用于 MapReduce,HTTP用于 HTTP,yarn用于 YARN 相关的服务(在这段代码中,kadmin:是提示;命令以粗体显示):

[root@pract_hdp_sec]# kadmin
Authenticating as principal root/admin@EXAMPLE.COM with password.
Password for root/admin@EXAMPLE.COM:
kadmin:  addprinc -randkey hdfs/pract_hdp_sec@EXAMPLE.COM
Principal "hdfs/pract_hdp_sec@EXAMPLE.COM" created.
kadmin:  addprinc -randkey mapred/pract_hdp_sec@EXAMPLE.COM
Principal "mapred/pract_hdp_sec@EXAMPLE.COM" created.
kadmin:  addprinc -randkey HTTP/pract_hdp_sec@EXAMPLE.COM
Principal "HTTP/pract_hdp_sec@EXAMPLE.COM" created.
kadmin:  addprinc -randkey yarn/pract_hdp_sec@EXAMPLE.COM
Principal "yarn/pract_hdp_sec@EXAMPLE.COM" created.
kadmin:

创建 Keytab 文件

Keytab 文件用于以非交互方式验证服务。因为您可以安排服务远程运行或在特定时间运行,所以您需要将认证信息保存在一个文件中,以便可以与 Kerberos 内部数据库进行比较。Keytab 文件用于此目的。

回到文件创建,提取相关的 keytab 文件(使用 kadmin)并将其放在各个组件的 keytab 目录(/etc/security/keytabs)中(kadmin:)是提示;命令以粗体显示):

[root@pract_hdp_sec]# kadmin
Authenticating as principal root/admin@EXAMPLE.COM with password.
Password for root/admin@EXAMPLE.COM:
kadmin: xst -k mapred.keytab hdfs/pract_hdp_sec@EXAMPLE.COM HTTP/pract_hdp_sec@EXAMPLE.COM
Entry for principal hdfs/pract_hdp_sec@EXAMPLE.COM with kvno 5, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/pract_hdp_sec@EXAMPLE.COM with kvno 5, encryption type des3-cbc-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/pract_hdp_sec@EXAMPLE.COM with kvno 5, encryption type arcfour-hmac added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/pract_hdp_sec@EXAMPLE.COM with kvno 5, encryption type des-hmac-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/pract_hdp_sec@EXAMPLE.COM with kvno 5, encryption type des-cbc-md5 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/pract_hdp_sec@EXAMPLE.COM with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/pract_hdp_sec@EXAMPLE.COM with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/pract_hdp_sec@EXAMPLE.COM with kvno 4, encryption type arcfour-hmac added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/pract_hdp_sec@EXAMPLE.COM with kvno 4, encryption type des-hmac-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/pract_hdp_sec@EXAMPLE.COM with kvno 4, encryption type des-cbc-md5 added to keytab WRFILE:mapred.keytab.

请注意,所有受支持加密类型的密钥条目(在配置文件kdc.conf中定义为参数supported_enctypes)都被添加到主体的 keytab 文件中。

回到 keytab 创建,为其他主体创建 keytab 文件(在 kadmin 提示符下),如下所示:

kadmin:xst -k mapred.keytab hdfs/pract_hdp_sec@EXAMPLE.COM http/pract_hdp_sec@EXAMPLE.COM
kadmin:xst -k yarn.keytab hdfs/pract_hdp_sec@EXAMPLE.COM http/pract_hdp_sec@EXAMPLE.COM

您可以使用klist命令验证正确的 keytab 文件和主体是否与正确的服务相关联。例如,在 NameNode 上:

[root@pract_hdp_sec]# klist -kt mapred.keytab
Keytab name: FILE:mapred.keytab
KVNO Timestamp Principal
---- ----------------- --------------------------------------------------------
   5 10/18/14 12:42:21 hdfs/pract_hdp_sec@EXAMPLE.COM
   5 10/18/14 12:42:21 hdfs/pract_hdp_sec@EXAMPLE.COM
   5 10/18/14 12:42:21 hdfs/pract_hdp_sec@EXAMPLE.COM
   5 10/18/14 12:42:21 hdfs/pract_hdp_sec@EXAMPLE.COM
   5 10/18/14 12:42:21 hdfs/pract_hdp_sec@EXAMPLE.COM
   4 10/18/14 12:42:21 HTTP/pract_hdp_sec@EXAMPLE.COM
   4 10/18/14 12:42:21 HTTP/pract_hdp_sec@EXAMPLE.COM
   4 10/18/14 12:42:21 HTTP/pract_hdp_sec@EXAMPLE.COM
   4 10/18/14 12:42:21 HTTP/pract_hdp_sec@EXAMPLE.COM
   4 10/18/14 12:42:21 HTTP/pract_hdp_sec@EXAMPLE.COM

到目前为止,您已经为 HDFS、MapReduce 和 YARN 相关的主体定义了主体并提取了 keytab 文件。您将需要遵循相同的过程,并为运行在您的 Hadoop 集群上的任何其他组件服务(如 Hive、HBase、Oozie 等)定义主体。注意,web 通信的主体必须命名为HTTP,因为使用 Kerberos 的基于 web 的协议实现需要这个命名。

要将 keytab 文件部署到从节点,请将 keytab 文件复制(或移动,如果是新创建的)到/etc/hadoop/conf文件夹。您需要保护 keytab 文件(只有所有者可以看到此文件)。因此,您需要将所有者更改为访问 keytab 的服务用户名(例如,如果 HDFS 进程作为用户hdfs运行,那么用户hdfs应该拥有 keytab 文件)并设置文件权限 400。请记住,hdfsmapredhttp的服务主体有一个与用户名相关联的 FQDN(完全合格域名)。此外,服务主体是特定于主机的,对于每个节点都是唯一的。

[root@pract_hdp_sec]# sudo mv hdfs.keytab mapred.keytab /etc/hadoop/conf/
[root@pract_hdp_sec]# sudo chown hdfs:hadoop /etc/hadoop/conf/hdfs.keytab
[root@pract_hdp_sec]# sudo chown mapred:hadoop /etc/hadoop/conf/mapred.keytab
[root@pract_hdp_sec]# sudo chmod 400 /etc/hadoop/conf/hdfs.keytab
[root@pract_hdp_sec]# sudo chmod 400 /etc/hadoop/conf/mapred.keytab

为 Hadoop 实现 Kerberos

到目前为止,我已经安装并配置了 Kerberos,还创建了数据库、主体和 keytab 文件。那么,对 Hadoop 使用这种认证的下一步是什么呢?我需要将 Kerberos 设置信息添加到相关的 Hadoop 配置文件中,并将之前设置的 Kerberos 主体映射到操作系统用户(因为操作系统用户将用于实际运行 Hadoop 服务)。我还需要假设一个处于非安全模式的 Hadoop 集群已经配置好并且可用。总而言之,为 Kerberos 配置 Hadoop 将分两个阶段完成:

  • 将服务主体映射到其操作系统用户名
  • 向各种 Hadoop 配置文件添加信息

将服务主体映射到其操作系统用户名

规则用于将服务主体映射到它们各自的操作系统用户名。这些规则在 Hadoop 配置文件core-site.xml中被指定为可选键hadoop.security.auth_to_local的值。

默认规则简单地命名为DEFAULT。它将默认域中的所有主体转换为它们的第一个组件。例如,hdfs@EXAMPLE.COMhdfs/admin@EXAMPLE.COM都变成了hdfs,假设你的默认域或领域是EXAMPLE.COM。因此,如果服务主体和操作系统用户名相同,默认规则就足够了。如果两个名称不相同,您必须创建规则来进行映射。

每个规则分为三个部分:基本、过滤和替换。 base 首先指定主体名称(不包括领域)中的组件数量,然后是一个冒号,以及从主体名称的各个部分构建用户名的模式。在模式部分中,$0翻译成领域,$1翻译成第一个组件,$2翻译成第二个组件。例如,[2:$1]hdfs/admin@EXAMPLE.COM翻译成hdfs

过滤器由括号中的正则表达式组成,该表达式必须与要应用的规则所生成的字符串相匹配。例如,(.*@EXAMPLE.COM)匹配任何以@EXAMPLE.COM结尾的字符串。

替换是一个 sed(流行的 Linux 流编辑器)规则,它将正则表达式转换成固定的字符串。例如:s/@[A-Z]*\.COM//删除@的第一个实例,后面跟一个大写字母名称,后面跟.COM

在我的例子中,我使用操作系统用户hdfs来运行 NameNode 和 DataNode 服务。因此,如果我创建了 Kerberos 主体nn/pract_hdp_sec@EXAMPLE.COMdn/pract_hdp_sec@EXAMPLE.COM用于 Hadoop,那么我需要将这些主体映射到 os 用户hdfs。为此目的的规则是:

RULE: [2:$1@$0] ([nd]n@.*EXAMPLE.COM) s/.*/hdfs/

向各种 Hadoop 配置文件添加信息

要使 Kerberos 能够与 HDFS 一起工作,您需要修改两个配置文件:

  • core-site.xml
  • hdfs-site.xml

表 4-1 显示了core-site.xml内属性的修改。请记住将这些更改传播到集群中的所有主机。

表 4-1 。修改 Hadoop 配置文件core-site.xml 中的属性

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| hadoop.security.authentication | kerberos | 设置群集的认证类型。有效值为simple(默认值)或Kerberos。 |
| hadoop.security.authorization | true | 为不同的协议启用授权 |
| hadoop.security.auth_to_local | [2:$1]``DEFAULT | 使用映射规则从 Kerberos 主体名称到本地 os 用户名的映射 |
| hadoop.rpc.protection | privacy | 可能的值有authenticationintegrityprivacyauthentication =相互客户端/服务器认证integrity =认证和完整性;保证客户端和服务器之间交换的数据以及认证的完整性privacy =认证、完整性和保密性;加密客户端和服务器之间交换的数据 |

hdfs-site.xml配置文件指定了 keytab 位置以及各种 HDFS 守护进程的主体名称。请记住,hdfshttp主体是特定于特定节点的。

Hadoop 集群可能包含大量的 DataNodes,实际上不可能为每个 DataNodes 手动配置主体。因此,Hadoop 提供了一个在运行时解析为完全限定域名的_HOST变量。该变量允许站点 XML 在整个集群中保持一致。但是,请注意_HOST变量不能用于所有的 Hadoop 配置文件。比如 Zookeeper 使用的jaas.conf文件(它提供了跨集群节点的资源同步,应用程序可以使用它来确保跨集群的任务是序列化或同步的)和 Hive 不支持_HOST变量。表 4-2 显示了对hdfs-site.xml中属性的修改,其中一些使用了_HOST变量。请记住将这些更改传播到集群中的所有主机。

表 4-2 。修改了 Hadoop 配置文件hdfs-site. xml的属性

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| dfs.block.access.token.enable | True | 如果为 true,则访问令牌用于访问 DataNodes |
| dfs.namenode.kerberos. principal | hdfs/_HOST@EXAMPLE.COM | NameNode 的 Kerberos 主体名称 |
| dfs.secondary.namenode. kerberos.principal | hdfs/_HOST @EXAMPLE.COM | 辅助 NameNode 服务器的地址 |
| *dfs.secondary.https.port | 50490 | 辅助 NameNode 绑定到的 https 端口 |
| dfs.web.authentication.kerberos. principal | HTTP/_HOST@例。COM | Hadoop 使用的 Kerberos 主体 |
| dfs.namenode.kerberos.``internal.spnego.``principal | HTTP/_HOST@例。COM | 这是http校长对于 HTTP 服务 |
| dfs.secondary.namenode.``kerberos.internal.``spnego.principal | HTTP/_HOST@例。COM | 这是http校长对于 http 服务 |
| *dfs.secondary.http.address | 192.168.142.135:50090 | 辅助 NameNode 主机的 IP 地址和端口 50090 |
| dfs.web.authentication. kerberos.keytab | /etc/hadoop/conf/spnego.service.keytab | 带有http主体凭证的 Kerberos keytab 文件 |
| dfs.datanode.kerberos.principal | hdfs/_HOST@例。COM | 运行 DataNode 的 Kerberos 主体 |
| dfs.namenode. keytab.file | /etc/hadoop/conf/``hdfs.keytab | 包含 NameNode 服务和主机主体的 keytab 文件 |
| dfs.secondary.namenode. keytab.file | /etc/hadoop/conf/``hdfs.keytab | 包含 NameNode 服务和主机主体的 keytab 文件 |
| dfs.datanode. keytab.file | /etc/hadoop/conf/``hdfs.keytab | DataNode 的 keytab 文件 |
| *dfs.https.port | 50470 | NameNode 绑定到的 https 端口 |
| *dfs.https.address | 192.168.142.135:50470 | NameNode 的 https 地址(主机的 IP 地址+端口 50470) |
| dfs.datanode.address | 0.0.0.0:1019 | 用于数据传输的 DataNode 服务器地址和端口。 |
| dfs.datanode.http.address | 0.0.0.0:1022 | DataNode http 服务器地址和端口 |

* 这些值可能会因集群而异

文件core-site.xmlhdfs-site. xml包含在下载中供您参考。它们还包含为其他组件(如 Hive、Oozie 和 HBase)设置的 Kerberos 相关属性。

MapReduce 相关配置

对于 MapReduce(版本 1),mapred-site.xml文件需要配置为与 Kerberos 一起工作。它需要指定 keytab 文件的位置以及 JobTracker 和 TaskTracker 守护程序的主体名称。使用表 4-3 作为指南,记住mapred原则是特定于特定节点的。

表 4-3 。mapred校长

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| mapreduce.jobtracker.``kerberos.principal | mapred/_HOST@例。COM | mapred用于启动 JobTracker 守护程序的主体 |
| mapreduce.jobtracker.``keytab.file | /etc/hadoop/conf/mapred.keytab | mapred用户的 keytab 文件的位置 |
| mapreduce.tasktracker.``kerberos.principal | mapred/_HOST@例。COM | mapred用于启动 TaskTracker 守护程序的主体 |
| mapreduce.tasktracker.``keytab.file | /etc/hadoop/conf/mapred.keytab | mapred用户的 keytab 文件的位置 |
| mapred.task.tracker.``task-controller | org.apache.``hadoop.mapred.``LinuxTaskController | TaskController用于启动子 JVM 的类 |
| mapreduce.tasktracker.group | mapred | 运行 TaskTracker 的组 |
| mapreduce.jobhistory.keytab | /etc/hadoop/conf/``mapred.keytab | mapred用户的 keytab 文件的位置 |
| mapreduce.jobhistory.principal | mapred/_HOST@例。COM | mapred用于启动作业历史守护程序的主体 |

对于 YARN,需要配置yarn-site.xml文件来指定 keytab 和 principal details 表 4-4 保存了详细信息。

表 4-4 。纱校长

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| yarn.resourcemanager.principal | yarn/_HOST@例。COM | yarn用于启动资源管理器守护程序的主体 |
| yarn.resourcemanager.keytab | /etc/hadoop/conf/yarn.keytab | yarn用户的 keytab 文件的位置 |
| yarn.nodemanager.principal | yarn/_HOST@例。COM | yarn用于启动节点管理器守护进程的主体 |
| yarn.nodemanager.keytab | /etc/hadoop/conf/yarn.keytab | yarn用户的 keytab 文件的位置 |
| yarn.nodemanager.container-executor.class | org.apache.hadoop.yarn.server.nodemanager.``LinuxContainerExecutor | 用于在yarn中启动应用程序的执行器类 |
| yarn.nodemanager.linux-containerexecutor.group | yarn | 执行 Linux 容器的组 |

对于 MapReduce(版本 1),TaskController类定义启动(和控制)哪个 Map 或 Reduce 任务,并使用一个名为task-controller.cfg的配置文件。该配置文件存在于 Hadoop 配置文件夹(/etc/hadoop/conf/)中,应该具有表 4-5 中列出的配置。

表 4-5 。TaskController配置

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| hadoop.log.dir | /var/log/hadoop-``0.20-mapreduce | Hadoop 日志目录(将因您的 Hadoop 发行版而异)。该位置用于确保存在写入日志文件的适当权限。 |
| mapreduce.``tasktracker.group | mapred | 任务跟踪器所属的组 |
| banned.users | mapred, hdfs,bin | 应该向其展示的用户运行 MapReduce |
| min.user.id | 1000 | 允许运行 MapReduce 任务的用户 ID |

这里有一个例子:

hadoop.log.dir=/var/log/hadoop-0.20-mapreduce/
mapred.local.dir=/opt/hadoop/hdfs/mapred/local
mapreduce.tasktracker.group=mapred
banned.users=mapred,hdfs,bin
min.user.id=500

请注意,min.user.id的值可能会因操作系统而异。一些操作系统使用 0 值而不是 500。

对于纱线,需要用表 4-6 中的配置定义containerexecutor.cfg

表 4-6 。纱线containerexecutor.cfg配置

|

属性名称

|

属性值

|

描述

|
| --- | --- | --- |
| yarn.nodemanager.log-dirs | /var/log/yarn | Hadoop 日志目录(将因您的 Hadoop 发行版而异)。该位置用于确保存在写入日志文件的适当权限。 |
| yarn.nodemanager.linux-containerexecutor.group | yarn | 容器所属的组 |
| banned.users | hdfs, yarn, mapred, bin | 运行 mapreduce 时应该显示的用户 |
| min.user.id | 1000 | 允许运行 MapReduce 任务的用户 ID |

最后一步,您必须在文件/etc/default/hadoop-hdfs-datanode中的所有 DataNodes 上设置以下变量。这些变量为 Jsvc 提供了必要的信息,Jsvc 是一组使 Java 应用程序更容易在 Unix 上运行的库和应用程序,因此它可以在安全模式下运行 DataNode。

export HADOOP_SECURE_DN_USER=hdfs
export HADOOP_SECURE_DN_PID_DIR=/var/lib/hadoop-hdfs
export HADOOP_SECURE_DN_LOG_DIR=/var/log/hadoop-hdfs
export JSVC_HOME=/usr/lib/bigtop-utils/

如果目录/usr/lib/bigtop-utils不存在,将JSVC_HOME变量设置为/usr/libexec/bigtop-utils,如下所示:

export JSVC_HOME=/usr/libexec/bigtop-utils

因此,最后,在安装、配置和实现了 Kerberos 并修改了各种 Hadoop 配置文件(带有 Kerberos 实现信息)之后,您就可以启动带有认证的 NameNode 和 DataNode 服务了!

使用认证启动 Hadoop 服务

首先启动 NameNode。以root的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start namenode";

NameNode 启动后,您可以在 NameNode 日志文件中看到与 Kerberos 相关的消息,表明使用 keytab 文件成功进行了认证(对于主体hdfshttp):

信息安全。用户组信息(用户组信息. Java:loginUserFromKeytab(844))-用户 hdfs/pract_hdp_sec@EXAMPLE.COM 使用 Keytab 文件/etc/hadoop/conf/hdfs.keytab 成功登录

2013-12-10 14:47:24288 信息服务器。KerberosAuthenticationHandler(KerberosAuthenticationHandler . Java:init(185))-使用 keytab/etc/Hadoop/conf/HDFS . keytab 登录,用于主体 HTTP/pract_hdp_sec@EXAMPLE.COM

现在启动 DataNode:以root的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start datanode"

在 DataNode 启动后,您可以在 DataNode 日志文件中看到以下与 Kerberos 相关的消息,这些消息指示使用 keytab 文件成功进行了认证(针对主体hdfs)

信息安全。用户组信息(用户组信息. Java:loginUserFromKeytab(844))-用户 hdfs/pract_hdp_sec@EXAMPLE.COM 使用 Keytab 文件/etc/hadoop/conf/hdfs.keytab 成功登录

2013-12-08 10:34:34587 信息 http。http server(http server . Java:addGlobalFilter(525))-添加了全局过滤器' safety '(class = org . Apache . Hadoop . http . http server $ QuotingInputFilter)

2013-12-08 10:34:35,502 信息数据节点。DataNode(blockpoolmanager . Java:doRefreshNamenodes(193))-为名称服务启动 BPOfferServices:

2013-12-08 10:34:35,554 信息数据节点。DataNode(bpserviceactor . Java:run(658))-块池(存储 id 未知)服务到 pract _ HDP _ sec/192 . 168 . 142 . 135:8020 开始提供服务

最后,启动 SecondaryNameNode。以root的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start secondarynamenode";

祝贺您,您已经成功地“kerberized 化”了 HDFS 服务!您现在也可以启动 MapReduce 服务了(您已经在 MapReduce 配置文件中设置了必要的主体和配置)。

请理解,我在本节中使用的命令可能会因操作系统(和 Hadoop 发行版)的版本而异。最好是查阅您的操作系统和 Hadoop 发行商的手册,以防出现任何错误或意外行为。

保护客户端-服务器通信

对于早期的 Hadoop 版本,当守护进程(或服务)相互通信时,它们不会验证另一个服务是否真的是它所声称的那样。因此,很容易启动一个流氓 TaskTracker 来访问数据块。模拟服务可以很容易地访问敏感数据、破坏数据或关闭集群!即使现在,除非您安装并配置了 Kerberos,并且加密了正确的通信协议,否则情况不会有很大的不同。对于 Hadoop 来说,保证进程间通信的安全是非常重要的。仅仅使用认证机制(比如 Kerberos)是不够的。您还必须保护 Hadoop 用于在其守护进程之间传输数据的所有通信方式,以及客户端和 Hadoop 集群之间的通信。

Hadoop 中的节点间通信使用 RPC、TCP/IP 和 HTTP 协议。具体来说,RPC(远程过程调用)用于 NameNode、JobTracker、DataNodes 和 Hadoop 客户端之间的通信。此外,客户端和 DataNodes 之间文件数据的实际读写使用 TCP/IP 协议,默认情况下该协议并不安全,这使得通信容易受到攻击。最后,HTTP 协议用于 web 控制台的通信,用于 NameNode/二级 NameNode 之间的通信,也用于 MapReduce shuffle 数据传输。除非受到保护,否则这种 HTTP 通信也容易受到攻击。

因此,您必须保护所有这些 Hadoop 通信,以便保护存储在 Hadoop 集群中的数据。你最好的选择是使用加密。恶意攻击者无法使用加密的数据,除非他们有解密的方法。您使用的加密方法取决于所涉及的协议。例如,为了加密 TCP/IP 通信,在 Hadoop 数据传输协议之上需要一个 SASL 包装器,以确保 Hadoop 客户端和 DataNode 之间的安全数据传输。Hadoop 的当前版本通过在配置文件core-site.xmlhdfs-site.xml中设置显式值来允许网络加密(结合 Kerberos)。为了保护使用 RPC 协议的 Hadoop 守护进程之间的进程间通信,您需要使用 SASL 框架。接下来的几节将进一步研究加密,从基于 RPC 的通信开始。

安全的进程间通信

Hadoop 中的进程间通信是通过 RPC 调用实现的。这包括 Hadoop 客户端和 HDFS 之间的通信,以及 Hadoop 服务之间的通信(例如,JobTracker 和 TaskTrackers 或 NameNode 和 DataNodes 之间的通信)。

SASL(简单认证和安全层)是认证框架,可用于保证客户端和服务器之间交换的数据被加密,并且不易受到“中间人”攻击(请参考第一章了解此类攻击的详细信息)。SASL 支持可用于不同上下文的多种认证机制(例如,MD5-DIGEST、GSSAPI、SASL 平原、CRAM-MD5)。

例如,如果您使用 Kerberos 进行认证,那么 SASL 会使用 GSSAPI(通用安全服务应用程序接口)机制来验证 Hadoop 客户端和 Hadoop 守护程序之间的任何通信。对于提交作业的安全 Hadoop 客户端(使用 Kerberos 进行认证),使用委托令牌认证,该认证基于 SASL MD5-DIGEST 协议。客户端向 NameNode 请求一个令牌,并将收到的令牌传递给 TaskTracker,并可以使用它与 NameNode 进行任何后续通信。

当您将 Hadoop 配置文件core-site.xml中的hadoop.rpc.protection属性设置为 privacy 时,RPC 上的数据将使用对称密钥加密。下面是 XML:

<property>
<name>hadoop.rpc.protection</name>
<value>privacy</value>
<description>authentication, integrity & confidentiality guarantees that data exchanged between client and server is encrypted
</description>
</property>

然而,加密是有代价的。如表 4-1 所述,将hadoop.rpc.protection设置为privacy意味着 Hadoop 执行完整性检查、加密和认证,所有这些额外的处理都会降低性能。

加密 HTTP 通信

Hadoop 将 HTTP 通信用于 web 控制台、NameNode/二级 NameNode 之间的通信以及 MapReduce(混洗数据)。对于 MapReduce 作业,数据通过 HTTP 协议在映射器和 Reducers 之间移动,这个过程称为 shuffle 。缩减器启动到映射器的连接,请求数据,并充当 SSL 客户端。下面将详细介绍启用 HTTPS 加密无序传输流量的步骤。

证书用于保护使用 HTTP 协议的通信。您可以使用 Java 实用工具 keytool 来创建和存储证书。证书存储在密钥库(文件)中,包含密钥(私钥和身份)或证书 (公钥和身份)。有关密钥库的其他详细信息,请参考第八章和附录 c。一个信任库文件包含来自可信来源的证书,由安全 HTTP (https)客户端使用。Hadoop HttpServer 使用密钥库文件。

创建 HTTPS 证书并将其分发到所有节点后,您可以为 HTTP 加密配置 Hadoop。具体来说,您需要通过在 Hadoop 配置文件hdfs-site.xml中将属性dfs.https.enable设置为true来在 NameNode 和所有 DataNodes 上配置 SSL。

大多数时候,SSL 被配置为只对服务器进行认证,这种模式被称为单向 SSL 。对于单向 SSL,您只需要在 NameNode(和每个 DataNode)上配置 KeyStore,使用表 4-7 中的所示的属性。这些参数在 NameNode 和每个 DataNodes 上的ssl-server.xml文件中设置。

您还可以配置 SSL 来验证客户端;这种模式被称为相互认证双向 SSL 。要配置双向 SSL,除了将属性dfs.https.enable设置为true之外,还要在 Hadoop 配置文件hdfs-site.xml中将属性dfs.client.https.need-auth设置为true(在 NameNode 和每个 DataNode 上)。

表 4-7 。加密 HTTP 通信的 SSL 属性

|

财产

|

缺省值

|

描述

|
| --- | --- | --- |
| ssl.server.keystore.type | jks | 密钥库文件类型 |
| ssl.server.keystore.location | NONE | 密钥库文件位置。mapred用户应该拥有这个文件,并拥有对它的独占读取权限。 |
| ssl.server.keystore.password | NONE | 密钥库文件密码 |
| ssl.server.truststore.type | jks | 信任库文件类型 |
| ssl.server.truststore.location | NONE | 信任库文件位置。mapred用户必须是具有独占读取权限的文件所有者。 |
| ssl.server.truststore.password | NONE | 信任库文件密码 |
| ssl.server.truststore.reload.interval | 10000 | 信任库重新加载间隔,以毫秒为单位 |

附录 C 详细介绍了如何设置用于 HTTP 加密的密钥库和信任库。

要配置加密混洗,需要在集群中所有节点的core-site.xml文件中设置表 4-8 中列出的属性。

表 4-8 。core-site.xml启用加密随机播放的属性(适用于 MapReduce)

|

财产

|

价值

|

说明

|
| --- | --- | --- |
| hadoop.ssl.enabled | true | 对于 MRv1,将该值设置为true将启用加密随机播放和加密 Web UI 功能。对于 MRv2,该属性只启用加密的 WebUI 如“加密 HTTP 通信”中所述,使用mapred-site.xml文件中的一个属性启用加密无序播放 |
| hadoop.ssl.require. client.cert | true | 当设置为true时,所有随机播放操作和用于访问 Web 用户界面的所有浏览器都需要客户端证书。 |
| hadoop.ssl.hostname. verifier | DEFAULT | 为HttpsURLConnections提供的主机名验证器。有效值为DEFAULTSTRICTSTRICT_I6DEFAULT_AND_LOCALHOSTALLOW_ALL。 |
| hadoop.ssl.keystores. factory.class | org.apache.hadoop.security. ssl.FileBasedKeyStoresFactory | 要使用的KeyStoresFactory实现。 |
| hadoop.ssl.server.conf | ssl-server.xml | 从中提取 SSL 服务器密钥库信息的资源文件。在类路径中查找该文件;通常它应该在/etc/hadoop/conf/目录中。 |
| hadoop.ssl.client.conf | ssl-client.xml | 从中提取 SSL 服务器密钥库信息的资源文件。在类路径中查找该文件;通常它应该在/etc/hadoop/conf/目录中。 |

要为 MRv2 启用加密混洗,请在集群中的每个节点上将mapred-site.xml文件中的属性mapreduce.shuffle.ssl.enabled设置为true

总而言之,要配置加密随机播放(针对 MapReduce 作业)和加密 Web 用户界面,需要使用/修改以下配置文件:

  • core-site.xml / hdfs-site.xml:启用 HTTP 加密,定义实现
  • mapred-site.xml:启用 MRv2 的加密洗牌
  • ssl-server.xml:存储服务器的密钥库和信任库设置
  • ssl-client.xml:存储客户端的密钥库和信任库设置

保护数据通信

客户端和 DataNodes 之间的数据传输(读/写)使用 Hadoop 数据传输协议。因为这里没有使用 SASL 框架进行认证,所以如果数据传输需要安全或加密,则需要 SASL 握手包装器。这个包装器可以通过在配置文件hdfs-site.xml中将属性 dfs.encrypt.data.transfer 设置为 true 来启用。当启用 SASL 包装器时,NameNode 会生成一个数据加密密钥,并将其传递给 DataNodes 和客户端。客户端使用该密钥作为任何后续通信的凭证。NameNode 和 DataNodes 使用它来验证客户端通信。

如果您对想要用于加密的实际算法有偏好,可以使用属性dfs.encrypt.data.transfer.algorithm来指定。可能的值是3desrc4(默认值通常是 3DES。)3DES 或“三重 DES”是流行的对称密钥算法 DES 的变体,它使用三个密钥(而不是 DES 使用的单个密钥)来增强协议。你用一个密钥加密,用第二个解密,用第三个加密。该过程给出了相当于 112 位密钥(而不是 DES 的 56 位密钥)的强度,并使加密更强,但速度较慢(由于加密需要多次迭代)。有关 DES 协议的更多详细信息,请参考第八章中的。RC4 是另一种对称密钥算法,与 3DES 相比,它执行加密的速度快得多,但具有潜在的不安全性(微软和思科都在逐步淘汰这种算法,并向用户提供了避免使用它的明确指南)。

请注意,由于 RPC 协议用于向客户端发送数据加密密钥,因此有必要在配置文件core-site.xml中将hadoop.rpc.protection设置配置为privacy(客户端和服务器都适用),以确保密钥本身的传输是加密和安全的。

摘要

在本章中,您学习了如何从客户端开始,为您的 Hadoop 集群建立整体安全性或“防护”。目前,PuTTY 为保护您的客户端提供了最好的开源选项。我讨论了使用密钥对和密码短语,而不是我们熟悉的登录/密码。原因很简单——让恶意攻击更难突破您的安全。每个人都使用过 PuTTY,但是很多时候他们没有考虑底层技术和使用一些可用选项的原因。我曾试图阐明腻子的这些方面。

我不确定麻省理工学院开发 Kerberos 时是否考虑了 Hadoop 但是目前 Kerberos 和 Hadoop 的使用可能会让你有不同的想法!同样,这是(到目前为止)Hadoop 认证最流行的替代方案。

对于非 Java 人员来说,处理密钥库和信任库总是有点困难。如果你需要另一个例子,附录 C 将帮助你进一步理解这些概念。

使用 SASL 协议进行 RPC 加密和加密数据传输协议的底层技术是复杂的主题。本章中实现安全集群的例子仅仅是为了介绍这个主题。

你从这里去哪里?既然您的群集外围已经安全,那么这项工作是否已经完成?肯定不是!这就是它开始的地方——它通过指定更详细的授权来进一步保护您的集群。那是下一章的主题。

五、实现粒度授权

设计细粒度的授权让我想起了一个故事,一位著名的银行经理被一次对他的保险箱的抢劫所困扰。银行经理非常不安,他立即为金库设置了多层安全和密码。第二天,客户要求他打开保险库。经理在极度兴奋中忘记了密码,保险库不得不被强行打开(当然是合法的)。

您可能会发现,设计细粒度的安全性是一个棘手的问题。太多的安全和太少的安全一样会适得其反。没有什么魔法可以让它变得恰到好处。如果您分析了所有流程(包括手动和自动流程)并对数据进行了很好的分类,您就可以确定谁需要访问哪些特定资源以及需要什么级别的访问权限。这就是细粒度授权的定义:每个用户都拥有对必要资源的正确访问级别。微调 Hadoop 安全性以允许由功能需求驱动的访问将使您的 Hadoop 集群更不容易受到黑客和未授权访问的攻击,而不会牺牲可用性。

在本章中,您将学习如何确定安全需求(基于应用程序),然后研究如何使用目录和文件级权限为应用程序设计高级安全性和细粒度授权。为了说明这一点,我将带您看一个修改过的真实世界的例子,这个例子涉及交通罚单数据以及警察、法院和报告机构对这些数据的访问。本章最后讨论了如何使用 Apache Sentry 实现细粒度的授权,并回顾了交通票据的例子,以突出 Sentry 在 Hive 中的使用,Hive 是一个与 HDFS 协同工作的数据库。在本章结束时,你将会对如何设计细粒度授权有一个很好的理解。

设计用户授权

定义细粒度授权的细节是一个多步骤的过程。这些步骤是:

  1. 分析你的环境,
  2. 对数据进行分类以便访问,
  3. 确定谁需要访问什么数据,
  4. 确定必要的访问级别,以及
  5. 实现您设计的安全模型。

下面几节将通过这个完整的过程来定义真实场景中的细粒度授权。

打电话给警察:一个真实世界的安全例子

几年前我为芝加哥警察局做过一些工作,涉及到该部门的票务系统。该系统基本上有三个部分:警车上的移动控制台,当地警察局的本地数据库,以及芝加哥市中心警察总部的中央数据库。为什么微调授权在这种情况下很重要?考虑一下没有它的潜在滥用:例如,如果 it 部门拥有对数据的修改权限,某个既得利益者可以修改特定票据的数据。最初的系统是使用 Microsoft SQL Server 开发的,但是对于我的例子,我将针对 Hadoop 环境重新设计它。同时,您还将了解 Hadoop 实现与基于关系数据库的实现有何不同。

分析和分类数据

第一步是检查和分析所涉及的系统(或应用程序)。此外,审查系统的高级目标和用例有助于阐明访问需求。在考虑用例时,不要忘记维护、备份和灾难恢复。系统概述是一个很好的起点,回顾所涉及的手动过程也是如此(按照逻辑顺序)。在这两种情况下,您的目标是了解每个流程中的功能需求,了解流程之间的交互方式,确定每个流程中生成的数据,并跟踪这些数据是如何传递给下一个流程的。图 5-1 说明了一个系统的分析。

9781430265443_Fig05-01.jpg

图 5-1 。分析系统或应用程序

在我的例子中,第一个过程是由警官(签发罚单的人)生成罚单数据。这些数据被传输到当地警察局的数据库中,显然,检票员、他或她在警察局的主管以及警察总部的上层管理人员都需要拥有修改权限。

当地警察局的其他警察需要读取这些数据的权限,因为他们可能想要查看在特定日期开出的所有罚单或一个人的驾驶历史,同时决定是开罚单还是只开警告。因此,警官在当地警察局数据库(当天)以及位于警察总部的中央数据库中查找罚单数据(使用司机的社会安全号码或 SSN)。

作为第二个过程,来自当地警察局(来自整个芝加哥地区)的罚单数据每晚被传送到警察总部的中央数据库。

第三个也是最后一个过程是每天晚上为所有警察局的主管自动生成每日报告。这些报告汇总了当天的票证活动,由报告用户(由 IT 创建)运行。

票证数据的详细信息

这个票据数据不是一个单独的实体,而是一组包含所有数据的相关实体。理解保存这些数据的数据库的设计将有助于设计详细的安全级别。

两个,或者 Hadoop 术语中的文件,保存所有的票数据。正如表被用来在关系数据库中存储数据一样,HDFS 使用文件。在这种情况下,假设 Hadoop 将数据存储为逗号分隔的文本文件。(当然,Hadoop 支持多种格式来存储数据,但是一个简单的例子有助于更好地理解这些概念。)表格和文件详情汇总在图 5-2 中。

9781430265443_Fig05-02.jpg

图 5-2 。票证数据的详细信息:信息的分类和表格与文件的存储

第一个表Driver_details,保存司机的所有个人信息:合法全名、SSN、当前地址、电话号码等等。第二个表Ticket_details包含罚单的详细信息:罚单编号、司机的 SSN、违规代码、签发官员等等。

此外,这些表彼此“相关”。关系符号表明每个司机(在Driver_details中出现)可能有一张或多张他名下的票,细节在Ticket_details中。罚单怎么会和司机有关系?通过使用 SSN。SSN 是主键(表示为 PK )或Driver_details表的唯一标识符,因为 SSN 唯一地标识一个驱动程序。然而,由于一个司机可能有多张票,SSN 不是Ticket_details表的唯一标识符,仅用于将票关联到一个司机(表示为 FK外键)。

请理解,票证数据示例非常简单,只是演示了如何使用粒度权限。此外,它还做出了以下假设:

  • 该示例使用 Hadoop 2.x,因为我们需要向所有数据文件追加数据,而早期版本不支持追加。当地警察局当天的所有罚单将在每晚附加到位于警察总部的适当数据文件中。
  • 记录不会被更新,但状态标志将用于指示活动记录(最近的记录被标记为活动的,较早的记录被标记为非活动的)。
  • 没有对记录的并发修改。
  • 在写入数据时没有会损害系统完整性的故障。
  • 功能需求是,只有警官(签发罚单的人)、警官的主管和更高级别的管理人员应该有权修改罚单,但是这种期望的粒度在 HDFS 中是不可能的!为此需要使用 Hive 或另一个 NoSQL 数据库。目前,我只是给所有警察提供了修改权。然而,在下一节中,您将学习如何使用 Hive 和 Sentry 来重新实现这个示例,以达到期望的粒度。

生产系统可能要复杂得多,需要更复杂的设计来保证有效的安全性。

回到我们的例子,我们如何设计角色来保护票据数据并根据需要提供访问?我们的设计必须满足所有的功能需求(对于系统内的所有过程),而不提供太多的访问(由于数据的敏感性)。本节的下一部分将解释如何实现。

确定访问组及其访问级别

根据三个流程的功能需求,车票数据需要读写(修改)访问权限。接下来的问题是,哪些组需要哪些权限(图 5-3 )?三个子组需要对此数据的部分读写权限;称他们为第一组:

  • 出票警官
  • 当地警察主管
  • 总部的高级管理层

9781430265443_Fig05-03.jpg

图 5-3 。使用详细的访问权限对票证数据进行分组访问

第 2 组,警察总部的 IT 部门,需要读取权限。图 5-3 说明了这种访问。

表 5-1 列出了权限。

表 5-1 。组和实体的权限详细信息(表)

|

桌子

|

第一组

|

第二组

|
| --- | --- | --- |
| Driver_details | 读/写 | 阅读 |
| Ticket_details | 读/写 | 阅读 |

因此,总结、分析和分类您的数据,然后确定需要访问数据适当部分的逻辑组。有了这些认识,您就可以设计用于定义细粒度授权的角色,并确定这些角色所需的权限组。

逻辑设计(即使是像票务系统这样非常高级的例子)也必须导致物理实现。只有这样,你才能有一个有效的系统。下一节重点介绍实现该示例设计的细节。

实现安全模型

实现安全模型是一个多步骤的过程。一旦您很好地理解了角色及其权限需求,您就可以开始了。以下是要遵循的步骤:

  1. 安全的数据存储。
  2. 根据需要创建用户和组。
  3. 分配所有权、组和权限。

理解一些关于 Hadoop 文件权限的基本事实将在这个过程中帮助你。

Hadoop 中的票证数据存储

对于票务系统的例子,我将从在 HDFS 实现数据存储开始。正如您之前看到的,Hadoop 中的数据存储在文件Driver_detailsTicket_details中。这些文件位于 Hadoop 的根数据目录下,如图图 5-4 所示。为了更好地理解该图,考虑一些关于 HDFS 文件权限的基本事实。

9781430265443_Fig05-04.jpg

图 5-4 。HDFS 目录和文件权限

  • HDFS 文件有三组权限,分别针对所有者、组和其他人。使用十个字符的字符串来指定权限,比如-rwxrwxrwx
  • 第一个字符表示目录或文件(-表示文件或d表示目录),接下来的三个字符表示文件所有者的权限,接下来的三个表示所有者的组,最后三个表示其他组。
  • 任何分组的可能值是r(读权限)、w(写权限)、x(执行权限)或(占位符)。注意x只对可执行文件或目录有效。

在图 5-4 中,文件Driver_detailsticket_details的所有者(root)拥有rw-权限,即读写权限。接下来的三个字符是组的权限(意味着属于该文件所属组的所有用户,在本例中为hdfs)。组的权限为rw-,表示所有组成员对该文件都有读写权限。最后三个字符表示对其他人的权限(不拥有该文件且不属于该文件所属的同一组的用户)。对于这个例子,其他人只有读权限(r--)。

添加 Hadoop 用户和组以实现文件权限

作为实现该系统基本授权的最后一步,我需要在 Hadoop 中定义适当的用户和组,并调整文件权限。

首先,我为这个服务器创建了与示例中的两个组相对应的组:组 1 称为POfficers,组 2 称为ITD

[root@sandbox ~]# groupadd POfficers
[root@sandbox ~]# groupadd ITD

列出并验证组是一个好主意:

[root@sandbox ~]# cut –d: -f1 /etc/group | grep POfficers

我还为组POfficers创建了用户Puser,为组ITD创建了用户Iuser:

[root]# useradd Puser –gPOfficers
[root]# useradd Iuser –gITD

接下来,我设置了密码:

[root]# passwd Puser
Changing password for user Puser.
New password:
Retype password:
Passwd: all authentication tokens updated successfully.

现在,作为最后一步,我分配所有者和组来实现权限。在图 5-5 中可以看到,文件Driver_detailsTicket_details的所有者被更改为虚拟用户Puser,组权限被设置为写;因此来自组POfficers(所有警察)的用户将拥有读/写权限,来自其他组的用户(即 IT 部门)将只有读取权限。

9781430265443_Fig05-05.jpg

图 5-5 。更改 HDFS 文件的所有者和组

将表 5-1 与所有实体(HDFS 同名文件)的最终权限进行比较,你会发现目标已经达到:Puser拥有文件Driver_detailsTicket_details,属于组POfficers(组 1)。权限-rw-rw-r--表示组 1 中的任何一个用户都有读/写权限,而属于任何其他组(例如组 2)的用户只有读权限。

这个例子让您对 Hadoop 集群的微调授权有了一个基本的了解。不幸的是,现实世界是复杂的,我们不得不与之打交道的系统也是如此!所以,为了让事情更真实一点,我将扩展这个例子,你可以看到在票旁边发生了什么。

扩展票证数据

罚单只来自警方。最终,法院会介入进一步处理罚单。因此,一些票据数据需要与司法系统共享。该组需要读取以及修改数据的某些部分的权利,但只有在罚单通过交通法院处理后。此外,机票数据的某些部分需要与报告机构共享,报告机构根据需要将这些数据提供给保险公司、征信机构和其他国家实体。

这些假设不会改变基本组,但将需要两个新的组:一个用于司法机构(组 3),另一个用于报告机构(组 4)。现在权限结构看起来像图 5-6 。

9781430265443_Fig05-06.jpg

图 5-6 。使用详细的访问权限对票证数据进行分组访问,显示新的组

随着功能和组的增加,数据也必须增加。例如,表Judgement_details将包含罚单的司法历史,比如案件日期、最终判决、罚单支付细节等等。Hadoop 将以相同的名称将该表存储在一个文件中(图 5-7 )。

9781430265443_Fig05-07.jpg

图 5-7 。票证数据的详细信息—信息分类—增加了法律详细信息表

像图 5-2 ,图 5-7 也说明了如果关系数据库用于存储,数据将如何保存在表格中。这只是为了比较 Hadoop 中的数据存储和关系数据库系统中的数据存储。正如我前面所讨论的,存储在关系数据库系统中的数据是相关的:司机数据(Driver_details表)与票据数据(Ticket_details表)相关,使用 SSN 来关联或链接数据。使用附加表(Judgement_details),票据的法院判决再次使用 SSN 与驾驶员和票据细节相关或链接。

众所周知,Hadoop 使用文件来存储数据。所以,就 Hadoop 而言,有一个额外的数据文件用于存储与司法相关的数据— Judgement_details。没有关联或链接存储在多个文件中的数据的概念。当然,您可以通过编程的方式链接数据,但是 Hadoop 不会自动为您这样做。当您在 HDFS 存储数据时,了解这种差异非常重要。

添加一个表也会改变权限结构,正如你在表 5-2 中看到的。

表 5-2 。组和实体的权限详细信息

Table5-2.jpg

添加新的组增加了可能的权限排列,但无助于解决复杂的权限需求(请参考“使用 Apache Sentry 进行基于角色的授权”一节,以了解如何实现粒度权限)。例如,如果警察部门只希望出票官员和车站负责人拥有车票的书面许可,该怎么办?在图 5-7 和表 5-2 中定义的组显然不能用于实现这一要求。针对如此复杂的需求,Hadoop 提供了访问控制列表(ACL),与 Unix 和 Linux 使用的 ACL 非常相似。

HDFS 的访问控制列表

根据 HDFS 权限模型,对于任何文件访问请求,HDFS 会针对最适用的特定用户类别实现权限。例如,如果请求者是文件所有者,则检查所有者类权限。如果请求者是拥有该文件的组的成员,则检查组类权限。如果请求者不是文件所有者或文件所有者组的成员,则检查其他类权限。

这种权限模型适用于大多数情况,但不是所有情况。例如,如果所有警察、IT 部门经理和负责管理票务系统的系统分析师都需要对Ticket_detailsDriver_details文件的写权限,那么现有的四个组不足以实现这些安全要求。您可以创建一个名为Ticket_modifiers的新所有者群组,但是保持群组成员的最新状态可能会有问题,因为人员变动(人们更换工作),以及由手动错误或疏忽导致的错误或不适当的权限。

用于限制对数据的访问,ACL 在您的权限需求复杂且具体的情况下提供了一个非常好的替代方案。因为 HDFS 使用与 Linux 相同的(基于 POSIX 的)权限模型,所以 HDFS ACL 是模仿 Unix 和 Linux 已经使用了很长时间的 POSIX ACLs。Apache Hadoop 2.4.0 以及所有其他主要供应商的发行版中都提供了 ACL。

除了文件的所有者和组之外,您还可以使用 HDFS ACL 为特定用户或组定义文件权限。但是,对文件使用 ACL 确实会导致 NameNode 使用额外的内存,因此您的最佳实践是为特殊情况保留 ACL,并为常规安全实现使用个人和组所有权。

要使用 ACL,您必须首先在 NameNode 上启用它们,方法是将以下配置属性添加到hdfs-site.xml并重新启动 NameNode:

<property>
<name>dfs.namenode.acls.enabled</name>
<value>true</value>
< /property>

启用 ACL 后,HDFS CLI(命令行界面)中会添加两个新命令:setfaclgetfaclsetfacl命令分配权限。通过它,我可以为票务示例的 it 经理(ITMgr)和分析师(ITAnalyst)设置读写权限:

> sudo -u hdfs hdfs dfs -setfacl -m user:ITMgr:rw- /Driver_details
> sudo -u hdfs hdfs dfs -setfacl -m user:ITAnalyst:rw- /Driver_details

使用getfacl,我可以验证权限:

> hdfs dfs -getfacl /Driver_details
# file: /Driver_details
# owner: Puser
# group: POfficers
user::rw-
user:ITAnalyst:rw-
user:ITMgr:rw-
group::r--
mask::rw-
other::r--

当 ACL 被启用时,文件列表显示a + in权限:

> hdfs dfs -ls /Driver_details
-rw-rw-r--+ 1 Puser POfficers 19 2014-09-19 18:42 /Driver_details

您可能会遇到需要对目录中的所有文件或目录中的所有子目录和文件应用特定权限的情况。在这种情况下,您可以为目录指定默认 ACL,该 ACL 将自动应用于该目录中所有新建的子文件和子目录:

> sudo -u hdfs hdfs dfs -setfacl -m default:group:POfficers:rwx /user

验证权限显示已应用默认设置:

> hdfs dfs -getfacl /user

# file: /user
# owner: hdfs
# group: hdfs
user::rwx
group::r-x
other::r-x
default:user::rwx
default:group::r-x
default:group:POfficers:rwx
default:mask::rwx
default:other::r-x

请注意,在我们的简单示例中,我为来自组POfficers的所有用户保留了rw-访问权限,因此 ACL 实际上没有限制任何内容。在现实世界的应用程序中,我很可能会将组POfficers的访问权限限制为比批准的 ACL 定义的用户更少(可能只是读权限)。

请注意hdfs将默认 ACL 仅应用于新创建的子目录或文件;默认 ACL 的应用或对父目录的默认 ACL 的后续更改不会自动应用到现有子目录或文件的 ACL。

您还可以使用 ACL 来阻止特定用户对目录或文件的访问,而不会意外撤销任何其他用户的权限。假设一名分析师已被调到另一个部门,因此不再有权访问票据信息:

> sudo -u hdfs hdfs dfs -setfacl -m user:ITAnalyst:--- /Driver_details

验证更改:

> hdfs dfs -getfacl /Driver_details

# file: /Driver_details
# owner: Puser
# group: POfficers
user::rw-
user:ITAnalyst:---
user:ITMgr:rw-
group::r--
mask::rw-
other::r--

有效使用 ACL 的关键是了解用户访问 HDFS 文件时 ACL 条目的评估顺序。权限按以下顺序评估和实现:

  1. 如果用户拥有该文件,则强制实现所有者权限。
  2. 如果用户有 ACL 条目,则这些权限将被强制执行。
  3. 如果用户是(文件所有权)组的成员,则使用这些权限。
  4. 如果某个组有一个 ACL 条目,并且用户是该组的成员,则使用这些权限。
  5. 如果用户是文件组或任何其他具有拒绝访问文件的 ACL 条目的组的成员,则用户被拒绝访问(文件)。如果用户是多个组的成员,则对所有匹配条目实现权限联合。
  6. 最后,如果没有其他权限适用,则使用组others的权限。

总而言之,HDFS ACL 对于实现复杂的权限需求或向特定用户或组提供不同于文件所有权的权限非常有用。但是,请记住,要明智地使用 ACL,因为带有 ACL 的文件会导致 NameNode 占用更多的内存。如果您确实计划使用 ACL,请确保在确定 NameNode 内存大小时考虑到这一点。

基于角色的 Apache Sentry 授权

Sentry 是一个为存储在 HDFS 的数据提供基于角色的授权的应用程序,由 Cloudera 开发并提交给 Apache Hadoop 社区。它提供了与关系数据库非常相似的细粒度授权。在撰写本文时,Sentry 是为存储在 HDFS 的数据提供 RBAC(基于角色的授权控制)的最成熟的开源产品,尽管 Hortonworks (Argus)的另一个项目是一个挑战者。Sentry 目前与 Hive(由 Apache 软件基金会提供的数据库/数据仓库)和 Impala(由 Cloudera 开发的查询引擎,受谷歌 Dremel 的启发)合作。

Hive 架构和授权问题

Hive 是一个与 HDFS 合作的数据库。它的查询语言在语法上非常类似于 SQL,这也是它受欢迎的原因之一。需要记住的数据库的主要方面如下:

  • Hive 将数据组织成熟悉的数据库概念,如表、行、列和分区。
  • Hive 支持原始数据类型:整数、浮点数、双精度数和字符串。
  • 配置单元表是 HDFS 目录(和其中的文件)。
  • 分区(对于配置单元表)是“表”HDFS 目录中的子目录。
  • 配置单元权限存在于数据库或表级别,可以授予用户、组或角色。
  • 配置单元权限包括 select(读取)、update(修改数据)和 alter(修改元数据)。

然而,Hive 并不完美。它使用存储库(Metastore)来存储与表相关的元数据,因此,如果直接更改底层 HDFS 对象的权限,可能会出现表元数据和 HDFS 权限不匹配的情况。Hive 没有能力阻止或识别这种情况。因此,通过用户的操作系统用户或组,用户可能被授予对某个表的 select 权限,但对 HDFS 内的相应目录/文件具有 update 或 write 权限。此外,Hive 无法为表数据的特定部分或部分表数据提供权限。无法提供列级权限、定义视图(用于更精细的数据访问控制)或定义服务器级角色。

Sentry 解决了其中的一些问题。它提供了服务器、数据库和表级别的角色,并且可以使用 Hive 外部表—您可以使用这些表对用户进行部分数据访问控制。

图 5-8 展示了 Hive 的架构以及它与 HDFS 的关系。

9781430265443_Fig05-08.jpg

图 5-8 。Hive 体系结构及其授权

哨兵建筑

作为一个集成了 Hive 和 Impala 的安全模块,Sentry 提供了高级授权控制,能够更安全地访问 HDFS 数据。我们将关注 Sentry 与 Hive 的集成(因为它的使用更广泛)。Sentry 使用规则为数据库对象指定精确的权限,并使用角色来组合或合并规则,从而可以轻松地对不同数据库对象的权限进行分组,同时提供为各种类型的权限创建规则的灵活性(如选择或插入)。

为哨兵创建规则和角色

Sentry 使用规则授予精确的控制权,以指定用户对数据库、模式或表中数据子集的访问。例如,如果数据库db1有一个名为Employee的表,那么为Insert提供访问的规则可以是:

server=MyServer->db=db1->table=Employee->action=Insert

一个角色是一组访问配置单元对象的规则。各个规则用逗号分隔,并分组形成一个角色。

例如,Employee_Maint角色可以指定为:

Employee_Maint = server=Myserver->db=db1->table=Employee->action=Insert, \
server=server1->db=db1->table=Employee_Dept->action=Insert, \
server=server1->db=db1->table=Employee_salary->action=Insert

这里,Employee_Maint角色允许任何用户(拥有该角色)在表EmployeeEmployee_DeptEmployee_salary中插入行。

基于角色的授权简化了权限管理,因为管理员可以根据其组织内的职能角色为权限分组创建模板。

多部门管理使中央管理员能够委托单个管理员使用数据库级角色管理每个独立数据库或模式的安全设置。例如,在下面的代码中,DB2_Admin角色授权数据库db2的所有权限,而Svr_Admin授权服务器MyServer的所有权限:

DB2_Admin = server=MyServer->db=db2
Svr_Admin = server=MyServer

在 Sentry 中创建规则和角色只是第一步。如果要使用角色,需要将角色分配给用户和组。Sentry 如何识别用户和群组?下一节将对此进行解释。

了解 Sentry 中的用户和组

用户是由认证子系统认证并被允许访问 Hive 服务的人。因为该示例假设正在使用 Kerberos,所以用户将是 Kerberos 主体。一个是被授予一个或多个授权角色的一个或多个用户的集合。Sentry 目前支持 HDFS 支持的组和本地配置的组(在配置文件policy.xml中)。例如,考虑policy.xml中的以下条目:

Supervisor = Employee_Maint, DB2_Admin

如果Supervisor是一个 HDFS 支持的组,那么属于这个组的所有用户都可以执行角色Employee_MaintDB2_Admin允许的任何 HiveQL 语句。但是,如果Supervisor是一个本地组,那么属于这个组的用户(称他们为ARobertsMHolding)必须在文件policy.xml中定义:

[users]
ARoberts = Supervisor
MHolding = Supervisor

图 5-9 展示了 Sentry 在带有 Kerberos 认证的 Hadoop 架构中的位置。

9781430265443_Fig05-09.jpg

图 5-9 。使用 Sentry 的 Hadoop 授权

总的来说,在回顾了 Hive 和 Sentry 架构之后,您已经了解了它们各自提供的安全范围。您已经简要了解了如何设置规则、角色、用户和组。因此,您现在已经准备好重新实现本章前面部分定义的票务系统(使用 Sentry)。

实现角色

在用适当的规则、角色、用户和组重新实现票务系统之前,花点时间回顾一下它的功能需求。罚单是由开罚单的警察开出的。罚单数据存储在当地警察局的数据库中,所有警察都需要有修改权限。位于警察总部的 IT 部门需要对这些数据的读取权限,以便进行报告。一些罚单数据由司法系统共享,他们需要对部分数据的读取和修改权限,因为数据在罚单通过交通法院处理后被修改。最后,这些数据的某些部分需要与报告机构共享,这些报告机构根据需要向保险公司、征信机构和其他国家机构提供这些数据。表 5-3 总结了这些要求;更多细节,请参考图 5-7 。

表 5-3 。组和实体的权限详细信息

Table5-3.jpg

最初使用 HDFS 文件权限的实现很简单,但是没有考虑以下问题:

  • 创建票证时,会自动创建一个司法记录(案例),其中包含父记录ticket_id(指明该案例属于哪个票证)和案例详细信息。警察应该有权将该记录插入到包含罚单详细信息的Judgement_details表中,但不允许修改判决和其他案件详细信息的列。文件权限不够灵活,无法实现这一要求。
  • (为案例分配的)法官应该对包含案例详细信息的列拥有修改权限,但不应该对包含票证详细信息的列拥有修改权限。还是那句话,文件权限处理不了这个。

要实现这些需求,您需要 Sentry(或其等价物)。然后,使用 Hive,您需要创建具有相关列的外部表(司法人员或警察需要写访问的列),并为适当的部门提供对这些外部表的写访问,而不是对Ticket_detailsJudgement_details表的写访问。

对于此示例,假设集群(用于实现)运行的是 CDH4.3.0 (Cloudera Hadoop 发行版 4.3.0)或更高版本,并且安装了带有 Kerberos 认证的 HiveServer2。

作为第一步,您需要进行一些配置更改。将配置单元仓库目录(/user/hive/warehouse或配置单元配置文件hive-site.xml中为属性hive.metastore.warehouse.dir指定的任何其他路径)的所有权更改为用户hive和组hive。将仓库目录的权限设置为770 (rwxrwx---),即所有者和组的读、写、执行权限;但是对于others或不属于组hive的用户没有权限。您可以在hive-site.xml中将属性hive.warehouse.subdir.inherit.perms设置为true,以确保子目录上的权限也将被设置为770。接下来,将属性hive.server2.enable.doAs更改为false。这将作为运行服务Hiveserver2的用户执行所有查询。最后,在配置文件taskcontroller.cfg中将属性min.user.id设置为0。这是为了确保hive用户可以提交 MapReduce 作业。

完成这些配置更改后,您就可以设计必要的表、规则、角色、用户和组了。

设计表格

您需要创建表 Driver_detailsTicket_detailsJudgement_details,以及一个外部表Judgement_details_PO,如下所示:

CREATE TABLE Driver_details (SocialSecNum STRING,
Last Name STRING,
First Name STRING,
Address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>,
Phone BIGINT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Driver_details";

CREATE TABLE Ticket_details (TicketId BIGINT,
DriverSSN STRING,
Offense STRING,
Issuing Officer STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Ticket_details";

CREATE TABLE Judgement_details (CaseID BIGINT,
TicketId BIGINT,
DriverSSN STRING,
CaseDate STRING,
Judge STRING,
Judgement STRING,
TPaymentDetails STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Judgement_details";

CREATE EXTERNAL TABLE Judgement_details_PO (CaseID BIGINT,
TicketId BIGINT,
DriverSSN STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/user/hive/warehouse/Judgement_details";

如果你参考图 5-5 中的,你会发现我使用了相同的列(就像我们在 Hadoop 文件或表格中使用的一样)来创建这些表格,并且只是根据需要替换数据类型(例如,Last Name是一个字符串,或者数据类型STRING;但是TicketId是大整数还是BIGINT。最后一个表Judgement_details_PO被创建为 Hive 外部表,这意味着 Hive 只管理这个表的元数据,而不管理实际的数据文件。我创建这个表作为外部表,表的前两列是Judgement_details,因为我需要某些资源来拥有只修改这两列的权限——而不是那个表中的其他列。

设计规则

我需要设计规则来提供实现票务系统所需的安全性。该示例有四个表,各种角色将需要读取(选择)或修改(插入)权限,因为没有对 Hive 或 HDFS 数据的“更新”。我将简单地追加(或插入)记录的新版本。所以,规则如下:

server=MyServer->db=db1->table=Driver_details->action=Insert
server=MyServer->db=db1->table=Ticket_details->action=Insert
server=MyServer->db=db1->table=Judgement_details->action=Insert
server=MyServer->db=db1->table=Judgement_details_PO->action=Insert
server=MyServer->db=db1->table=Driver_details->action=Select
server=MyServer->db=db1->table=Ticket_details->action=Select
server=MyServer->db=db1->table=Judgement_details->action=Select

这些规则只是对所有表执行选择或修改操作。

设计角色

让我们使用我们创建的规则来设计角色。第一个角色是所有警察:

PO_role = server=Myserver->db=db1->table= Driver_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Insert, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details_PO ->action=Insert

请注意,该角色允许所有警官对表Driver_detailsTicket_details拥有读/写权限,但只对Judgement_details拥有读权限。理由是警察不应该被允许改变判决的细节。您还将观察到警察拥有对Judgement_details_PO的写权限,这是为了纠正前两列(没有任何司法信息)——以防有任何错误!

下一个角色是 IT 部门的员工:

IT_role = server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select

IT 员工对所有的表只有读权限,因为他们不允许修改任何数据。

司法机构的作用如下:

JU_role = server=MyServer->db=db1->table= Judgement_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select

judiciary 拥有驾驶员和票证数据的读取权限(因为他们不应该修改这些数据),但拥有输入司法数据的写入权限,因为只有他们才可以修改这些数据。

最后,对于报告机构来说,作用很简单:

RP_role = server=MyServer->db=db1->table=Judgement_details->action=Select

报告机构拥有对Judgement_details表的读取权限,只是因为他们被允许报告判决。所有其他数据都是保密的,他们对此没有任何权限。

设置配置文件

我必须为 Sentry 设置各种配置文件,以整合我们之前设置的角色。第一个文件是sentry-provider.ini,它定义了每个数据库的策略文件(及其位置)、任何服务器级或数据库级角色,以及 Hadoop 组及其分配的(服务器级或数据库级)角色。下面是sentry-provider.ini如何寻找我们的例子:

[databases]
# Defines the location of the per DB policy file for the db1 DB/schema
db1 = hdfs://Master:8020/etc/sentry/customers.ini

[groups]
# Assigns each Hadoop group to its set of roles
db1_admin = db1_admin_role
admin = admin_role

[roles]
# Implies everything on MyServer -> db1\. Privileges for
# db1 can be defined in the global policy file even though
# db1 has its only policy file. Note that the Privileges from
# both the global policy file and the per-DB policy file
# are merged. There is no overriding.
db1_admin_role = server=MyServer->db=db1

# Implies everything on server1
admin_role = server=MyServer

在本例中,数据库db1 ( customers.ini)有一个特定的策略文件,并使用其位置进行定义。定义了服务器和数据库db1的管理员角色(admin_roledb1_admin_role)。适当的 Hadoop 组(db1_adminadmin)被分配给这些管理员角色。

下一个文件是db1.ini。它是数据库db1的每个数据库的策略文件:

[groups]
POfficers = PO_role
ITD = IT_role
Judiciary = JU_role
Reporting = RP_role

[roles]
PO_role = server=MyServer->db=db1->table= Driver_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Insert, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details_PO ->action=Insert

IT_role = server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select

JU_role = server=MyServer->db=db1->table= Judgement_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select

RP_role = server=MyServer->db=db1->table=Judgement_details->action=Select

注意上面我已经在roles部分定义了所有的角色(之前设计的)。groups部分将 Hadoop 组映射到定义的角色。现在,我之前建立了 Hadoop 组POfficersITD。我将需要建立两个额外的组(JudiciaryReporting),因为我在db1.ini文件中为它们映射了角色。

最后一步是设置哨兵配置文件sentry-site.xml:

<configuration>
  <property>
    <name>hive.sentry.provider</name>
    <value>org.apache.sentry.provider.file.HadoopGroupResourceAuthorizationProvider</value>
  </property>

  <property>
    <name>hive.sentry.provider.resource</name>
    <value>hdfs://Master:8020/etc/sentry/authz-provider.ini</value>
  </property>

  <property>
    <name>hive.sentry.server</name>
    <value>Myserver</value>
  </property>
</configuration>

最后,要启用 Sentry,我们需要向hive-site.xml添加以下属性:

<property>
<name>hive.server2.session.hook</name>
<value>org.apache.sentry.binding.hive.HiveAuthzBindingSessionHook</value>
</property>

<property>
<name>hive.sentry.conf.url</name>
<value>hdfs://Master:8020/etc/sentry-site.xml</value>
</property>

这就结束了使用 Apache Sentry 的票务系统示例的重新实现。为我们的票务系统指定正确的授权级别是可能的,因为 Sentry 允许我们定义规则和角色,在必要时限制对数据的访问。如果没有这种灵活性,要么分配太多的访问权限,要么没有访问权限。

摘要

作为为数不多的为 Hadoop 数据提供基于角色的授权的应用程序之一,Sentry 是一个相对较新的版本,仍处于萌芽状态。尽管如此,它在实现基于角色的安全性方面还是提供了一个良好的开端,尽管它远不能与现有的关系数据库技术所提供的安全性相媲美。诚然,Sentry 在提供可与 Oracle 或 Microsoft SQL Server 相媲美的产品方面还有很长的路要走,但目前它是为数不多的可用选项之一。这也是为什么最佳实践是用 Hive 的一些特性来补充哨兵功能的原因!

您可以使用 Hive 来补充和扩展 Sentry 的功能。例如,在票务示例中,我使用 Hive 的外部表特性来创建一个角色,该角色只对表的某些列提供写权限。Sentry 本身不能提供对表的部分写权限,但是您可以将它与 Hive 结合使用来提供这样的权限。我鼓励您研究其他有用的 Hive 特性,并创建自己的角色来扩展 Sentry 的功能。位于https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL的 Apache 文档提供了许多有用的建议

最后,本章的票务示例证明了您可以通过在 Hive 中定义一个外部表来为角色提供部分数据访问(从第一列开始的列数)。有趣的是,对于一个使用 Sentry 的表,您不能只提供对某些列的访问(例如第四至第八列)。当然,使用 Hive 提供的特性,还有其他方法来实现这样的请求!

六、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 说明了它们在框架中的位置。

9781430265443_Fig06-01.jpg

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

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

记录器

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

Log4j 的日志记录级别

Log4j API 有七个日志记录级别。它们按照严重性顺序记录信息,每个级别都包含所有更高的级别。例如,日志级别INFO包括信息性消息、警告(包括更高级别的WARN)、非致命错误(包括更高级别的ERROR)和致命错误(包括更高级别的FATAL)。类似地,日志级别WARN包括警告、非致命错误和致命错误。图 6-2 总结了这些内含物。

9781430265443_Fig06-02.jpg

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

七个日志级别如下:

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

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

记录器继承

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

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

9781430265443_Fig06-03.jpg

图 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 定义了记录器。

9781430265443_Fig06-04.jpg

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

图 6-5 是来自log4j.properties的 HDFS 审计记录器的示例条目。

9781430265443_Fig06-05.jpg

图 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 列出了结果。

9781430265443_Fig06-06.jpg

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

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

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

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

9781430265443_Fig06-07.jpg

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

在图 6-7 中,我将RollingFileAppender与 HDFS 审计记录器一起使用。输出按照布局(PatternLayout)和定义的转换模式格式化(我稍后将讨论布局和转换模式),如下所示:

2014-02-09 16: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

Image 注意 HDFS 审计输出可能会产生一个大文件。因此,每天或按大小将它回滚到一个新文件是一个好主意。

布局

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

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

布局使用转换模式来格式化和输出日志消息。转换模式由格式修饰符和转换字符组成。例如,修饰符t输出生成日志事件的线程的名称,转换字符%5p使用五个字符显示(或写入)日志级别,在左边填充空格。因此,日志级别INFO显示(或写入)为"INFO"

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

9781430265443_Fig06-08.jpg

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

图 6-8 中的转换图形%d{ISO8601} %p %c{2}: %m%n输出为:

2014-01-27 20: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 CONSOLE
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.layout=org.apache.log4j.TTCCLayout
    #configuring the Layout TTCCLayout
    log4j.appender.CONSOLE.layout.ThreadPrinting=false
    log4j.appender.CONSOLE.layout.ContextPrinting=false
    log4j.appender.CONSOLE.layout.CategoryPrefixing=false
    log4j.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 审计事件:

9781430265443_Fig06-09.jpg

图 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 审计配置的部分。

9781430265443_Fig06-10.jpg

图 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-07 08: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-06 22:26:08,280 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy (auth:SIMPLE) ip=/127.0.0.1 cmd=getfileinfo
    src=/Ticketing/Ticket_details_20140220
          dst=null perm=null
    
    2014-03-06 22: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-06 22:27:02,666 INFO FSNamesystem.audit: allowed=true ugi=RogueITGuy
    (auth:SIMPLE) ip=/127.0.0.1 cmd=open
          src=/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-06 22:42:36,948 INFO
    org.apache.hadoop.hive.metastore.HiveMetaStore.audit: ugi=RogueITGuy
    ip=/127.0.0.1 cmd=source:/127.0.0.1 get_table : db=default tbl=ticket_details
    
    2014-03-06 22:42:37,184 INFO
    org.apache.hadoop.hive.metastore.HiveMetaStore.audit: ugi=RogueITGuy
    ip=/127.0.0.1 cmd=source:/127.0.0.1 append_partition: db=default
    tbl=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-06 22:28:01,590 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0008 RESULT=SUCCESS
2014-03-06 22:42:07,415 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0009 RESULT=SUCCESS
2014-03-06 22:45:55,399 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0010 RESULT=SUCCESS
2014-03-06 22:47:39,380 INFO mapred.AuditLogger: USER=RogueITGuy IP=127.0.0.1
        OPERATION=SUBMIT_JOB TARGET=job_201403042158_0011 RESULT=SUCCESS
2014-03-06 22: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_00010job_201403042158_0011job_201403042158_0012是没有修改任何数据的精选语句,但是乔布斯job_201403042158_0008job_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 所示的条目。

9781430265443_Fig06-11.jpg

图 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=getfileinfojob_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-06 22: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-06 22: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=null

2014-03-06 22: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-06 22:28:01,394 INFO org.apache.hadoop.mapred.JobInProgress: job_201403042158_0008: nMaps=1 nReduces=0 max=-1

2014-03-06 22:28:01,764 INFO org.apache.hadoop.mapred.JobInProgress: Input size for job job_201403042158_0008 = 74\. Number of splits = 1

2014-03-06 22:28:01,765 INFO org.apache.hadoop.mapred.JobInProgress: tip:task_201403042158_0008_m_000000 has split on node:/default/localhost.localdomain

2014-03-06 22:28:01,765 INFO org.apache.hadoop.mapred.JobInProgress: Job job_201403042158_0008 initialized successfully with 1 map tasks and 0 reduce tasks.

2014-03-06 22: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)以了解运行特定守护程序和端口的主机的详细信息。文件名可能因发行版而异,但日志文件的名称中会有TaskTrackerJobTracker,使它们易于识别。

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

9781430265443_Fig06-12.jpg

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

如果使用 YARN,那么对应的守护进程是 ResourceManager(而不是 JobTracker)和 NodeManager(而不是 TaskTracker)。请检查纱线配置文件(yarn-site.xml)中的网络访问端口(mapreduce.johistory.webapp.addressyarn.resourcemanager.webapp.address的值)。例如,在图 6-13 的中,资源管理器使用端口 8088。

9781430265443_Fig06-13.jpg

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

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

9781430265443_Fig06-14.jpg

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

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

9781430265443_Fig06-15.jpg

图 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 )。

9781430265443_Fig07-01.jpg

图 7-1 。简单监控系统

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

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

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

Hadoop 监控系统

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

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

9781430265443_Fig07-02.jpg

图 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 指标的上下文

Table7-1.jpg

早期版本的 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 with names starting with Cluster2

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

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

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

# This will filter out Metrics with names 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 分布式监控系统。

9781430265443_Fig07-03.jpg

图 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.confgmetad.confhadoop-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 with this 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 with server 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 使用率、内存使用率和网络使用率。从控制面板中,您可以选择任何这些资源的详细图表,或者为您需要的特定指标创建自定义图表。

9781430265443_Fig07-04.jpg

图 7-4 。神经节仪表盘

Image 神经节在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 生成的网页,显示关于被监控资源的概要信息。

9781430265443_Fig07-05.jpg

图 7-5 。Nagios 架构

Image 注意 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 说明了这个过程。

9781430265443_Fig07-06.jpg

图 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_heartbeatcheck_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 6 2014 05: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$是经常使用的宏。宏也可以使用\(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_heartbeatcheck_multiple_metrics插件已经就位,并由 Nagios 管理。

9781430265443_Fig07-07.jpg

图 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 次。在最后一个循环完成后,执行最终的转置(与初始置换相反)以完成算法。

9781430265443_Fig08-01.jpg

图 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. 添加循环密钥:最后,对这个循环唯一的密钥(子密钥)的一部分进行异或运算或添加到每个数据列。子密钥是通过对密钥进行一系列置换、替换和异或运算而从密钥中得到的。

9781430265443_Fig08-02.jpg

图 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 位),因式分解 P e 来解密加密的明文几乎是不可能的。选择解密密钥 d 使得(Pe)dmodn=P。因此,知道 d 的合法接收者可以简单地确定(Pe)dmodn=P,从而恢复 P ,而不需要因式分解 P e 。加密算法基于分解大数的基本问题,该问题没有简单或快速的解决方案。

如何确定加密密钥?如果你的明文是 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 总结了该过程。

9781430265443_Fig08-03.jpg

图 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.pathhive.server2.keystore.password来指定密钥库)。因此,本章重点介绍静态配置 Hadoop 数据。

Image 注意加密是一项 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 提供了加密过程的概述。

9781430265443_Fig08-04.jpg

图 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) image配置image安全image密钥管理在集群中分发创建的密钥库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

9781430265443_Fig08-05.jpg

图 8-5 。AWS 管理控制台

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

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

9781430265443_Fig08-06.jpg

图 8-6 。AWS 的信封加密

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

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

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

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

通过 AWS 创建 S3 存储

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

9781430265443_Fig08-07.jpg

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

为您创建的文件夹test指定服务器端加密(图 8-8 )。

9781430265443_Fig08-08.jpg

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

根据需要调整先前创建的存储桶htestbucket的权限(图 8-9 )。

9781430265443_Fig08-09.jpg

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

创建一个密钥对(bclkey)用于认证

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

9781430265443_Fig08-10.jpg

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

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

这些密钥用作加密的凭证,并与用户相关联。如果您没有创建任何用户,并且正在使用 AWS 的root帐户,那么您需要为root创建这些密钥。从身份和访问管理(IAM)管理控制台 ( 图 8-11 ),选择 Dashboard,然后点击第一个选项,删除您的根访问密钥。(如果你没有为root创建这些键,你不会看到这个警告)。要访问 IAM 控制台,请在 AWS 管理控制台上选择服务“身份&访问管理”。

9781430265443_Fig08-11.jpg

图 8-11 。AWS 的 IAM 控制台

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

9781430265443_Fig08-12.jpg

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

你的 AWS root账户就像一个 UNIX root账户,AWS 不建议使用它。相反,根据需要创建具有角色、权限和访问密钥的用户帐户。如果这样做,您可以更容易地自定义权限,而不会影响安全性。关于使用root账户,另一件要记住的事情是,如果你丢失了访问密钥 ID 或秘密访问密钥,你将无法找回它们!因此,我创建了一个用户Bhushan,用于我的 EMR 集群(图 8-13 )。我使用身份和访问管理(IAM)管理控制台中的“用户”选项和“创建新用户”按钮(图 8-11 )来创建这个新用户。

9781430265443_Fig08-13.jpg

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

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

Image 注意当您创建访问密钥 ID 和秘密访问密钥时,您可以下载它们并将其保存在安全的地方作为备份。采取这种预防措施肯定比在丢失钥匙的情况下重新创建一套钥匙容易。

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

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

9781430265443_Fig08-14.jpg

图 8-14 。创建 EMR 集群

在硬件配置部分(图 8-15 ,请求一个主 EC2 实例运行 JobTracker 和 NameNode,请求一个核心 EC2 实例运行 TaskTrackers 和 DataNodes。(这只是为了测试;在现实世界中,根据您所需的处理能力,您需要获得多个主实例或核心实例。)在 Security Access 部分,指定前面创建的密钥对之一(bclkey),而在 IAM Roles 部分,为 EMR 角色设置EMR_DefaultRoleEMR_EC2_DefaultRole。确保这些角色有权访问 S3 存储(存储桶和文件夹)以及您需要使用的任何其他资源。

9781430265443_Fig08-15.jpg

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

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

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

9781430265443_Fig08-16.jpg

图 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/10 03:27:47 INFO s3distcp.S3DistCp: Running with args: -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/10 03:27:51 INFO client.RMProxy: Connecting to ResourceManager at
14/10/10 03:27:54 INFO mapreduce.Job: The url to track the job: http://10.232.45.82:9046/proxy/application_1412889867251_0001/
14/10/10 03:27:54 INFO mapreduce.Job: Running job: job_1412889867251_0001
14/10/10 03:28:12 INFO mapreduce.Job: map 0% reduce 0%
....
....
14/10/10 03:30:17 INFO mapreduce.Job: map 100% reduce 100%
14/10/10 03:30:18 INFO mapreduce.Job: Job job_1412889867251_0001 completed successfully

显然,MapReduce 作业成功地将文件复制到了 S3 存储。现在,您需要验证文件是否加密存储在 S3。为此,使用 S3 管理控制台并检查存储桶htestbucket中文件夹test内文件test1的属性(图 8-17 )。

9781430265443_Fig08-17.jpg

图 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 总结了通用步骤。

9781430265443_Fig08-18.jpg

图 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 说明了选择和添加密钥。

9781430265443_AppA-01.jpg

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

当您选择一个密钥时(此处为testkey.ppk,系统会提示您输入密码短语(图 A-2 )。

9781430265443_AppA-02.jpg

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

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

9781430265443_AppA-03.jpg

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

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

9781430265443_AppA-04.jpg

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

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

9781430265443_AppA-05.jpg

图 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 所示。

9781430265443_AppA-06.jpg

图 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 )。

9781430265443_AppB-01.jpg

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

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

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

9781430265443_AppB-02.jpg

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

使用 SSH 进行远程访问

您还可以使用 SSH 远程连接到主机。如果您想使用一个密钥对通过 SSH 进行认证,首先需要使用一个名为 ssh-keygen 的实用程序来生成密钥。默认情况下,密钥以文件id_rsa(私钥)和id_rsa.pub(公钥)的形式保存在$HOME/.ssh目录中。图 B-3 显示了在默认位置生成的不带密码短语的密钥对(您可以指定一个密码短语以增加安全性)。

9781430265443_AppB-03.jpg

图 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

十一、附录 C:为 HTTP 加密设置密钥库和信任库

一个密钥库是一个数据库或密钥和证书库,用于各种目的,包括认证、加密或数据完整性。一般来说,密钥库包含两种类型的信息:密钥条目和可信证书。

我已经在第四章的“加密 HTTP 通信”一节中讨论了如何用网络加密配置您的 Hadoop 集群。作为设置的一部分,您需要创建 HTTPS 证书和密钥库。

创建 HTTPS 证书和密钥库/信任库文件

要创建 HTTPS 证书和密钥库,您需要执行以下步骤:

  1. 对于每个主机,在SKEYLOC创建一个目录来存储密钥库和信任库(您可以根据自己的喜好替换目录名)。

  2. For each host, create a key pair and a separate KeyStore. If your operating system command prompt is $, you have set the SKEYLOC directory parameter, and assuming an example of a two-node cluster with hosts pract_hdp_sec and pract_hdp_sec2, the necessary code would look like the following:

    $ cd $SKEYLOC
    
    $ keytool -genkey -alias pract_hdp_sec -keyalg RSA -keysize 1024 –dname "CN=pract_hdp_sec,OU=IT,O=Ipsos,L=Chicago,ST=IL,C=us" -keypass 12345678 -keystore phsKeyStore1 -storepass 87654321
    
    $ keytool -genkey -alias pract_hdp_sec2 -keyalg RSA -keysize 1024 -dname "CN=pract_hdp_sec2,OU=IT,O=Ipsos,L=Chicago,ST=IL,C=us" -keypass 56781234 -keystore phsKeyStore2 –storepass 43218765
    
    

    这段代码生成两个密钥对(一个公钥和相关的私钥)和单元素证书链,分别存储为密钥库phsKeyStore1中的条目pract_hdp_sec和密钥库phsKeyStore2中的条目pract_hdp_sec2。请注意,RSA 算法用于公钥加密,密钥长度为 1024。

  3. 对于每台主机,将证书的公钥导出到单独的证书文件:

    $cd $SKEYLOC;
    $keytool -export -alias pract_hdp_sec -keystore phsKeyStore1 -rfc -file pract_hdp_sec_cert -storepass 87654321
    $keytool -export -alias pract_hdp_sec2 -keystore phsKeyStore2 -rfc -file pract_hdp_sec2_cert -storepass 43218765
    
    
  4. For all the hosts, import the certificates into TrustStore file:

    $cd $SKEYLOC;
    $keytool -import -noprompt -alias pract_hdp_sec -file pract_hdp_sec_cert -keystore phsTrustStore1 -storepass 4324324
    $keytool -import -noprompt -alias pract_hdp_sec2 -file pract_hdp_sec2_cert -keystore phsTrustStore1 -storepass 4324324
    
    

    注意,信任库文件是新创建的,以防它不存在。

  5. 将密钥库和信任库文件复制到相应的节点:

    $scp phsKeyStore1 phsTrustStore1 root@pract_hdp_sec:/etc/hadoop/conf/
    $scp phsKeyStore2 phsTrustStore2 root@pract_hdp_sec2:/etc/hadoop/conf/
    
    
  6. 验证通用信任库文件:

    $keytool -list -v -keystore phsTrustStore1 -storepass 4324324
    
    

调整密钥库/信任库文件的权限

Keystore 文件只需要拥有所有者和组的读取权限,组应该设置为hadoop。信任库文件应该对每个人(所有者、组和其他人)都有读取权限。以下命令对此进行了设置:

$ssh root@pract_hdp_sec "cd /etc/hadoop/conf;chgrp hadoop phsKeyStore1;
chmod 0440 phsKeyStore1;chmod 0444 phsTrustStore1

$ssh root@pract_hdp_sec2 "cd /etc/hadoop/conf;chgrp hadoop phsKeyStore2;
chmod 0440 phsKeyStore2;chmod 0444 phsTrustStore2

如果需要,您可以生成公钥证书安装在您的浏览器中。这就完成了 HTTP 加密的密钥库和信任库的设置。

十二、附录 D:Hadoop 指标及其与安全性的相关性

在第七章的“Hadoop 指标”部分,您回顾了什么是 Hadoop 指标,如何对指标应用过滤器,以及如何将它们定向到文件或监控软件,如 Ganglia。您将很快了解到,您也可以将这些指标用于安全性。

您应该记得,您可以使用 Hadoop 指标来设置警报,以捕捉系统资源中的突然变化。此外,您可以设置 Hadoop 集群来监控 NameNode 资源,并在任何指定的资源偏离所需参数时生成警报。例如,我将向您展示当以下资源的偏差超过月平均值 50%或更多时,如何生成警报:

FilesCreated
FilesDeleted
Transactions_avg_time
GcCount
GcTimeMillis
LogFatal
MemHeapUsedM
ThreadsWaiting

首先,我将 NameNode 指标输出到一个文件中。为此,我将下面几行添加到目录$HADOOP_INSTALL/hadoop/conf中的文件hadoop-metrics2.properties中:

*.sink.tfile.class=org.apache.hadoop.metrics2.sink.FileSink
namenode.sink.tfile.filename = namenode-metrics.log

接下来,我设置过滤器只包含必要的指标:

*.source.filter.class=org.apache.hadoop.metrics2.filter.GlobFilter
*.record.filter.class=${*.source.filter.class}
*.metric.filter.class=${*.source.filter.class}
namenode.sink.file.metric.filter.include=FilesCreated
namenode.sink.file.metric.filter.include=FilesDeleted
namenode.sink.file.metric.filter.include=Transactions_avg_time
namenode.sink.file.metric.filter.include=GcCount
namenode.sink.file.metric.filter.include=GcTimeMillis
namenode.sink.file.metric.filter.include=LogFatal
namenode.sink.file.metric.filter.include=MemHeapUsedM
namenode.sink.file.metric.filter.include=ThreadsWaiting

我过滤后的指标列表现在正被写入输出文件namenode-metrics.log

接下来,我开发了一个脚本,每天将这个文件加载到 HDFS,并将其作为一个新分区添加到一个 Hive 表中。然后,我重新计算 30 天的平均值,同时考虑新的值,并将平均值与新加载的每日值进行比较。

如果这些值的偏差超过 50%,我可以向我的 Hadoop 系统管理员发送一条消息,告知该节点的名称和偏离的指标。然后,系统管理员可以检查适当的日志,以确定是否存在任何安全漏洞。例如,如果ThreadsWaiting指标偏离超过 50%,那么系统管理员将需要检查审计日志,以查看当时谁在访问集群以及谁在执行作业,然后检查审计日志指示的相关作业。例如,一个可疑的作业可能需要检查 JobTracker 和适当的 TaskTracker 日志。

或者,您可以将这些作业的输出定向到 Ganglia,然后使用 Nagios 在任何指标值出现偏差时生成警报。

表 D-1 到 D-4 列出了一些常用的 Hadoop 指标。首先列出 JVM 和 RPC 上下文指标,因为它们是由所有 Hadoop 守护进程生成的。

表 D-1 。JVM 和 RPC 上下文度量

|

度量组

|

度量名称

|

描述

|
| --- | --- | --- |
| 虚拟机(Java Virtual Machine 的缩写) | GcCount | 企业控制台 JVM 的垃圾收集数量 |
|   | GcTimeMillis | 计算所有垃圾收集花费的总时间(以毫秒为单位) |
|   | LogError | 出现 Log4j 级别错误的日志行数 |
|   | LogFatal | Log4j 级别致命的日志行数 |
|   | LogWarn | Log4j 级别警告的日志行数 |
|   | LogInfo | 包含 Log4j 级别信息的日志行数 |
|   | MemHeapCommittedM | 计算企业控制台 JVM 提交的堆内存 |
|   | MemHeapUsedM | 计算企业控制台 JVM 提交的堆内存 |
|   | ThreadsBlocked | 处于阻塞状态的线程数,这意味着它们正在等待锁 |
|   | ThreadsWaiting | 处于等待状态的线程数,这意味着它们正在等待另一个线程执行某个操作 |
|   | ThreadsRunnable | 在 JVM 中执行但可能正在等待系统资源(如 CPU)的处于可运行状态的线程数 |
|   | ThreadsTerminated | 处于终止状态的线程数,这意味着它们已完成执行。该值应该大约为零,因为该指标仅收集活动线程的信息。 |
|   | ThreadsNew | 处于新状态的线程数,这意味着它们尚未启动 |
| 位置遥控(remote position control) | ReceivedBytes | RPC 接收的字节数 |
|   | SentBytes | RPC 发送的字节数 |
|   | RpcProcessingTimeAvgTime | 处理 RPC 请求的平均时间 |
|   | RpcProcessingTimeNumOps | 已处理的 RPC 请求数 |
|   | RpcQueueTimeAvgTime | RPC 请求在队列中花费的平均时间 |
|   | RpcQueueTimeNumOps | 排队的 RPC 请求数 |
|   | RpcAuthorizationSuccesses | 成功的 RPC 授权调用数 |
|   | RpcAuthorizationFailures | 失败的 RPC 授权调用数 |
|   | RpcAuthenticationSuccesses | 成功的 RPC 认证调用的次数 |
|   | RpcAuthenticationFailures | 失败的 RPC 认证调用数 |

表 D-2。NameNode 和 DataNode 指标

|

度量组

|

度量名称

|

描述

|
| --- | --- | --- |
| Hadoop.HDFS.NameNode | AddBlockOps | 群集的添加块操作数 |
|   | CapacityRemaining | HDFS 剩余的总产能 |
|   | CapacityTotal | HDFS 和其他分布式文件系统中剩余的总容量 |
|   | CapacityUsed | HDFS 使用的总容量 |
|   | CreateFileOps | 群集的创建文件操作次数 |
|   | DeadNodes | 群集中存在的死节点数 |
|   | DecomNodes | 群集中存在的退役节点的数量 |
|   | DeleteFileOps | 在 HDFS 发生的“删除”文件操作的数量 |
|   | FSState | NameNode 的状态,可以是安全模式或操作模式 |
|   | FileInfoOps | 群集中发生的文件访问操作的数量 |
|   | FilesAppended | 集群中附加的文件数量 |
|   | FilesCreated | 群集中创建的文件数量 |
|   | FilesDeleted | 群集中删除的文件数 |
|   | FilesInGetListingOps | 群集中发生的获取列表操作的数量 |
|   | FilesRenamed | 群集中重命名的文件数 |
|   | LiveNodes | 群集中活动节点的数量 |
|   | NonDfsUsedSpace | 计算群集中使用的非 HDFS 空间 |
|   | PercentRemaining | 剩余 HDFS 容量的百分比 |
|   | PercentUsed | 已用 HDFS 容量的百分比 |
|   | Safemode | 计算安全模式状态:1 表示安全模式开启;0 表示安全模式关闭 |
|   | SafemodeTime | 显示 NameNode 在安全模式下花费的时间 |
|   | Syncs_avg_time | 同步操作的平均时间 |
|   | Syncs_num_ops | 同步操作的次数 |
|   | TotalBlocks | 簇中的总块数 |
|   | TotalFiles | 群集中的文件总数 |
|   | Transactions_avg_time | 交易的平均时间 |
|   | Transactions_num_ops | 交易操作的数量 |
|   | UpgradeFinalized | 指示升级最终确定为真还是假 |
|   | addBlock_avg_time | 在集群中创建新块的平均时间 |
|   | addBlock_num_ops | 在集群中添加数据块的操作次数 |
|   | blockReceived_avg_time | 接收块操作的平均时间 |
|   | blockReceived_num_ops | 块接收操作的数量 |
|   | blockReport_num_ops | 块报告操作的数量 |
|   | blockReport_avg_time | 块报告操作的平均时间 |
|   | TimeSinceLastCheckpoint | 计算自上次检查点以来的时间 |
| Hadoop.HDFS.DataNode | BlocksRead | 从硬盘读取块的次数,包括复制块 |
|   | BlocksRemoved | DataNode 上已删除或失效的块数 |
|   | BlocksReplicated | 从一个 DataNode 传输或复制到另一个 DataNode 的块数 |
|   | BlocksVerified | 块验证的次数,包括成功或失败的尝试 |
|   | BlocksWritten | 写入磁盘的块数 |
|   | BytesRead | 读取和复制块时读取的字节数 |
|   | BytesWritten | 为响应接收到的块而写入磁盘的字节数 |
|   | HeartbeatsAvgTime | 从 DataNode 向 NameNode 发送心跳的平均时间 |
|   | BlocksRemoved | DataNode 上已删除或失效的块数 |
|   | BlocksReplicated | 从一个 DataNode 传输或复制到另一个 DataNode 的块数 |
|   | HeartbeatsNumOps | 群集中发生的心跳操作的数量 |

表 D-3。JobTracker 生成的 MapReduce 度量

|

度量组

|

度量名称

|

描述

|
| --- | --- | --- |
| Hadoop.Mapreduce.Jobtracker | blacklisted_maps | 每个任务跟踪者中列入黑名单的地图槽的数量 |
|   | Heartbeats | JobTracker 检测信号的总数 |
|   | blacklisted_reduces | 每个 TaskTracker 中列入黑名单的 reduce 槽的数量 |
|   | callQueueLen | 计算 RPC 调用队列长度 |
|   | HeartbeatAvgTime | 心跳的平均时间 |
|   | jobs_completed | 已完成作业的数量 |
|   | jobs_failed | 失败的作业数 |
|   | jobs_killed | 被终止的作业数量 |
|   | jobs_running | 正在运行的作业数量 |
|   | jobs_submitted | 提交的作业数量 |
|   | maps_completed | 已完成地图的数量 |
|   | maps_failed | 失败地图的数量 |
|   | maps_killed | 被杀死的地图数量 |
|   | maps_launched | 已启动地图的数量 |
|   | memNonHeapCommittedM | 非堆提交的内存(MB) |
|   | memNonHeapUsedM | 非堆使用的内存(MB) |
|   | occupied_map_slots | 已占用地图位置的数量 |
|   | map_slots | 地图位置的数量 |
|   | occupied_reduce_slots | 已占用的缩减插槽数量 |
|   | reduce_slots | 缩减插槽的数量 |
|   | reduces_completed | 完成的减速器数量 |
|   | reduces_failed | 失败的减速器数量 |
|   | reduces_killed | 死亡人数减少 |
|   | reduces_launched | 投放的减速器数量 |
|   | reserved_map_slots | 保留的映射槽数量 |
|   | reserved_reduce_slots | 保留的缩减插槽数量 |
|   | running_0 | 正在运行的作业数量 |
|   | running_1440 | 运行时间超过 24 小时的作业数 |
|   | running_300 | 运行时间超过五小时的作业数 |
|   | running_60 | 运行超过一小时的作业数 |
|   | running_maps | 运行地图的数量 |
|   | running_reduces | 跑步次数减少 |
|   | Trackers | TaskTrackers 数量 |
|   | trackers_blacklisted | 列入黑名单的 TaskTrackers 数量 |
|   | trackers_decommissioned | 退役的 TaskTrackers 数量 |
|   | trackers_graylisted | 灰色列表任务跟踪器的数量 |
|   | waiting_reduces | 等待次数减少 |
|   | waiting_maps | 等待地图的数量 |

表 D-4 。h 基本指标

|

度量组

|

度量名称

|

描述

|
| --- | --- | --- |
| hbase.master | MemHeapUsedM | 使用的堆内存(MB) |
|   | MemHeapCommittedM | 提交的堆内存(MB) |
|   | averageLoad | 每个区域服务器服务的平均区域数 |
|   | numDeadRegionServers | 死区服务器的数量 |
|   | numRegionServers | 在线区域服务器的数量 |
|   | ritCount | 转型区域的数量 |
|   | ritCountOverThreshold | 超过由属性rit.metrics.threshold.time定义的阈值的过渡区域的数量 |
|   | clusterRequests | 从所有区域服务器到群集的请求总数 |
|   | HlogSplitTime_mean | 分割预写日志文件总大小的平均时间 |
|   | HlogSplitTime_min | 分割预写日志文件总大小的最短时间 |
|   | HlogSplitTime_max | 重新启动后分割预写日志文件的最长时间 |
|   | HlogSplitTime_num_ops | 分割预写日志文件的时间 |
|   | HlogSplitSize_mean | 分割 Hlog 文件总大小的平均时间 |
|   | HlogSplitSize_min | 分割 Hlog 文件总大小的最短时间 |
|   | HlogSplitSize_max | 分割 Hlog 文件总大小的最长时间 |
|   | HlogSplitSize_num_ops | 被拆分的预写日志文件的大小 |
| hbase.regionserver | appendCount | WAL 附加的数量 |
|   | blockCacheCount | 块缓存中缓存的存储文件数 |
|   | blockCacheEvictionCount | 已从块缓存中收回的块的总数 |
|   | blockCacheFreeSize | 块缓存中空闲的字节数 |
|   | blockCacheExpressHitPercent | 计算打开缓存的请求的块缓存命中率 |
|   | blockCacheHitCount | 请求的块缓存命中总数,不考虑缓存设置 |
|   | blockCountHitPercent | 不管缓存设置如何,所有请求的块缓存命中率 |
|   | blockCacheMissCount | 请求的块缓存未命中总数,不考虑缓存设置 |
|   | blockCacheSize | 缓存块使用的字节数 |
|   | compactionQueueLength | CompactionQueue 上的 HRegions 数。这些区域对所有存储调用 compact,然后确定是否需要压缩以及压缩的类型。 |
|   | MemMaxM | 计算使用的总堆内存(MB) |
|   | MemHeapUsedM | 计算使用的堆内存(MB) |
|   | MemHeapCommittedM | 计算提交的堆内存(MB) |
|   | GcCount | 垃圾收集总数 |
|   | updatesBlockedTime | 为了刷新内存存储而被阻止的内存存储更新的数量 |
|   | memstoreSize | 以 MB 为单位计算所有区域中所有内存的大小 |
|   | readRequestCount | 区域服务器读取请求的数量 |
|   | regionCount | 区域服务器服务的在线区域数量 |
|   | slowAppendCount | 花费 1000 毫秒以上完成的追加数 |
|   | slowGetCount | 完成时间超过 1000 毫秒的获取数 |
|   | slowPutCount | 花费超过 1000 毫秒完成的 put 数 |
|   | slowIncrementCount | 完成时间超过 1000 毫秒的增量数 |
|   | slowDeleteCount | 完成时间超过 1000 毫秒的删除数 |
|   | storeFileIndexSize | 以 MB 为单位计算所有存储文件索引的大小。这些不一定在内存中,因为它们也存储在块缓存中,可能已经被收回。 |
|   | storeFileCount | 所有商店和地区的商店文件数量 |
|   | storeCount | 所有地区的商店数量 |
|   | staticBloomSize | 计算所有布隆过滤器的总大小,这些过滤器不一定加载到内存中 |
|   | writeRequestCount | 对区域服务器的写入请求数 |
|   | staticIndexSize | 计算所有区域服务器实体的总静态索引大小 |

第一部分:Hadoop 及其安全性简介

第二部分:在您的 Hadoop 集群中进行认证和授权

第三部分:审核日志记录和安全监控

第四部分:Hadoop 加密

第五部分:附录

posted @ 2024-08-13 14:29  绝不原创的飞龙  阅读(17)  评论(0编辑  收藏  举报