Docker基本概念
什么是Docker
Docker
是使用 Google公司推出的Go 语言
进行开发实现,基于Linux 内核
的cgroup、namespace、以及AUFS类的Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
Docker
在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得Docker
技术比虚拟机技术更为轻便、快捷。下面的图片比较了Docker
和传统虚拟化方式的不同之处。
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。
而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比 传统虚拟机更为轻便。
为什么要使用Docker
作为一种新兴的虚拟化方式,Docker
跟传统的虚拟化方式相比具有众多的优势。
更高效的利用系统资源:
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker
对系统资源的利用率更高。更快速的启动时间:
Docker
容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间一致的运行环境:
Docker
的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现这段代码在我机器上没问题啊这类问题。持续交付和部署:
Docker
可以通过定制应用镜像来实现持续集成、持续交付、部署。可以通过Dockerfile
来进行镜像构建,结合持续集成系统进行集成测试、自动部署。更轻松的迁移:
由于
Docker
确保了执行环境的一致性,使得应用的迁移更加容易,而不用担心运行环境的变化导致应用无法正常运行的情况。更轻松的维护和扩展:
Docker
使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker
团队提供了一大批高质量的官方镜像,既可以直接使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为 MB | 一般为 GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
基本概念
镜像Image
镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含任何动态数据,其内容在构建之后也不会被改变。
Docker
设计时,将其设计为分层存储的架构。镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除 前一层的文件,而是仅在当前层标记为该文件已删除。分层存储的特征使得镜像的复用、定制变的更为容易。
容器Container
镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的root
文件系统、自己的网络配置、自己的进程空间,甚至自己的用户ID空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。容器也具备分层存储的特征。
Kubernetes
什么是Kubernetes
Kubernetes
是一个完备的分布式系统支撑平台。Kubernetes
具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。同时,Kubernetes
提供了完善的管理工具,这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。因此,Kubernetes
是一个全新的基于容器技术的分布式架构解决方案,并且是一个一站式的完备的分布式系统开发和支撑平台。
Kubernetes
英文中字母K和S中间有8个英文,所以也简称为K8S。
为什么要使用Kubernetes
轻装上阵地开发复杂系统
可以全面拥抱微服务架构
可以随时随地迁移系统
拥有横向弹性扩容机制
Kubernetes基本概念
Kubernetes
中的大部分概念如Node、Pod、Replication Controller、Service
等都可以被看作一种资源对象,几乎所有资源对象都可以通过Kubernetes
提供的kubectl
工具(或者API编程调用)执行增、删、改、查等操作并将其保存在etcd
中持久化存储。从这个角度来看,Kubernetes
其实是一个高度自动化的资源控制系统,它通过跟踪对比etcd库里保存的“资源期望状态”与当前环境中的“实际资源状态”的差异来实现自动控制和自动纠错的高级功能。
Master
Kubernetes里的Master
指的是集群控制节点,在每个Kubernetes集群里都需要有一个Master
来负责整个集群的管理和控制,基本上Kubernetes的所有控制命令都发给它,它负责具体的执行过程,我们后面执行的所有命令基本都是在Master
上运行的。Master
通常会占据一个独立的服务器(高可用部署建议用3台服务器),主要原因是它太重要了,是整个集群的“首脑”,如果它宕机或者不可用,那么对集群内容器应用的管理都将失效。
在Master
上运行着以下关键进程:
Kubernetes API Server(kube-apiserver)
提供了HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程。
Kubernetes Controller Manager(kube-controller-manager)
Kubernetes里所有资源对象的自动化控制中心,可以将其理解为资源对象的大总管。
Kubernetes Scheduler(kube-scheduler)
负责资源调度(Pod调度)的进程,相当于公交公司的调度室,在
Master
上通常还需要部署etcd
服务,因为Kubernetes里的所有资源对象的数据都被保存在etcd
中。
Node
除了Master,Kubernetes集群中的其他机器被称为Node
,在较早的版本中也被称为Minion。与Master一样,Node
可以是一台物理主机,也可以是一台虚拟机。Node
是Kubernetes集群中的工作负载节点,每个Node
都会被Master
分配一些工作负载(Docker容器),当某个Node
宕机时,其上的工作负载会被Master
自动转移到其他节点上。
在每个Node
上都运行着以下关键进程:
kubelet
负责Pod对应的容器的创建、启停等任务,同时与Master密切协作,实现集群管理的基本功能。
kube-proxy
实现Kubernetes Service的通信与负载均衡机制的重要组件。
Docker Engine(docker)
Docker引擎,负责本机的容器创建和管理工作。
Node
可以在运行期间动态增加到Kubernetes集群中,前提是在这个节点上已经正确安装、配置和启动了上述关键进程,在默认情况下kubelet
会向Master
注册自己,这也是Kubernetes推荐的Node
管理方式。
一旦Node
被纳入集群管理范围,kubelet
进程就会定时向Master
汇报自身的情报,例如操作系统、Docker版本、机器的CPU和内存情况,以及当前有哪些Pod在运行等,这样Master就可以获知每个Node
的资源使用情况,并实现高效均衡的资源调度策略。
而某个Node
在超过指定时间不上报信息时,会被Master
判定为“失联”,Node
的状态被标记为不可用(Not Ready),随后Master
会触发“工作负载大转移”的自动流程。
我们可以执行下述命令查看在集群中有多少个Node
:
然后可以通过kubectl describe node <node_name>
查看某个Node的详细信息:
Pod
Pod
是Kubernetes最重要的基本概念,下图所示是Pod
的组成示意图,我们看到每个Pod
都有一个特殊的被称为根容器的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器。
为什么Kubernetes会设计出一个全新的Pod的概念并且Pod
有这样特殊的组成结构?
原因之一:在一组容器作为一个单元的情况下,我们难以简单地对“整体”进行判断及有效地行动。比如,一个容器死亡了,此时算是整体死亡么?是N/M的死亡率么?引入业务无关并且不易死亡的Pause容器作为Pod
的根容器,以它的状态代表整个容器组的状态,就简单、巧妙地解决了这个难题。
原因之二:Pod
里的多个业务容器共享Pause容器的IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
Kubernetes为每个Pod
都分配了唯一的IP地址,称之为Pod IP
,一个Pod
里的多个容器共享Pod IP
地址。Kubernetes要求底层网络支持集群内任意两个Pod
之间的TCP/IP直接通信,这通常采用虚拟二层网络技术来实现,例如Flannel、Open vSwitch
等
因此我们需要牢记一点:在Kubernetes里,一个Pod
里的容器与另外主机上的Pod
容器能够直接通信,同一个Pod
里的容器之间仅需通过localhost就能互相通信。
Pod
、容器与Node
的关系:
一个Pod中的应用容器共享同一组资源:
PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID
网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围
IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信
UTS命名空间:Pod中的多个容器共享一个主机名
Volumes(共享存储卷):Pod中的各个容器可以访问在Pod级别定义的Volumes
Pod的生命周期通过Replication Controller
来管理;通过模板进行定义,然后分配到一个Node
上运行,在Pod
所包含容器运行结束后,Pod
结束。
Kubernetes为Pod
设计了一套独特的网络配置,包括:为每个Pod
分配一个IP地址,使用Pod
名作为容器间通信的主机名等。
Label
Label
(标签)是Kubernetes系统中另外一个核心概念。一个Label
是一个key=value的键值对,其中key与value由用户自己指定。Label
可以被附加到各种资源对象上,例如Node、Pod、Service、RC
等,一个资源对象可以定义任意数量的Label
,同一个Label
也可以被添加到任意数量的资源对象上。Label
通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。
我们可以通过给指定的资源对象捆绑一个或多个不同的Label
来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
Label
相当于我们熟悉的“标签”。给某个资源对象定义一个Label
,就相当于给它打了一个标签,随后可以通过Label Selector
(标签选择器)查询和筛选拥有某些Label
的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。
Service
在Kubernetes的世界里,虽然每个Pod都会被分配一个单独的IP地址,但这个IP地址会随着Pod
的销毁而消失,这就引出一个问题:如果有一组Pod
组成一个集群来提供服务,那么如何来访问它呢?Service
!
一个Service
可以看作一组提供相同服务的Pod
的对外访问接口,Service
作用于哪些Pod
是通过Label Selector
来定义的。
拥有一个指定的名字(比如my-mysql-server)
拥有一个虚拟IP(Cluster IP、Service IP或VIP)和端口号,销毁之前不会改变,只能内网访问
能够提供某种远程服务能力
被映射到了提供这种服务能力的一组容器应用上
如果
Service
要提供外网服务,需指定公共IP和NodePort,或外部负载均衡器
Service
可以通过配置NodePort
,在Node上打开一个主机的真实端口,这样,能够访问Node
的客户端就能通过这个端口访问到内部的Service
了
Replication Controller
Replication Controller
(简称RC)是Kubernetes系统中的核心概念之一,简单来说,它其实定义了一个期望的场景,即声明某种Pod
的副本数量在任意时刻都符合某个预期值
- 目标Pod的定义
- 目标Pod需要运行的副本数量
- 要监控的目标Pod标签(Label)
Kubernetes通过RC中定义的Label
筛选出对应的Pod
实例,并实时监控其状态和数量,如果实例数量少于定义的副本数量(Replicas),则会根据RC中定义的Pod模板来创建一个新的Pod
,然后将此Pod
调度到合适的Node
上启动运行,直到Pod
实例数量达到预定目标。
最后更新: 2020年05月26日 12:00
原始链接: https://midkuro.gitee.io/2020/05/21/kubernetes-introduction/