在学习k8s之前,必须先了解 Kubernetes 的几个重要概念,它们是组成 Kubernetes 集群的基石。(参考Kubernetes权威指南)
一、Master
Kubernetes 里的Master指的是集群的控制节点, 每个Kubernetes 集群里至少需要有一个Master节点负责整个集群的管理和控制,基本上Kubernetes的所有控制命令都发给它,它来负责具体的执行过程,我们后面执行的所有命令基本都是在Master节点上运行。为了实现高可用,可以运行多个Master。
Master节点上运行着以下一组关键进程。
- Kubernetes API Server(kube-apiserver), 提供 HTTP Rest 接口的关键服务程序,kubernets里所有资源增、删、改、查等操作的唯一入口,也是集群控制的入口进程。
- Kubernetes Controller Manager(kube-controller-manager),所有资源对象的自动化控制中心可以理解为资源对象的大总管。
- Kubernetes Scheduler(kube-scheduler),资源调度(pod)的进程,相当于调度室。
- etcd Server,Kubernetes 里所有资源对象的数据全部是保持在etcd中,etcd是一种key-value类型的数据库
二、Node
Node 的职责是运行各种容器应用。Node 由 Master 管理,Node 上有相应的服务负责监控并汇报容器的状态,并根据 Master 的要求管理容器的生命周期。Node 可以是物理机或者是虚拟机,可以是Windows或者是Linux的操作系统。Master节点也可以充当为node节点。
Node运行着一些关键进程:
- kubelet:负责Pod对应的容器的创建、启停等任务,同时与Master节点密切协作,实现集群管理的基本功能。
- kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件。
- Docker Engine (docker):Docker引擎,负责本机的容器创建和管理工作。
我们可以执行下述命令查看集群中有多少个Node(master节点也算是node节点中的一种):
[root@k8s-m1 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-m1 Ready master 111d v1.19.16
k8s-m2 Ready master 111d v1.19.16
k8s-m3 Ready master 111d v1.19.16
三、Pod
Pod 是 Kubernetes 的最小工作单元。每个 Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被 Master 调度到某个 Node 上运行。(可以把pod想象成豌豆荚,里面的豌豆就是容器,可以有一个或多个。)
说到Pod,简单介绍其概念。首先,Pod运行在一个我们称之为节点(Node)的环境中,这个节点可能是物理机或虚拟机,通常一个节点上上面运行几百个Pod;其次每个Pod运行着一个特殊的被称之为根容器(Pause),和一组用户容器组成。一方面,用Pause 容器的状态代表整个容器组的状态;另一方面,这些业务容器共享根容器(Pause)的网络栈和Volume挂载卷,因此它们之间的通信和数据交换效率更为高效。在设计时我们可以充分利用这一特性将一组密切相关的服务进程放到同一个Pod中。最后需要注意的是并不是每一个Pod和它里面运行的容器都能映射到一个Service上,只有那些提供服务的一组Pod才会被映射成一个服务。
Kubernetes 引入 Pod 主要基于下面两个目的:
- 可管理性:
在一组容器作为一个单元的情况下,我们难以对“整体”简单地进行判断及有效地进行行动。比如,一个容器死亡了,此时算是整体死亡么?引入业务无关并且不易死亡的Pause容器作为Pod的根容器,以它的状态代表整体容器组的状态,就简单、巧妙地解决了这个难题。 - 通信和资源共享:
Pod里的多个业务容器共享Pause容器的IP,即相同的 IP 地址和 Port 空间。它们可以直接用 localhost 通信。同样的,这些容器可以共享存储,当 Kubernetes 挂载 volume 到 Pod,本质上是将 volume 挂载到 Pod 中的每一个容器。这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。
静态Pod & 普通Pod
-
普通的Pod:
普通Pod一旦被创建,就会被放入到etcd中存储,随后会被Kubernetes Master调度到某个具体的Node上并进行绑定(Binding),随后该Pod 被对应的Node上的kubelet进程实例化成一组相关的docker容器运行起来。
当Pod里的某个容器停止时,Kubernetes会自动检测到这个问题并且重新启动这个Pod (重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上所有的Pod从新调度到其他节点上。 -
静态Pod (Static Pod):
静态Pod不存放在Kubernetes的etcd存储里,而是存放在某个具体的Node上的文件夹中(如果是k8s集群是通过kubeadm部署的,该文件夹默认是/etc/kubernetes/manifests/),并且只在此Node上启动运行。
静态Pod是由kubelet进行管理的仅存在于特定Node上的Pod。他们不能通过API Server进行管理,无法与ReplicationController(RC)、Deployment、或者DaemonSet进行关联,并且kubelet也无法对它们进行健康检查。静态Pod总是由kubelet进行创建的,并且总是在kubelet所在的Node上运行的
三、副本控制器类型(Pod叫副本)
ReplicationController (简称为RC)
ReplicaSet (简称为RS)
Deployment
StatefulSet
DaemonSet
Job,Cronjob
Pods 有两种使用方式:
运行单一容器:
one-container-per-Pod 是 Kubernetes 最常见的模型,这种情况下,只是将单个业务容器简单封装成 Pod。即便是只有一个容器,Kubernetes 管理的也是 Pod 而不是直接管理容器。
运行多个容器:
但问题在于:哪些容器应该放到一个 Pod 中?
答案是:这些容器联系必须 非常紧密,而且需要 直接共享资源。
示例:
下面这个 Pod 包含两个容器:一个 File Puller,一个是 Web Server。他们两个container的net namespace、uts namespace、ipc namespace是属于共享的。 mnt namespace、user namespace、pid namespace是互相隔离的。
四、Label:
Label是Kubernetes系统中另外一个核心概念。一个Label是一个key=value的键值对,其中key与vaue由用户自己指定。Label可以附加到各种资源对象上,例如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去,Label通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。
我们可以通过指定的资源对象捆绑一个或多个不同的Label来实现多维度的资源分组管理功能,以便于灵活、方便地进行资源分配、调度、配置、部署等管理工作。例如:部署不同版本的应用到不同的环境中;或者监控和分析应用(日志记录、监控、告警)等。一些常用等label示例如下
版本标签:“release”:“stable”,“release”:“canary”…
环境标签:“environment”:“dev”,“environment”:“qa”,“environment”:“production”
架构标签:“tier”:“fronted”,“tier”:“backend”,“tier”:"middleware”
分区标签:“partition”:“customerA”,“partition”:"customerB”…
质量管控标签:“track”:“daily”:“rack”:“weekly”
Label相当于我们熟悉的“标签”,給某个资源对象定义一个Label,就相当于給它打了一个标签,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。
Label Selector可以被类比为SQL语句中的where查询条件,例如,name=redis-slave这个label Selector作用于Pod时,可以被类比为select * from pod where pod’s name = 'redis-slave’这样的语句。当前有两种Label Selector的表达式:基于等式的(Equality-based)和基于集合的(Set-based),前者采用“等式类”的表达式匹配标签,下面是一些具体的例子。
-
基于等式的表达式匹配标签实例:
name=redis-slave:匹配所有具有标签name=redis-slave的资源对象。
env != production:匹配所有不具有标签env=production的资源对象。 -
基于集合方式的表达式匹配标签实例:
name in (redis-master,redis-slave):匹配所有具有标签name=redis-master或者name=redis-slave的资源对象。
name notin (php-frontend):匹配所有不具有标签name=php-frontend的资源对象。
可以通过多个Label Selector表达式的组合实现复杂的条件,多个表达式之间用“,”进行分隔即可,几个条件之间是“AND”的关系,即同时满足多个条件,比如下面的例子:
name=redis-slave,env!=production
name notin (php-fronted),env!=production
Label Selector在Kubernetes中重要使用场景有以下几种:
- kube-controller进程通过资源对象RC上定义都Label Selector来筛选要监控的Pod副本的数量,从而实现Pod副本的数量始终符合预期设定的全自动控制流程。
- kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立起每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制。
通过对某些Node定义特定的Label,并且在Pod定义文件中使用NodeSelector这种标签调度策略,kube-scheduler进程可以实现Pod“定向调度”的特性。 - 前面我们只是介绍了一个name=XXX的Label Selector。让我们看一个更复杂的例子。假设为Pod定义了Label: release、env和role,不同的Pod定义了不同的Label值,如图下图所示,如果我们设置了“role=frontend”的Label Selector,则会选取到Node 1和Node 2上到Pod。
而设置“release=beta”的Label Selector,则会选取到Node 2和Node 3上的Pod,如下图所示。
总结:使用Label可以給对象创建多组标签,Label和Label Selector共同构成了Kubernetes系统中最核心的应用模型,使得被管理对象能够被精细地分组管理,同时实现了整个集群的高可用性。
五、service
Service也是Kubernetes里的最核心的资源对象之一,Kubernetes里的每个Service其实就是我们经常提起的微服务架构中的一个“微服务”,之前我们所说的Pod、RC等资源对象其实都是为这节所说的“服务”------Kubernetes Service作“嫁衣”的。下图显示了Pod、RC与Service的逻辑关系。
Service和ReplicationController之间的关系
对于这两种对象的Label选择器是用map定义在json或者yaml文件中的,并且只支持基于等式(Equality-based)的条件:
"selector": { "component" : "redis",}
#要么:
selector: component: redis
此选择器(分别为json或yaml格式)等同于component=redis或component in (redis)。
支持set-based的资源
Job,Deployment,Replica Set,和Daemon Set,支持基于等式和基于集合方式(set-based)的两种表达式。
selector:
matchLabels:
component: redis
matchLabels 是一个{key,value}的映射。一个单独的 {key,value} 。
selector:
matchExpressions:
- {key: tier, operator: In, values: [prod,backup]}
- {key: environment, operator: NotIn, values: [dev]}
注意:以上实例表示
key 键 tier
operator 操作符 in
values 值 [prod,backup]
表示key键tier要包含cache和backup
matchExpressions 是一个pod的选择器条件的list 。有效运算符包含In, NotIn, Exists, 和DoesNotExist。在In和NotIn的情况下,value必须不能为空列表。Exists和DoesNotExist的情况下,value必须为空列表。当包含 matchLabels 和 matchExpressions都纯在时,会用AND符号连接,他们必须都被满足才能完成匹配。
六、Replication Controller
RC是Kubemetes系统中的核心概念之一,简单来说,它其实是定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包括如下几个部分。
Pod期待的副本数(replicas)。
用于筛选目标Pod的LabelSelector.
当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模板(template)。
需要注意的是,删除RC并不会影响通过该RC己创建好的Pod。为了删除所有Pod,可以设置replicas的值为0,然后更新该RC。另外,kubectl提供了stop和delete命令来一次性删除RC和RC控制的全部Pod。
七、Deployment
Deployment是Kubemetesvl .2 引入的新概念,引入的目的是为了更好地解决Pod的编排问题。 为此,Deployment在内部使用了Replica Set来实现目的,无论从Deployment的作用与目的、它的Yaml定义,还是从它的具体命令行操作来看,我们都可以把它看作RC的一次升级,两者的相似度超过90%。
Deployment相对于RC的一个最大升级是我们可以随时知道当前Pod“部署”的进度。实
际上由于一个Pod的创建、调度、绑定节点及在目标Node上启动对应的容器这一完整过程需
要一定的时间,所以我们期待系统启动N个Pod副本的目标状态,实际上是一个连续变化的“部
署过程”导致的最终状态。
Deployment的典型使用场景有以下几个。
创建一个Deployment对象来生成对应的ReplicaSet井完成Pod副本的创建过程。
检查Deployment的状态来看部署动作是否完成(Pod副本的数量是否达到预期的值)。
更新Deployment以创建新的Pod (比如镜像升级)。
如果当前Deployment不稳定,则回滚到一个早先的Deployment版本。
暂停Deployment 以便于一次性修改多个PodTemplateSpec 的配置项,之后再恢复Deployment,进行新的发布。
扩展Deployment以应对高负载。
查看Deployment的状态,以此作为发布是否成功的指标。
清理不再需要的旧版本ReplicaSets。
八、StatefulSet
在Kubemetes系统中, Pod的管理对象RC、 Deplo严nent、 DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、 MongoDB集群、Kafka集群、 ZooKeeper集群等, 这些应用集群有以下一些共同点:
每个节点都有固定的身份田,通过这个ID,集群中的成员可以相互发现并且通信。
集群的规模是比较固定的,集群规模不能随意变动。
集群里的每个节点都是有状态的,通常会持久化数据到永久存储中。
如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
九、Horizontal Pod Autoscaler (水平pod自动伸缩)
应用场景,分布式系统要能够根据当前负载的变化情况自动触发水平扩展或缩容的行为,因为这一过程可能是频繁发生的、不可预料的,所以手动控制的方式是不现实的。
HPA与之前的RC、 Deployment一样,也属于一种Kubemetes资源对象。通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。常用的HPA可以有以下两种方式作为Pod负载的度量指标。
CPUUtilizationPercentage。
应用程序自定义的度量指标,比如服务在每秒内的相应的请求数(TPS或QPS)。
十、Service (服务)
Service也是Kubemetes里的最核心的资源对象之一, Kubernetes里的每个Service其实就是我们经常提起的微服务架构中的一个“微服务”,之前我们所说的Pod、 RC等资源对象其实都是为这节所说的“服务”---- Kubemetes Service作“嫁衣”的。 下图显示了Pod、 RC与Service的逻辑关系。
Kubernetes的Service定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与其后端Pod副本集群之间则是通过LabelSelector来实现“无缝对接”的。而RC(常用deployment)的作用实际上是保证Service的服务能力和服务质量始终处于预期的标准。
十一、Volume (存储卷)
Volume是Pod中能够被多个容器访问的共享目录。Kubemetes的Volume概念、用途和目的与Docker的Volume比较类似,但两者不能等价。 首先,Kubemetes中的Volume定义在Pod
上,然后被一个Pod里的多个容器挂载到具体的文件目录下;其次,Kubemetes中的Volume与
Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时,Volume中的数据
也不会丢失。最后,Kubemetes支持多种类型的Volume,例如GlusterFS、 Ceph等先进的分布
式文件系统。
十二、Persistent Volume
之前我们提到的Volume是定义在Pod上的,属于“计算资源”的一部分,而实际上,“网络存储”是相对独立于“计算资源”而存在的一种实体资源。比如在使用虚拟机的情况下,我们通常会先定义一个网络存储,然后从中划出一个“网盘”并挂接到虚拟机上。PersistentVolume (简称PV)和与之相关联的PersistentVolume Claim (简称PVC)也起到了类似的作用。
PV可以理解成Kubemetes集群中的某个网络存储中对应的一块存储,它与Volume很类似,但有以下区别。
PV只能是网络存储,不属于任何Node,但可以在每个Node上访问。
PV井不是定义在Pod上的,而是独立于Pod之外定义。
PV 目前支持的类型包括: gcePersistentDisk、 AWSElasticBlockStore、 AzureFile、
AzureDisk、 FC(Fibre Channel)、 Flocker、 NFS、 iSCSI、 RBD(Rados Block Device)、
CephFS、Cinder、GlusterFS、Vsphere Volume、QuobyteVolumes、VMwarePhoton、Portwonc
Volumes、 ScaleIOVolumes和HostPath。
十三、Namespace (命名空间)
Namespace (命名空间〉是Kubemetes系统中的另一个非常重要的概念,Namespace在很多
情况下用于实现多租户的资源隔离。Namespace 通过将集群内部的资源对象“分配”到不同的
Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个
集群的资源的同时还能被分别管理。
默认使用的命名空间为default,默认的命名空间有default、kube-system
以上只是做一个大致了解,后面将对部分内容详细分享。
更多关于kubernetes的知识分享,请前往博客主页。