Docker容器端口映射后Hadoop突然无法连接

1 篇文章 0 订阅
1 篇文章 0 订阅

Docker容器端口映射后Hadoop突然无法连接

一、背景

​ 一般需要对外提供服务的Docker容器,我们在启动时后使用-p命令将对外访问端口暴露给外部,故在创建容器是,我们将Hadoop的端口隐射出来供外部访问:

docker run -itd --privileged --name singleNode -h singleNode \
-p 2222:22 \
-p 3306:3306 \
-p 8020:8020 \
-p 9870:9870 \
-p 19888:19888 \
-p 8088:8088 \
-p 9083:9083 \
-p 10000:10000 \
-p 2181:2181 \
-p 9092:9092 \
-p 8091:8091 \
-p 8080:8080 \
-p 16010:16010 \
-p 4000:4000 \
-p 3000:3000 \
centos:7 /usr/sbin/init

# 其中端口号解释
2222:22# SSH
3306:3306 #MySQL
8020:8020 # HDFS RPC
9870:9870 # HDFS web UI
19888:19888 # Yarn job history 
8088:8088 # Yarn web UI
9083:9083 # Hive metastore
10000:10000 # HiveServer2
2181:2181 # zk
9092:9092 # kafka
8091:8091 # flink

​ 但最近碰到一个非常奇怪的情况:在一个CentOS 7测试环境里部署有Docker Hadoop,并对外暴露了端口。启动容器后一段时间内都是可以正常工作的,但在不定时间间隔后,Hadoop的web端就访问不了:

在这里插入图片描述

​ 原本以为是我们的Hadoop服务没有正常启动,但是Jps查看时,却发现正常:

在这里插入图片描述

​ 至于这个问题,只有手动重启出问题的Docker,然后在重启Hadoop服务后,外部才可以重新访问,但只要再过一段时间又会出现这样的问题。

二、问题排查

情况一:开着防火墙但没有开放端口

​ CentOS 7自带并启用了防火墙FirewallD,我们可以通过下面的命令检查FirewallD的状态:

firewall-cmd --state

在这里插入图片描述

​ 如果输出的是“not running”则FirewallD没有在运行,且所有的防护策略都没有启动,那么可以排除防火墙阻断连接的情况了。

​ 如果输出的是“running”,表示当前FirewallD正在运行,需要再输入下面的命令查看现在开放了哪些端口和服务:

firewall-cmd --list-ports
firewall-cmd --list-services

在这里插入图片描述

​ 可以看到当前防火墙只开放了ssh服务(22/tcp)和dhcpv6-client服务,并没有打开Docker容器映射的Hadoop端口。

解决方案有两种:
1.关闭FirewallD服务:

​ 如果您不需要防火墙,那直接关掉FirewallD服务就好了

systemctl stop firewalld.service

​ 但是在部署Hadoop服务之前,就已经将firewalld服务禁用了,故此问题的根源不在这

2.添加策略对外打开指定的端口:

​ 比如我们现在要打开对外9870/tcp端口,可以使用下面的命令:

firewall-cmd --add-port=9870/tcp --permanent
firewall-cmd --reload

​ 如果只是临时打开端口,去掉第一行命令中的“–permanent”参数,那么当再次重启FirewallD服务时,本策略将失效。 此命令不建议执行,毕竟Hadoop服务端口那么多…

情况二:没有启用IP_FORWARD

​ 因为一直没法定位出问题的所在,所以不能正常访问HadoopWeb端时,手动登陆宿主机重启Docker,再重启 Hadoop服务。

​ 在有一次登录到宿主服务器上准备重启Docker daemon服务前,我突然想起之前在用Docker的时候还碰到过另一个问题:如果宿主机没有启用IP_FORWARD功能,那Docker容器在启动时会输出一条警告消息:

WARNING: IPv4 forwarding is disabled. Networking will not work.

​ 会不会是因为宿主机的IP_FORWARD功能没有启用所以才引起的这个故障呢?

sysctl net.ipv4.ip_forward

在这里插入图片描述

​ 因为,我这里是设置过的,原本的结果为:net.ipv4.ip_forward = 0,表示当前系统的IP_FORWARD功能处于停用状态!

​ 可是问题来了,当时启动容器的时候都是好的啊,什么都没有输出,怎么用着用着IP_FORWARD功能就被禁用了呢?

​ Docker daemon服务在启动的时候会自动设置iptables设置,难不成它还会检查IP_FORWARD设置,并帮我临时启用吗?

​ 带着这个假设,我手动重启了一下Docker Hadoop服务

[root@singlenode /]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
[root@singlenode /]# systemctl restart docker
[root@singlenode /]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

​ 果然,Docker 服务在启动过程中会检查系统的IP_FORWARD配置项,如果当前系统的IP_FORWARD功能处于停用状态,会帮我们临时启用IP_FORWARD功能,然而临时启用的IP_FORWARD功能会因为其他各种各样的原因失效…

​ 问题找到,至于修复方案倒非常简单,只要一行命令就可以了:

echo 'net.ipv4.ip_forward = 1' >> /usr/lib/sysctl.d/50-default.conf

​ 执行完成后,重启服务器或使用下面的命令从文件中加载配置:

sysctl -p /usr/lib/sysctl.d/50-default.conf

在这里插入图片描述

​ 就OK了。Hadoop正常访问咯!

在这里插入图片描述

三、小结

​ Docker 服务在启动的时候会帮帮我们调整很多的配置项,比如这次出事儿的IP_FORWARD配置。

​ Docker 启用IP_FORWARD功能是因为Docker容器默认的网络模式(bridge/网桥模式)会给每个容器分配一个私有IP,如果容器需要和外部通信,就需要使用到NAT。NAT需要IP_FORWARD功能支持,否则无法使用。这也解释了为什么会出现在IP_FORWARD功能停用的情况下,使用bridge模式的容器内外均无法访问的情况。

​ 只是在Linux下,出于安全考虑,默认是停用IP_FORWARD功能的,Docker 服务在启动时会检查IP_FORWARD功能是否已经启用,如果没有启用的话,Docker 会悄无声息的临时启用此功能,然而临时启用的IP_FORWARD功能并不能持久化,会因为其他命令的干扰导致失效。

Author:洋群满满
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值