Docker
参考文档
OCI
https://github.com/opencontainers
- Open Container Initiative,围绕容器技术创建开放标准
Namespace
- namespace 是 Linux 系统的底层概念,在内核层实现,即有一些不同类型的名称空间部署在内核内;
- 名称空间可以实现宿主机与容器间的资源隔离;
- 可以隔离的资源有磁盘挂载点、文件系统、进程、主机名、网络、用户等。
| 隔离类型 | 功能 | 系统调用参数 | 起始内核版本 |
|---|---|---|---|
| MNT NameSpace (mount) | 提供磁盘挂载点和文件系统的隔离能力 | CLONE_NEWNS | 2.4.19 |
| IPC NameSpace (Inter-Process Communication) | 提供进程通信的隔离能力,包括信号量、消息队列、共享内存 | CLONE_NEWIPC | 2.6.19 |
| UTS NameSpace (UNIX Timesharing system) | 提供内核,主机名和域名隔离能力 | CLONE_NEWUTS | 2.6.19 |
| PID NameSpace (Process Identification) | 提供进程隔离能力 | CLONE_NEWPID | 2.6.24 |
| NET NameSpace(network) | 提供网络隔离能力,包括网络设备、网络栈、端口等 | CLONE_NEWNET | 2.6.29 |
| User NameSpace(user) | 提供用户隔离能力,包括用户和组 | CLONE_NEWUSER | 3.8 |
MNT NameSpace
- 宿主机使用了 chroot 技术把容器锁定到一个指定的运行目录中,从而禁止容器访问宿主机的资源。
IPC NameSpace
- 允许一个容器内的不同进程的(内存、缓存等)数据访问,但是不能跨容器直接访问其他容器的数据
UTS NameSpace
- UNIX Timesharing System,UNIX分时系统,包含了运行内核的名称、版本、底层体系结构类型等信息;
- 用于系统标识,其中包含了主机名 hostname 和域名 domainname,它使得一个容器拥有属于自己的主机名标识,这个主机名标识独立于宿主机系统和其他的容器。
Control Groups
-
Cgroup 是一个 Linux 内核特性,它可以实现对一组进程的资源使用(CPU、内存、磁盘 I/O 和网络等)进行限制、审计和隔离。
-
Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上线,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(如:将进程挂起和恢复等操作)
验证系统 cgroups
- cgroups在内核层中默认已经开启,内核版本越新支持的功能越多
CentOs 8.3 cgroups:
[root@docker ~]# cat /etc/centos-release
CentOS Linux release 8.3.2011
[root@docker ~]# grep CGROUP /boot/config-4.18.0-240.el8.x86_64
CONFIG_CGROUPS=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_SOCK_CGROUP_DATA=y
CONFIG_BLK_CGROUP_IOLATENCY=y
# CONFIG_BLK_CGROUP_IOCOST is not set
# CONFIG_BFQ_CGROUP_DEBUG is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=yCentOS 7.6 cgroups:
[root@localhost ~]#cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[root@localhost ~]#grep CGROUP /boot/config-3.10.0-957.el7.x86_64
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=yUbuntu 20.04 cgroups:
root@ubuntu:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal
root@ubuntu:~# cat /etc/issue
Ubuntu 20.04.1 LTS \n \l
root@ubuntu:~# grep CGROUP /boot/config-5.4.0-42-generic
CONFIG_CGROUPS=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_SOCK_CGROUP_DATA=y
# CONFIG_BLK_CGROUP_IOLATENCY is not set
CONFIG_BLK_CGROUP_IOCOST=y
# CONFIG_BFQ_CGROUP_DEBUG is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=ycgroups 中内存模块:
root@ubuntu:~# grep MEMCG /boot/config-5.4.0-42-generic
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
# CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_MEMCG_KMEM=y
CONFIG_SLUB_MEMCG_SYSFS_ON=ycgroups 具体实现
- blkio:块设备IO限制
- cpu:使用调度程序为 cgroup 任务提供 cpu 的访问
- cpuacct:产生 cgroup 任务的 cpu 资源报告
- cpuset:如果是多核心的 cpu ,这个子系统会为 cgroup 任务分配单独的 cpu 和内存
- devices:允许或拒绝 cgroup 任务对设备的访问
- freezer:暂停和恢复 cgroup 任务
- memory:设置每个 cgroup 的内存限制以及产生内存资源报告
- net_cls:标记每个网络包以供 cgroup 方便使用
- ns:命名空间子系统
- perf_event:增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的 group 的所有线程以及运行在特定CPU上的线程
查看系统 cgroups
# ll /sys/fs/cgroup/
total 0
drwxr-xr-x 15 root root 380 Dec 12 22:02 ./
drwxr-xr-x 11 root root 0 Dec 12 22:02 ../
dr-xr-xr-x 6 root root 0 Dec 12 22:02 blkio/
lrwxrwxrwx 1 root root 11 Dec 12 22:02 cpu -> cpu,cpuacct/
lrwxrwxrwx 1 root root 11 Dec 12 22:02 cpuacct -> cpu,cpuacct/
dr-xr-xr-x 6 root root 0 Dec 12 22:02 cpu,cpuacct/
dr-xr-xr-x 3 root root 0 Dec 12 22:02 cpuset/
dr-xr-xr-x 6 root root 0 Dec 12 22:02 devices/
dr-xr-xr-x 4 root root 0 Dec 12 22:02 freezer/
dr-xr-xr-x 3 root root 0 Dec 12 22:02 hugetlb/
dr-xr-xr-x 6 root root 0 Dec 12 22:02 memory/
lrwxrwxrwx 1 root root 16 Dec 12 22:02 net_cls -> net_cls,net_prio/
dr-xr-xr-x 3 root root 0 Dec 12 22:02 net_cls,net_prio/
lrwxrwxrwx 1 root root 16 Dec 12 22:02 net_prio -> net_cls,net_prio/
dr-xr-xr-x 3 root root 0 Dec 12 22:02 perf_event/
dr-xr-xr-x 6 root root 0 Dec 12 22:02 pids/
dr-xr-xr-x 2 root root 0 Dec 12 22:02 rdma/
dr-xr-xr-x 6 root root 0 Dec 12 22:02 systemd/
dr-xr-xr-x 5 root root 0 Dec 12 22:02 unified/Cgroup Driver
- cgroupfs:
- systemd:新版k8s需修改为此Cgroup Driver
容器 Runtime
- Runtime 是真正运行容器的地方,而 docker 则是 Runtime 的一种。
- 为了运行不同的容器,Runtime 需要和操作系统内核紧密协作,以便为容器提供相应的运行环境。
- 如果大家用过 Java,可以这样来理解 runtime 与容器的关系:Java 程序就好比是容器,JVM 则好比是 runtime。JVM 为 Java 程序提供运行环境。同样的道理,容器只有在 runtime 中才能运行。
查看 docker 默认的 runtime
# docker info | grep runtime -i
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc容器 runtime 类型
- **lxc:**Linux 上老牌的容器 runtime。Docker 最初也是用 lxc 作为 runtime。
- **runc:**Docker 自己开发的容器 runtime,符合 oci 规范,也是现在 Docker 的默认 runtime。
- **rkt:**CoreOS 开发的容器 runtime,符合 oci 规范,因而能够运行 Docker 的容器。
Docker Storage Driver
About storage drivers | Docker Documentation
Docker storage drivers | Docker Documentation
使用覆盖 FS 存储驱动程序|码头工人文档 (docker.com)
- 容器使用了联合文件系统(Union File System,UnionFS),将多个目录,挂载成为一个虚拟目录。不同的目录在这个虚拟目录里面又可以拥有独立的权限(镜像层只读,容器层读写)。这个虚拟的目录加上宿主机的内核就模拟成了一个完整的操作系统,最终呈现给容器使用。
- Docker 使用的存储驱动都是联合文件系统类型的
查看 Docker 默认的 Storage Driver:
- 目前 Docker 默认的 Storage Driver 为 overlay2,通常无需额外修改。
# docker info | grep 'Storage Driver'
Storage Driver: overlay2UnionFS 范例
- 下面以aufs文件系统举例,aufs 也是 UnionFS 的一种。
# 创建挂载目录和文件
# mkdir ./dir{1..2}
# echo 'here is dir1' > ./dir1/file1
# echo 'here is dir2' > ./dir2/file2
# 创建挂载点
# mkdir -p /data/overlay
# 使用aufs文件系统进行挂载,dir1为只读,dir2为读写
# mount -t aufs -o br=./dir1/=ro:./dir2/=rw none /data/overlay/
# 与正常挂载看起来无异
# ls -l /data/overlay/
total 8
-rw-r--r-- 1 root root 13 Dec 14 19:06 file1
-rw-r--r-- 1 root root 13 Dec 14 19:06 file2
# 但dir1为只读,dir2为读写,因为在挂载时分别对两个目录定义了不同的挂载选项
# echo newdata > /data/overlay/file1
-bash: /data/overlay/file1: Read-only file system
# echo newdata > /data/overlay/file2
# cat /data/overlay/file2
newdata
# df -Th /data/overlay/
Filesystem Type Size Used Avail Use% Mounted on
none aufs 24G 14G 9.4G 59% /data/overlaydocker info 输出说明
# docker info
Client:
Context: default
Debug Mode: false # client端是否开启debug
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 1 # 当前主机运行容器的总数
Running: 0 # 有几个容器是正在运行的
Paused: 0 # 有几个容器是暂停的
Stopped: 1 # 有几个容器是停止的
Images: 1 # 当前服务端存在的镜像数
Server Version: 20.10.21
Storage Driver: overlay2 # 正在使用的存储驱动
Backing Filesystem: extfs # 后端文件系统,即服务器磁盘的文件系统
Supports d_type: true # 是否支持d_type
Native Overlay Diff: true # 是否支持差异数据存储
userxattr: false
Logging Driver: json-file # 日志类型
Cgroup Driver: cgroupfs # Cgroup类型
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay # overlay跨主机通信
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive # 是否支持swarm
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc # 已安装的容器运行时
Default Runtime: runc # 默认使用的容器运行时
Init Binary: docker-init # 初始化容器的守护进程,即pid为1的进程
containerd version: 3df54a852345ae127d1fa3092b95168e4a88e2f8
runc version: v1.0.3-0-gf46b6ba
init version: de40ad0
Security Options: # 安全选项
apparmor # 安全模块
seccomp # 安全计算模块
Profile: default
Kernel Version: 5.4.0-131-generic # 宿主机内核版本
Operating System: Ubuntu 20.04.4 LTS # 宿主机系统版本
OSType: linux # 宿主机系统类型
Architecture: x86_64 # 宿主机架构
CPUs: 2 # 宿主机CPU数量
Total Memory: 2.855GiB # 宿主机内存大小
Name: gitlab-server # 宿主机主机名,hostname
ID: KMMF:2WZW:L34V:RTUN:E6JL:BV74:EMJ3:DOAB:EUDG:SDCZ:P56Y:E76O # 宿主机ID
Docker Root Dir: /var/lib/docker # 宿主机关于docker数据的保存目录
Debug Mode: false # server端是否开启debug
Registry: https://index.docker.io/v1/ # 镜像仓库
Labels:
Experimental: false # 是否为测试版
Insecure Registries:
127.0.0.0/8 # 非安全的镜像仓库
Live Restore Enabled: false # 是否开启活动重启(重启docker-daemon不关闭容器)
WARNING: No swap limit support # 未开启swap限制