mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1134 字
3 分钟
容器化面试题
2023-10-17

一、Docker 的六大命名空间#

Linux 容器技术的核心是**命名空间(Namespace)控制组(cgroup)**两大机制。命名空间隔离了系统中正在运行的进程,让它们以为自己拥有独立的资源视图;控制组则限制这些进程可以使用的资源上限。

Docker 依赖 Linux 内核的六种命名空间实现容器隔离:

命名空间功能对应系统调用
UTS隔离主机名和域名unshare --uts
Mount隔离文件系统挂载点unshare --mount
PID隔离进程 ID 空间unshare --pid
Network隔离网络设备、端口等unshare --net
User隔离用户和组 IDunshare --user
IPC隔离信号量、共享内存、消息队列unshare --ipc

1.1 UTS 命名空间#

UTS(Unix Time-sharing System)命名空间隔离主机名(hostname)和域名(domainname)。在容器内修改主机名,不会影响宿主机或其他容器:

# 在容器内查看
hostname # 输出容器的 hostname
# 修改容器主机名
hostname new-container-name # 仅影响当前容器

1.2 Mount 命名空间#

Mount 命名空间隔离文件系统挂载点。容器内的挂载操作不会影响宿主机,实现原理是chroot(在容器内重新定义根目录的视图):

# Docker 的层叠文件系统(UnionFS)
# 容器启动时,Docker 将容器的根文件系统挂载为只读层
# 然后在之上叠加油写层(Copy-on-Write)
# 所有修改写入写层,基础镜像保持不变

1.3 PID 命名空间#

PID 命名空间隔离进程 ID。容器内的进程从 PID 1 开始编号,与宿主机上的 PID 完全独立:

# 容器内
ps aux
# PID 1 是容器的 init 进程(如 /bin/sh 或 CMD 指定的进程)
# 宿主机上查看
docker top <container>
# 显示容器内所有进程,但 PID 是宿主机视角的

PID 命名空间的嵌套:PID 命名空间可以嵌套,子命名空间可以看到父命名空间中的进程,但父命名空间看不到子命名空间中的进程。这使得 Kubernetes 的 Pod 实际上共享同一个 PID 命名空间(Pause 容器作为 PID 1)。

1.4 Network 命名空间#

Network 命名空间隔离网络设备、IP 地址、端口号、路由表、防火墙规则等:

# 查看容器的网络命名空间
docker exec <container> cat /proc/1/ns/net
# 容器有独立的:
# - 网络设备(eth0 vethxxx)
# - IP 地址和路由表
# - 端口空间(容器内 8080 端口不影响宿主机)
# - iptables 规则

Docker 通过veth pair(虚拟以太网对)将容器连接到宿主机网桥,实现容器与外界的通信。

1.5 IPC 命名空间#

IPC 命名空间隔离 System V IPC 对象(信号量、共享内存、消息队列)以及 POSIX 消息队列:

# 容器内创建的共享内存在宿主机或其他容器不可见
# IPC 机制原本是为了进程间通信,但在容器化场景下需要隔离

1.6 User 命名空间#

User 命名空间隔离用户和组的 ID 映射:

# 容器内 root (UID 0) 可以映射到宿主机上的普通用户
# 例如容器内 UID 0 -> 宿主机 UID 100000
# 这样即使容器内 root 提权,在宿主机上也只是普通用户
# /etc/subuid 和 /etc/subgid 定义映射关系

二、cgroup 的作用与实现#

命名空间解决了「隔离」问题,但容器使用的资源上限由 cgroup(Control Group)控制。

2.1 cgroup 核心概念#

cgroup 将进程组织为层级结构,每个层级可以设置资源上限:

cgroup 层级:
/sys/fs/cgroup/
├── cpu/ # CPU 时间配额
├── memory/ # 内存上限
├── pids/ # 进程数上限
└── blkio/ # 磁盘 I/O 上限

2.2 Docker 的资源限制#

# 内存限制
docker run -m 512m nginx
# CPU 限制(限制到 0.5 核)
docker run --cpu-quota=50000 --cpu-period=100000 nginx
# 更简洁的写法
docker run --cpus=0.5 nginx
# 限制 I/O 带宽
docker run --device-read-bps /dev/sda:10mb nginx
# 限制进程数
docker run --pids-limit 100 nginx

2.3 cgroup v2#

新版 Linux 使用 cgroup v2(unified hierarchy),相比 v1 有更好的层级管理和资源分配:

# 检查当前 cgroup 版本
mount | grep cgroup
# cgroup2 on /sys/fs/cgroup/unified 表示 v2

三、Docker 的存储驱动#

Docker 使用存储驱动(Storage Driver)实现层叠文件系统:

驱动原理特点
overlay2现代首选,性能好适用于大多数场景
aufs早期使用,多层叠加拿兼容性广但性能差
devicemapper块设备映射性能一般
btrfs/zfs文件系统级别的 COW适合特定场景

3.1 Copy-on-Write 机制#

Docker 镜像的每一层都是只读的。当容器修改某个文件时,Docker 会将该文件复制到容器的写层(container layer),这就是 Copy-on-Write。

镜像层(只读):
layer1: /bin
layer2: /lib
layer3: /app
容器层(可写):
container-layer: /app/config.py # 覆盖了镜像层的文件

四、Kubernetes 与容器的关系#

4.1 Pod 是最小调度单元#

Kubernetes 中,Pod 是容器编排的最小单元。一个 Pod 可以包含多个容器,这些容器共享 PID、Network、IPC 命名空间:

apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: app
image: myapp:v1
- name: sidecar # 共享网络和 PID 空间
image: sidecar:v1

Pause 容器(infra container)是 Pod 中所有其他容器的父容器,负责维护命名空间。

4.2 Kubernetes 的网络模型#

Kubernetes 要求每个 Pod 拥有独立的 IP 地址,Pod 之间的通信无需 NAT。这通过 CNI(Container Network Interface)插件实现:

  • Flannel:Overlay 网络,通过 VXLAN 封装
  • Calico:纯三层网络,通过 BGP 路由
  • Cilium:基于 eBPF,提供更丰富的网络策略

4.3 容器安全#

容器安全需要关注以下几个方面:

  1. 容器的非 root 化:使用 USER 指令切换到非 root 用户
  2. 只读文件系统readOnlyRootFilesystem: true
  3. 资源限制:始终设置 CPU 和内存限制
  4. 网络策略:使用 NetworkPolicy 限制 Pod 间通信
  5. Secrets 管理:通过 Kubernetes Secrets 传递敏感信息

五、参考#


参考#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

容器化面试题
https://blog.souloss.com/posts/interview/container/
作者
Souloss
发布于
2023-10-17
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时