Hadoop 安全实践指南(三)
十一、附录 C:为 HTTP 加密设置密钥库和信任库
一个密钥库是一个数据库或密钥和证书库,用于各种目的,包括认证、加密或数据完整性。一般来说,密钥库包含两种类型的信息:密钥条目和可信证书。
我已经在第四章的“加密 HTTP 通信”一节中讨论了如何用网络加密配置您的 Hadoop 集群。作为设置的一部分,您需要创建 HTTPS 证书和密钥库。
创建 HTTPS 证书和密钥库/信任库文件
要创建 HTTPS 证书和密钥库,您需要执行以下步骤:
-
对于每个主机,在
SKEYLOC创建一个目录来存储密钥库和信任库(您可以根据自己的喜好替换目录名)。 -
For each host, create a key pair and a separate KeyStore. If your operating system command prompt is
$, you have set theSKEYLOCdirectory parameter, and assuming an example of a two-node cluster with hostspract_hdp_secandpract_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。 -
对于每台主机,将证书的公钥导出到单独的证书文件:
$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 -
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注意,信任库文件是新创建的,以防它不存在。
-
将密钥库和信任库文件复制到相应的节点:
$scp phsKeyStore1 phsTrustStore1 root@pract_hdp_sec:/etc/hadoop/conf/ $scp phsKeyStore2 phsTrustStore2 root@pract_hdp_sec2:/etc/hadoop/conf/ -
验证通用信任库文件:
$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 | 计算所有区域服务器实体的总静态索引大小 |