1.Docker 介绍和基础操作

理解,docker (容器),
理解,docker (容器),

1.1 docker 是什么

Docker (码头工人)是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司(后由于 Docker 开源后大受欢迎就将公司改名为 Docker Inc ,总部位于美国加州的旧金山)内部的一个开源的 PAAS 服务 (Platform as a ServiceService )的业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。

Docker 是基于 linux 内核实现,Docker 最早采用 LXC 技术 ,LXC 是 Linux 原生支持的容器技术 ,可以提供轻量级的虚拟化 ,可以说 docker 就是基于 LXC 发展起来 的,提供 LXC 的高级封装,标准的配置方法,在LXC的基础之上,docker提供了一系列更强大的功能。而虚拟化技术 KVM(KernelKernel-based Virtual Machine Machine) 基于 模块实现, 后来Docker 改为自己研发并开源的 runc 技术运行容器,彻底抛弃了LXC。

Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程API来管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是build(构建)、ship(运输)、 run(运行),Docker遵从apache 2.0协议,并通过(namespace及cgroup等)来提供容器的资源隔离与安全保障等,所以Docke容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机.类似于VM但是在原理和应用上和VM的差别还是很大的,并且docker的专业叫法是应用容器(Application Container)。

1.2 个人理解

我们可以看图理解docker ,docker 翻译过来是码头工人,我们可以这么理解,架设公司一批货物,这批货物分类,有些是给宝宝用的,有的是给孕妇使用的,有的是给成年人使用的,这三个货物,最好不要混在一起,因此对三种货物分类也不一样,锁的机制不同,之前货物运输的话,可能回混到一起,然后卸货的时候,一点一点拆开卸货,

使用docker 之后,我们可以把同类的货物 放在一起,然后集中存放在一个集装箱中,利用码头工人,docker放在货船上,卸货时候,我们独立打开一种集装箱就可以获取我们的货物,比较方便,

理解,docker (容器),

虽然有些不同,我们这里是IT技术,一种容器技术,我们可以通过容器将每种技术放在一起,把你的应用放在一起,然后放在容器中,这样应用和应用之前火线不会干扰,同时可以装在容器里面,可以方便搬运,这也是最理想的状态,(可移植性,标准化,隔离性)

1.2 使用Docker 容器化封装应用程序的意义:

理解,docker (容器),
统一基础设施环境-docker环境

  • 硬件的组成配置
    操作系统的版本
    运行时环境的异构

  • 统一程序打包(装箱)方式-docker镜像
    java程序
    python程序
    nodejs程序

  • 统一程序部署(运行)方式-docker容器
    java-jar...→ docker run...
    python manage.py runserver... → docker run...
    npm run dev ... → docker run...

1.3 Docker 和虚拟机,物理主机对比

理解,docker (容器),

  • 传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统 ,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空间,用户空间等,所以在同一个宿主机上的多个容器之间彼此不会相互影响

理解,docker (容器),理解,docker (容器),

  • 资源利用率更高: 开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨至极致.虚拟机一般会有5-20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个虚拟机,但是一般可以运行数百个容器
  • 启动速度更快: 可以在数秒内完成启动
  • 占用空间更小: 容器一般占用的磁盘空间以MB为单位,而虚拟机以GB
  • 集成性更好: 和CI/CD(持续集成/持续部署)相关技术结合性更好,实现打包镜像发布测试可以一键运行,做到自动化并快速的部署管理,实现高效的开发生命周期

使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升。

根据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用100~200 MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常大。

比如: 一台96G内存的物理服务器,为了运行java程序的虚拟机一般需要分配8G内存/4核的资源,只能运行13台左右虚拟机,但是改为在docker容器上运行Java程序,每个容器只需要分配4G内存即可,同样的物理服务器就可以运行25个左右容器,运行数量相当于提高一倍,可以大幅节省IT支出,通常情况下至少可节约一半以上的物理设备

image-20201113203122631

Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,
node节点
Docker 服务端(Server): Docker守护进程,运行docker容器
Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API
Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
Docker 仓库(Registry): 保存镜像的仓库,官方仓库: https://hub.docker.com/,可以搭建私有仓库harbor
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中的程序启动后生成的进程

*Docker deamon 为docker 守护进程,每个容器,是其的子进程

chroot 是被认为最早的容器技术之一,它可以把一个进程的文件系统隔离起来.

1.4 Namespace(提供隔离功能)

一个宿主机,运行多个容器,必然带来一些问题,而namespace恰好解决了这些

namespace是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在核内,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统 空间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:

MNT Namespace: 每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubuntu的服务器,可以在里面启动一个centos运行环境的容器并且在容器里面启动一个Nginx服务,此Nginx运行时使用的运行环境就是centos系统目录的运行环境,但是在容器里面是不能访问宿主机的资源,宿主机是使用了chroot技术把容器锁定到一个指定的运行目录里面。

IPC Namespace:一个容器内的进程间通信,允许一个容器内的不同进程的(内存、缓存等)数据访问,但是不能跨容器直接访问其他容器的数据

UTS namespace(UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,其中包含了主机名hostname 和域名domainname ,它使得一个容器拥有属于自己主机名标识,这个主机名标识独立于宿主机系统和其上的其他容器

ID NamespaceLinux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、器内的主进程生成与回收子进程等)

理解,docker (容器),

NET Namespace每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口(成对产生),这样你的容器将拥有它自己的桥接ip地址,通常是docker0,而docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据

User Namespace: 允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是会把用户的作用范围限制在每个容器内,即A容器和B容器可以有相同的用户名称和ID的账户,但是此用户的有效范围仅是当前容器内,不能访问另外一个容器内的文件系统,即相互隔离、互不影响、永不相见。

理解,docker (容器),

1.5 cgroups (主要对内核程序做些限制)

Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操作)。

  • blkio: 块设备IO限制
  • cpu: 使用调度程序为 cgroup 任务提供 cpu 的访问
  • cpuacct: 产生 cgroup 任务的 cpu 资源报告
  • cpuset: 如果是多核心的 cpu,这个子系统会为 cgroup 任务分配单独的 cpu 和内存
  • devices: 允许或拒绝 cgroup 任务对设备的访问
  • freezer: 暂停和恢复 cgroup 任务
  • memory: 设置每个 cgroup 的内存限制以及产生内存资源报告
  • net_cls: 标记每个网络包以供 cgroup 方便使用
  • ns: 命名空间子系统
  • perf_event: 增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的 group 的所有线程以及运行在特定CPU上的线程

1.6 Dockers的优势

  • 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
  • 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
  • 节省开支: 提高服务器利用率,降低IT支出
  • 简化配置: 将运行环境打包保存至容器,使用时直接启动即可
  • 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题
  • 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
  • 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响

1.7 Docker的缺点

  • 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
  • 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
  • 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费

1.8 容器的核心技术

容器 runtime 是真正运行容器的地方,因此运行不同的容器,runtime 需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境

runc: 早期libcontainer是Docker公司控制的一个开源项目,OCI的成立后,Docker把libcontainer
项目移交给了OCI组织,runC就是在libcontainer的基础上进化而来,目前Docker默认的runtime,
runc遵守OCI规范,管*理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给runtime执行

1.8.1容器定义工具

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。
Docker image: *是docker 容器的模板,runtime依据docker image创建容器

Dockerfile: *包含N个命令的文本文件,通过dockerfile创建出docker image

ACI(App container image): 与docker image类似,是CoreOS开发的rkt容器的镜像格式

1.8.2 镜像仓库 Registry

统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库
Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用
阿里云,网易等第三方镜像的公共仓库
Image registry: docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少
Harbor: vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用

1.8.3 容器编排工具

当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎容器编排通常包括容器管理、调度、集群定义和服务发现等功能

Docker compose : docker 官方实现单机的容器的编排工具
Docker swarm: docker 官方开发的容器编排引擎
Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的
集群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能
Kubernetes: google领导开发的容器编排引擎,内部项目为Borg,且其同时支持 docker 和
CoreOS,当前已成为容器编排工具事实上的标准

1.8.4 docker (容器) 的依赖技术

容器网络:
docker自带的网络docker network仅支持管理单机的容器网络,当多主机运行的时候需要使用第三方开源网络,例如:calico、flannel等

服务发现:
容器的动态扩容特性决定了容器IP也会随之变化,因此需要有一种机制开源自动识别并将用户请求动态转发到新创建的容器上,kubernetes自带服务发现功能,需要结合kube-dns服务解析内部域名

容器监控:
可以通过原生命令docker ps/top/stats 查看容器运行状态,另外也可以使用Prometheus 、heapster等第三方监控工具监控容器的运行状态
数据管理:
容器的动态迁移会导致其在不同的Host之间迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决
日志收集:
docker 原生的日志查看工具docker logs,但是容器内部的日志需要通过ELK等专门的日志收集分析和展示工具进行处理