Docker与K8s

1.Docker

1.1 容器简介与 Docker 容器引擎

1.1.1 什么是容器

容器又称为容器虚拟化技术,从名称可以看出容器也是一种虚拟化技术。容器是基于操作系统的轻量级的虚拟化技术。容器的英文名称是 Container,该单词的另一个意思是集装箱,其实容器和集装箱确实有很多相似的地方。下面就通过集装箱这个例子来讲一下什么是容器。如果把容器比作集装箱,容器上面运行的应用服务比作集装箱里面的货物,则运载货物的轮船就是物理机。集装箱可以将不同的货物隔离开来,只不过容器隔离的是应用服务罢了。其实容器就是将软件打包到一个平台中,用来开发、发布和部署的一种工具。容器镜像是一个轻量级、独立、可执行的软件包,包含运行它所需的所有内容:代码、运行时、系统工具、系统库、设置等。不管环境如何,容器化软件在 Linux 系统和 Windows 系统平台上都可以运行相同的应用程序。容器可以将软件与其周围环境隔离开来,解决开发环境和安装环境之间存在差异的问题,还有助于减少团队之间在同一基础架构上运行不同软件的冲突。

1.1.2Docker 容器

一说到容器,几乎立马想到的就是 Docker 了,Docker 似乎已经成为容器的代名词,导致现在很多人以为容器就是 Docker。其实 Docker 只是容器的其中一种而已,它将容器技术发扬光大。

(1)Docker 的由来

2013 年,dotCloud 公司决定开源他们内部使用的容器技术,这就是 Docker 的由来。之后,Docker 很快在各大论坛火爆起来。到了 2013 年 10 月,dotCloud 公司甚至直接更名为 Docker 股份有限公司,工作重心也转向全面围绕 Docker 来开发,可见 Docker 的火爆程度与崛起速度。Docker 之所以能迅速崛起,是因为它解决了传统方式的各种问题,在很大程度上提高了软件的生产效率,这是很多用户在生产环境中真实遇到的痛点。

(2)Docker 是什么

其实 Docker 并不能算一种新技术,因为 Docker 是基于 LXC(LinuxContainers),并使用了一些已经存在了很长的时间并且被广泛应用的技术来实现的。Docker 主要是将这些复杂、琐碎的底层技术服务化了。之所以能够获得如此巨大的成功,受到如此多用户的青睐,因为它能够更加了解用户的需求,且足够的简单方便。

(3)Docker 的基本操作

Docker 的基本操作主要包含安装 docker、拉取镜像、镜像的保存和加载,容器的导入和导出、启动 docker 容器、进入容器、终止容器和删除容器

1.2Docker 镜像及镜像仓库

1.2.1****什么是 Docker 镜像

Docker 镜像是由一层层的文件系统组成的特殊文件系统,为容器提供了运行时所需要的程序、配置、环境等。镜像属于只读文件系统,不能包含任何的动态数据,在构建完成后就不会被改变。

Docker 在运行容器前需要在本地存在对应的容器镜像,如果本地不存在该镜像,则 Docker 会先从镜像仓库中将对应的镜像拉取到本地,然后通过该镜像启动容器。

1.3Docker 网络

1.3.1Docker 网络架构

从 Docker1.7 版本开始,Docker 已经将网络部分的代码单独分离出来,成为 Docker 网络库 Libnetwork。为了标准化网络的驱动开发步骤并支持多种网络驱动,Docker 通过 Libnetwork 实现了 CNM 网络模型。Docker 网络的整体架构如图 1-4 所示。

image.png

图 1-4Docker 网络的整体架构

从图 1-4 中可以看出 Dockerdaemon 通过 Libnetwork 提供的 API 接口实现对网络的创建和管理功能。而 Libnetwork 通过 CNM 来实现这些网络功能,CNM 模型有三个组件:Sandbox(沙盒)、端点(Endpoint)、网络(Network),具体如下。

Sandbox(沙盒):每个沙盒包含一个容器网络栈(Networkstack)的配置,配置包括容器的网口、路由表和 DNS 设置等。

Endpoint(端点):通过 Endpoint,Sandbox 可以被加入一个 Network 里。

Network(网络):一组能相互直接通信的 Endpoints。上面的定义还是比较抽象的,理解起来比较困难,所以可以参考 CNM 模型在 Linux 上的实现技术来理解。比如,沙盒的实现可以是一个 LinuxNetworkNamespace,Endpoint 可以是一对 VETH,Network 则可以用 LinuxBridge 或 Vxlan 实现。

Libnetwork 提供了 Bridge、Host、Overlay、Remote 和 Null 五种网络模式。

  1. Bridge 驱动:此驱动为 Docker 的默认驱动,使用该驱动时,Libnetwork 将创建出来的 Docker 容器连接到 Docker 网桥上,能够满足容器的基本使用性需求。
  2. Host 驱动:在该驱动模式下,Docker 容器直接使用宿主机的网络,与宿主机享有完全相同的网络环境。
  3. Overlay 驱动:此驱动采用 VXLAN 中的 SDNcontroller 模式。在使用过程中,需要一个额外的配置存储服务,例如 Consul、etcd 和 Zookeeper 等,并在启动 Dockerdaemon 的时候通过参数指定所使用的配置存储服务地址。
  4. Remote 驱动:该驱动实际上并没有实现 Docker 自己的网络服务,而是通过调用外部的网络驱动插件的形式实现网络服务。用户可以根据自己的需求选择或开发合适的网络插件。
  5. Null 驱动:在这种网络模式下,Docker 仅仅为容器创建自己的 NetworkNamespace,提供网络隔离的功能,但并不会为容器创建任何网络配置,需要用户根据自己的需求为容器添加网络,并配置网络环境。

1.3.2Docker 网络原理

这部分主要介绍 Docker 的网络原理,通过 Linux 系统模拟实现一个 Docker 默认网络的方法。

首先对 Docker 网络的实现原理进行整体简略的介绍,当 Docker 服务安装并启动后,在主机上输入 ifconfig 命令,可以发现主机上多了一个 docker0 的虚拟网桥,这个网桥为 Docker 的网络通信提供支持。如图 1-5 所示,在默认网络情况下,当启动一个 Docker 容器时,Docker 会为容器分配一个 IP 地址,并通过一对 vethpair 将容器的 eth0 绑定到主机的 docker0 网桥中。

image.png

图 1-5Docker 网络的实现原理

1.3.3Docker 容器端口映射原理

上一节已经通过模拟实现 Docker 网络的方式讲解了 Docker 的网络原理。但还有一个重要的功能没有讲,就是容器端口映射的功能,即将容器的服务端 a 绑定到宿主机的端口 b 上,最终达到一种效果:外部程序通过宿主机的端口 b 访问,就像直接访问 Docker 容器网络内部容器提供的服务一样。

2Kubernetes

2.1Kubernetes 概述

概述 Kubernetes 作为近几年火热的技术之一,受到了大量技术爱好者的关注。Kubernetes 也成了云计算领域中的一颗明星。本章分别从 Why、What、How 开始,介绍 Kubernetes 诞生的原因、Kubernetes 的发展历史、核心概念及它所带来的优势,帮助读者初步且完备地了解 Kubernetes。

2.1.1 什么是 KubernetesKubernetes

官方文档给出了一个简短的解释:“Kubernetes 是一个管理跨主机容器应用的开源系统,提供了应用的部署、维护及扩容缩容的基本机制。Kubernetes 项目由云原生计算基金会(CNCF)进行托管。”维基百科给出的解释是:“Kubernetes(简称 k8s)用于提供容器应用的自动部署、扩容缩容以及管理容器应用,最开始由 Google 设计开发最后贡献给 CNCF 的开源容器集群管理项目。旨于提供管理跨主机的应用的部署、维护以及扩容缩容能力。Kubernetes 适用包括 Docker 在内的一系列容器工具。”

如何更通俗地理解 Kubernetes 是什么呢?其实,Kubernetes 是基于 GoogleBorg 系统超过 15 年的实践进行开源的分布式的容器编排管理平台,Kubernetes 旨在降低计算、网络和存储资源编排的复杂度,让运维人员和开发人员专注于以容器为载体的应用程序。Kubernetes 具备完善的集群管理能力,包括应用的快速部署,快速扩容缩容,跨主机调度,安全防护和准入机制,多租户资源隔离,透明的服务注册和服务发现机制,负载均衡、故障发现以及修复能力,多维度的资源配额管理能力。Kubernetes 还提供完善的管理工具,包括开发、部署测试、监控日志等各个环节。同时,Kubernetes 自身具备分布式、可扩展、可移植的特点。

  1. 分布式平台

Kubernetes 是一个分布式平台,模块组件之间相互分离,各个模块各自负责一个功能,通过 RESTFul 及 gRPC 方式进行通信,模块之间保证了故障隔离。

  1. 可扩展性

Kubernetes 具有各种扩展插件(Add-on),为 Kubernetes 提供了更加丰富的扩展功能。Kubernetes 也提供了可插拔式的调度模式。另外,Kubernetes 开放包括 CRI、CNI、CSI 等基础资源接口,在此基础上可以进一步对接支持,为 Kubernetes 提供更好的扩展性。

  1. 可移植性

Kubernetes 平台自身不依赖于底层资源,可以运行在物理机、虚拟机和各类云主机中。CNCF 提出 Kubernetes 一致性模型,确保 Kubernetes 在不同云环境的一致性;同时,Kubernetes 也集成了各大云厂商的 CloudProvider,它可以帮助 Kubernetes 在对应的公有云环境上创建公有云上的资源。

2.1.2 为什么选择 Kubernetes

说到为什么选择 Kubernetes,就不得不提容器。

回顾一下云计算的历史。1959 年,学术中提出了虚拟化的概念,虚拟化是云计算基础架构的基石。之后,云计算始终只是停留在学术层面上。直到 1998 年,VMware 成立并首次引入 X86 的虚拟技术,真正迎来了云计算的时代。亚马逊云计算服务于 2006 年推出,在随后的互联网企业容器技术实践约 30 十年间,它可以说趁着云计算趋势改变了整个 IT 行业。2010 年,开源云计算 IaaS 平台 OpenStack 发布,在多家主流公司的推动下迎来了爆发,越来越多的企业利用 OpenStack 搭建公有云和私有云平台。2013 年,dotCloud 公司开源了容器引擎 Docker,相比于虚拟机,Docker 的秒级启动、环境标准化、轻量级、资源利用率高、快速扩缩容等优势立刻引起了行业的关注。

图 2-1 对比了容器方式(a)和传统虚拟化方式(b)的差别。容器是在操作系统层面的虚拟化,它复用了本地主机的操作系统;而传统虚拟化只是在硬件资源层面的虚拟化。

image.png

图 2-1 容器方式和传统虚拟化方式的差别

“容器的出现带来了很多好处,而在容器的实践过程中,容器的编排、管理平台变得更为迫切,关注程度也大大超过了容器本身。主流的容器编排、管理平台有:Kubernetes、Swarm、Mesos。Swarm 是 Docker 的原生编排工具,Kubernetes 和 Swarm 都是基于 Golang 语言进行开发的,Mesos 则采用 C++ 语言开发。图 2-2 是 GitHub 中三种编排管理工具的 Star 和 Fork 数量(数据 2018.03 采集)。

image.png

图 2-2GitHub 中三种编排管理工具的 Star 和 Fork 数量

可以看出 Kubernetes 在 Star 和 Fork 数量上明显领先于其他两者。2017 年,Docker 公司在巨大的争议中终于完成了向商业公司的重要转变,由 Kubernetes 社区所主导的、全新的容器生态正式拉开序幕,也宣告了 Kubernetes 已经在容器编排管理工具的角逐战中胜出。

使用 Kubernetes 究竟有什么好处呢?

(1)拥抱微服务

微服务架构将巨大单体式应用分解为多个服务,每个服务通过 RPC 或者 API 进行通信,具备了各个自服务容易开发、维护的优点,另外子服务还具备独立部署、快速扩展等优点。Kubernetes 对微服务本身有很好的支持,应用本身通过 Deployment 进行部署,各个服务运行在 Pod 中,Pod 之间服务通过 Service 具备的服务发现实现相互间的通信。同时微服务架构也恰好是云原生应用的一种体现。

(2)容器编排

Kubernetes 帮助使用者通过简单易用的 API 高效地管理成千上万个运行在容器中的微服务。Kubernetes 在 1.6 版本中已经支持 5000 个节点,这也说明 Kubernetes 具备大规模集群的编排管理能力。同时,Kubernetes 还具备包括监控、日志、包管理等各种完善而专业的工具链,这将大大减轻运维和开发人员的负担,传统动辄十几人的团队,采用 Kubernetes 方案之后只需精湛的小团队就能应付自如。

(3)服务注册发现

微服务的实践过程中存在各种服务依赖关系,因此服务的注册发现十分重要。Kubernetes 对服务进行抽象,通过抽象的服务层动态地解析到对应的容器服务。Kubernetes 同时提供了 DNS 和环境变量两种方式,帮助实现服务的注册和发现,Kubernetes 早期版本中使用的环境变量方式实现,现在 Kubernetes 则默认使用 DNS,通过使用 DNS 将服务名称解析为服务的 IP 地址,然后 Proxy 转到对应的 Pod。

2.1.3Kubernetes 基本概念

Kubernetes 定义了资源对象,资源对象是一种逻辑实体,使用者需要使用 kubectl 命令管理工具或者直接通过 KubernetesAPI 进行调用实现对资源对象的创建、修改或删除的操作。同时,将资源对象的状态保存到 etcd 中。Kubernetes 主要资源对象有 Pod、Service、ReplicaSet、Deployment、StatefulSet 和 PersistentVolume 等。

  1. Pod

Pod 是运行在 Kubernetes 集群上创建部署的最简单的构建单位。Pod 对一个或者多个应用程序的容器进行了封装,在 Pod 中,容器共享容器运行时所需要的网络与存储资源。一个 Pod 表示由一个容器或者一组耦合容器共享资源的 Kubernetes 应用实例。

网络与存储资源的共享:每一个 Pod 都被分配了一个唯一的 IP 地址。Pod 里的所有容器共享着一个网络空间,这个网络空间包含了 IP 地址和网络端口。Pod 内部的容器彼此之间可以通过 localhost 相互通信;Pod 可以指定一系列的共享存储卷。Pod 里所有的容器都有权限访问共享卷,同时可以使用共享卷分享数据。

Pause 容器被称为 Pod 的根容器,根容器的作用主要有两点:Pause 状态代表了 Pod 的状态;Pod 中其他容器共享 Pause 容器的网络资源和存储资源,实现了 Pod 中容器资源共享的问题。

  1. Service

KubernetesService 定义了这样一种抽象:通过 Service 资源可以访问相应的 Pod 资源,Pod 资源与 Service 的对应关系则通过 LabelSelector 关联实现。Service 在 Kubernetes 中十分重要,通过 Service 进行 Pod 之间的访问以及外部到 Pod 的访问。

  1. ReplicaSet

ReplicaSet(RS)是对 ReplicationController 在 Selector 功能上的升级,ReplicaSet 支持集群选择器的功能,而 ReplicationController 只支持等号选择器的功能。ReplicaSet 的使用场景是确保 Pod 在任何时候都能保持指定的副本数。

  1. Deployment

Deployment 的主要功能是为了提供更好的编排、部署的支持,在 Kubernetesv1.2 版本开始引入,它是在 ReplicaSet 基础上实现的。和 ReplicaSet 相似,根据 Deployment 中描述期望的集群状态,逐步更新成期望的集群状态。Deployment 的主要职责同样是为了保证 Pod 的数量和健康。相比 ReplicaSet 的不同点,Deployment 提供了上线部署、滚动升级、创建副本、暂停上线任务、恢复上线任务、回滚到以前某一版本等功能,Deployment 大大降低了部署的复杂度与风险性。

  1. StatefulSet

ReplicaSet 和 Deployment 主要针对的是无状态应用的部署,对于有状态并不能很好地支持。在 Kubernetesv1.5 中引入了 StatefulSet 的概念,并在 v1.9 版本中 stable、StatefulSet 是对 PetSet 的升级,用于对有状态应用的支持。StatefulSet 具备以下特性:

(1)StatefulSet 创建的 Pod 具备稳定、唯一的网络标识。

(2)StatefulSet 创建的 Pod 具备稳定的持久化存储,同时 Pod 的删除不会级联删除数据卷。

(3)在部署和扩容的过程中,Pod 是逐个进行创建的,创建下一个 Pod 之前需要保证之前的 Pod 是 ready 状态;同样,删除的过程也是逐个进行删除的,最后创建的 Pod 将最先被删除。

  1. PersisitentVolume

PersistentVolume(持久化存储,简称 PV)资源是 Kubernetes 对存储的抽象。研发人员或运维人员只需关心如何通过 PV 提供持久化存储功能而无须关注具体的存储底层的实现,PV 在 Kubernetes 中是独立于 Pod 存在的,那么在 Kubernetes 中如何为 Pod 提供数据卷呢?Kubernetes 提供了另一种资源 PersistentVolumeClaim(持久化存储声明,简称 PVC),PVC 允许 Pod 声明指定大小和指定访问模式的方式使用 PV 资源。

访问模式包括:

(1)ReadWriteOnce—卷可以被单个 Pod 以读写模式挂载。

(2)ReadOnlyMany—卷可以被多个 Pod 以只读模式挂载。

(3)ReadWriteMany—卷可以被多个 Pod 以读写模式挂载。Kubernetes 中 PV 支持的存储底层类型为插件的形式,目前支持的插件有:GCEPersistentDisk、互联网企业容器技术实践 º36AWSElasticBlockStore、AzureFile、AzureDisk、FC(FibreChannel)、FlexVolume、Flocker、NFS、iSCSI、RBD(CephBlockDevice)、CephFS、Cinder(OpenStackblockstorage)、Glusterfs、VsphereVolume、QuobyteVolumes、HostPath、VMwarePhoton、PortworxVolumes、ScaleIOVolumes 和 StorageOS。主要基于各大云厂商、存储厂商以及开源的存储方案。其中,HostPath 使用的宿主机的存储能力主要用于在单节点的场景。

2.2Kubernetes 架构及安装

Kubernetes 是一个分布式架构系统,各个组件各自负责一个功能,可以进行独立部署。Kubernetes 也支持在各种平台环境下进行部署,并保证系统的一致性。

2.2.1Kubernetes 架构

Kubernetes 主要分为两个节点类型:master 和 node(Kubernetes 较早版本中称为 Minion)。master 作为集群的控制节点,主要负责集群的控制、管理功能,以及负责接收对集群资源操作的命令;node 作为集群的工作节点,实际工作的 Pod 将运行在这类节点上。

2.2.2Kubernates 核心组件

(1)APIServer

KubernetesAPIServer 在 Kubernetes 的 master 节点启动运行,其核心功能:作为集群的 RESTAPI 请求入口,支持对 Kubernetes 的资源对象的增删改查及 watch;与集群其他模块进行交互,并作为 Kubernetes 中与 etcd 通信的唯一组件;拥有完备的集群安全机制(包括认证、授权、准入控制)。

(2)ControllerManager

ControllerManager 由 kube-controller-manager 和 cloud-controller-manager 两部分组成,是 Kubernetes 集群的控制中心,它通过 APIServer 监控整个集群的状态,并确保集群的状态达到期望的状态。cloud-controller-manager 是在 Kubernetesv1.6 中引入,在 Kubernetes 启用云服务商的 CloudProvider 的时候才需要,使用云服务商的 ControllerManager 进行控制。

(3)Scheduler

kube-scheduler 是 Kubernetes 的核心组件之一,具有可插拔、独立进程启动的特点。它负责分配调度 Pod 到集群内的节点上,通过监听 kube-apiserver,查询还未分配 Node 的 Pod 以及集群中所有节点的资源使用情况,然后根据调度策略将这些 Pod 绑定到优先级最高的可用节点上。

(4)kubelet

在 Kubernetes 集群中的每一个节点上会运行一个 agent 进程:kubelet,该进程默认监听 10250 端口。当 kube-scheduler 将 Pod 调度到某个节点时,Master 节点就会向该节点的 kubelet 下发 Pod 具体的配置信息,kubelet 将会负责 Pod 的创建,同时将管理 Pod 的整个生命周期,以及向 APIServer 上报 Pod 的状态。当新增节点时,kubelet 会向 APIServer 注册自身节点,然后定时上报节点中资源的使用情况,并通过 cAdvisor 监控节点及节点上容器的性能。

(5)Kube-Proxy

Service 通过 Selector 选择的一组 Pods 的服务抽象,其实就是一个微服务,提供了服务的负载均衡和反向代理的能力,而 Kube-Proxy 的主要作用就是负责管理 Service 的访问入口,包括集群内 Pod 到 Service 的访问和集群外访问 Service。Kube-Proxy 运行在 Kubernetes 集群的每个节点上,负责监听 APIServer 中 Service 和 Endpoint 的变化情况,并将服务的 TCP 或 UDP 流量以负载均衡的方式向 Pod 的转发。

3Docker 和 Kubernetes 的关系

3.1 背景

Kubernetes 是由 Google 与 RedHat 公司共同主导的开源“容器编排”项目,它起源于 Google 公司的 Borg 系统。所以它在超大规模集群管理方面的经验要明显优于其他容器编排技术,加上 Kubernetes 在社区管理方面的民主化,使得它很快打败了 Docker 公司推出的容器编排解决方案(Compose+Swarm),从而成为了容器编排领域事实上的标准。

3.2 功能

功能上 Kubernetes 是一种综合的基于容器构建分布式系统的基础架构环境,它不仅能够实现基本的拉取用户镜像、运行容器,还可以提供路由网关、水平扩展、监控、备份、灾难恢复等一系列运维能力,而更重要的是 Kubernetes 可以按照用户的意愿和整个系统的规则,高度自动化的处理好容器之间的各种关系实现“编排”能力。

此外 Kubernetes 的出现也重新定义了微服务架构的技术方向,目前通常所说的“云原生”及“ServiceMesh(服务网格)”等概念,很大程度上也是依赖于 Kubernetes 所提供的基础能力。

3.3 架构设计

从 Kubernetes 架构设计上看,Kubernetes 对已有的容器技术进行替代,它更关注的是对运行在大规模集群中的各种任务根据其关系进行作业编排及管理,所以任何实现了 CRI、CNI、CSI 等协议标准的容器技术都可以无缝地与 Kubernetes 集成。从这个角度看,Docker 与 Kubernetes 的关系并不是替代的关系,而是平台与组件的关系,Kubernetes 可以利用现有的 Docker 容器运行时技术,但却并不完全依赖 Docker。而这也正是 Kubernetes 为什么被称作容器编排技术而不仅仅只是容器技术的原因。