石头记

Docker、Kubernetes、CI/CD 等技术分享

Docker 生命周期管理

运行容器

docker run 是启动容器的方法,容器启动后返回的是 “长ID”,我们可以通过这个长ID去访问这个容器,也可以通过启动时指定的名字访问这个容器。docker ps 能够看到容器的“短ID”,通过短ID同样可以访问这个容器,甚至只要能够唯一标识这个容器也可使用更短的ID。

docker run

-d 指定容器以后台方式运行;–restart 指定容器的重启策略,默认值no,容器退出时不要重启,on-failure[:max-retries] 只在容器以非0状态码退出时重启。max-retries可以指定尝试重启容器的次数;always 不管退出状态码是什么始终重启容器。当指定容器退出后,docker daemon将无限次数地重启容器。–name 指定容器的名称。

容器的生命周期依赖于启动时执行的命令,只要该命令不结束,容器也就不会退出。理解了这个原理,我们就可以通过执行一个长期运行的命令来保持容器的运行状态。

进入容器

我们经常需要进到容器里去做一些工作,比如查看日志、调试、启动其他进程等。有两种方法进入容器:attach 和 exec。

docker attach

通过 docker attach 可以 attach 到容器启动命令的终端,可通过 Ctrl+p 然后 Ctrl+q 组合键退出 attach 终端。

docker exec

通过 docker exec 进入相同的容器。docker exec -ti bash|sh 是执行 exec 最常用的方式。-ti 以交互模式打开 pseudo-TTY,执行 bash,其结果就是打开了一个 bash 终端。

docker exec

attach VS exec

attach 与 exec 主要区别如下:

  • attach 直接进入容器 启动命令 的终端,不会启动新的进程。
  • exec 则是在容器中打开新的终端,并且可以启动新的进程。

容器的常用操作

docker cmd

stop/start/restart|kill 容器

启动、停止、重启、杀死容器:

1
docker start|stop|restart|kill [容器名|容器ID]

pause/unpause 容器

有时我们只是希望暂时让容器暂停工作一段时间,比如要对容器的文件系统打个快照,这时可以执行 docker pause。

挂起、唤醒容器:

1
docker pause/unpause [容器名|容器ID]

删除容器

1
docker rm -f [容器名|容器ID]

-f 参数可以强制删除运行中的容器。

可以用如下命令删除所有已退出的容器:

1
docker rm $(docker ps -a -q -f status=exited)

可以用如下命令强制删除所有容器:

1
docker rm -f $(docker ps -a -q)

注意:docker rm 是删除容器,而 docker rmi 是删除镜像。

容器的生命周期

对容器的生命周期有了大致的理解,下面这张状态机很好地总结了容器各种状态之间是如何转换的。容器有五种状态:已创建、运行中、已挂起、已停止、已销毁,我们可以通过执行命令让docker在这五种状态间转换。

docker 状态

docker run 是docker pull(如果镜像不存在)、docker create、docker start的复合命令。

容器资源限制

限制内存资源

与操作系统类似,容器可使用的内存包括两部分:物理内存和 swap。 Docker 通过下面两组参数来控制容器内存的使用量。

  • -m 或 –memory:设置内存的使用限额,例如 100M, 2G。
  • –memory-swap:设置 内存+swap 的使用限额。

当我们执行如下命令:

1
docker run -m 200M --memory-swap=300M ubuntu

其含义是允许该容器最多使用 200M 的内存和 100M 的 swap。默认情况下,上面两组参数为 -1,即对容器内存和 swap 的使用没有限制。如果在启动容器时只指定 -m 而不指定 –memory-swap,那么 –memory-swap 默认为 -m 的两倍。

内存限额测试:
docker run -it -m 300M progrium/stress –vm 1 –vm-bytes 280M 未超过限额,容器启动成功

docker mem

docker run -it -m 300M progrium/stress –vm 1 –vm-bytes 320M 超过限额,容器失败退出

docker mem

限制CPU资源

Docker 可以通过 -c 或 –cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。

与内存限额不同,通过 -c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。

CPU限额测试:

1
2
3
4
5
6
# 启动cpu_a,--cpu-shares为1024
# --cpu 用来设置工作线程的数量,宿主机是4核CPU,设置为4表示使用所有CPU
docker run --name cpu_a -it -c 1024 -d progrium/stress --cpu 4
# 启动cpu_b,cpu-shares为512
# --cpu 用来设置工作线程的数量,宿主机是4核CPU,设置为4表示使用所有CPU
docker run --name cpu_b -it -c 512 -d progrium/stress --cpu 4

docker cpu
CPU资源使用对比:
docker cpu stats

当CPU资源紧张时,–cpu-shares设置为1024的容器占用CPU的时间大约是设置为512的容器的两倍

限制磁盘IO

Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。

注意:目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。

block IO 权重

默认情况下,所有容器能平等地读写磁盘,可以通过设置 –blkio-weight 参数来改变容器 block IO 的优先级。

–blkio-weight 与 –cpu-shares 类似,设置的是相对权重值,默认为 500。在下面的例子中,blockio_a 读写磁盘的带宽是 blockio_b 的两倍。

1
2
docker run -it --name blockio_a --blkio-weight 600 ubuntu
docker run -it --name blockio_b --blkio-weight 300 ubuntu

限制 bps 和 iops

可通过以下参数控制容器的 bps 和 iops:

  • –device-read-bps,限制读某个设备的 bps
  • –device-write-bps,限制写某个设备的 bps
  • –device-read-iops,限制读某个设备的 iops
  • –device-write-iops,限制写某个设备的 iops

磁盘IO限额测试:

docker IO

限制容器写 /dev/vda 的速率为 30 MB/s,通过 dd 测试在容器中写磁盘的速度。因为容器的文件系统是在 host /dev/vda 上的,在容器中写文件相当于对 host /dev/vda 进行写操作。另外,oflag=direct 指定用 direct IO 方式写文件,这样 –device-write-bps 才能生效。当去掉oflag=direct后–device-write-bps设置并没有生效,磁盘写入速度达到了 1.4 GB/s。

容器底层实现

cgroup实现资源限额:

  • 通过 cgroup 可以设置进程使用 CPU、内存 和 IO 资源的限额
  • –cpu-shares、-m、–device-write-bps 实际上就是在配置 cgroup
  • cgroup配置目录:/sys/fs/cgroup/cpu|memory|blkio/docker

namespace实现资源隔离:

  • Mount 让容器看上去拥有整个文件系统
  • UTS 让容器有自己hostname
  • IPC 让容器有自己的共享内存和信号量
  • PID 让容器有自己的进程空间
  • Network 让容器有自己的网络空间
  • User 让容器有自己的用户

Proudly powered by Hexo and Theme by Hacker
© 2019 ist0ne