当前位置:首页 » 文件传输 » 宿主机访问容器的ip
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

宿主机访问容器的ip

发布时间: 2023-01-08 08:15:51

Ⅰ Docker:Docker实现同Ip网段联通

最近解决docker与宿主机同网段通信的问题,写此文章记录一下整个过程。
例如

宿主机A 和宿主机B是网络联通关系,在宿主机A上面创建了多个容器组成集群,但是我希望通过宿主机B也可以访问到宿主机A的容器,当然,你也可能会说,端口映射非常方便,如果我需要的端口比较多,或者着如果我临时需要增加某些端口,可能设置起来比较麻烦,那么如果我们将宿主机A里面的容器的IP与宿主机的IP在同一个网络,不就可以直接来进行互联互通了么。

安装 Docker

安装 pipework 这个工具可以使用一条命令就可以实现更改容器的IP,更准确来说为容器IP添加一个新的网卡。

编辑默认ip配置文件,eth0或者ens33(不同操作系统,名称不一致,例如我操作的这台机器的名称为ifcfg-ens33)

输入 i 进入到编辑模式,将下面的内容复制到文件中

并且将配置内容复制到配置文件中

重启虚拟机网络服务

修改docker的配置文件 /etc/sysconfig/

修改内容如下

修改完之后:

--net=none 代表容器的网卡都是为空的,需要通过 pipework 进行自定义指定

修改主机ip,网段与宿主机A网桥IP段保持一致。设置后,宿主机A,B之间可以互相ping通

到这里,就完成了Docker网络之间的通信。

Ⅱ docker容器网络

利用Net Namespace可以为Docker容器创建隔离的网络环境,容器具有完全独立的网络栈,与宿主机隔离。也可以使Docker容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。

Docker支持 4种网络模式 :

1)host模式,--net=host指定,不支持多主机。

2)container模式,--net = container : name_or_id指定,不支持多主机。

3)none模式,--net=none指定,不支持多主机。

4)bridge模式,--net=bridge指定,默认设置,不支持多主机。

启动容器的时候使用Host模式,那么该容器与宿主机共用一个Network Namespace,因此容器将不会虚拟自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口。

采用Host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,无需额外进行NAT转换。由于容器通信时,不再需要通过Linux Bridge等方式转发或者数据包的拆封,性能上有很大优势。当然, Host模式有利也有弊 ,主要包括以下缺点:

1)容器没有隔离、独立的网络栈。容器因与宿主机共用网络栈而争抢网络资源,并且容器崩溃也可能导致宿主机崩溃,这在生产环境中是不允许发生的。

2)容器不再拥有所有的端口资源,因为一些端口已经被宿主机服务、Bridge模式的容器端口绑定等其他服务占用了。

需要补充说明的是,Host模式下的容器仅仅是网络命名空间与主机相同,但容器的文件系统、进程列表等还是和与宿主机隔离的。

Container模式是一种特殊的网络模式。该模式下的容器使用其他容器的网络命名空间,网络隔离性会处于Bridge模式与Host模式之间。当容器与其他容器共享网络命名空间时,这两个容器间不存在网络隔离,但它们与宿主机及其他容器又存在网络隔离。

在Kubernetes体系架构下引入Pod概念,Kubernetes为Pod创建一个基础设施容器, 同一Pod下的其他容器都以Container模式 共享这个基础设施容器的网络命名空间,相互之间以localhost访问,构成一个统一的整体。

与前两种不同,None模式的Docker容器拥有自己的Network Namespace,但并不为Docker容器进行网络配置。该Docker容器没有网卡、IP、路由等信息。需要用户为Docker容器添加网卡、配置IP等。

Bridge模式是Docker默认的网络模式,也是开发者最常使用的网络模式。在这种模式下,Docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的Docker0网桥,容器可以与宿主机乃至外界进行网络通信。

同一宿主机上,容器之间都是连接在Docker0这个网桥上,Docker0作为虚拟交换机使容器间相互通信 。但是, 由于宿主机的IP地址与容器veth pair的IP地址均不在同一个网段 ,故仅仅依靠 veth pair和NameSpace的技术 并不足以使宿主机以外的网络主动发现容器的存在。Docker采用了 端口绑定的方式(通过iptables的NAT) ,将宿主机上的端口流量转发到容器内的端口上,这样一来,外界就可以与容器中的进程进行通信。 iptables的介绍,请点我点我 。

创建容器,并将宿主机的3306端口绑定到容器的3306端口:docker run -tid --name db -p 3306:3306 mysql

在宿主机上,可以通过“iptables -t nat -L -n”,查到一条DNAT规则:DNAT tcp --0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

Bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,这会造成对宿主机端口管理很复杂。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率损耗是显而易见的。

NAT将地址空间分段的做法引入了额外的复杂度。比如容器中应用所见的IP并不是对外暴露的IP, 因为网络隔离,容器中的应用实际上只能检测到容器的IP,但是需要对外宣称的则是宿主机的IP,这种信息的不对称将带来诸如破坏自注册机制等问题 。

摘抄自陆平的《基于Kubernetes的容器云平台实战》一书的第10章Kubernetes网络

Ⅲ docker从容器中怎么访问宿主机

例如你的docker环境的虚拟IP是192.168.99.100,那么宿主机同样会托管一个和192.168.99.100同网段的虚拟IP,并且会是主IP:192.168.99.1,那么就简单了,在容器中访问192.168.99.1这个地址就等于访问宿主机。

注意,通过192.168.99.1访问宿主机,等于换了一个ip,如果数据库或中间件限制了本机访问或者做了ip段限制,要记得添加192.168.99.1到白名单。

Docker容器运行的时候有 host 、 bridge 、 none 三种网络可供配置。默认是 bridge ,即桥接网络,以桥接模式连接到宿主机; host 是宿主网络,即与宿主机共用网络; none 则表示无网络,容器将无法联网。

当容器使用 host 网络时,容器与宿主共用网络,这样就能在容器中访问宿主机网络,那么容器的 localhost 就是宿主机的 localhost 。

(3)宿主机访问容器的ip扩展阅读

宿主机和容器通信原理的问题:

考虑重启速度:在实际的运维过程中,部分场景下,会出现主机卡死,或者docker进程卡死, 这时,最快恢复业务的方法是重启主机。

容器在主机重启后,可以自动恢复,因此可以做到在1到2分钟内快速恢复业务。这一点太重要了,物理机重启由于需要做各种硬件检测,重启时间一般在5到10分钟, 虚拟机重启一般在1分钟以内 , 物理机显然无法满足需求。

重建能力很重要:

容器平台经常需要更新操作系统,或者根据需要调整主机规格。

运行一段时间后,发现内存配置偏少了, 需要添加内存。这时候申请一台新的机器加入到集群中,将旧机器下线即可。

运行多年的 ubuntu 12.04 官方已经不再维护, 需要全量替换,工作量相当大。好的方法就是使用全新的服务器替换旧服务器。

当发生故障,主机无法恢复时, 直接申请新服务器加入集群即可。

Ⅳ Docker容器网络-实现篇

前面介绍了: Docker容器网络-基础篇

前文说到容器网络对Linux虚拟化技术的依赖,这一篇章我们将一探究竟,看看Docker究竟是怎么做的。通常,Linux容器的网络是被隔离在它自己的Network Namespace中,其中就包括:网卡(Network Interface)、回环设备(Loopback Device)、路由表(Routing Table)和iptables规则。对于一个进程来说,这些要素,就构成了它发起和响应网络请求的基本环境。

我们在执行 docker run -d --name xxx 之后,进入容器内部:

并执行 ifconfig:

我们看到一张叫eth0的网卡,它正是一个Veth Pair设备在容器的这一端。

我们再通过 route 查看该容器的路由表:

我们可以看到这个eth0是这个容器的默认路由设备。我们也可以通过第二条路由规则,看到所有对 169.254.1.1/16 网段的请求都会交由eth0来处理。

而Veth Pair 设备的另一端,则在宿主机上,我们同样也可以通过查看宿主机的网络设备来查看它:

在宿主机上,容器对应的Veth Pair设备是一张虚拟网卡,我们再用 brctl show 命令查看网桥:

可以清楚的看到Veth Pair的一端 vethd08be47 就插在 docker0 上。

我现在执行docker run 启动两个容器,就会发现docker0上插入两个容器的 Veth Pair的一端。如果我们在一个容器内部互相ping另外一个容器的IP地址,是不是也能ping通?

容器1:

容器2:

从一个容器ping另外一个容器:

我们看到,在一个容器内部ping另外一个容器的ip,是可以ping通的。也就意味着,这两个容器是可以互相通信的。

我们不妨结合前文时所说的,理解下为什么一个容器能访问另一个容器?先简单看如一幅图:

当在容器1里访问容器2的地址,这个时候目的IP地址会匹配到容器1的第二条路由规则,这条路由规则的Gateway是0.0.0.0,意味着这是一条直连规则,也就是说凡是匹配到这个路由规则的请求,会直接通过eth0网卡,通过二层网络发往目的主机。而要通过二层网络到达容器2,就需要127.17.0.3对应的MAC地址。所以,容器1的网络协议栈就需要通过eth0网卡来发送一个ARP广播,通过IP找到MAC地址。

所谓ARP(Address Resolution Protocol),就是通过三层IP地址找到二层的MAC地址的协议。这里说到的eth0,就是Veth Pair的一端,另一端则插在了宿主机的docker0网桥上。eth0这样的虚拟网卡插在docker0上,也就意味着eth0变成docker0网桥的“从设备”。从设备会降级成docker0设备的端口,而调用网络协议栈处理数据包的资格全部交给docker0网桥。

所以,在收到ARP请求之后,docker0就会扮演二层交换机的角色,把ARP广播发给其它插在docker0网桥的虚拟网卡上,这样,127.17.0.3就会收到这个广播,并把其MAC地址返回给容器1。有了这个MAC地址,容器1的eth0的网卡就可以把数据包发送出去。这个数据包会经过Veth Pair在宿主机的另一端veth26cf2cc,直接交给docker0。

docker0转发的过程,就是继续扮演二层交换机,docker0根据数据包的目标MAC地址,在CAM表查到对应的端口为veth8762ad2,然后把数据包发往这个端口。而这个端口,就是容器2的Veth Pair在宿主机的另一端,这样,数据包就进入了容器2的Network Namespace,最终容器2将响应(Ping)返回给容器1。在真实的数据传递中,Linux内核Netfilter/Iptables也会参与其中,这里不再赘述。

CAM就是交换机通过MAC地址学习维护端口和MAC地址的对应表

这里介绍的容器间的通信方式就是docker中最常见的bridge模式,当然此外还有host模式、container模式、none模式等,对其它模式有兴趣的可以去阅读相关资料。

好了,这里不禁问个问题,到目前为止只是单主机内部的容器间通信,那跨主机网络呢?在Docker默认配置下,一台宿主机的docker0网桥是无法和其它宿主机连通的,它们之间没有任何关联,所以这些网桥上的容器,自然就没办法多主机之间互相通信。但是无论怎么变化,道理都是一样的,如果我们创建一个公共的网桥,是不是集群中所有容器都可以通过这个公共网桥去连接?

当然在正常的情况下,节点与节点的通信往往可以通过NAT的方式,但是,这个在互联网发展的今天,在容器化环境下未必适用。例如在向注册中心注册实例的时候,肯定会携带IP,在正常物理机内的应用当然没有问题,但是容器化环境却未必,容器内的IP很可能就是上文所说的172.17.0.2,多个节点都会存在这个IP,大概率这个IP是冲突的。

如果我们想避免这个问题,就会携带宿主机的IP和映射的端口去注册。但是这又带来一个问题,即容器内的应用去意识到这是一个容器,而非物理机,当在容器内,应用需要去拿容器所在的物理机的IP,当在容器外,应用需要去拿当前物理机的IP。显然,这并不是一个很好的设计,这需要应用去配合配置。所以,基于此,我们肯定要寻找其他的容器网络解决方案。

在上图这种容器网络中,我们需要在我们已有的主机网络上,通过软件构建一个覆盖在多个主机之上,且能把所有容器连通的虚拟网络。这种就是Overlay Network(覆盖网络)。

关于这些具体的网络解决方案,例如Flannel、Calico等,我会在后续篇幅继续陈述。

Ⅳ k8s-pod-初探2

踩坑完毕,回到主线。

前面关于port的理解存在偏差,需要用实验来确认port配置的含义。

k8s官方文档对于对于这些配置项的解释还是没有很完善。下面是在其他博文中找到的解释。

已知:

从k8s集群内部的宿主机(物理机、虚拟机)可以直接访问pod的服务地址 ip:80

未知(需要测试):

1、同一局域网内,但没有加入k8s集群的其他服务器能否访问pod的服务地址 ip:80---无法访问

2、能否跳过pod直接访问容器的服务地址 ip:80---没查到ip

首先要知道容器的IP地址

可以看到上面的命令查出的结果是 - 无法看出ip,尝试进入容器查看

然后我就没辙了,不过根据linux系统的精神,所有内容都是文件,但是我google了好久也没找到ip地址到底存在哪一个文件中。然后我就怀疑是不是一定要容器开放端口,ip地址才可以用docker inspect查询,起了一个不开端口的容器,结果也是有ip的。后来问了一个底层开发的朋友,据说ip是不写文件的。

那只能先认为通过k8s启动的容器其实是没有容器ip的。

从侧面看,也很有可能k8s启动的容器确实没有ip

3、访问pod所在的主机的80端口能否返回相同的响应---无法访问

从以上的信息来看,这个port配置应该和docker中暴露端口的意思是一样的,例如下面的例子

来做一下实验:

在我们之前的pod配置文件上增加配置,如下

结果和我们之前的猜测保持一致,增加ports的配置之后,访问宿主机的ip:80也可以访问到pod的内容了。

我这里pod ip 是 10.19.130.67,宿主机是 10.100.1.237。curl 10.19.130.67 和 curl 10.100.1.237 得到的结果是一样的。正当我想再仔细看看的时候,服务器又挂了,wc,只能明天找网管重启了。

---第二天

昨天,我还想看看

1、关了这个pod之后是否就不能访问了

启动了2个pod如下,mynginx1没有配置ports,mynginx2配置了ports。

当我关了pod-mynginx2之后访问宿主机10.100.2.167应该就不能通了,结果居然是---能访问到!

大吃一惊!结果ip弄错了,宿主机不是10.100.2.167,而是10.100.1.237,犯了个低级错误。

结果如下:这回和预期的结果终于一样了。

2、宿主机上是不是本身就开启了nginx,所以恰巧就能访问

确认宿主机上没有开启nginx

3、宿主机上的端口开放情况

使用netstat查看宿主机的端口开放,居然没有发现80端口开着,好奇怪。

那如果在10.100.1.237宿主机上启动一个nginx端口开在80,结果会是什么样子呢。

我居然启动了,没有端口已被占用的报错。现在把宿主机上的nginx的index页面的内容改一下,看访问10.100.1.237:80时,到底访问的是哪一个nginx。

分别从集群内部3台服务器和集群外部1台服务器的机器取访问10.100.1.237:80,访问到的都是pod中的nginx。

会不会跟启动顺序有关,因为现在的情况是先启动了pod-nignx,后启动 宿主机-nginx,那现在将pod-nginx关闭,访问10.100.1.237:80,看是啥。

集群内部3台服务器和集群外部1台服务器访问10.100.1.237:80,结果一致,都是宿主机-nginx。

再启动pod-nginx,查看结果。

访问结果又变回pod-nginx了,4台服务器结果一致。

再去看一下宿主机-nginx的日志,有没有报错信息-----------没有错误日志

现在基本可以得出结论了:当pod和宿主机同时使用某一个端口时,不会因为冲突而报错,但是pod会优先占用端口,而与启动顺序无关。

至于为什么会这样,就不去深究了,毕竟精力有限,作为运维实施,了解到这样子的程度应该够用了。

Ⅵ 宿主机telnet不通docker容器内的ip地址怎么解决

Docker搭建了lnmp环境后,如果需要访问安装在宿主机上的数据库或中间件,是不能直接使用127.0.0.1这个ip的,这个ip在容器中指向容器自己,那么应该怎么去访问宿主机呢:

例如你的docker环境的虚拟IP是192.168.99.100,那么宿主机同样会托管一个和192.168.99.100同网段的虚拟IP,并且会是主IP:192.168.99.1,那么就简单了,在容器中访问192.168.99.1这个地址就等于访问宿主机,问题解决注意,通过192.168.99.1访问宿主机,等于换了一个ip,如果数据库或中间件限制了本机访问或者做了ip段限制,要记得添加192.168.99.1到白名单