容器实战高手课
李程远
eBay 总监级工程师,云平台架构师
4426 人已学习
立即订阅
登录后,你可以任选4讲全文学习
推荐试读
换一换
01 | 认识容器:容器的基本操作和实现原理
07 | Load Average:加了CPU Cgroup限制,为什么我的容器还是很慢?
11 | 容器文件系统:我在容器中读写文件怎么变慢了?
课程目录
已完结/共 31 讲
开篇词 (2讲)
开篇词 | 一个态度两个步骤,成为容器实战高手
01 | 认识容器:容器的基本操作和实现原理
容器进程 (6讲)
02 | 理解进程(1):为什么我在容器中不能kill 1号进程?
03|理解进程(2):为什么我的容器里有这么多僵尸进程?
04 | 理解进程(3):为什么我在容器中的进程被强制杀死了?
05|容器CPU(1):怎么限制容器的CPU使用?
06 | 容器CPU(2):如何正确地拿到容器CPU的开销?
07 | Load Average:加了CPU Cgroup限制,为什么我的容器还是很慢?
容器内存 (3讲)
08 | 容器内存:我的容器为什么被杀了?
09 | Page Cache:为什么我的容器内存使用量总是在临界点?
10 | Swap:容器可以使用Swap空间吗?
容器存储 (4讲)
11 | 容器文件系统:我在容器中读写文件怎么变慢了?
12 | 容器文件Quota:容器为什么把宿主机的磁盘写满了?
13 | 容器磁盘限速:我的容器里磁盘读写为什么不稳定?
14 | 容器中的内存与I/O:容器写文件的延时为什么波动很大?
容器网络 (4讲)
15 | 容器网络:我修改了/proc/sys/net下的参数,为什么在容器中不起效?
16 | 容器网络配置(1):容器网络不通了要怎么调试?
17|容器网络配置(2):容器网络延时要比宿主机上的高吗?
18 | 容器网络配置(3):容器中的网络乱序包怎么这么高?
容器安全 (2讲)
19 | 容器安全(1):我的容器真的需要privileged权限吗?
20 | 容器安全(2):在容器中,我不以root用户来运行程序可以吗?
结束语 (4讲)
结束语 | 跳出舒适区,突破思考的惰性
结课测试|这些容器技术的问题,你都掌握了么?
用户故事 | 莫名:相信坚持的力量,终会厚积薄发
加餐福利 | 课后思考题答案合集
专题加餐 (6讲)
加餐01 | 案例分析:怎么解决海量IPVS规则带来的网络延时抖动问题?
加餐02 | 理解perf:怎么用perf聚焦热点函数?
加餐03 | 理解ftrace(1):怎么应用ftrace查看长延时内核函数?
加餐04 | 理解ftrace(2):怎么理解ftrace背后的技术tracepoint和kprobe?
加餐05 | eBPF:怎么更加深入地查看内核中的函数?
加餐06 | BCC:入门eBPF的前端工具
容器实战高手课
15
15
1.0x
00:00/00:00
登录|注册
开通超级会员可免费学习本课程,还可解锁海量内容免费学特权。

01 | 认识容器:容器的基本操作和实现原理

你好,我是程远。作为一名工程师,我猜在过去的几年时间里,你肯定用过或者听人提起过容器(Container)。
说实话,容器这东西一点都不复杂,如果你只是想用的话,那跟着Docker 官网的说明,应该十来分钟就能搞定。
简单来说,它就是个小工具,可以把你想跑的程序,库文件啊,配置文件都一起“打包”。
然后,我们在任何一个计算机的节点上,都可以使用这个打好的包。有了容器,一个命令就能把你想跑的程序跑起来,做到了一次打包,就可以到处使用。
今天是咱们整个课程的第一讲,我想和你来聊聊容器背后的实现机制。
当然,空讲原理也没什么感觉,所以我还是会先带着你启动一个容器玩玩,然后咱们再一起来探讨容器里面的两大关键技术—— Namespace 和 Cgroups。基本上理解了这两个概念,你就能彻底搞懂容器的核心原理了。

做个镜像

话不多说,咱们就先动手玩一玩。启动容器的工具有很多,在这里我们还是使用 Docker 这个最常用的容器管理工具。
如果你之前根本没用过 Docker 的话,那我建议你先去官网看看文档,一些基础的介绍我就不讲了,那些内容你随便在网上一搜就能找到。
安装完 Docker 之后,咱们先来用下面的命令运行一个 httpd 服务。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/1000字
划线
笔记
复制
01 | 认识容器:容器的基本操作和实现原理
07 | Load Average:加了CPU Cgroup限制,为什么我的容器还是很慢?
11 | 容器文件系统:我在容器中读写文件怎么变慢了?
13 | 容器磁盘限速:我的容器里磁盘读写为什么不稳定?
加餐03 | 理解ftrace(1):怎么应用ftrace查看长延时内核函数?
加餐05 | eBPF:怎么更加深入地查看内核中的函数?
开通超级会员免费畅看本课程
开通会员
该文章仅可免费阅读部分内容,如需阅读完整文章,请开通超级会员或单独购买本课程。
登录 后留言

精选留言(42)

  • leslie
    置顶
    透彻,之前被人问过,资料方面同样查过,架构同样明了,如此通俗明了-难得。

    作者回复: 感谢你的肯定。

    2021-05-13
    6
  • 那时刻
    求教老师一个问题,我们有三个服务A B C部署在K8S里,它们各自设置了resouce limit(cpu, memory),其中恰好 A1 B1 C1被分配到同一个node上,A2 B2分配到另外一个node上。流量经过load balance之后打到 A1 A2和 B1 B2各自是均匀的,但是A1 B1使用的cpu 占比相对于 A2 B2要高出5% ~ 6%。我认为尽管docker通过namespace和cgroups来隔离和限制使用的资源,但是对于宿主机而言,各个docker实例之间还是存在竞争cpu和memory的,不知这么理解是否正确?

    作者回复: @那时刻,

    这种情况,如果A1/A2, B1/B2 都运行在自己的cgroup limit之内,那么需要先从两个宿主机的整体情况先做一个比较,从硬件类型开始,OS版本, 宿主机上的其他负载的情况,如果这些都一样,那么可以对A1/A2, B1/B2做perf看看热点函数。

    2020-11-18
    16
  • Richur
    老师好,求教一个问题,docker stop containerId,容器中的进程是如何退出的,是kill pid,kill -15 pid 还是kill -9 pid 亦或是其他?

    作者回复: containerd会先向容器中的init进程发送SIGTERM,如果init进程注册了SIGTERM handler(并且handler让进程退出了)那么整个容器就退出了,如果容器的init进程没有注册SIGTERM, 那么过30秒, containerd再向容器的init进程发送SIGKILL.

    2020-12-21
    2
    7
  • JianXu
    老师,能帮忙扫盲一下 PID namespace 那张图里 的shim 吗?为什么要使用Shim 呢?

    作者回复: containerd 启动当容器的时候先会启动一个shim, 然后由shim运行runc去创建container. 这样相当于一个shim来管理一个container. shim作为container的“父进程”, 接管了容器的stdin/stdout, containerd服务出问题,不会影响到用户的container。

    2020-11-16
    4
    8
  • heihei
    第一节就22分钟,我傻了,老师也太实在了😂
    2020-11-16
    2
    7
  • MYG
    我在macOS下用multipass启动Ubuntu 20.04的VM,貌似已经升级到了containerd-shim-runc-v2,同时在/sys/fs/cgroup/memory/system.slice下也找不到每个container的子目录了,请问在哪里能找到呢?还是v2的设计完全不一样了?谢谢🙏

    作者回复: @MYG, 你的系统上应该还是Cgroup V1.
    试试这样找一下:
    # docker inspect 4d3cf63512a2 | grep \"Pid\"
                "Pid": 4384,
    # cat /proc/4384/cgroup | grep memory
    5:memory:/system.slice/docker-4d3cf63512a2b89c0982724a6c12cb9b69781676aa93ab4fb2060f47908c6b94.scope

    2020-12-13
    5
  • 朱雯
    老师好 1.我们现在对docker容器的使用就如同虚拟机一样 一个容器运行多个进程 但是我听说docker是天生是单进程的 是否需要改造 2.之前在某次创建docker容器时 要设置资源控制好像必须修改grub的某个配置 不配置就真的无法限制 这是啥原理 3. 容器使用过程中 其实我大多数时候的交互方式是-it binbash的方式 当成虚拟机来用 这样是否有问题 4. 我们现在的环境 其实并没有做过多限制 容器之间相互干扰和影响 要设置限制 然后平滑的设置限制有没有好的方法

    作者回复: 1. 把容器当成虚拟机使用,可以是容器化过程中的一个过渡方案,但是长期的方向是native的方式来使用容器。
    2. 我不清楚你具体修改的是哪个kernel参数,不过对于资源的限制比如cgroup, 或者xfs quota, 这些都是Linux 内核中的特性,所以有时候就需要在grub中对内核的启动参数做修改。
    3. 这个没有什么问题。
    4. 这个就需要用cgroup做限制了, 我在后面的课程里有很多这方面的介绍。

    2020-11-17
    3
    5
  • 上邪忘川
    centos7.4测试,docker在cgroup下的目录为/sys/fs/cgroup/memory/docker/40152218ccc9d2bcda0e146efdfed871a78480712cb9675404af800c2e812ea9/

    作者回复: @上邪忘川,
    请问一下, 你是否是通过systemd来启动dockerd的?

    容器在cgroup下的目录树结构会受容器管理平台的影响。

    2020-11-16
    5
    5
  • conanforever22
    有个疑问, dockerfile中FROM后边的基础镜像应该怎么做?

    作者回复: docker base image, 拿centos为例子,可以建一个目录,让后把需要的rpm 安装在这个目录下面,然后把目录打成一个tarball, 用docker import成为一个base image.


    https://github.com/moby/moby/blob/master/contrib/mkimage-yum.sh

    2020-11-20
    2
    4
  • JianXu
    ”会导致对同一进程的资源协调比较困难,比如 memory Cgroup 与 blkio Cgroup 之间就不能协作“ --> CY 老师能展开介绍一下为什么 memory cgroup 和 blkio cgroup 不能协作的问题吗?为什么cgroup v2 就可以了呢?

    另外,cgroup v1 可以管理disk IO 和 network IO 吗?那 cgroup v2 呢

    作者回复:
    > 老师能展开介绍一下为什么 memory cgroup 和 blkio cgroup 不能协作的问题吗?为什么cgroup v2 就可以了呢?

    这一部分我在第13讲"容器磁盘限速里" 会详细的解释。

    cgroup v1 blkio 可以对 Direct I/O做限流。
    cgroup v1 net_cls 配合 tc 可以对网络限流。

    cgroup v2 io + memory 一起可以对 Direct I/O 和 Buffered I/O做限流,但是不支持xfs

    2020-11-16
    4
  • 布凡
    哇,老师的课程真的是干货满满,这样一节课让Linux新手的我整整操作了一下午,顺便又属性了下Linux下命令的各做操作,给老师点赞,也给自己加油o(* ̄▽ ̄*)ブ!

    作者回复: @布凡, 赞! 操作很重要!

    2021-02-10
    3
  • Action
    "Host PID Namespace,它是其他 Namespace 的父亲 Namespace" 其中我看图中有containerd的pid 和shim的pid分别代表什么呀?这些是怎么关联起来的呢?

    作者回复: containerd是宿主机上的一个守护进程,用来建立容器。每建立一个容器,就会有一个shim进程,它是容器中init进程的父进程。

    2020-12-18
    3
  • 海盗船长
    请教老师一个问题,执行 ls -l /proc/self/ns,我们的服务器上只支持6种namespace:ipc,mnt,net,pid,user,uts。请问这是怎么回事?

    作者回复: @思维,请看一下你的内核版本号。比如time namespace是Linux kernel 5.6之后才有的。

    2020-11-18
    2
    3
  • 云原生生态圈
    使用了这么多年的Docker, 再回头看还是受益匪浅。
    2020-11-17
    3
  • JianXu
    那张网络图里 172.17.0.21 是什么呢?

    作者回复: 这个是宿主机上Linux bridge interface docker0上的IP, 和容器里的IP在同一个网段,用来宿主机和容器进行网络通讯

    2020-11-16
    3
  • wuyang-ligerj
    centos 7.9 cd /sys/fs/cgroup/memory/system.slice/ 进入这个目录没有找到正在运行的容器id

    作者回复: @wuyang-ligerj
    可以尝试用find命令去找一下

    ```
    -bash-4.2# docker ps -q
    8c28cc9c5db8
    -bash-4.2# pwd
    /sys/fs/cgroup/memory
    -bash-4.2# find . -name *8c28cc9c5db8*
    ./system.slice/docker-8c28cc9c5db88bf08b6ccc79aed58b8ec4afaeb1ef7ff27aaabfa60229824c08.scope
    ```

    2021-01-12
    2
    1
  • chon
    希望在课程最后能给个书单,怎么才能掌握linux的内核,谢谢

    作者回复: "Understanding the Linux Kernel"
    "Linux Kernel Development"

    虽然这两本书是10多年前的了,讲述的内核版本和目前的有差距,不过基本的概念原理都是一样的。认真读完,对于内核会有一个比较完整的认识。

    2020-11-17
    1
  • JianXu
    我在Mac 笔记本上安装了 docker daemon. 但是下载的 centos/httpd:latest 似乎找不到 ip 或者 ifconfig 命令:

     ~  docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    955d78842ca8 centos/httpd:latest "/run-httpd.sh" 15 minutes ago Up 15 minutes 80/tcp vigilant_jones
     ~  docker exec -it 955d78842ca8 ip addr
    OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"ip\": executable file not found in $PATH": unknown
     ✘  ~  docker exec -it 955d78842ca8 ifconfig
    OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"ifconfig\": executable file not found in $PATH": unknown
     ✘  ~ 

    作者回复: @JianXu,

    因为我的介绍后面有很多内容涉及到了Linux相关的功能,需要在Linux的机器里运行容器。


    “在这个容器课程中,每一讲里都会有一些小例子,所以需要你有一台安装有 Linux 的机器,或者用 VirtualBox 安装一个虚拟机来跑 Linux。Linux 的版本建议是 CentOS 8 或者是 Ubuntu 20.04。"

    2020-11-16
    2
    1
  • Geek4437
    老师你好,为什么 memery.limit_in_bytes 的默认值是9223372036854771712,而不是 uint64 的最大值或者其他值呢?

    uint64 的最大值 9223372036854775807 - 9223372036854771712 = 4095。
    2021-12-13
  • 小Y
    我的,/sys/fs/cgroup/memory/system.slice/下 没有 docker-<id>结构的目录或文件是咋回事呢? 我已经运行了2个容器的
    2021-11-13
收起评论
42
返回
顶部