容器名称解析难题

在 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 为什么这样做,但我不想去探究,而且当我们与 Docker 不完全兼容时,Podman 用户会指责我们。我*不想*默认启用名称解析的第二个原因是,容器运行需要*稍微*长一点的时间。Podman 总是需要使用 netavark 来设置网络,但当启用名称解析时,netavark 还必须调用 aardvark-dns。所需的时间可能微乎其微,但在某些情况下这很重要。

Brent Baude

高级首席软件工程师,Podman 架构师

“容器名称解析难题”的一个回应

  1. runiq Avatar

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

发表回复

订阅

输入您的电子邮件地址以接收来自本网站的电子邮件更新。

返回

您的消息已发送

警告
警告
警告。

分类


搜索