探索容器技术:从LXC到Podman的演进
容器是一种轻量级的虚拟化技术,它允许开发者将应用程序及其依赖项打包成一个独立的运行环境。这个环境可以在任何地方运行,无论是在开发者的本地机器、测试服务器还是生产环境中,都能保证一致的行为和性能。容器技术的发展经历了几个重要阶段,从Linux Containers(LXC)到现在的Docker和Podman等。
容器管理工具
有了以上的chroot、namespace、cgroups就具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决,于是容器管理技术出现了。目前主要是使用docker,早期使用 LXC。
LXC
LXC:Linux Container。可以提供轻量级的虚拟化功能,以便隔离进程和资源,包括一系列容器的管理工具软件,如lxc-create,lxc-start,lxc-attach等,但这技术功能不完善,目前较少使用。
官方网站:https://linuxcontainers.org/
lxc启动容器依赖于模板,清华模板源: https://mirrors.tuna.tsinghua.edu.cn/help/lxc-images/,但是做模板相对较难,需要手动一步步创构建文件系统、准备基础目录及可执行程序等,而且在大规模使用容器的场景很难横向扩展,另外后期代码升级也需要重新从头构建模板,基于以上种种原因便有了docker。
docker
Docker 相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具 Docker 先启动一个容器也需要一个外部模板,也称为镜像,docke的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。
Docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删除容器后也会被随之删除。
pouch
项目网点:https://github.com/alibaba/pouch
Pouch (小袋子)起源于 2011 年,并于2017年11月19日上午,在中国开源年会现场,阿里巴巴正式开源了基于 Apache 2.0 协议的容器技术 Pouch。Pouch 是一款轻量级的容器技术,拥有快速高效、可移植性高、资源占用少等特性,主要帮助阿里更快的做到内部业务的交付,同时提高超大规模下数据中心的物理资源利用率
目前的容器方案大多基于 Linux 内核提供的 cgroup 和 namespace 来实现隔离,然后这样轻量级方案存在弊端。
- 容器间,容器与宿主间,共享同一个内核
- 内核实现的隔离资源,维度不足
面对如此的内核现状,阿里巴巴采取了三个方面的工作,来解决容器的安全问题
- 用户态增强容器的隔离维度,比如网络带宽、磁盘使用量等
- 给内核提交 patch,修复容器的资源可见性问题,cgroup 方面的 bug
- 实现基于 Hypervisor 的容器,通过创建新内核来实现容器隔离
Podman
虽然目前 Docker 是管理 Linux 容器最好的工具,注意没有之一,但是podman的横空出现即将改变这一点。
什么是Podman? Podman即Pod Manager tool,从名称上可以看出和kubernets的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-O 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/libpod
Podman 和docker不同之处
docker 需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman不需要。
启动容器的方式不同:docker cli 命令通过API跟 docker Engine 才会调用 Docker Engine(引擎) 交互告诉它我想创建一个container,然后 container的process(进程)不会是 OCI container runtime(runc) 来启动一个container。这代表 Docker CLI 的 Engine 的 child process。child process(子进程),而是Docker Podman 是直接给 container process 直接是 OCI containner runtime(runc) 进行交互来创建container的,所以 podman 的 child process。
因为docke有docker daemon,所以docker启动的容器支持–restart 策略,但是podman不支持。
docker需要使用root用户来创建容器。这可能会产生安全风险,尤其是当用户知道docker run命令的–privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行。
docker在Linux上作为守护进程运行扼杀了容器社区的创新。如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。没有守护进程,容器基础结构更加模块化,更容易进行更改。podman的无守护进程架构更加灵活和安全
Docker的优势
- 快速部署:短时间内可以部署成百上千个应用,更快速交付到线上
- 高效虚拟化:不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
- 节省开支:提高服务器利用率,降低IT支出
- 简化配置:将运行环境打包保存至容器,使用时直接启动即可
- 环境统一:将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题
- 快速迁移和扩展:可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
- 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响
Docker 的缺点
多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费
容器的相关技术
容器规范
OCI 官网:https://opencontainers.org/
容器技术除了的docker之外,还有coreOS的rkt,还有阿里的Pouch,为了保证容器生态的标准性和健康可持续发展,包括Linux 基金会、Docker、微软、红帽、谷歌和IBM等公司在2015年6月共同成立了一个叫Open Container Initiative(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了两个规范,分别是runtime spec和image format spec,有了这两个规范,不同的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。
容器 runtime
runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境。
对于容器运行时主要有两个级别:Low Level(使用接近内核层) 和 High Level(使用接近用户层)目前,市面上常用的容器引擎有很多,主要有下图的那几种。
dockershim, containerd 和cri-o都是遵循CRI的容器运行时,我们称他们为高层级运行时(High-level Runtime)。其他的容器运营厂商最底层的runc仍然是Docker在维护的
Google,CoreOS,RedHat都推出自已的运行时:lmctfy,rkt,cri-o,但到目前Docker仍然是最主流的容器引擎技术。
runtime 类型
- Lxc:linux上早期的runtime,在 2013 年 Docker 刚发布的时候,就是采用lxc作为runtime, Docker 把 LXC 复杂的容器创建与使用方式简化为 Docker 自己的一套命令体系。随着Docker的发展,原有的LXC不能满足Docker的需求,比如跨平台功能。
- Libcontainer:随着 Docker 的不断发展,重新定义容器的实现标准,将底层实现都抽象化到 Libcontainer的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用 namespace、cgroups 技术抑或是使用 systemd 等其他方案,只要实现了 Libcontainer 定义的一组接口,Docker 都可以运行。这也为 Docker 实现全面的跨平台带来了可能。
- runc:早期libcontainer是Docker公司控制的一个开源项目,OCI的成立后,Docker把libcontainer 项目移交给了OCI组织,runC就是在libcontainer的基础上进化而来,目前Docker默认的runtime,runc遵守OCI规范。
- rkt:是CoreOS开发的容器runtime,也符合OCI规范,所以使用rktruntime也可以运行Docker容器。
Docker 的运行机制
查看docker的runtime
[root@ubuntu2404 ~]# docker info
Client: Docker Engine - CommunityVersion: 28.0.1Context: defaultDebug Mode: falsePlugins:buildx: Docker Buildx (Docker Inc.)Version: v0.21.1Path: /usr/libexec/docker/cli-plugins/docker-buildxcompose: Docker Compose (Docker Inc.)Version: v2.33.1Path: /usr/libexec/docker/cli-plugins/docker-composeServer:Containers: 0Running: 0Paused: 0Stopped: 0Images: 0Server Version: 28.0.1Storage Driver: overlay2Backing Filesystem: extfsSupports d_type: trueUsing metacopy: falseNative Overlay Diff: trueuserxattr: falseLogging Driver: json-fileCgroup Driver: systemdCgroup Version: 2Plugins:Volume: localNetwork: bridge host ipvlan macvlan null overlayLog: awslogs fluentd gcplogs gelf journald json-file local splunk syslogSwarm: inactiveRuntimes: runc io.containerd.runc.v2Default Runtime: runcInit Binary: docker-initcontainerd version: bcc810d6b9066471b0b6fa75f557a15a1cbf31bbrunc version: v1.2.4-0-g6c52b3finit version: de40ad0Security Options:apparmorseccompProfile: builtincgroupnsKernel Version: 6.8.0-49-genericOperating System: Ubuntu 24.04.1 LTSOSType: linuxArchitecture: x86_64CPUs: 4Total Memory: 3.778GiBName: ubuntu2404ID: 7a1cd16c-63cd-4efe-9025-eb94997a4b1bDocker Root Dir: /var/lib/dockerDebug Mode: falseExperimental: falseInsecure Registries:::1/128127.0.0.0/8Live Restore Enabled: false
镜像仓库 Registry
统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库。
- Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用。
- 阿里云,网易等第三方镜像的公共仓库。
- Image registry:docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少。
- Harbor:vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用。
镜像地址格式
docker.io/library/nginx
harbor.caoge.com/ubuntu
容器编排工具
当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎。
容器编排通常包括容器管理、调度、集群定义和服务发现等功能。
- Docker compose:docker 官方实现单机的容器的编排工具。
- Docker swarm:docker 官方开发的容器编排引擎,支持overlay network。
- Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能。
- Kubernetes:google领导开发的容器编排引擎,内部项目为Borg,且其同时支持docker 和 CoreOS,当前已成为容器编排工具事实上的标准。
容器技术的未来
随着云原生应用的普及,容器技术也在不断演进。Kubernetes已经成为容器编排的事实标准,而容器管理工具如Podman也正朝着更加安全、灵活的方向发展。同时,边缘计算和物联网(IoT)的兴起,为容器技术提供了新的应用场景和发展机遇。
总之,从LXC到Podman,容器技术已经走了很长一段路。每种工具都有其独特的优势和适用场景,理解这些差异有助于更好地选择适合自己的技术栈。无论是追求极致的安全性,还是希望简化部署流程,现在都已有合适的工具可供选择,下一篇讲docker的安装和部署。