目录
Pod从入门到精通
1.管理器管理Pod
2.资源清单YAML文件注解
3.Node节点选择器
4.亲和性和污点容忍度
1. node节点亲和性
2. Pod节点亲和性
3.污点和容忍度
5.Pod的状态和重启策略
6.Pod初始化容器-钩子-启动退出流程
pod创建过程
钩子
7.Pod终止过程
8.Pod探针
Pod从入门到精通
Pod是k8s中的最小调度单元,k8s首先会通过定义一个Pod的资源,然后在 Pod里面运行容器,容器的运行需要指定一个镜像,这样就可以用来运行具体的应用服务。一个 Pod中封装一个容器(也可以封装多个容器),Pod中包含了一个默认的Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过 Pause容器可以使同一个 Pod里面的多个容器共享存储、网络、PID、IPC等。
Pod是需要被调度到k8s集群的工作((Node/Work)节点上来运行的,具体调度到哪个节点,是根据k8s 的组件Icheduler调度器来实现的。
Pod中可以同时运行多个容器。同一个 Pod中的容器会自动的分配到同一个node节点上。同一个Pod中的容器共享资源、网络环境,在一个 Pod中同时运行多个容器是一种比较高级的用法,只有当你的容器需要紧密配合协作的时候才会考虑用这种模式。例如,你有一个容器作为web服务器运行,需要用到共享的volume,有另一个容器用来从远端获取资源更新这些文件。 一些Pod有init(初始化容器),容器和应用容器。在应用程序容器启动之前,需要先运行初始化容器。
1.管理器管理Pod
常见的Pod控制器有Replicaset、Deployment、Daemonset、Statefulset、Job、CronJob等。控制器管理的Pod可以确保Pod始终维持在用户指定的副本数状态运行。
2.资源清单YAML文件注解
apiVersion:v1 ## api版本
kind: pod ##创建的资源类型
metadata: ##资源详细信息 元信息
name: nginx-pod ##pod的名字
namespace: default ##pod所在的名称空间
labels:
app: nginx ##pod具有的标签
spec: ##定义pod的规格
containers:
- name: nginx-pod #pod里容器的名字
ports:
- containerPort:80 ##容器里暴露的端口
images: nginx:1.21.5
imagesPullPolicy:IfNotPresent ##镜像拉取策略
3.Node节点选择器
在创建pod资源的时候,pod会通过 schduler.组件进行调度到Node节点,默认会调度到随机的一个Node节点,如果我们想要把pod调度到指定节点或者调度到一些具有相同特点的Node节点,可以使用pod中的nodeName或者nodeSelector (标签)字段指定要调度到的node节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: test
labels:
app: nginx
spec:
containers:
nodeName: dreamnode1 #####
- name: nginx-pod
ports:
- containerPort: 80
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
给node节点打标签: kubectl label nodes dream-node1 disk=ceph
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: test
labels:
app: nginx
spec:
containers:
nodeSelector: !!!!!!
disk: ceph
- name: nginx-pod
ports:
- containerPort: 80
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
4.亲和性和污点容忍度
1. node节点亲和性
Node节点亲和性针对的是pod和node的关系,pod调度到node节点的时候匹配的条件
preferredDuringSchedulinglgnoredDuringExecution表示有节点尽量满足这个定义的亲和性,不是一个必须的条件,属于软亲和性 requiredDuringSchedulinglgnoredDuringExecution表示必须有节点满足这个定义的亲和性,是一个必须的条件,属于硬亲和性
硬亲和性
vim nodeaffinity
apiVersion: v1
kind: Pod
metadata:
name: pod-nodeaffinity
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: nginx:1.21.5
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- foo
- bar
k8s会检测当前集群中那个节点上配置了zone标签,并且值是foo或者bar。k8s就会把pod调度到这个node节点上。必须满足条件才能完成调度
kubectl label nodes node1 zone=foo
这时候Pod就会running
2. Pod节点亲和性
Pod 自身的关和性调度有两种表示形式;
podAffinity(亲和性):两个Pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和 pod之间通信更好,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx,和tomcat都部署同一个地方的node节点上,可以提高通信效率;I
podAntiAffinity(反亲和性)﹔两个Pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。
第一个pod会随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的; 我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?可以以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。
pod节点亲和性 定义两个pod,以第一个pod为基准,第二个pod跟着他走
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: dream1 !!!
tier: frontend
spec:
containers:
- name: dream
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: dream2
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["dream1"]} !!!!
topologyKey: kubernetes.io/hostname !!!
pod反亲和性
定义两个pod,以第一个pod为基准,第二个pod反着在第二个节点上
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: dream1
tier: frontend
spec:
containers:
- name: dream
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: dream2
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["dream1"]}
topologyKey: kubernetes.io/hostname ##这个是node的标签 可以通过改node的标签然后这里换
3.污点和容忍度
污点是定义在节点上的键值属性数据,可以定决定拒绝那些pod来运行;污点是给节点选则的主动权,我们可以给节点打一个污点,不容忍的pod就不会到此节点运行。
taints是键值数据,配置在节点上,用于定义污点; tolerations.是键值数据,配置在pod 上,用于定义容忍度,能容忍哪些污点;
查看节点的taints值排斥等级信息: kubectl describe node master | grep "Taints"
节点对pod对象的排斥等级:
NoSchedule:仅影响pod调度过程,当pod能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的pod不能容忍了,那这个pod会怎么处理,也不会对现存的pod对象产生影响;
NoExecuter既影响调度过程,又影响现存的pod对象,如果现存的pod不能容忍节点后来加的污点,这个pod就会被驱逐;
PreferNoSchedule:最好不,也可以,是NoSchedule的柔性版本;
节点的污点taints是一个键值对 : key=values:排斥等级
Pod资源定义容忍度支持两种操作 1.等值密钥 Equal: key,value和effect全部都要匹配一样,才可以被节点调用 2.存在性判断 Exists: key和effect(排斥等级)必须同时匹配,value可以是空
给节点设置污点: kubectl taint node dream-node1 dream=king:NoSchedule 这个时候node1的污点taint就为 dream=king这个键值和NoSchedule这个排斥等级
pod如果不能容忍这个节点的污点就不会被节点调度使用
给pod配置容忍度:
apiVersion: v1
kind: Pod
metadata:
name: dream-deploy
namespace: default
labels:
app: dream22
release: king22
spec:
containers:
- name: dream
image: nginx:1.21.1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
tolerations:
- key: "dream"
operator: "Equal"
value: "king"
effect: "NoExecute"
删除node节点污点: kubectl taint nodes dream-node1 dream-king:NoExeute-
5.Pod的状态和重启策略
Pod 的 status 状态被定义在 PodStatus对象中,其中有一个phase字段。它简单描述了Pod在其生命周期的阶段。熟悉Pod 的各种状态对我们理解如何设置Pod的调度策略、重启策略是很有必要的。下面是 phase可能的出现值,也就是pod常见的状态。
挂起( Pending):我们在请求创建pod时,条件不满足,调度没有完成,没有任何一 个Node节点能满足调度条件,已经创建了pod但是没有适合它运行的节点时状态叫做挂起,任务调度没有完成,处于pending状态的Pod会持续一段时间:包括调度Pod的时间和通过网络下载镜像的时间。
运行中(Running) : Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
成功(Succeeded) : Pod中的所有容器都被成功终止,并且不会再重启。
失败(Failed) : Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非О状态退出或者被系统终止。
未知(Unknown):未知状态,pod状态是通过apiserver.和 node节点的 kubelet进行通信获取状态信息的,如果 node节点之上的kubelet,本身出故障,那么apiserver.就连不到 kubelet 了,也得不到信息了,这是就会看到Unknown状态。
Evicted状态:出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。
CrashLoopBackOff:Pod 曾经启动了,但可能又异常退出了。
Error状态: Pod启动过程中发生了错误。
Pod的重启策略(RestartPolicy)会应用于Pod 内的所有容器,并且仅在Pod所在的Node节点上的 kubelet,进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置来进行相应的操作(初步故障修复方案)。
Pod的重启策略包括 Always、OnFailure和Never,默认值为Always 。 Always:当容器失败时,由kubelet,自动重启该容器。
OnFailure:当容器终止运行且退出码不为0时,由kubelet,自动重启该容器。
Never:不论容器运行状态如何,kubelet都不会重启该容器。
应用RestartPolicy
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
restarPolicy: Always ###添加这个就可以应用这个策略
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: 192.168.120.104/dreamlinux/nginx:1.21.5
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
6.Pod初始化容器-钩子-启动退出流程
pod创建过程
1)运行初始化容器(init container)过程(可多可少,可有可无)
2)运行主容器(main container)过程
3)容器启动后执行的钩子函数(post start),容器终止前执行的钩子函数(pre stop)
4)容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
5)pod终止过程
Init,容器与普通的容器区别是: 1、Init容器不支持 Readiness,因为它们必须在Pod就绪之前运行完成;
2、每个Init容器必须运行成功,下一个容器才能够运行;
3、如果 Pod中的 lnit容器失败,Kubernetes会不断地重启该Pod,直到Ilnit容器成功为止,如果Pod对应的restartPolicy值为Never它不会重新启动。
钩子
Pod中的初始化容器启动之后,会开始启动主容器,在主容器启动之前有一个 Post StartHook(容器启动后钩子)和Pre Stop Hook(容器结束前钩子),无论启动后还是结束前要做的事可以放两个钩子里,这两个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清理,与awk, 中的BEGIN,END 效果类似;
postStart:该钩子是在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的 hook handler执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。
preStop:该钩子是在容器被删除前触发,所对应的 hook handler必须在删除该容器的请求发送给Docker daemon之前完成。在该钩子对应的hook handler完成后不论执行的结果如何,Docker daemon会发送一个SGTERN信号量给Docker daemon来删除该容器,这个钩子不需要传递任何参数。
钩子应用场景 postStart:容器创建成功后立刻触发,用于资源部署、环境准备等。 preStop:容器被终止前要执行的任务,用于优雅关闭应用程序、通知其他系统等。
默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户身份来修改默认值。o表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。
containers:
- image: sample:v2
name: war
lifecycle:
postStart:
exec:
command:
- “cp”
- “/sample.war”
- “/app”
prestop:
httpGet:
host: monitor.com
path:/waring
port:8080
scheme: HTTP
7.Pod终止过程
1、用户向apiserver.发送删除pod对象的命令; 2、apiserver中的pod对象信息会随着时间的推移而更新,在宽限期内(默认是 30s), pod被视为dead; 3、将pod标记为terminating(正在删除)状态; 4、kubelet,在监控到pod对象转为terminating 状态的同时启动pod关闭过程; 5、endpoint端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除; 6、如果当前pod对象定义了preStop,钩子处理器,则在其标记为terminating后即会以同步的方式启动执行; 7、pod对象中的容器进程收到停止信号; 8、宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号;9、kubelet,请求apiserver.将此pod资源的宽限期设置为o,从而完成删除操作,此时 pod对于用户己不可见;
8.Pod探针
检测顺序为startupProbe>readinessProbe>livenessProbe。
livenessProbe:存活性探测 主要是用指定的方式检测pod中的容器应用是否正常运行,如果检测失败,则认为容器不健康,那么、Kubelet将根据Pod中设置的restartPolicy来判断Pod是否要进行重启操作,如果容器配置中没有配置livenessProbe,Kubelet将认为存活探针探测一直为成功状态。探测检测应用是否存活 许多应用程序经过长时间运行,最终会过渡到无法运行的状态,除了重启,无法恢复。K&S集群发现应用程序已经终止状态,然后重启应用程序pod。有时应用程序可能因为某些原因(后端服务故障等)导致暂时无法对外提供服务,但应用软件没有终止,导致K8S 无法隔离有故障的pod,调用者可能会访问到有故障的pod,导致业务不稳定。K8S提供 livenessProbe来检测容器是否正常运行,并且对相应状况进行相应的补救措施。
readinessProbe:就绪性探测 主要是用于判断容器中应用是否启动完成,当探测成功后才使Pod对外提供网络访问,设置容器Ready状态为true,如果探测失败,则设置容器的Ready状态为false。检测是否已经准备好了 能不能对外提供服务应用 在没有配置readinessProbe的资源对象中,pod中的容器启动完成后,就认为pod中的应用程序可以对外提供服务,该pod就会加入相对应的service,对外提供服务。但有时一些应用程序启动后,需要较长时间的加载才能对外服务,如果这时对外提供服务,执行结果必然无法达到预期效果,影响用户体验。比如拿tomcat的应用程序来说,并不是简单地tomcat启动成功就可以对外提供服务的,还需要等待spring容器初始化,数据库连接上等。
startupProbe:启动探测 startupProbe是在 k8s v1.16 加入了alpha 版。 startupProbe启动探测:探测容器中的应用是否已经启动。如果提供了startupProbe探测,则会禁用所有其他探测方式,直到startupProbe成功为止。如果startupProbe,探测失败,kubelet将杀死容器,容器将服从其重启策略进行重启。如果容器没有提供 startupRobe探测,则默认状态为成功Success 。 可以在pod 启动时定义是否执行这些检测,如果不设置,则检测结果默认均为通过,如果设置 一般startupProbe跟livenessProbe 一起使用 消除漏洞 检测更准确
目前LivenessProbel,ReadinessProbe和startupProbe,三种探针都支持三种探测方法: 1)ExecAction:在容器中执行指定的命令,如果执行成功,退出码为О则探测成功。
2)TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,如果能够建立 TCP连 接,则表明容器健康。
3)HTTPGetAction:通过容器的IP地址、端口号及路径 调用HTTP Get方法,如果响应的状 态码大于等于200且小于400,则认为容器健康。 httpGet探测方式可选的控制字段:· scheme:用于连接host的协议,默认为HTTP。 host:要连接的主机名,默认为Pod IP,可以在 http request head中设置host头部。 port:容器上要访问端口号或名称。 path: http服务器上的访问URI。 httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。
探针探测结果: 1)Success(成功):表示通过检测。
2)Failure(失败):表示未通过检测。
3)Unknown(未知):表示检测没有正常进行。
Pod探针相关的属性: 探针有很多可选配置字段,可以用来精确的控制 Liveness.和 Readiness两种探针的行为:
initialDelaySeconds: Pod启动后首次进行检查的等待时间,单位“秒”。 periodSeconds:检查的间隔时间,默认为10s,单位“秒”。 timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”。 successThreshold:连续探测几次成功,才认为探测成功,默认为1,在 Liveness 探针中必须为1,最小值为位。 failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,在readiness 探针中,Pod会被标记为未就绪,默认为3,最小值为1。
ReadinessProbe和 livenessProbe可以使用相同探测方式,只是对 Pod的处置方式不同: readinessProbe当检测失败后,将 Pod 的 IP ,Port 从对应的EndPoint列表中删除。 livenessProbe当检测失败后,将杀死容器并根据Pod的重启策略来决定作出对应的措施。
livenesprobe 通过执行命令的方式案例测试
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
labels:
app: liveness
spec:
containers:
- name: liveness
image: busybox:latest
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
initialDelaySeconds: 10 ##首次检测等待10秒再检测
periodSeconds: 5 ##每隔5秒检测一次
exec:
command:
- cat
- /tmp/healthy
livenesprobe 通过httpGet的方式案例测试
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
test: liveness
spec:
containers:
- name: liveness
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
livenessProbe:
initialDelaySeconds: 20 #延迟加载时间
periodSeconds: 5 #每隔5秒检测一次
timeoutSeconds: 10 #如果5秒内我没有检测到你 我还可以等你10秒 就相当于每隔15秒检测一次
httpGet:
scheme: HTTP
port: 80
path: /actuator/health #连接检测你页面是否正常
livenesprobe 通过tcpSocket的方式案例测试
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
test: liveness
spec:
containers:
- name: liveness
image: nginx:1.21.5
imagePullPolicy: IfNotPresent
livenessProbe:
initialDelaySeconds: 20 #延迟加载时间
periodSeconds: 5 #每隔5秒检测一次
timeoutSeconds: 10 #如果5秒内我没有检测到你 我还可以等你10秒 就相当于每隔15秒检测一次
tcpSocket:
port: 80 #连接检测你端口是否正常
readinessprobe 通过执行命令exec的方式案例测试
apiVersion: v1
kind: Service
metadata:
name: springboot
labels:
app: springboot
spec:
type: NodePort
ports:
- name: server
port: 8080
targetPort: 8080
nodePort: 31180
- name: management
port: 8081
targetPort: 8081
nodePort: 31181
selector:
app: springboot
---
apiVersion: v1
kind: Pod
metadata:
name: springboot
labels:
app: springboot
spec:
containers:
- name: springboot
image: mydlqclub/springboot-helloworld:0.0.1
imagePullPolicy: IfNotPresent
ports:
- name: server
containerPort: 8080
name: management
containerPort: 8081
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8081
path: /actuator/health
也就是Liveness probes 并不会等到 Readiness probes成功之后才开始探测,官方文档介绍Liveness和readiness应该是某种并发的探测关系。