迁移至 podman

本贴最后更新于 231 天前,其中的信息可能已经事过景迁

因为个人的开发环境已经用 podman 替换掉了 docker-desktop,打算把服务器的容器运行时从 docker 替换成 podman

  podman 最大的亮点是支持 rootless 模式 和 no-daemon(通过 systemd service unit 来管理容器进程)。

  服务器系统为 debian 12,踩坑如下:

apt 默认官方源版本落后

  debian 官方 apt 源,版本过于落后(目前才到 4.3.1)。

➜ sudo apt search podman  -n 2>/dev/null| grep -iE ^podman/stable
podman/stable 4.3.1+ds1-8+b1 amd64
  1. <4.7 不支持 compose 子命令。当时心想反正不影响 docker-compose 通过 socket 运行容器。无关紧要,没想到这才是深渊的开始。
  2. <4.8 keep-id 创建的容器,容器销毁时 ip 不回收,导致 IPAM 消耗完最终无法再创建出新的容器。https://github.com/containers/podman/issues/18615 (属实天坑,这个参数在 rootless 下很常用的)从 https://packages.debian.org/trixie/podman 上,整一个 4.9 来用吧。
  3. 不支持 socket 方式创建的容器生成 systemd 单元文件:https://github.com/containers/podman/issues/13289。好吧,没有关系,我切换到 podman-compose,其原理是生成 podman run 命令进行调用。(podman 现在在推 Quadlets/systemd,但又不能直接把 docker-compose.yml 无缝转换)
  4. podman-compose volumes 绑定,需要绝对路径。好吧,podman 兼容 docker ,但是没有说 podman-compose` 要完全兼容 docker-compose volume

  当我以为这一切都解决了的时候,发现

  没错,debian apt 官方的版本还是 1.0.3。一口老血喷出,换成 pip3 安装了。

➜ sudo apt search podman  -n 2>/dev/null| grep -iE podman-compose
podman-compose/stable 1.0.3-3 all

结论

  虽然 podman 声称自己完美兼容了 docker,并且在前几年就软文不断,各种文章说 应该用 podman 替换掉 docker 云云,并且极力夸奖 podman 的 rootless 多么的好用。实际上看来,当初吹嘘这些人不一定真的有用过 rootless 模式,严重怀疑当时收了红帽的钱。

  不过至少从最新的版本来看,它可以满足我目前切换的需求。

更新

2024 年 4 月 4 日

Note: Rootlesskit changes the source IP address of incoming packets to an IP address in the container
network namespace, usually 10.0.2.100. If your application requires the real source IP address, e.g.
web server logs, use the slirp4netns port handler

背景: podman rootless 默认网桥下/用户自建网桥下,端口转发通过 Rootlesskit,容器内无法获取客户端的 remote ip。这会严重影响诸如 web 服务的访问统计等功能。

相关问题见:https://github.com/containers/podman/issues/17765 https://github.com/containers/podman/issues/17765

按照其中的描述,network 模式使用 pasta 或者 slirp4netns:port_handler=slirp4netns 可以拿到外部的 ip。

podman rm -af

podman run --name myNginx6443.rootless --publish 6443:80  --rm -d docker.io/library/nginx:alpine
podman run --name myNginx6444.rootless --publish 6444:80  --network pasta  --rm -d docker.io/library/nginx:alpine
podman run --name myNginx6445.rootless --publish 6445:80  --network slirp4netns:port_handler=slirp4netns --rm -d docker.io/library/nginx:alpine


curl http://172.27.215.8:6443 >/dev/null 2>&1
curl http://172.27.215.8:6444 >/dev/null 2>&1
curl http://172.27.215.8:6445 >/dev/null 2>&1

# 内部ip
podman logs myNginx6443.rootless 2>1 | grep GET
10.0.2.100 - - [04/Apr/2024:08:31:12 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1" "-"
# 外部ip
podman logs myNginx6444.rootless 2>1 | grep GET
172.27.215.8 - - [04/Apr/2024:08:31:16 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1" "-"
podman logs myNginx6445.rootless 2>1 | grep GET
172.27.215.8 - - [04/Apr/2024:08:31:19 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1" "-"

根据 podman network 不能将将 bridge 类型和 pastra/slirp4netns options 混合使用podman compose 暂不支持 network_mode: pasta 的说法,本以为单独跑 podman run 且网络单独绑定绑定在 pasta 上可以解决问题,结果这两个模式下 containerIPAddr 信息为空。

podman inspect myNginx6444.rootless | grep  IPAddress
               "IPAddress": "",
podman inspect myNginx6445.rootless | grep  IPAddress
               "IPAddress": "",

traefik 的服务发现绑定的 load-balance ip 就是通过 IPAddress 字段获取。。。。属于是无解了。

time="2024-04-04T08:49:19Z" level=error msg="service \"traefik-traefik\" error: unable to find the IP address for the container \"/traefik\": the server is ignored"

目前看到部分的解决方案是在外部套一层 cdn,然后通过 x-real-ip/x-forwarded-for 来尝试解决。。。

我得收回 podman rooltess 服务器目前可以用的言论了。之前在开发环境完全没有注意到这点。

2 操作
bingoct 在 2024-04-04 16:59:21 更新了该帖
bingoct 在 2024-03-29 10:07:05 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...