,

容器名称解析难题

我们在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 架构师高级首席软件工程师

对“容器名称解析难题”的一条回复

  1. runiq Avatar

    有没有办法在 containers.conf 中为默认网络启用名称解析?

发表评论

订阅

使用您的电子邮件地址注册,以便从本网站接收电子邮件更新。


类别


搜索