1.1.7 容器管理工具

有了以上的chroot、namespace、cgroups就具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决,于是容器管理技术出现了。目前主要是使用docker,早期使用LXC

1.1.7.1 LXC

LXC:Linux Container。可以提供轻量级的虚拟化功能,以便隔离进程和资源,包括一系列容器的管理工具软件,如,lxc-create,lxc-start,lxc-attach等,但这技术功能不完善,目前较少使用

官方网站:https://linuxcontainers.org/

案例:Ubuntu安装和使用LXC

[root@ubuntu1804 ~]#apt install lxc lxd
Reading package lists... Done
Building dependency tree   
Reading state information... Done
lxd is already the newest version (3.0.3-0ubuntu1~18.04.1).
lxc is already the newest version (3.0.3-0ubuntu1~18.04.1).
......

[root@ubuntu1804 ~]#lxc-checkconfig   #检查内核对lxc的支持状况,必须全部为enabled
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-4.15.0-29-generic
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
......

[root@ubuntu1804 ~]#lxc-create -t download --name alpine1 --  --dist alpine  --release 3.9 --arch amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created an Alpinelinux 3.9 x86_64 (20200121_13:00) container.
[root@ubuntu1804 ~]#lxc-start alpine1    #启动lxc容器
[root@ubuntu1804 ~]#lxc-attach alpine1   #进入lxc容器
~ # ifconfig
eth0      Link encap:Ethernet  HWaddr 00:16:3E:DF:9E:45  
          inet addr:10.0.1.51  Bcast:10.0.1.255  Mask:255.255.255.0
          inet6 addr: fe80::216:3eff:fedf:9e45/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:23 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2484 (2.4 KiB)  TX bytes:1726 (1.6 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

~ # uname -r
4.15.0-29-generic
~ # uname -a
Linux alpine12 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 Linux
~ # cat /etc/issue 
Welcome to Alpine Linux 3.9
Kernel \r on an \m (\l)

~ # exit
[root@ubuntu1804 ~]#

命令选项说明:

-t 模板: -t选项后面跟的是模板,模板可以认为是一个原型,用来说明需要一个什么样的容器(比如容器里面需不需要有vim,apache等软件),模板实际上就是一个脚本文件(位于/usr/share/lxc/templates目录),我们这里指定download模板(lxc-create会调用lxc-download脚本,该脚本位于刚说的模板目录中)是说明我们目前没有自己模板,需要下载官方的模板

--name 容器名称: 为创建的容器命名
-- : --用来说明后面的参数是传递给download脚本的,告诉脚本需要下载什么样的模板
--dist 操作系统名称: 指定操作系统
--release 操作系统: 指定操作系统,可以是各种Linux的变种
--arch 架构: 指定架构,是x86还是arm,是32位还是64位

lxc启动容器依赖于模板,清华模板源:https://mirrors.tuna.tsinghua.edu.cn/help/lxc-images/,但是做模板相对较难,需要手动一步步创构建文件系统、准备基础目录及可执行程序等,而且在大规模使用容器的场景很难横向扩展,另外后期代码升级也需要重新从头构建模板,基于以上种种原因便有了docker

1.1.7.2 docker

Docker相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具

Docker先启动一个容器也需要一个外部模板,也称为镜像,docker的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。

Docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删除容器后也会被随之删除。

1.1.7.3 pouch

项目网点:https://github.com/alibaba/pouch

Pouch(小袋子)起源于2011年,并于2017年11月19日上午,在中国开源年会现场,阿里巴巴正式开源了基于Apache 2.0协议的容器技术Pouch。Pouch是一款轻量级的容器技术,拥有快速高效、可移植性高、资源占用少等特性,主要帮助阿里更快的做到内部业务的交付,同时提高超大规模下数据中心的物理资源利用率

目前的容器方案大多基于Linux内核提供的cgroup和namespace来实现隔离,然后这样轻量级方案存在弊端:

  • 容器间,容器与宿主机间,共享同一个内核
  • 内核实现的隔离资源,维度不足

面对如此的内核现状,阿里巴巴采取了三个方面的工作,来解决容器的安全问题:

  • 用户态增强容器的隔离维度,比如网络带宽、磁盘使用量等
  • 给内核提交patch,修复容器的资源可见性问题,cgroup方面的bug
  • 实现基于Hypervisor的容器,通过创建新内核来实现容器隔离

1.1.7.4 Podman

虽然目前Docker是管理Linux容器最好的工具,注意没有之一,但是podman的横空出现即将改变这一点

什么是Podman?

Podman即Pod Manager tool,从名称上可以看出和Kubernetes的pod的密切联系,不过就其功能来说,简而言之:alias docker = podman,是CentOS 8新集成的功能,或许不久的未来会代替docker

Podman是一个为Kubernetes而生的开源的容器管理工具,原来是CRI-O(即容器运行时接口CRI和开放容器计划OCI)项目的一部分,后来被分离成一个单独的项目叫libpod。其可在大多数Linux平台上使用,它是一种无守护程序的容器引擎,用于在Linux系统上开发,管理和运行任何符合Open Container Initiative (OCI) 标准的容器和容器镜像。

Podman提供了一个与Docker兼容的命令行前端,Podman里面87%的指令都和Docker CLI相同,因此可以简单地为Docker CLI别名,即"alias docker = podman",事实上,podman使用的一些库也是docker的一部分。

CRI-0 is an implementation of the Kubernetes CRI (Container Runtime Interface) to enable using OCI (Open Container Initiative) compatible runtimes

官网地址:https://podman.io/

项目地址:https://github.com/containers/podman

Podman和docker不同之处

  • docker需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman不需要
  • 启动容器的方式不同:
    docker cli命令通过API跟Docker Engine(引擎)交互告诉它我想创建一个container,然后docker Engine才会调用OCI container runtime(runc)来启动一个container。这代表container的process(进程)不会是Docker CLI的child process(子进程),而是Docker Engine的child process 。
    Podman是直接给OCI containner runtime(runc)进行交互来创建container的,所以container process直接是podman的child process。
  • 因为docker有docker daemon,所以docker启动的容器支持--restart策略,但是podman不支持
  • docker需要使用root用户来创建容器。这可能会产生安全风险,尤其是当用户知道docker run命令的--privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行
  • docker在Linux上作为守护进程运行扼杀了容器社区的创新。如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。没有守护进程,容器基础结构更加模块化,更容易进行更改。podman的无守护进程架构更加灵活和安全。