一、Kubernetes入门
1. kind
kind 用来表明此资源类型的类型。
# Pod 这种资源对象归属于V1这个核心API。
# Kubernetes大部分常见的核心 资源对象都归属于v1这个核心API,比如Node、Pod、Service、 Endpoints、Namespace、RC、PersistentVolume等
apiVersion: v1
kind: Pod
2. 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中。
3. Node
除了Master,Kubernetes集群中的其他机器被称为Node.Node是Kubernetes集群中的工作负载节点,每个 Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机 时,其上的工作负载会被Master自动转移到其他节点上。
在每个Node上都运行着以下关键进程。
- kubelet:负责Pod对应的容器的创建、启停等任务,同时与 Master密切协作,实现集群管理的基本功能。
- kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件。
- Docker Engine(docker):Docker引擎,负责本机的容器创建 和管理工作。
查看在集群中有多少个Node:
[root@node2 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready deploy,master,node 72d v1.14.3
node2 Ready master,node 72d v1.14.3
node3 Ready master,node 72d v1.14.3
node4 Ready node 72d v1.14.3
node5 Ready node 72d v1.14.3
通过kubectl describe node <node_name>查看某个Node的详细信息
4. Pod
每个Pod都有一个特殊的被称为“根容器”的Pause容器。 Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器, 每个Pod还包含一个或多个紧密相关的用户业务容器。
为什么Kubernetes会设计出一个全新的Pod的概念并且Pod有这样特殊的组成结构?
- 在一组容器作为一个单元的情况下,我们难以简单地 对“整体”进行判断及有效地行动。比如,一个容器死亡了,此时算是整 体死亡么?是N/M的死亡率么?引入业务无关并且不易死亡的Pause容器作为Pod的根容器,以它的状态代表整个容器组的状态,就简单、巧 妙地解决了这个难题。
- Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器之间的通信问 题,也很好地解决了它们之间的文件共享问题。
每个Pod都可以对其能使用的服务器上的计算资源设置限额,当前 可以设置限额的计算资源有CPU与Memory两种,其中CPU的资源单位 为CPU(Core)的数量,是一个绝对值而非相对值。
在 Kubernetes里通常以千分之一的CPU配额为最小单位,用m来表示。通 常一个容器的CPU配额被定义为100~300m,即占用0.1~0.3个CPU。
在Kubernetes里,一个计算资源进行配额限定时需要设定以下两个参数。
- Requests:该资源的最小申请量,系统必须满足要求。
- Limits:该资源最大允许使用的量,不能被突破,当容器试图 使用超过这个量的资源时,可能会被Kubernetes“杀掉”并重启。
5. Label
一个Label是 一个key=value的键值对,其中key与value由用户自己指定。Label可以被 附加到各种资源对象上,例如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。Label通常在资源对象定义时确定,也可以在对象创建后 动态添加或者删除。
可以通过给指定的资源对象捆绑一个或多个不同的Label来实现多维度的资源分组管理功能,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
6. Replication Controller
简单来说,它其实定义了 一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值
RC的定义包括如下几个部分。
- Pod期待的副本数量。
- 用于筛选目标Pod的Label Selector。
- 当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模板 (template)。
7. StatefulSet
在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet 和Job都面向无状态的服务。但现实中有很多服务是有状态的,特别是 一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Akka集 群、ZooKeeper集群等,这些应用集群有4个共同点。
(1)每个节点都有固定的身份ID,通过这个ID,集群中的成员可 以相互发现并通信。
(2)集群的规模是比较固定的,集群规模不能随意变动。
(3)集群中的每个节点都是有状态的,通常会持久化数据到永久存储中。
(4)如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
Kubernetes从1.4版本开始引入了PetSet这个新的资源对象,并且在1.5版本时更名为StatefulSet,StatefulSet从本质上来说,可以看作
Deployment/RC的一个特殊变种,它有如下特性。
- StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来 发现集群内的其他成员。假设StatefulSet的名称为kafka,那么第1个Pod 叫kafka-0,第2个叫kafka-1,以此类推。
- StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经是运行且准备好的状态。
- StatefulSet里的Pod采用稳定的持久化存储卷,通过PV或PVC来 实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)。
StatefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,即在每个StatefulSet定义中都要声明它属于 哪个Headless Service。Headless Service与普通Service的关键区别在于,它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的 基础上又为StatefulSet控制的每个Pod实例都创建了一个DNS域名,这个域名的格式为:
${podname}${headless service name}
比如一个3节点的Kafka的StatefulSet集群对应的Headless Service的名 称为kafka,StatefulSet的名称为kafka,则StatefulSet里的3个Pod的DNS 名称分别为kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,这些DNS名称 可以直接在集群的配置文件中固定下来。
8. Service
Kubernetes里的每个Service其实就是我们经常提起的微服务架构中的一个微服务。
既然每个Pod都会被分配一个单独的IP地址,而且每个Pod都提供了一个独立的Endpoint(Pod IP+ContainerPort)以被客户端访问,现在多 个Pod副本组成了一个集群来提供服务,那么客户端如何来访问它们呢?
Kubernetes在每个Node上的kube-proxy 进程其实就是一个智能的软件负载均衡器,负责把对Service的请求转发 到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制。但Kubernetes发明了一种很巧妙又影响深远的设计:Service没有共 用一个负载均衡器的IP地址,每个Service都被分配了一个全局唯一的虚拟IP地址,这个虚拟IP被称为Cluster IP。这样一来,每个服务就变成了 具备唯一IP地址的通信节点,服务调用就变成了最基础的TCP网络通信问题。
我们知道,Pod的Endpoint地址会随着Pod的销毁和重新创建而发生改变,因为新Pod的IP地址与之前旧Pod的不同。而Service一旦被创建,Kubernetes就会自动为它分配一个可用的Cluster IP,而且在Service的整个生命周期内,它的Cluster IP不会发生改变。于是,服务发现这个棘手 的问题在Kubernetes的架构里也得以轻松解决:只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完美解决问题。
9. Volume
Volume(存储卷)是Pod中能够被多个容器访问的共享目录。
首先,Kubernetes中的Volume被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下;其次,Kubernetes中的 Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时,Volume中的数据也不会丢失。最后,Kubernetes支持多 种类型的Volume,例如GlusterFS、Ceph等先进的分布式文件系统。
10. Persistent Volume
Volume是被定义在Pod上的,属于计算资源的一部分,而实际上,网络存储是相对独立于计算资源而存在的一种实体资源。比 如在使用虚拟机的情况下,我们通常会先定义一个网络存储,然后从中划出一个“网盘”并挂接到虚拟机上。Persistent Volume(PV)和与之相 关联的Persistent Volume Claim(PVC)也起到了类似的作用。
最后说说PV的状态。PV是有状态的对象,它的状态有以下几种。
- Available:空闲状态。
- Bound:已经绑定到某个PVC上。
- Released:对应的PVC已经被删除,但资源还没有被集群收回。
- Failed:PV自动回收失败。
11. Namespace
Namespace在很多情况下用于实现多租户的资源隔离。Namespace通过将集群内部的资源对象“分配”到不同的Namespace中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。
[root@node2 ~]# kubectl get namespaces --namespace=default
NAME STATUS AG
default Active 73d
kube-efk Active 73d
kube-node-lease Active 73d
kube-public Active 73d
kube-system Active 73d
monitoring Active 73d
12. Annotation
Annotation(注解)与Label类似,也使用key/value键值对的形式进行定义。不同的是Label具有严格的命名规则,它定义的是Kubernetes对象的元数据(Metadata),并且用于Label Selector。
13. ConfigMap
Docker通过将程序、依赖库、数据及配置文件“打包固化”到一个不变的镜像文件中的做法,解决了应用的部署的难题,但这同时带来了棘手的问题,即配置文件中的参数在运行期如何修改的问题。
首先,把所有的配置项都当作key-value字符串,当然value可以来自某个文本文件,比如配置项password=123456、user=root、 host=192.168.8.4用于表示连接FTP服务器的配置参数。这些配置项可以作为Map表中的一个项,整个Map的数据可以被持久化存储在 Kubernetes的Etcd数据库中,然后提供API以方便Kubernetes相关组件或客户应用CRUD操作这些数据,上述专门用来保存配置参数的Map就是Kubernetes ConfigMap资源对象。
接下来,Kubernetes提供了一种内建机制,将存储在etcd中的ConfigMap通过Volume映射的方式变成目标Pod内的配置文件,不管目 标Pod被调度到哪台服务器上,都会完成自动映射。进一步地,如果ConfigMap中的key-value数据被修改,则映射到Pod中的“配置文件”也会随之自动更新。于是,Kubernetes ConfigMap就成了分布式系统中最为 简单(使用方法简单,但背后实现比较复杂)且对应用无侵入的配置中心。
二、kubectl命令行工具
kubectl作为客户端CLI工具,可以让用户通过命令行对Kubernetes集群进行操作。
1. kubectl用法概述
语法:kubectl command NAME
其中,command、TYPE、NAME、flags的含义如下。
- command:子命令,用于操作Kubernetes集群资源对象的命令,例如create、delete、describe、get、apply等。
- TYPE:资源对象的类型,区分大小写,能以单数、复数或者简写形式表示。
- NAME:资源对象的名称,区分大小写。如果不指定名称,系统则将返回属于TYPE的全部对象的列表。
- flags:kubectl子命令的可选参数,例如使用“-s”指定APIServer的URL地址而不用默认值。
2.kubectl输出格式
kubectl命令可以用多种格式对结果进行显示,输出的格式通过-o参数指定。
语法:kubectl command [NAME] -o=<output_format>
常用的输出格式示例如下。
# 显示Pod的更多信息
kubectl get pod <podname> -o wide
# 以YAML格式显示Pod的详细信息
kubectl get pod <podname> -o yaml
# 以自定义列名显示Pod的信息
kubectl get pod <podname> -o=custom-columns=NAME:.metadta.name
# 基于文件的自定义列名输出
kubectl get pod <podname> -o=custom-columns-file=template.txt
template.txt 文件的内容为:
NAME RSRC
metadata.name metadta.recourceVersion