podman-pod笔记
Podman Pod 完整指南
目录
1. Pod 基础概念
什么是 Pod?
Pod 是 Podman 中一组容器的集合,这些容器共享:
- 网络命名空间(Network Namespace)
- IPC 命名空间(Inter-Process Communication)
- 存储卷(Volumes)
Pod 的组成
┌─────────────────────────────────────┐
│ Pod: gateway (共享 IP) │
│ │
│ ┌──────────────┐ │
│ │ Infra 容器 │ ← 自动创建,维护网络 │
│ │ (pause) │ 命名空间 │
│ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌─────────────┐ │
│ │ Caddy │ │ Typecho │ │
│ │ :80/:443 │ │ :8080 │ │
│ └──────────────┘ └─────────────┘ │
└─────────────────────────────────────┘
│
│ 宿主机端口映射
▼
宿主机: 80 → Pod 80
宿主机: 443 → Pod 443Infra 容器(基础设施容器)
- 作用:维护 Pod 的网络命名空间
- 命名:默认
<Pod_ID>-infra,可自定义 - 镜像:
k8s.gcr.io/pause或localhost/podman-pause - 资源:几乎不消耗 CPU/内存(< 1MB)
- 日志:基本为空,很少需要查看
2. Pod 的核心优势
2.1 网络简化(最大优势)
Pod 内的容器可以通过 localhost 直接通信:
# Pod 内 Caddy 反向代理 Typecho
# 无需配置复杂网络,直接使用 localhost
reverse_proxy localhost:8080对比:
| 通信方式 | 网络路径 | 延迟 |
|---|---|---|
| 同一 Pod | localhost → loopback | 极低 |
| 不同容器 | 网桥 + iptables/NAT | 略高 |
2.2 资源共享
- 共享网络命名空间:共用 IP 和端口
- 共享 IPC 命名空间:支持进程间通信
- 共享存储卷:挂载一次,所有容器可访问
2.3 管理便捷
# 一键管理整个应用栈
podman pod start gateway # 启动所有容器
podman pod stop gateway # 停止所有容器
podman pod restart gateway # 重启所有容器
podman pod rm gateway # 删除 Pod(含所有容器)3. Pod 的负载影响
⚠️ Pod 不会减小负载
| 维度 | 影响 | 说明 |
|---|---|---|
| CPU 开销 | ❌ 不减少 | 容器内进程消耗不变 |
| 内存开销 | ❌ 不减少 | 每个容器独立内存空间 |
| 网络延迟 | ✅ 略有降低 | localhost 通信快几毫秒 |
| 资源隔离 | ⚠️ 降低隔离性 | 共享网络,风险增加 |
何时使用 Pod?
适合:
- ✅ 紧密耦合的服务(Web 服务器 + 应用)
- ✅ 需要极低延迟通信
- ✅ Sidecar 模式(主容器 + 辅助容器)
- ✅ 简化管理
不适合:
- ❌ 独立的大型服务(数据库)
- ❌ 需要网络隔离的安全组件
- ❌ 需要独立扩展的服务
4. Pod 的创建与管理
4.1 创建 Pod
基础创建:
podman pod create --name gateway完整配置:
podman pod create \
--name gateway \ # Pod 名称
--infra-name gateway-infra \ # 自定义 infra 容器名(可选)
--memory 512m \ # 内存限制
--cpus 0.6 \ # CPU 限制
--publish 80:80 \ # 端口映射
--publish 443:443 \
--network bridge \ # 网络模式
--volume data:/data # 共享卷4.2 查看 Pod
# 查看所有 Pod
podman pod ls
podman pod ps
# 查看 Pod 详情
podman pod inspect gateway
# 查看 Pod 内的容器
podman ps --pod gateway
podman ps -a --filter "pod=gateway"4.3 添加容器到 Pod
# 方法1:使用 --pod 参数(推荐)
podman run -d \
--name caddy \
--pod gateway \
caddy:latest
# 方法2:使用 --net=container 方式
podman run -d \
--name typecho \
--net=container:gateway-infra \
typecho:latest4.4 管理 Pod
# 启动/停止/重启
podman pod start gateway
podman pod stop gateway
podman pod restart gateway
# 删除 Pod(会自动删除所有容器)
podman pod rm gateway
podman pod rm --force gateway # 强制删除
# 查看 Pod 资源使用
podman pod stats gateway5. 端口管理
5.1 核心规则
同一个 Pod 内的容器不能监听同一个端口
原因:所有容器共享网络命名空间,就像运行在同一台机器上。
5.2 端口分配示例
# 推荐分配方案
Caddy: 80, 443 # 对外服务
Typecho: 8080 # 内部应用
MySQL: 3306 # 数据库
Redis: 6379 # 缓存5.3 查看端口占用
方法1:使用临时容器(最可靠)
podman run --rm -it --pod gateway alpine sh
apk add iproute2
ss -tln方法2:通过 infra 容器
podman exec gateway-infra ss -tln
# 或使用 nsenter
INFRA_PID=$(podman inspect gateway-infra | grep -i '"Pid"' | grep -o '[0-9]\+')
sudo nsenter -t $INFRA_PID -n ss -tln方法3:测试特定端口
podman run --rm --pod gateway alpine sh -c \
"nc -l -p 8080 & sleep 1 && echo '端口可用' || echo '端口被占用'"方法4:查看 /proc/net/tcp
podman exec gateway-infra cat /proc/net/tcp | awk '{print $2}' | \
grep -v "local_address" | cut -d: -f2 | \
while read hex; do printf "%d\n" 0x$hex; done | sort -n6. 容器日志查看
6.1 日志查看方式对比
| 命令 | 查看范围 | 说明 |
|---|---|---|
podman logs gateway-infra | 仅 infra 容器 | 基本无日志 |
podman logs caddy | 仅 caddy 容器 | 查看具体应用 |
podman pod logs gateway | Pod 内所有容器 | 一次性查看所有 |
podman logs caddy typecho | 指定的多个容器 | 灵活组合 |
6.2 常用日志命令
# 查看最近 100 行
podman logs --tail 100 caddy
# 实时跟踪
podman logs -f caddy
# 查看所有容器日志(脚本方式)
for cont in $(podman ps --pod gateway --format "{{.Names}}" | grep -v infra); do
echo "=== $cont ==="
podman logs --tail 20 $cont
done7. 网络调试
7.1 进入 Pod 网络命名空间
# 方法1:使用临时容器
podman run --rm -it --pod gateway alpine sh
# 方法2:使用 infra 容器
podman exec -it gateway-infra sh
# 方法3:使用 nsenter(最底层)
INFRA_PID=$(podman inspect gateway-infra | grep -i '"Pid"' | grep -o '[0-9]\+')
sudo nsenter -t $INFRA_PID -n sh7.2 网络排查命令
# 查看网络接口
ip addr show
# 查看路由表
route -n
ip route
# 查看端口监听
ss -tln
netstat -tln
# 抓包分析
tcpdump -i any -n port 80
# 测试连通性
curl localhost:8080
ping 8.8.8.88. 最佳实践
8.1 命名规范
| 组件 | 推荐命名 | 示例 |
|---|---|---|
| Pod | 项目/服务名称 | gateway、web-app |
| Infra 容器 | Pod名称 + -infra | gateway-infra |
| 应用容器 | 应用名称 | caddy、typecho |
8.2 创建 Pod 示例
# 生产环境推荐配置
podman pod create \
--name gateway \
--infra-name gateway-infra \
--memory 1g \
--cpus 1 \
--publish 80:80 \
--publish 443:443 \
--volume shared_data:/data:z
# 添加容器
podman run -d --name caddy --pod gateway caddy:latest
podman run -d --name typecho --pod gateway typecho:latest8.3 数据持久化
# 创建命名卷
podman volume create typecho_data
# 挂载到容器
podman run -d \
--name typecho \
--pod gateway \
-v typecho_data:/app/usr \
typecho:latest8.4 资源限制
# Pod 级别限制
podman pod create \
--memory 1g \
--cpus 1.5 \
--name limited-pod
# 容器级别限制会覆盖 Pod 限制
podman run -d \
--pod limited-pod \
--memory 512m \
--cpus 0.5 \
--name app \
app:latest9. 常见问题
Q1: Pod 名称和 Infra 容器名称可以相同吗?
不可以。Pod 名称和容器名称在同一命名空间中必须唯一,会导致冲突。
Q2: 同一个 Pod 里的容器可以监听同一个端口吗?
不可以。会报 address already in use 错误。
Q3: 如何查看 Pod 内所有容器的日志?
使用 podman pod logs <pod-name>(如果版本支持)或循环查看每个容器。
Q4: Infra 容器有什么用?可以删除吗?
Infra 容器维护网络命名空间,不建议删除。删除会导致 Pod 网络功能失效。
Q5: Pod 会减少资源占用吗?
不会。Pod 不减少 CPU/内存占用,只是简化网络和管理。
Q6: 如何将一个现有容器加入 Pod?
无法直接加入,需要重新创建容器时指定 --pod 参数。
Q7: Pod 内容器如何访问外部网络?
通过 Pod 的网络接口,自动共享主机的网络配置,无需额外配置。
Q8: 端口映射是在 Pod 级别还是容器级别?
在 Pod 创建时通过 --publish 设置,Pod 内所有容器共享这些映射。
Q9: 如何调试 Pod 网络问题?
使用 podman exec 进入 infra 容器或使用 nsenter 进入网络命名空间。
Q10: Pod 和 Docker Compose 有什么区别?
- Pod:共享网络命名空间,容器间 localhost 通信
- Compose:容器独立网络,通过服务名通信
10. 快速参考
常用命令速查表
| 操作 | 命令 |
|---|---|
| 创建 Pod | podman pod create --name <name> |
| 查看 Pod | podman pod ls |
| 查看 Pod 内容器 | podman ps --pod <pod> |
| 添加容器 | podman run --pod <pod> ... |
| 启动 Pod | podman pod start <pod> |
| 停止 Pod | podman pod stop <pod> |
| 删除 Pod | podman pod rm <pod> |
| 查看日志 | podman pod logs <pod> |
| 查看资源 | podman pod stats <pod> |
| 查看端口 | podman run --rm --pod <pod> alpine ss -tln |
总结
Pod 是 Podman 中强大的容器编排功能,核心价值在于:
- 简化网络:容器间 localhost 通信
- 统一管理:一键操作整个应用栈
- 生产就绪:与 Kubernetes 概念一致
何时使用:紧密耦合的服务需要低延迟通信时
何时避免:需要独立扩展或严格隔离的服务
记住:Pod 不会让容器变"轻",但能让管理变"简"!