我们在Podman社区经常被问到的问题之一是:“为什么我的容器无法通过名称解析其他容器?” 很多情况下,答案是……因为你在一个禁用名称解析的网络上运行。事实上,你很可能在*默认*网络上运行;而这个网络确实没有启用名称解析。下一个问题就是:“为什么Podman会这样做?” 标准答案是:“因为Docker就是这样做的,人们希望尽可能地与Docker兼容。”
让我们通过一个例子来仔细看看。我将使用特权用户创建的容器,因为这有点像Docker的标准。在每个例子中,我都会在同一个网络上启动两个命名容器,并展示名称解析成功和失败的情况。
在第一个例子中,我们确认只有默认的Podman网络存在。它叫做podman,无法删除。记住默认网络没有启用名称解析,任何尝试进行名称解析的尝试都应该并且确实会失败。请注意,test2无法通过名称解析test1。
$ sudo podman network ls NETWORK ID NAME DRIVER 2f259bab93aa podman bridge $ sudo podman run --rm -dt --name test1 alpine top 3703d80740513421772db407972111ad6f535f5ca214f11ddb714a7d64ee140c $ sudo podman run --rm -it --name test2 alpine /bin/sh / # ping test1 ping: bad address 'test1' / # exit
一个解决方案是创建一个新的网络,我把它命名为new。默认情况下,所有创建的网络都启用了名称解析,必须选择退出才能禁用它。然后,我以与之前相同的方式运行两个容器,只是我引用了不同的网络,并且名称解析按预期工作。
$ sudo podman network create new new $ sudo podman network ls NETWORK ID NAME DRIVER d9376e135b46 new bridge 2f259bab93aa podman bridge $ sudo podman run --rm -dt --name test1 --network new alpine top f5a8d256f29221676dc7fca36bca0b680dd7de4a5aa20af2a9d9a02072b34fc7 $ sudo podman run --rm -it --name test2 --network new alpine /bin/sh / # ping test1 PING test1 (10.89.0.2): 56 data bytes 64 bytes from 10.89.0.2: seq=0 ttl=42 time=0.114 ms 64 bytes from 10.89.0.2: seq=1 ttl=42 time=0.107 ms ^C
我之前提到过,Podman 这样做的原因之一是Docker也是这样做的。使用Docker的默认网络执行相同的测试,我们可以看到名称解析也不起作用。解决方案与Podman相同,你需要创建一个新的网络并在那里运行你的容器。
ubuntu@ubuntu:~$ sudo docker network ls NETWORK ID NAME DRIVER SCOPE cb0c4d38339a bridge bridge local 5d0fce56bcad host host local 18c31437e8d0 none null local ubuntu@ubuntu:~$ sudo docker run -dt --name test1 alpine top b23e15c969d253f33f99bd2cecb00b4b061e2a7605190eae683f546692ea34cc ubuntu@ubuntu:~$ sudo docker run -it --name test2 alpine /bin/sh / # ping test1 ping: bad address 'test1' / # exit
如果你希望你的容器始终拥有名称解析功能,但又不想为每个容器都引用不同的网络,你可以将任何网络设置为容器的默认网络。这需要对/etc/containers/containers.conf进行一个小改动(或者如果containers.conf不存在则简单地添加)。
$ sudo cat /etc/containers/containers.conf [network] default_network = "new" $ sudo podman run -dt --rm --name test1 alpine top 18d033aeec0640100bf8165c23b01e55c03fbd5bc320d874a3f4f01f755512c7 $ sudo podman run -it --rm --name test2 alpine /bin/sh / # ping test1 PING test1 (10.89.0.5): 56 data bytes 64 bytes from 10.89.0.5: seq=0 ttl=42 time=0.137 ms 64 bytes from 10.89.0.5: seq=1 ttl=42 time=0.106 ms ^C --- test1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.106/0.121/0.137 ms / # exit
请注意,这里new是默认网络,并且名称解析有效。
我们还被问到,为什么Podman 在这种行为上模仿Docker,尤其是当很多人默认希望启用名称解析时。我的个人答案是双重的。我不知道为什么Docker这样做,但我不想知道,并且Podman用户喜欢在我们与Docker 的bug兼容性不一致时指责我们。我不想默认启用名称解析的第二个原因是,这会让容器运行速度稍微慢一点。Podman 总是必须使用netavark 来设置网络,但当启用名称解析时,netavark 还必须调用aardvark-dns。这段时间可能几乎为零,但在某些情况下却很重要。

Brent Baude
Podman 架构师高级首席软件工程师
发表评论