最近几个月,我一直在重构 GoPanel 的底层容器架构。
在这个过程中,我做了一个很多人看来有点折腾的决定:
在生产环境逐步从 Docker 迁移到 Rootless Podman 。
这次迁移并不是为了追新。
而是因为随着 SaaS 场景越来越复杂,多租户隔离、安全边界以及资源利用率的问题开始变得越来越重要。
前后折腾了三个月,踩了不少权限和网络相关的坑。
今天把这段迁移过程中的经验、避坑方案以及一些实际感受整理出来,希望能给正在评估 Podman 的朋友一点参考。
Docker 依然是非常优秀的容器方案。
事实上,过去很多年我也一直是 Docker 的重度用户。
但随着业务的发展,我越来越关注下面几个问题。
Docker 的核心架构依赖 Docker Daemon 。
Docker Daemon 通常以 Root 权限运行。
对于多租户 SaaS 场景来说,它天然会成为一个高价值目标。
而 Rootless Podman 最大的特点之一就是:
容器可以完全以普通用户身份运行。
即使容器内部拥有 Root 权限。
在宿主机层面,它依然只是一个普通用户。
对于需要暴露公网服务的 SaaS 系统来说,这种隔离方式很有吸引力。
Podman 本身没有中心化守护进程。
容器本质上就是普通 Linux 进程。
整个运行模型更加接近 Linux 原生系统。
对于长期运行的服务器来说:
这也是我最终决定研究 Rootless Podman 的原因。
我希望未来的面板底层具备:
因此最终把目光放到了 Rootless Podman 上。
如果你准备在生产环境使用 Rootless Podman 。
下面几个坑建议提前了解。
Rootless 模式下。
Podman 是以普通用户运行的。
而 Linux 默认不允许普通用户绑定:
1~1023
范围内的端口。
例如:
podman run -p 80:80 nginx
大概率会直接报错。
修改内核参数:
# 临时生效
sysctl net.ipv4.ip_unprivileged_port_start=80
# 永久生效
echo "net.ipv4.ip_unprivileged_port_start=80" >> /etc/sysctl.conf
sysctl -p
这样普通用户也能绑定低位端口。
这是我踩得最深的坑。
例如:
-v /data:/app
容器启动正常。
目录挂载正常。
但是程序疯狂报:
Permission denied
检查半天发现:
最终问题出在:
subuid
subgid
Rootless Podman 的 UID 映射机制。
使用:
--userns=keep-id
保持容器内外 UID 一致。
podman run -d \
--name my_app \
--userns=keep-id \
-v /home/user/data:/app:Z \
my_image
如果系统开启 SELinux:
:Z
一定不要省略。
例如:
-v /home/user/data:/app:Z
否则即使 Linux 权限正确。
SELinux 依然可能拒绝访问。
大多数 Docker 用户已经习惯:
docker-compose.yml
切换到 Podman 后。
很多人会先尝试:
podman-compose
对于普通项目来说完全够用。
但在复杂网络场景下:
偶尔还是会遇到一些需要额外排查的问题。
对于未来有 Kubernetes 规划的项目。
我更倾向于直接使用:
podman play kube
例如:
podman play kube cluster.yaml
Podman 对 Kubernetes YAML 提供了不错的兼容支持。
对于未来需要迁移 Kubernetes 的团队来说比较友好。
说了这么多坑。
收益呢?
在我们的测试环境中:
观察到整体内存占用有一定幅度下降。
不同业务场景差异较大。
目前我仍在持续压测和验证数据。
但至少从现阶段来看:
Rootless Podman 在资源利用率方面表现不错。
这是我个人最喜欢的能力之一。
Podman 可以直接生成 Systemd 服务:
podman generate systemd \
--new \
--files \
my_app
之后直接:
systemctl enable container-my_app.service
systemctl start container-my_app.service
以后:
全部交给 Linux 原生 Systemd 管理。
整个运行模型非常干净。
最后也和大家坦诚聊聊 GoPanel 目前的情况。
目前 GitHub 上公开的 GoPanel v1.x 版本,并不是一个从零开始凭空写出来的项目。
它的基础架构借鉴和参考了 1Panel 的优秀设计。
这也是为什么很多朋友第一次看到 GoPanel 时,会觉得界面和交互有些熟悉。
原因很简单。
我认为 1Panel 在易用性和交互体验方面做得非常优秀。
对于服务器管理面板来说,这是值得学习的地方。
所以在项目早期,我选择站在前人的肩膀上,把更多时间投入到自己真正想解决的问题上。
而我真正关注的问题主要有三个:
最近几个月我做得最多的工作,其实都在底层:
很多工作甚至看不到界面变化。
但它决定了系统未来能走多远。
目前仓库中的代码仍然保留着部分历史实现。
后续会逐步把新的 Rootless Podman 架构合并进入主分支。
我的目标很简单:
保留优秀的交互体验,
用更轻量、更安全、更适合 SaaS 场景的底层架构重新实现它。
这些年我做过很多事情。
修过车。
跑过长途。
做过户外垂钓项目。
写过 PHP 。
后来又写 Golang 。
创业成功过,也失败过。
最近整理这套架构的时候。
顺手把这些年从辍学到创业、从修车到写代码的经历整理成了一个 GitHub 项目。
算是给自己这些年的一次归档。
有兴趣的话可以看看。
Life is a legacy system that requires constant refactoring.
https://github.com/aihop/Refactoring-the-Self
https://github.com/aihop/gopanel
如果你在生产环境落地过 Rootless Podman 。
或者对下面这些问题有经验:
欢迎一起交流。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.