zoukankan      html  css  js  c++  java
  • 容器(四)实现容器的底层技术【25】

    (九)实现容器的底层技术

    ​ 为了更好地理解容器的特性,本节我们将讨论容器的底层实现技术。 cgroup 和 namespace 是最重要的两种技术。cgroup 实现资源限额, namespace 实现资源隔离。

    (1)cgroup

    ​ cgroup 全称 Control Group。Linux 操作系统通过 cgroup 可以设置进程使用 CPU、内存 和 IO 资源的限额。相信你已经猜到了:前面我们看到的--cpu-shares-m--device-write-bps 实际上就是在配置 cgroup。

    ​ cgroup 到底长什么样子呢?我们可以在 /sys/fs/cgroup 中找到它。还是用例子来说明,启动一个容器,设置 --cpu-shares=512

    root@cuiyongchao:~# docker run -it --cpu-shares 512 progrium/stress -c 1
    stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
    stress: dbug: [1] using backoff sleep of 3000us
    stress: dbug: [1] --> hogcpu worker 1 [6] forked
    
    
    

    查看容器ID:

    root@cuiyongchao:~# docker ps
    CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                 PORTS               NAMES
    b473e4497b3b        progrium/stress          "/usr/bin/stress --v…"   17 seconds ago      Up 16 seconds                              friendly_kepler
    
    

    在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每个容器创建一个 cgroup 目录,以容器长ID 命名:

    root@cuiyongchao:~# ls /sys/fs/cgroup/cpu/docker/b473e4497b3b63c0ea4907857bcd4ef0ea3a455bce20f0715ecfeb5afd047bba/
    cgroup.clone_children  cpuacct.usage_all          cpuacct.usage_sys   cpu.shares
    cgroup.procs           cpuacct.usage_percpu       cpuacct.usage_user  cpu.stat
    cpuacct.stat           cpuacct.usage_percpu_sys   cpu.cfs_period_us   notify_on_release
    cpuacct.usage          cpuacct.usage_percpu_user  cpu.cfs_quota_us    tasks
    root@cuiyongchao:~# cat /sys/fs/cgroup/cpu/docker/b473e4497b3b63c0ea4907857bcd4ef0ea3a455bce20f0715ecfeb5afd047bba/cpu.shares 
    512
    root@cuiyongchao:~# 
    
    

    ​ 目录中包含所有与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值为 512。同样的,/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置。

    (2)namespace

    ​ 在每个容器中,我们都可以看到文件系统,网卡等资源,这些资源看上去是容器自己的。拿网卡来说,每个容器都会认为自己有一块独立的网卡,即使 host 上只有一块物理网卡。这种方式非常好,它使得容器更像一个独立的计算机。

    ​ Linux 实现这种方式的技术是 namespace。namespace 管理着 host 中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。换句话说,namespace 实现了容器间资源的隔离。Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User,下面我们分别讨论。

    (3)Mount namespace

    ​ Mount namespace 让容器看上去拥有整个文件系统。容器有自己的 / 目录,可以执行 mountumount 命令。当然我们知道这些操作只在当前容器中生效,不会影响到 host 和其他容器。

    (4)UTS namespace

    ​ 简单的说,UTS namespace 让容器有自己的 hostname。 默认情况下,容器的 hostname 是它的短ID,可以通过 -h 或 --hostname 参数设置。

    root@cuiyongchao:~# docker run -it -h zhangsan ubuntu
    root@zhangsan:/# hostname 
    zhangsan
    root@zhangsan:/# 
    
    

    (5)IPC namespace

    ​ IPC namespace 让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起。

    (6)PID namespace

    我们前面提到过,容器在 host 中以进程的形式运行。例如当前 host 中运行了两个容器:

    root@cuiyongchao:~# docker ps
    CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                 PORTS               NAMES
    1c07fc518fbc        ubuntu                   "/bin/bash"              29 minutes ago      Up 29 minutes                              upbeat_knuth
    b473e4497b3b        progrium/stress          "/usr/bin/stress --v…"   55 minutes ago      Up 55 minutes                              friendly_kepler
    137cc65e3025        progrium/stress:latest   "/usr/bin/stress --v…"   14 hours ago        Up 14 hours                                container_B
    2d54da22fd5f        progrium/stress:latest   "/usr/bin/stress --v…"   14 hours ago        Up 14 hours (Paused)                       container_A
    root@cuiyongchao:~# 
    
    

    通过 ps axf 可以查看容器进程:

    24709 ?        Ssl    4:43 /usr/bin/containerd
     88927 ?        Sl     0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.cont
     88948 pts/0    Ds+    0:00  |   \_ /usr/bin/stress --verbose --cpu 4
     88990 pts/0    D+     1:25  |       \_ /usr/bin/stress --verbose --cpu 4
     88991 pts/0    D+     1:25  |       \_ /usr/bin/stress --verbose --cpu 4
     88992 pts/0    D+     1:25  |       \_ /usr/bin/stress --verbose --cpu 4
     88993 pts/0    D+     1:25  |       \_ /usr/bin/stress --verbose --cpu 4
     89014 ?        Sl     0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.cont
     89037 pts/0    Ss+    0:00  |   \_ /usr/bin/stress --verbose --cpu 4
     89075 pts/0    R+   139:11  |       \_ /usr/bin/stress --verbose --cpu 4
     89076 pts/0    R+   139:22  |       \_ /usr/bin/stress --verbose --cpu 4
     89077 pts/0    R+   138:13  |       \_ /usr/bin/stress --verbose --cpu 4
     89078 pts/0    R+   136:01  |       \_ /usr/bin/stress --verbose --cpu 4
     90634 ?        Sl     0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.cont
     90659 pts/0    Ss+    0:00  |   \_ /usr/bin/stress --verbose -c 1
     90701 pts/0    R+    55:18  |       \_ /usr/bin/stress --verbose -c 1
     91164 ?        Sl     0:00  \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.cont
     91192 pts/0    Ss+    0:00      \_ /bin/bash
     27166 ?        Ss     0:00 /usr/sbin/sshd -D
     86477 ?        Ss     0:00  \_ sshd: root@pts/3
     86604 pts/3    Ss     0:00  |   \_ -bash
     88907 pts/3    Sl+    0:00  |       \_ docker run --name container_A -it -c 1024 progrium/stress:la
     88307 ?        Ss     0:00  \_ sshd: root@pts/4
     88391 pts/4    Ss     0:00  |   \_ -bash
     88994 pts/4    Sl+    0:00  |       \_ docker run --name container_B -it -c 512 progrium/stress:lat
     88502 ?        Ss     0:00  \_ sshd: root@pts/5
     88585 pts/5    Ss+    0:00  |   \_ -bash
     88603 ?        Ss     0:00  \_ sshd: root@pts/6
     88686 pts/6    Ss+    0:00  |   \_ -bash
     89700 ?        Ss     0:00  \_ sshd: root@pts/7
     89828 pts/7    Ss     0:00  |   \_ -bash
     90615 pts/7    Sl+    0:00  |       \_ docker run -it --cpu-shares 512 progrium/stress -c 1
     90702 ?        Ss     0:00  \_ sshd: root@pts/8
     90782 pts/8    Ss     0:00  |   \_ -bash
     91146 pts/8    Sl+    0:00  |       \_ docker run -it -h zhangsan ubuntu
     91249 ?        Ss     0:00  \_ sshd: root@pts/0
     91371 pts/0    Ss     0:00      \_ -bash
     91397 pts/0    R+     0:00          \_ ps -axf
     28349 ?        Ss     0:01 /lib/systemd/systemd --user
     28350 ?        S      0:00  \_ (sd-pam)
     83248 ?        Ss     0:00 /lib/systemd/systemd-networkd
     87520 ?        Ssl    0:02 /usr/bin/dockerd --insecure-registry 10.0.0.20:5000
    root@cuiyongchao:~# 
    
    

    所有容器的进程都挂在 dockerd 进程下,同时也可以看到容器自己的子进程。 如果我们进入到某个容器,ps 就只能看到自己的进程了:

    root@cuiyongchao:~# docker exec -it 1c07fc518fbc bash
    root@zhangsan:/# ps axf        
       PID TTY      STAT   TIME COMMAND
        16 pts/1    Ss     0:00 bash
        25 pts/1    R+     0:00  \_ ps axf
         1 pts/0    Ss+    0:00 /bin/bash
    root@zhangsan:/# 
    
    

    ​ 而且进程的 PID 不同于 host 中对应进程的 PID,容器中 PID=1 的进程当然也不是 host 的 init 进程。也就是说:容器拥有自己独立的一套 PID,这就是 PID namespace 提供的功能。

    (7)Network namespace

    Network namespace 让容器拥有自己独立的网卡、IP、路由等资源 。

    (8)User namespace

    User namespace 让容器能够管理自己的用户,host 不能看到容器中创建的用户。

    root@cuiyongchao:~# docker run -it -h zhangsan ubuntu
    root@zhangsan:/# 
    root@zhangsan:/# userzhangsan333
    bash: userzhangsan333: command not found
    root@zhangsan:/# useradd zhangsan333
    root@zhangsan:/# exit
    exit
    root@cuiyongchao:~# su - zhangsan333
    No passwd entry for user 'zhangsan333'
    
    
    

    在容器中创建了用户 cloudman,但 host 中并不会创建相应的用户。

    (9)小结

    本章首先通过大量实验学习了容器的各种操作以及容器状态之间如何转换,然后讨论了限制容器使用 CPU、内存和 Block IO 的方法,最后学习了实现容器的底层技术:cgroup 和 namespace。

    下面是容器的常用操作命令:

    create      创建容器  
    run         运行容器  
    pause       暂停容器  
    unpause     取消暂停继续运行容器  
    stop        发送 SIGTERM 停止容器  
    kill        发送 SIGKILL 快速停止容器  
    start       启动容器  
    restart     重启容器  
    attach      attach 到容器启动进程的终端  
    exec        在容器中启动新进程,通常使用 "-it" 参数  
    logs        显示容器启动进程的控制台输出,用 "-f" 持续打印  
    rm          从磁盘中删除容器
    
    
  • 相关阅读:
    1282 回文数猜想
    1279 验证角谷猜想
    1205 吃糖果
    1201 18岁生日
    1106 排序
    2024 C语言合法标识符
    196 让气球飞吧
    1001 Sum Problem
    if语句
    三元运算符
  • 原文地址:https://www.cnblogs.com/cuiyongchao007/p/13970712.html
Copyright © 2011-2022 走看看