行业资讯
在k8s集群环境部署高可用的Apache Hadoop3.1.1定制版集群
Hadoop 3.1.1 on Kubernetes — 生产级 HA 部署与运维指南版本v4NameNode HA YARN HA 全栈生产验证日期2026-07-24开发者腾讯workbuddy腾讯hy3大模型实际部署命名空间hadoop本文命令统一用-n hadoop要部署到其他命名空间必须改 configmap 里的 FQDN web-ui-access 的 namespace 字段详见 §16不能只改-n架构NN HAActive/Standby JournalNode ZooKeeper ZKFC YARN HA双 ResourceManager ZKRMStateStore 3× DataNode 3× NodeManager验证状态NN HA、YARN HA、K8s 三必改坑、Web UI 访问、以及「杀 active RM 运行中作业零中断」的真 failover 均已实测通过见第 9 节。缺陷resourcemanager和nodemanager的web界面偶发异常受限主角色随机分配pod仅web界面展示功能偶发无法正常访问。下载资源https://atomgit.com/zhudev2026/hadoop-deploy高可用部署需参考目录v41. 架构概述1.1 组件清单组件数量存储作用NameNode2 PodActive Standbyopenebs-hostpath 50GiHDFS 元数据ZKFC 自动故障切换JournalNode3 Podopenebs-hostpath 20Gi共享编辑日志仲裁ZooKeeper3 Podopenebs-hostpath 10GiZKFC leader 选举 RM 状态存储ZKFC2 sidecarNN Pod 内无监控 NN 健康触发切换DataNode3 Podopenebs-hostpath 100GiHDFS 数据3 副本ResourceManager2 PodHA无 PVCYARN 调度ZKRMStateStore 状态恢复NodeManager3 PodemptyDirYARN 任务执行1.2 HA 核心原理存储层NN HAActive NN 写 edits → JournalNode 仲裁(3/3 多数) Standby NN 从 JN 实时 tail → 元数据一致 ZKFC 经 ZooKeeper 抢 Active 锁 → 节点故障 Active 释放锁 → Standby 秒级接管~30s零数据丢失计算层YARN HA两个 RMrm1resourcemanager-0, rm2resourcemanager-1 → 经 ZooKeeper ActiveStandbyElector 选主仅一个为 Active → RM 状态app/attempt/令牌存 ZKRMStateStore与选主同源单一真相 → 杀 Active RM Pod → 原 Standby 秒级升 Active → 运行中作业靠 ZKRMStateStore 恢复 attempt 继续实测通过见第 9 节1.3 存储策略全部使用openebs-hostpathlocal 存储无需 Longhorn 等网络存储。HA 在应用层解决节点故障不依赖存储层跨节点复制。2. 前置条件Kubernetes ≥ 1.20至少 3 个 K8s 节点NN 硬反亲和需 2 否、DN/NM 硬反亲和需 3 节点openebs-hostpathStorageClass 已安装并设为默认镜像Hadoopswr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/zhuyifeiruichuang/hadoop:3.1.1ZooKeeperswr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/zookeeper:3.4.143. 文件清单文件作用namespace.yaml命名空间本集群实际为hadoopconfigmap.yaml全部 Hadoop 配置NN HA YARN HA 三必改坑配置zookeeper.yamlZK 3 节点 StatefulSet PDBjournalnode.yamlJN 3 节点 StatefulSet PDBnamenode.yamlNN 2 节点 HA ZKFC sidecar PDBdatanode.yamlDN 3 节点 反亲和 PDBresourcemanager.yamlRM 2 Pod HAZKRMStateStore PDBnodemanager.yamlNM 3 节点 反亲和 PDBtcpSocket 探针web-ui-access.yaml每 Pod 独立 NodePort 服务随机端口确定性访问 Web UI4. 部署顺序与步骤① namespace → ② configmap → ③ zookeeper → ④ journalnode → ⑤ namenode → ⑥ datanode → ⑦ resourcemanager → ⑧ nodemanagerZK 和 JN必须在 NN 之前。本集群已部署于hadoop无需重复建 namespace。kubectl apply-fnamespace.yaml# 仅首次 / 切换到新 ns 时kubectl apply-fconfigmap.yaml-nhadoop kubectl apply-fzookeeper.yaml-nhadoop kubectl apply-fjournalnode.yaml-nhadoop kubectl apply-fnamenode.yaml-nhadoop kubectl apply-fdatanode.yaml-nhadoop kubectl apply-fresourcemanager.yaml-nhadoop# RM 2 Pod HAkubectl apply-fnodemanager.yaml-nhadoop kubectl apply-fweb-ui-access.yaml-nhadoop# 可选Web UI 确定性访问等待就绪kubectlwait--forconditionready pod-lapphadoop-namenode-nhadoop--timeout300s kubectlwait--forconditionready pod-lapphadoop-datanode-nhadoop--timeout180s kubectlwait--forconditionready pod-lapphadoop-resourcemanager-nhadoop--timeout180s kubectlwait--forconditionready pod-lapphadoop-nodemanager-nhadoop--timeout180s5. NameNode HA 初始化序列5.1 namenode-0nn1/ActiveinitContainermkdir 数据目录 → 等 ZK 3/3 → 等 JN ≥2/3 → formatZK → format NN → initializeSharedEdits 主容器NameNode daemon → ZKFC 获 Active 锁 → nn1 成为 Active5.2 namenode-1nn2/StandbyinitContainer等 ZK/JN → 等 namenode-0 RPC → bootstrapStandby须用 root见踩坑 主容器NameNode daemon 从 JN 同步 → ZKFC 发现锁被持 → nn2 保持 Standby5.3 首次 vs 后续重启步骤首次后续重启formatZK / format NN / initializeSharedEdits / bootstrapStandby执行跳过initContainer 靠 VERSION 与 znode 判断幂等6. 基础验证# NN HA 状态kubectlexec-nhadoop namenode-0-cnamenode -- hdfs haadmin-getServiceStatenn1# activekubectlexec-nhadoop namenode-1-cnamenode -- hdfs haadmin-getServiceStatenn2# standby# HDFSkubectlexec-nhadoop namenode-0-cnamenode -- hdfs dfsadmin-report# YARN 节点kubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnnode-list# 3 个 NM7. YARN HA 专属三必改K8s 部署踩坑缺一不可Hadoop 3.1.1 在 K8s 上跑通 MapReduce必须解决以下三道 K8s 特有坑。任一道不修作业都会失败且报错极具迷惑性。7.1 NM 注册必须用 FQDN去掉127.0.0.1绑定现象NM 注册成localhost:portAM 无法路由 → 作业卡住或失败。根因NM 的InetAddress.getLocalHost()把127.0.0.1反解成localhost。若在hadoop-env/yarn-env里写127.0.0.1 $(hostname)NM 就以 localhost 注册。修复nodemanager.yaml启动命令中去掉127.0.0.1 $(hostname片段容器nsswitch.conf保持hosts: files dns依赖 K8s 注入的PodIP hostname.svc让 NM 注册 FQDN如nodemanager-2.nodemanager.hadoop.svc.cluster.local:43167。RM 主容器可保留127.0.0.1 $(hostname)RM 用配置的yarn.resourcemanager.hostname.rmXFQDN不依赖 getLocalHost无害。7.2 AM 的 log4j 必须进 classpath现象AM 崩溃client 的 Diagnostics 只显示log4j:WARN No appenders真实异常被静默吞。根因AM 子进程HADOOP_CONF_DIR缺少log4j.properties异常无 appender。修复三处协同configmap.yaml增加log4j.propertieskey带 ConsoleAppender 打到 stderrnodemanager.yaml增加 volumeMountsubPath 挂载log4j.properties到/opt/hadoop/etc/hadoop/log4j.propertiesmapred-site.xml增加yarn.app.mapreduce.am.command-opts -Xmx1024m -Dlog4j.configurationfile:///opt/hadoop/etc/hadoop/log4j.properties。subPath 不热更新改 configmap 后必须kubectl rollout restart statefulset/nodemanager才生效。7.3 AM Web 服务在 HA 下必须补 per-RM-id web 地址最隐蔽的 NPE现象AM 启动即java.lang.NullPointerException→RMCommunicator.register→MRClientService.getHttpPort()作业 FAILED。源码级根因Hadoop 3.1.1ERROR client.MRClientService: Webapps failed to start. Ignoring for now: java.lang.NullPointerException at org.apache.hadoop.util.StringUtils.join(StringUtils.java:941) at org.apache.hadoop.yarn.server.webproxy.amfilter.AmFilterInitializer.initFilter(AmFilterInitializer.java:74) at org.apache.hadoop.http.HttpServer2.initializeWebServer(HttpServer2.java:587)AM 的AmFilterInitializer取RM 代理主机列表时在 HA 模式下走 per-RM-id 地址yarn.resourcemanager.webapp.address.rm1/.rm2。只设hostname.rm1/.rm2而没设webapp.address.rm1/.rm2→ 列表返回 null →StringUtils.join(null)NPE →webApp留 null →getHttpPort()崩溃。注yarn.app.mapreduce.am.webapp.address0.0.0.0:0AM 自身绑 0.0.0.0 临时端口方向正确但非本 NPE 解药保留即可真正的修复是补 per-RM-id web 地址。修复configmap.yaml→yarn-site.xmlpropertynameyarn.resourcemanager.webapp.address/namevalueresourcemanager-0.resourcemanager.hadoop.svc.cluster.local:8088,resourcemanager-1.resourcemanager.hadoop.svc.cluster.local:8088/valuedescriptionbase 读取路径逗号分隔两 RM保非 null/description/propertypropertynameyarn.resourcemanager.webapp.address.rm1/namevalueresourcemanager-0.resourcemanager.hadoop.svc.cluster.local:8088/value/propertypropertynameyarn.resourcemanager.webapp.address.rm2/namevalueresourcemanager-1.resourcemanager.hadoop.svc.cluster.local:8088/value/property7.4 配套坑同样会卡作业NM 探针必须tcpSocket不是httpGetHadoop 3.1.1 NM REST/ws/v1/nodeinfo返回 404kubelet 会把 NM 杀进 restart loop。所有 NM 探针用tcpSocket:{port:8042}。RM/ws/v1/cluster/info:8088httpGet 正常active/standby 都返回 200。改 configmap 后必须rollout restartRM NMsubPath 挂载不随 ConfigMap 变更热更新。修改yarn-site.xml/mapred-site.xml后kubectl apply -f configmap.yaml -n hadoop kubectl rollout restart statefulset/resourcemanager -n hadoop kubectl rollout restart statefulset/nodemanager -n hadoop。yarn jarglob 需sh -c包裹kubectl exec pod -- yarn jar /p/*.jar不生成 shell*.jar被字面传递 → 用sh -c yarn jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar pi 2 10。AM 真因定位用yarn logs而非 Diagnosticsclient Diagnostics 只贴 “Last 4096 bytes of stderr”会把更早的Webapps failed to start截断藏掉。yarn logs -applicationId id取全量再grep -A40 Webapps failed to start看完整 Caused by。8. Web UI 访问确定性8.1 问题默认的resourcemanager-external(30088) /nodemanager-external(31799) 用 StatefulSet 级 selectorapp: hadoop-*负载均衡到全部 Pod。HA 下访问 30088 有一半概率命中 standby节点表空访问 31799 每次刷新跳不同 NM → “看不到 node”。8.2 方案 Aper-pod NodePort随机端口—web-ui-access.yaml每个 Pod 用statefulset.kubernetes.io/pod-name标签建独立 NodePort 服务NodePort 不指定由 K8s 随机分配30000-32767。应用后查端口kubectl apply-fweb-ui-access.yaml-nhadoop kubectl get svc-nhadoop-lapphadoop-webui# 看自动分配的 NodePort# 浏览器http://worker-ip:rm-port/cluster/nodes 用 yarn rmadmin -getServiceState 选 active 对应端口# http://worker-ip:nm-port/node8.3 方案 Bport-forward推荐零改动kubectl port-forward-nhadoop pod/resourcemanager-active8088:8088# 本地开 http://localhost:8088kubectl port-forward-nhadoop pod/nodemanager-08042:8042# http://localhost:8042/node9. YARN 真 failover 验证HA 毕业考目标杀掉 active RM证 standby 秒级接管 运行中作业零中断。# 1. 先确认谁是 active一次只一个 serviceIdkubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnrmadmin-getServiceStaterm1 kubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnrmadmin-getServiceStaterm2# 2. 后台启一个长作业留时间杀 RMkubectlexec-nhadoop resourcemanager-0-cresourcemanager --\sh-cyarn jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar pi 16 10000# 3. 作业跑到 map 阶段时删【active】那个 Pod下例假设 rm2 activekubectl delete pod resourcemanager-1-nhadoop# 4. 观察翻转 作业存活kubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnrmadmin-getServiceStaterm1# → activekubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnrmadmin-getServiceStaterm2# → standbykubectlexec-nhadoop resourcemanager-0-cresourcemanager --yarnapplication-statusapplication_xxxx_xxxx实测结果2026-07-24杀 active(rm2) 时作业map 25%rm1翻为activerm2重建后以standby归队RESTARTS 0作业State: RUNNING→ 继续跑到State: FINISHED / Final-State: SUCCEEDEDDiagnostics: Attempt recovered after RM restartEstimated value of Pi is 3.1412750000000000000016 万样本证明蒙特卡洛正确早先 3.8 仅为 20 样本噪声。关键结论早先RM 重启后集群空、需手动restart nodemanager是同时冷重启两个 RM的副作用干净 failoverstandby 是热的、只杀一个 active下 NM 自动向新 active 重注册作业零中断。HA 本身完全正确。10. 节点故障恢复组件自动恢复备注NameNodeZKFC 释放锁 → Standby 升 Active(~30s)PVC 在故障节点则重建后从 JN 同步数据零丢失DataNode3 副本保护NN 触发补齐永久故障删 PVC 缩/扩容 StatefulSetJournalNode仲裁 2/3 多数可用永久故障删 PVC 重建ZooKeeper仲裁 2/3 多数可用同上ResourceManagerHA 自动 failover见第 9 节运行中作业不中断NodeManagerNM 向新 active RM 自动重注册干净 failover 无需手动重启11. 遗留写死地址清理HA 修正configmap.yaml中原写死resourcemanager-0单 Pod 的两项failover 后会失效已改为 RM headless 服务 DNS!-- yarn-site.xml --propertynameyarn.log.server.url/namevaluehttp://resourcemanager.hadoop.svc.cluster.local:19888/jobhistory/value/property!-- mapred-site.xml --propertynamemapreduce.jobtracker.address/namevalueresourcemanager.hadoop.svc.cluster.local:8032/value/propertyyarn.log.server.urlRM/NM Web UI 的历史链接目标JobHistoryServer标准端口 19888。原写死单 Pod → 变 standby/被删后链接失效改 headless 服务 DNS 后稳定。完整历史需单独部署 JobHistoryServer。mapreduce.jobtracker.addressMRv1 遗留属性YARN 下普通作业不依赖改 headless 服务 DNS 避免 legacy 路径在单 Pod 死亡后连不上。生效kubectl apply -f configmap.yaml -n hadoop kubectl rollout restart statefulset/resourcemanager -n hadoop kubectl rollout restart statefulset/nodemanager -n hadoop。12. 运维扩缩容kubectl scale statefulset datanode -n hadoop --replicasN≥3kubectl scale statefulset nodemanager -n hadoop --replicasN。滚动更新NN 用OrderedReadynn0 先 HA 初始化ZK/JN/DN/NM/RM 用Parallel。NN 元数据备份kubectl exec -n hadoop namenode-0 -c namenode -- hdfs dfsadmin -fetchImage /tmp/fsimage.img。查看 HA 状态kubectl exec -n hadoop namenode-0 -c namenode -- hdfs haadmin -getAllServiceState。13. 故障排查症状根因解决NM 一直 Error/restart loopNM 探针httpGet /ws/v1/nodeinfo返回 404改用tcpSocket:8042作业 AMgetHttpPort()NPE缺yarn.resourcemanager.webapp.address.rm1/.rm2补 per-RM-id web 地址§7.3AM 崩溃只见No appendersAM 缺 log4j.properties§7.2 三处协同修复作业卡 ACCEPTED / cluster resource emptyRM 重启丢失 NM 注册双 RM 冷重启才触发rollout restart statefulset/nodemanagerJAR does not exist: *.jarkubectl exec无 shellglob 字面传参sh -c yarn jar /p/*.jar ...两个 NN 都 standbyZKFC 异常看 zkfc 日志hdfs haadmin -transitionToActive nn1NN bootstrapStandby 报 superuser 拒绝init 用su hadoop降级init 全程用 root 跑 hdfs 命令14. 安全加固建议HDFS 权限dfs.permissions.enabledtrue超管组hadoopACLdfs.namenode.acls.enabledtrue、yarn.acl.enabletrue容器安全建议runAsUser:1000hadoop替代runAsUser:0去privileged:trueNetworkPolicy 限制 Pod 间访问生产建议启用 Kerberos、HDFS 传输加密15. 验证清单#验证项命令期望1ZK 仲裁kubectl get pods -l appzookeeper -n hadoop3/3 Running2JN 仲裁kubectl get pods -l apphadoop-journalnode -n hadoop3/3 Running3NN HAkubectl get pods -l apphadoop-namenode -n hadoop2/2 Running4nn1 Active / nn2 Standbyhdfs haadmin -getServiceState nn1/nn2active / standby5DNkubectl get pods -l apphadoop-datanode -n hadoop3/3 Running6HDFS 安全模式hdfs dfsadmin -safemode getOFF7RM HAkubectl get pods -l apphadoop-resourcemanager -n hadoop2/2 Running8RM 角色yarn rmadmin -getServiceState rm1/rm2一 active 一 standby9NMkubectl get pods -l apphadoop-nodemanager -n hadoop3/3 Running10YARN 节点yarn node -list3 个 NM11MapReduce 作业yarn jar ... pi 2 10Job FinishedSUCCEEDED12YARN 真 failover杀 active RM yarn application -statusstandby→active作业SUCCEEDED13Web UI 可访问kubectl get svc -n hadoop -l apphadoop-webui各 Pod 独立 NodePort16. 部署到不同命名空间namespace须知16.1 核心原理必读K8s 集群内 DNS 解析规则是service.namespace.svc.cluster.local。namespace 一旦改变所有写死在配置里的 FQDN 都会指向一个不存在的 DNS 名字服务发现集体失效——这是最致命也最易被忽略的一点也是本集群最早一版从hadoop1迁hadoop时踩过的坑。本套配置里 namespace 出现在两个层面改动量天差地别层面位置改动难度CLI / 文档层所有kubectl ... -n hadoop命令、namespace.yaml的name易全局替换配置层致命configmap.yaml内 14 处*.hadoop.svc.cluster.localFQDN web-ui-access.yaml内 5 处namespace: hadoop必须逐处改否则集群假死⚠️ 各 StatefulSet YAMLzookeeper / journalnode / namenode / datanode / resourcemanager / nodemanager不写死 namespace 和 FQDN靠kubectl apply -n ns注入 引用 configmap。所以只要-n正确它们自动落在目标 ns无需改文件内容。16.2 必须修改的配置清单①namespace.yamlapiVersion:v1kind:Namespacemetadata:name:新ns# 原 hadoop → 改为目标命名空间②configmap.yaml— 14 处 FQDN 全部替换把.hadoop.svc.cluster.local→.新ns.svc.cluster.local。覆盖以下服务节选关键项ZooKeeperzookeeper-0/1/2.zookeeper.hadoop.svc.cluster.local:2181ha.zookeeper.quorum、yarn.resourcemanager.zk-addressJournalNodeqjournal://journalnode-0/1/2.journalnode.hadoop.svc.cluster.local:8485/myclusterdfs.namenode.shared.edits.dirNameNodenamenode-0/1.namenode.hadoop.svc.cluster.local:9000rpc、:9870httpResourceManagerresourcemanager-0/1.resourcemanager.hadoop.svc.cluster.localhostname.rm1/rm2、:8088webapp.address 及其 .rm1/.rm2 变体RM headless DNSresourcemanager.hadoop.svc.cluster.localyarn.log.server.url、mapreduce.jobtracker.address、yarn.resourcemanager.address类③web-ui-access.yaml— 5 处namespace: hadoop→namespace: 新ns16.3 机械操作步骤以目标 ns prod为例# 0. 本地批量替换先备份原文件防改错无法回滚cpconfigmap.yaml configmap.yaml.bakcpweb-ui-access.yaml web-ui-access.yaml.bakcpnamespace.yaml namespace.yaml.baksed-is/\.hadoop\.svc\.cluster\.local/.prod.svc.cluster.local/gconfigmap.yamlsed-is/namespace: hadoop/namespace: prod/gweb-ui-access.yamlsed-is/name: hadoop/name: prod/gnamespace.yaml# 1. 创建 ns 全套 apply所有 -n 换成 prodkubectl apply-fnamespace.yaml kubectl apply-fconfigmap.yaml-nprod kubectl apply-fzookeeper.yaml-nprod kubectl apply-fjournalnode.yaml-nprod kubectl apply-fnamenode.yaml-nprod kubectl apply-fdatanode.yaml-nprod kubectl apply-fresourcemanager.yaml-nprod kubectl apply-fnodemanager.yaml-nprod kubectl apply-fweb-ui-access.yaml-nprod# 2. 校验进 pod 确认 FQDN 已生效关键漏改会立刻服务发现全断kubectlexec-nprod namenode-0-cnamenode --\grep-oprod.svc.cluster.local/opt/hadoop/etc/hadoop/hdfs-site.xml|head# 应输出若干行 *.prod.svc.cluster.local且不得有 *.hadoop.svc.cluster.local 残留# 3. 复验同 §15 验证清单把 -n hadoop 换成 -n prodkubectl get all-nprod kubectlexec-nprod resourcemanager-0-cresourcemanager --\sh-cyarn jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar pi 2 1016.4 警告与边界❌不要把新 ns 的 configmap apply 进旧 ns也不要把旧 ns 的 configmap apply 进新 ns—— FQDN 不匹配会立即导致服务发现全断NM 注册不了、NN/JN 连不上 ZK。新 ns 是全新空集群不会继承旧 ns 的数据数据存在旧 ns 的 PVC 里PVC 不跨 ns 共享。需要迁移数据请用distcp跨集群拷贝。存储与 ns 无关openebs-hostpath 是节点本地盘新 ns 部署会在节点上新建空 PVC。✅ 改完务必跑 §15 全量验证清单重点NN HA 角色、RM HA 角色、pi 作业、真 failover确认全绿再投产。
郑州网站建设
网页设计
企业官网