k8s--pod生命周期,pod调度
一:pod生命周期
1、基础概念

-
pod生命周期
1、pod创建过程
2、运行初始化过程,这是容器的一种,在运行主容器之前运行,否则,一直重启,知道初始化成功,运行主容器
3、运行主容器过程
容器启动后钩子,容器终止前钩子,启动之后先执行的命令,和结束前,执行的命令容器的存活性探测,就绪性探测
4、pod终止过程
-
pod的状态
1、挂起(pending),已经创建了pod资源对象,但是还没有被调度,或者是镜像仍然处于下载镜像过程
2、运行中(running),pod已经被调度到某一个节点上面了,并且里面所有的容器都被kubelet创建完了
3、成功(completed),pod中的所有容器都已经被终止了,并且不会被重启,就是运行一个容器,30秒后,打印,然后退出
4、失败(failed),所有容器都已经被终止了,但是至少有一个容器终止失败,即容器退出时返回非0的状态
5、未知(unknown),apiserver无法正常获取pod对象的状态信息,通常是网络通信失败的问题
-
pod创建过程
1、用户通过kubectl创建的pod的信息给apiserver
2、apiserver开始生成pod对象信息,并将信息存储etcd中,然后确认信息到客户端
3、apisever开始反映etcd中pod对象的变化,其他组件使用watch机制来跟踪检查apiserver上的变动
4、scheduler发现有新的Pod对象创建,开始为pod分配主机并将信息更新至apiserver
5、node节点上的kubelet发现有pod调度过来,创建容器,将结果告诉apiserver
6、apiserver将信息存放到etcd中

-
pod终止过程
1、用户向apiserver发送删除pod命令
2、apiserver中pod信息随着时间的推移更新,在(宽限期)默认30s内了,pod被视为dead
3、将pod标记为terminating状态
4、kubelet监控到pod的状态为terminating同时启动关闭pod过程
5、端点控制器监控到pod对象关闭行为时,将其从所有匹配到端点的service资源的端点列表移除
6、如果pod对象定义了prestop钩子处理器,则标记为terminating后,会以同步的方式执行,
7、pod对象中容器进程收到了停止信号
8、宽限期结束后,若Pod中还有存在运行的进程,那么pod会收到立即终止的信号
1、初始化容器
- 初始化容器
- 初始化容器执行完成后,才能运行主容器,如果初始化失败了,那么就必须要不断的重启才行
#任务,就是mysql和redis2个服务器,先去连mysql,不成功,则一直处于连接,否则就去连接redis,2个条件都满足了,nginx主容器就会启动
myql 192.168.109.201
redis 192.168.109.202
apiVersion: v1
kind: Pod
metadata:
name: nginx-init
namespace: dev
kind: Pod
metadata:
name: nginx-init
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
initContainers: #初始化容器
- name: test-mysql
image: busybox:1.30
command: ["sh","-c","util ping 192.168.109.201 -c 1;do echo waiting for mysql;sleep 2;done;"]
- name: test-redis
image: busybox:1.30
command: ["sh","-c","util ping 192.168.109.202 -c 1;do echo waiting for redis;sleep 2 ;done;"]
#由于没有初始化成功,所以的话,状态为初始化容器失败
[root@master pod]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-init 0/1 Init:CrashLoopBackOff 5 (2m51s ago) 6m5s
#网卡的设置
ifconfig ens33:1 192.168.109.201 netmask 255.255.255.0 up
ifconfig ens33:2 192.168.109.202 netmask 255.255.255.0 up
#发现容器启动了
[root@master pod]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-init 1/1 Running 0 20m
#查看容器详细信息
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 19m default-scheduler Successfully assigned dev/nginx-init to node1
Normal Pulled 19m kubelet Container image "busybox:1.30" already present on machine
Normal Created 19m kubelet Created container test-mysql
Normal Started 19m kubelet Started container test-mysql
Normal Pulled 19m kubelet Container image "busybox:1.30" already present on machine
Normal Created 19m kubelet Created container test-redis
Normal Started 19m kubelet Started container test-redis
Normal Pulled 19m kubelet Container image "nginx:1.17.1" already present on machine
Normal Created 19m kubelet Created container nginx
Normal Started 19m kubelet Started container nginx
2、主容器钩子函数
-
post start
1、容器启动后钩子,容器启动之后会立即执行,成功了,则启动,否则一直处于重启
-
post stop
1、容器终止前钩子,容器在删除之前执行,就terming状态,会阻塞容器删除,这个执行完才会删除容器
#格式有三种,start和stop一样的三种
##exec格式
lifecycle:
podstart:
exec:
command: ##command第一种写法,列表的形式
- cat
- /tmp/healthy
command: ["cat"] #第二种写法,当同事指定了这2个参数,command会覆盖容器镜像默认的ENTRYPOINT命令,args传入参数
args: ["/tmp/healthy"]
command: ["cat","/tmp/healthy"] #第三种写法
#tcpsocket格式 在当前容器内尝试访问指定socket,在容器内访问8080端口
lifecycle:
podstart:
tcpsocket:
port: 8080 #会尝试连接8080端口
#httpget 在当前的容器向url发起http请求
lifecycle:
podstart:
httpGet
path: url地址
host: 80
schme: http支持的协议
#nginx容器在启动时,传入一个网页内容,在结束后停止优雅的停止nginx容器
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","echo poststart > /usr/share/nginx/html/index.html"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
#访问网页内容
[root@master pod]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 13s 10.244.1.54 node1 <none> <none>
[root@master pod]# curl 10.244.1.54:80
poststart
#删除这个Pod
[root@master pod]# kubectl delete pod -n dev nginx
pod "nginx" deleted
3、容器探测
-
liveness probes
1、用于检测示例是否处于正常的状态,如果不是,k8s会重启容器,用于决定是否重启容器
-
readiness probes
1、用于检测实例是否可以接受请求,如果不能,k8s不会转发流量
2、nginx需要读取很多的web文件,在读取的过程中,service认为nginx已经成功了,如果有个请求转发的话,那么就无法提供这个服务了,所以不会将请求转发到这里来
-
作用
1、找出这些出来问题的pod
2、服务是否已经准备成功了
#三种格式
livenessProbe
exec:
command: ["cat","/tmp/healthy"]
livenessProbe:
tcpSocket:
port: 8080
livenessProbe:
httpGet:
path: /url地址
port: 80
scheme: http
1、操作
#nginx容器如果有/hello.txt这个文件话,pod一直进行重启
[root@master pod]# cat liveness.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-111
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.2
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
exec:
command: ["/bin/cat","/hello.txt"]
[root@master pod]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-111 1/1 Running 2 (28s ago) 88s
#查看详细信息
Normal Scheduled 33s default-scheduler Successfully assigned dev/nginx-111 to node2
Normal Pulled 3s (x2 over 33s) kubelet Container image "nginx:1.17.2" already present on machine
Normal Created 3s (x2 over 33s) kubelet Created container nginx
Normal Started 3s (x2 over 33s) kubelet Started container nginx
Warning Unhealthy 3s (x3 over 23s) kubelet Liveness probe failed: /bin/cat: /hello.txt: No such file or directory
Normal Killing 3s kubelet Container nginx failed liveness probe, will be restarted
2、补充
initialDelaySeconds <integer> 容器启动后等待多少秒执行第一次探测
timeoutSeconds <integer> 探测超时时间,默认是1秒,最小1秒
periodSeconds <integer> 执行探测的频率,默认是10秒,最小是1秒
failureThreshold <integer> 连续探测失败多少次后才被认为失败,默认是3,最小值是1
successThreshold <integer> 连续探测成功多少次后才被认定为成功,默认是1
4、重启策略
-
重启
1、容器探测出现了问题,k8s对容器所在的Pod进行重启,这个有pod的重启策略决定的2、always,容器失效时,自动重启容器,默认值
3、onfailure,容器终止运行退出码不为0时重启,异常的终止
4、never,不论状态为什么,都不重启容器
apiVersion: v1
kind: Pod
metadata:
name: nginx-111
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.2
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
exec:
command: ["/bin/cat","/hello.txt"]
restartPolicy: Never
#设置了重启策略后,不会对其进行反复的重启了
[root@master pod]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-111 0/1 Completed 0 84s
二、pod调度
1、概念
- 调度
1、pod在哪个节点上面运行,是有scheduler计算出来的,这个过程是不受人工控制的,但是在实际中,需要控制pod在哪个节点上面运行,就需要调度的规则了
2、自动调度,定向调度,亲和性调度,容忍调度
2、定向调度
- 就是以nodename,nodeselector,依次进行调度,强制性的,即使不存在node节点,也会进行调度,失败而已
1. nodename
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: dev
spec:
nodeName: node1
containers:
- name: nginx
image: nginx:1.17.2
2、nodeselector
#查看标签
[root@master pod]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready control-plane 6d13h v1.28.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node1 Ready <none> 6d13h v1.28.2 app=nginx-1,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
node2 Ready <none> 6d13h v1.28.2 app=nginx-2,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux
#调度到node2上面去
[root@master pod]# kubectl create -f nodeselector.yaml
pod/nginx-2 created
[root@master pod]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-2 1/1 Running 0 5s 10.244.2.53 node2 <none> <none>
nginx-pod 1/1 Running 0 5m32s 10.244.1.57 node1 <none> <none>
3、亲和性调度
1、node亲和性
-
主要就是关于node上面的标签来决定的,
-
有软和硬限制的操作
格式
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬亲和性
nodeSelectorTerms:
- matchExpressions:
- key:
operator:
values:
软亲和性
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight:
preference:
matchExpressions: #按照节点的标签列出的节点
- key:
operator:
values:
操作
#将pod调度到node1上面去
[root@master pod]# cat node-aff.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: dev
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app
operator: In
values: ["nginx-1"]
containers:
- name: nginx
image: nginx:1.17.2
[root@master pod]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pod 1/1 Running 0 44s 10.244.1.58 node1 <none> <none>
2、pod亲和性调度
- 主要就是pod上面的标签来决定的
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: #调度作用域,靠近节点,
labelSelector: #标签选择器
matchExpressions: #按照标签列出
- key:
operator:
values:
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight:
podAffinityTerm:
topologyKey:
labelSelector:
matchExpressions:
- key:
operator:
values:
#创建一个pod出来,node2上面,根据node2上面pod中的标签进行调度
[root@master pod]# cat podaff.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-nginx1
namespace: dev
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
values: ["nginx-111"]
operator: In
topologyKey: kubernetes.io/hostname
containers:
- name: nginx
image: nginx:1.17.2
[root@master pod]# kubectl get pod -n dev --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-2 1/1 Running 0 7m10s 10.244.2.56 node2 <none> <none> app=nginx-111
nginx-pod 1/1 Running 1 (29m ago) 139m 10.244.1.60 node1 <none> <none> <none>
pod-nginx1 1/1 Running 0 63s 10.244.2.57 node2 <none> <none> <none>
- 反亲和性调度
1、也是按照pod上面的标签来进行调度的,如果这个pod上面有标签的话,就不在pod上面调度即可,在其他的地方进行调度
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey:
labelSelector:
matchExpressions:
- key:
operator:
values:
[root@master podaff]# cat podanti.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx2
namespace: dev
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchExpressions:
- key: app
values: ["nginx-2"]
operator: In
containers:
- name: nginx2
image: nginx:1.17.2
[root@master podaff]# kubectl create -f podanti.yaml
pod/nginx2 created
[root@master podaff]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
centos 1/1 Running 0 29h 10.244.2.25 node2 <none> <none>
nginx2 1/1 Running 0 6s 10.244.1.16 node1 <none> <none>
4、污点和容忍
1、污点
-
污点解释
1、就是节点上面有一个污点,pod的调度不能调度到这个上面
2、污点有三个等级,NoExecute(节点上已有的pod全部销毁,不能调度到这个上面),PreferNoSchedule(万不得已才能在这个上面调度),NoSchedule(已有的可以在上面,但是不能进行调度)
-
污点操作
#打上一个污点
[root@master /]# kubectl describe node node1 | grep -i taint
Taints: <none>
[root@master /]# kubectl taint node node1 app=qq:NoExecute
node/node1 tainted
[root@master /]# kubectl describe node node1 | grep -i taint
Taints: app=qq:NoExecute
#发现node1上面的pod没有了
[root@master /]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
centos 1/1 Running 0 29h 10.244.2.25 node2 <none> <none>
#取消一个污点
##取消所有的污点
[root@master /]# kubectl taint node node1 app-
node/node1 untainted
[root@master /]# kubectl describe node node1 | grep -i taint
Taints: <none>
##取消单个污点
[root@master /]# kubectl taint node node1 app:NoExecute-
2、容忍
-
容忍
1、主要就是在pod上面,容忍节点的污点,可以在有污点的节点上面进行调度pod
-
格式
spec:
tolerations: #添加容忍
- key: #容忍的key
operator:
value: #容忍的值
effect: #添加的容忍的规划,这里必须是标记的污点
[root@master /]# kubectl taint node node1 app=nginx1:NoExecute
node/node1 tainted
[root@master podaff]# cat pod-tolerat.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1
namespace: dev
spec:
affinity: #亲和性
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app
values: ["node1"]
operator: In
tolerations: #容忍的key
- key: app
value: nginx1
operator: Equal
effect: NoExecute
containers:
- name: nginx1
image: nginx:1.17.2
三:总结
在同一个名称空间下面,如果2个pod中的容器都监听的是80端口的话,不会发生冲突,因为这个有网络隔离,不同的pod之间,共享ip地址和网络空间
1、

浙公网安备 33010602011771号