

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
简单来说Pod就是由若干容器组成的最小管理单元,在Pod内可以共享网络、存储和计算资源。Kubernetes为每个Pod都分配了唯一的IP地址,称之为Pod IP,一个Pod内的多个容器共享Pod IP地址。在同一节点上,Pod相互可见,但是Pod不能跨节点,一定在一个节点之上,如下图所示:

Pod有两种类型普通的Pod和静态Pod,静态Pod比较特殊,它并没有存放在K8S的etcd存储中,而是存放在某个具体的Node的一个具体文件中,并且只在此Node上启动运行。普通的Pod一旦被创建,就会放入etcd存储,随后被K8S Master调度到某个具体的Node上并进行绑定,随后该Pod被Kubelet进程实例化为一组Docker容器并启动。
###### 1.3.1 创建POD
K8S中的所有对象都可以通过yaml来定义,以下是Pod的yaml文件:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: “200Mi”
requests:
memory: “100Mi”
command: [“stress”]
args: [“–vm”, “1”, “–vm-bytes”, “150M”, “–vm-hang”, “1”]
volumeMounts:- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
- name: redis-storage
* apiVersion记录K8S的API Server版本,现在为v1
* kind记录该yaml的对象类型,这里是Pod
* metadata记录了Pod自身的元数据,比如Pod的名称、Pod属于哪个namespace
* spec记录了Pod内部所有的资源的详细信息:
+ containers记录了Pod内的容器信息,包括:name容器名、image容器的镜像地址,resources容器需要的CPU、内存、GPU等资源,comman容器的入口命令,args容器的入口参数,volumeMounts容器要挂载的Pod数据卷等
+ volumes记录了Pod内的数据卷信息
###### 1.3.2 POD创建过程

1. 用户通过kubectl命名发起请求。
2. apiserver通过对应的kubeconfig进行认证,认证通过后将yaml中的po信息存到etcd
3. Controller-Manager通过apiserver的watch接口发现了pod信息的更新
4. 执行该资源所依赖的拓扑结构整合,整合后将对应的信息交给apiserver
5. apiserver写到etcd,此时pod已经可以被调度了
6. Scheduler同样通过apiserver的watch接口更新到pod可以被调度,通过算法给pod分配节点
7. 并将pod和对应节点绑定的信息交给apiserver
8. apiserver写到etcd,然后将pod交给kubelet
9. kubelet收到pod后,调用CNI接口给pod创建pod网络
10. 调用CRI接口去启动容器,调用CSI进行存储卷的挂载
11. 网络,容器,存储创建完成后pod创建完成,等业务进程启动后,pod运行成功
###### 1.4 工作负载
Kubernetes集群中的Workload工作负载根据不同业务分为以下:
| 业务类型 | API对象 |
| --- | --- |
| 无状态 | ReplicaSet、Deployment |
| 有状态 | StatefulSet |
| 后台持续服务 | DaemonSet |
| 批处理型 | Job |
###### 1.4.1基础构成ReplicaSet
ReplicaSet声明需要多少个复本,由调度控制器通知节点启动副本,目的是维护一组在任何时候都处于运行状态的Pod副本的稳定集合。因此,它通常用来保证给定数量的、完全相同的Pod的可用性。RS的特性与作用总结如下:
* 通过定义RS实现Pod创建及副本数量的自动控制
* RS中包括完整的Pod定义模板
* 通过Label Selector机制实现对Pod副本的自动控制
* 通过改变RS里Pod副本数量,可以实现Pod的扩容与缩容
* 通过改变RS中Pod模板的镜像版本,可以实现Pod的滚动升级
如下图所示, ReplicaSets定义了5个副本分布在三个Node上,因此需要运行5个POD,而DaemonSet每个节点上只运行一个副本。

需要注意的是一般很少单独使用ReplicaSet,主要被Deployment这个更高层的资源对象引用,从而形成一整套Pod的创建、删除和更新的编排机制。
###### 1.4.2 基础构成Deployment
Deployment的作用是管理和控制Pod和ReplicaSet,通过声明某种Pod的副本数量在任意时刻都符合某个预期值,并由ReplicaSet 控制。Deployment和ReplicaSet之间的关系如下:

Deployment的典型使用场景如下:
1. 创建一个Deployment对象来生成对应的Replica Set并完成Pod副本的创建
2. 检查Deployment的状态来看部署动作是否完成(Pod副本数量是否达到预期的值)
3. 更新Deployment以创建新的Pod
4. 如果当前Deployment不稳定,则回滚到一个早先的Deployment版本
5. 暂停Deployment以便于一次性修改多个PodTemplateSpec的配置项,之后再恢复Deployment,进行新的发布
6. 扩展Deployment以应对高负载
7. 查看Deployment的状态,以此作为发布是否成功的指标
8. 清理不再需要的旧版本ReplicaSets
Deployment的定义如下所示,声明最终的部署结果,执行具体过程由kubernetes完成
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: luksa/kubia:v1
name: nodejs
运行下面命令创建Deployment
kubectl create -f tomcat-deployment.yaml
运行下面命令查看Deployment信息:
kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AGE
tomcat-deploy 1 1 1 4h
* DESIRED:Pod副本数量的期望值,即在Deployment里定义的Replica。
* CURRENT:当前Replica的值,实际上是Deployment创建的Replica Set里的Replica值,这个值不断增加,直到达到DESIRED为止,表明整个部署过程完成。
* UP-TO-DATE:最新版本的Pod的副本数量,用于指示在滚动升级的过程中,有多少个Pod副本已经成功升级。
* AVAILABLE:当前集群中可用的Pod副本数量,即集群中当前存活的Pod数量
###### 1.4.3 组成部分StatefulSet
在Kubernetes管理的对象中,ReplicaSet、Deployment、DaemonSet和Job都是面向无状态的服务,但现实中很多服务是有状态的,比如数据库集群、Zookeeper集群等。这些有状态的集群有一些共性的特征:
1. 每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并通信;
2. 集群的规模是比较固定的,集群规模不能随意变动;
3. 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中;
4. 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
为了解决这些有状态的服务,Kubernetes引入了StatefulSet资源,StatefulSet带有状态Pod,重启后依然具有原来的状态信息。具有以下特性:
* StatefulSet里每个Pod都要稳定的、唯一的网络标识,可以用来发现集群内的其它成员。StatefulSet 中的每个 Pod 的名字都是事先确定的,不能更改。
* StatefulSet控制的Pod的启停顺序是有依赖的,操作第n个Pod,前n-1个Pod已经运行且准备好
* StatefulSet 中的 Pod,每个 Pod 挂载自己独立的存储,通过PV或PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷。如果一个 Pod 出现故障,从其他节点启动一个同样名字的 Pod,要挂载上原来 Pod 的存储继续以它的状态提供服务。
适合于StatefulSet的业务包括数据库服务MySQL和PostgreSQL、集群化管理服务ZooKeeper、etcd等有状态服务。StatefulSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。使用 StatefulSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,StatefulSet做的只是将确定的 Pod 与确定的存储关联起来保证状态的连续性。
###### 1.4.4 后台支撑服务集DaemonSet
对于一些批处理型的业务,可能有些节点上运行多个同类业务的Pod,有些节点上又没有这类Pod运行。DaemonSet用于管理在集群中每个Node上仅运行一份Pod的副本实例。

典型的DaemonSet服务包括存储,日志和监控等在每个节点上支持Kubernetes集群运行的服务,比如每个Node上运行一个日志采集程序或者性能监控程序。
###### 1.4.5 组成部分job
Job是Kubernetes用来控制批处理型任务的API对象,在处理完成后整个批处理任务就结束了。Job管理的Pod根据用户的设置把任务成功完成就自动退出了,成功完成的标志根据不同的spec.completions策略而不同:
* 单Pod型任务有一个Pod成功就标志完成
* 定数成功型任务保证有N个任务全部成功,需设定参数.spec.completions
* 工作队列型任务根据应用确认的全局成功而标志成功
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob
spec:
schedule: “*/1 * * * *”
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob
image: busybox
command: [“/bin/sh”,“-c”,“date”]
restartPolicy: Never
按照批处理任务实现方式的不同,批处理任务可以分为几种模式:
1. Job Template Expansion模式:一个Job对象对应一个待处理的Work item,适用于Work item数量少每个work item需要处理大数据量的场景
2. Queue with Pod Per Work Item模式:采用任务队列存放Work item,一个job对象作为消费者去完成这些Work item;这种模式下会启动N个Pod,每个Pod对应一个Work item
3. Queue with Variable Pod Count模式:也是采用任务队列存放work item,不同的是Job启动的Pod数量是可变的

###### 1.5 基础构成Service
Service服务是Kubernetes中的核心资源对象之一,它屏蔽了服务细节,统一对外暴露服务接口,真正做到了“微服务”。在Kubernetes中RS和Deployment只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务的问题。一个 Pod 只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。

如果要稳定地提供服务需要服务发现和负载均衡能力:
* 服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。在K8S集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟 IP,集群内部通过虚拟IP访问一个服务。
* Kubernetes内部的负载均衡是由Kube-proxy实现的,Kube-proxy是一个分布式代理服务器,部署在K8S的每个节点上,负责把Service的请求转发到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制;Kube-proxy在设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的 Kube-proxy 就越多,高可用节点也随之增多。

从图中可以看出,Kubernetes的Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后由Pod副本组成的集群实例,Service与其后端的Pod副本是通过Label Selector来实现无缝对接的。
###### 1.6 基础构成Volume
Kubernetes提供了强大的Volume机制和丰富的插件,解决了容器数据持久化和容器间共享数据的问题。在容器部署过程中一般有以下三种数据:
* 启动时需要的初始数据,可以是配置文件
* 启动过程中产生的临时数据,该临时数据需要多个容器间共享
* 启动过程中产生的持久化数据
以上都不希望在容器重启时就消失,存储卷由此而来,K8S中可以根据不同场景提供不同类型的存储能力。K8S中支持的存储类型如下:
#hostPath – 挂载主机磁盘到容器
#NFS/NAS –挂载共享文件系统
#emptyDir
#awsElasticBlockStore / azureFileVolume
#Glusterfs
#Ceph rbd / Cephfs
Volume的使用比较简单,现在Pod中声明一个Volume,然后在容器内引用该Volume并mount到容器的某个目录上,如下图所示:

普通的Volume是定义在Pod上的,属于计算资源的一部分,实际上网络存储是相对独立于计算资源而存在的一种实体资源。因此PersistentVolumes可以理解为Kubernetes集群中某个网络存储对应的存储。如果某个Pod想申请某种类型的PV,首先需要定义一个PersistentVolumeClaims对象。
###### 1.6.1 持久化存储卷PersistentVolume
PersistentVolume是存储系统与应用系统区分开,单独资源对象。PV是对底层共享存储的一种抽象,将共享存储定义为一种资源。PV不直接和Pod发生关系,通过资源对象PVC (PersistentVolumeClaim)来绑定关联。PV与Volume的区别如下:
* PV只能是网络存储,不属于任何Node,但可以在每个Node上访问
* PV不是定义在Pod上的,而是独立于Pod之外定义的

PVC是用户存储的请求,在pod中定义存储卷,定义的时候直接指定大小,与对应的pv建立关系。PV的整个生命周期是:
Provisioning(配置)—>Binding(绑定)—>Using(使用)—>Releasing(释放)—>Recycling(回收)
PV的创建有两种模式:静态模式和动态模式,静态模式下除了创建PVC外,还需要手动创建PV。


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
态模式,静态模式下除了创建PVC外,还需要手动创建PV。
[外链图片转存中...(img-Fs0rAyXt-1715626240368)]
[外链图片转存中...(img-kZcTqaX8-1715626240368)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**


被折叠的 条评论
为什么被折叠?



