Pod 调度流程、状态、与容器探针

 Pod调度流程

 

 

 

master 节点:kubectl -> kube-api -> kubelet -> CRI 容器环境初始化

第一步:
客户端提交创建 Pod 的请求,可以通过调用 API Server 的 Rest API 接口,也可以通过 kubectl 命令行
工具。如 kubectl apply -f filename.yaml(资源清单文件)

第二步:
apiserver 接收到 pod 创建请求后,会将 yaml 中的属性信息(metadata)写入 etcd。
第三步:
apiserver 触发 watch 机制准备创建 pod,信息转发给调度器 scheduler,调度器使用调度算法选择
node,调度器将 node 信息给 apiserver,apiserver 将绑定的 node 信息写入 etcd

调度器用一组规则过滤掉不符合要求的主机。比如 Pod 指定了所需要的资源量,那么可用资源比 Pod 需要的资源量少的主机会被过滤掉。

scheduler 查看 k8s api ,类似于通知机制。
首先判断:pod.spec.Node == null?
若为 null,表示这个 Pod 请求是新来的,需要创建;因此先进行调度计算,找到最“闲”的 node。
然后将信息在 etcd 数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)

ps:同样上述操作的各种信息也要写到 etcd 数据库中中

第四步:
apiserver 又通过 watch 机制,调用 kubelet,指定 pod 信息,调用 Docker API 创建并启动 pod 内的容器。

第五步:
创建完成之后反馈给 kubelet, kubelet 又将 pod 的状态信息给

 

 

 

 

Pod 常见的状态和重启策略

常见的 pod 状态

Pod 的 status 定义在 PodStatus 对象中,其中有一个 phase 字段。它简单描述了 Pod 在其生命周
期的阶段。熟悉 Pod 的各种状态对我们理解如何设置 Pod 的调度策略、重启策略是很有必要的。
下面是 phase 可能的值,也就是 pod 常见的状态:
挂起(Pending):我们在请求创建 pod 时,条件不满足,调度没有完成,没有任何一个节点能满
足调度条件,已经创建了 pod 但是没有适合它运行的节点叫做挂起,调度没有完成,处于 pending
的状态会持续一段时间:包括调度 Pod 的时间和通过网络下载镜像的时间。
运行中(Running):Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容
器正在运行,或者正处于启动或重启状态。
成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。

失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是
说,容器以非 0 状态退出或者被系统终止。
未知(Unknown):未知状态,所谓 pod 是什么状态是 apiserver 和运行在 pod 节点的 kubelet 进
行通信获取状态信息的,如果节点之上的 kubelet 本身出故障,那么 apiserver 就连不上
kubelet,得不到信息了,就会看 Unknown

扩展:还有其他状态,如下:
Evicted 状态:出现这种情况,多见于系统内存或硬盘资源不足,可 df-h 查看 docker 存储所在目
录的资源使用情况,如果百分比大于 85%,就要及时清理下资源,尤其是一些大文件、docker 镜
像。
CrashLoopBackOff:容器曾经启动了,但可能又异常退出了
Error 状态:Pod 启动过程中发生了错误

pod 重启策略 Pod 的重启策略(RestartPolicy)应用于 Pod 内的所有容器,并且仅在 Pod 所处的 Node 上由
kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet 将根据
RestartPolicy 的设置来进行相应的操作。

Pod 的重启策略包括

Always、OnFailure 和 Never,默认值为 Always。 Always:当容器失败时,由 kubelet 自动重启该容器。
OnFailure:当容器终止运行且退出码不为 0 时,由 kubelet 自动重启该容

镜像拉取策略

lfNotPresent #node节点没有此镜像就去指定的镜像仓库拉取,node有就使用node本地镜像。

Always #每次重建pod都会重新拉取镜像

Never #从不到镜像中心拉取镜像,只使用本地镜像

Pod生命周期

 

 

 

 

init容器

init容器的特点:
1.一个pod可以有多个业务容器还能在有多个init容器,但是每个init容器和业务容器的运行环境都是隔离的。
2.init容器会比业务容器先启动。

3.init容器运行成功之后才会继续运行业务容器

4.如果一个pod有多个init容器,则需要从上到下逐个运行并且全部成功,最后才会运行业务容器。
5.init容器不支持探针检测(因为初始化完成后就退出再也不运行了)

6.Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成

7、每个 Init 容器必须运行成功,下一个才能够运行

8、如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,然 而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动

[root@xksmaster1 Others]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat
              /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do
              echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat
             /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do
             echo waiting for mydb; sleep 2; done"]
[root@xksmaster1 Others]# kubectl apply -f init.yaml
pod/myapp-pod created
#此时 service还有没有创建 所以pod一直init状态 等待service创建好 容器变为running状态 [root@xksmaster1 Others]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp
-pod 0/1 Init:0/2 0 9s nfs-provisioner-68d8f76665-cqftz 1/1 Running 0 4h19m pod-secret-volume 1/1 Running 0 26h web-0 1/1 Running 0 4h14m web-1 1/1 Running 0 4h11m
vim service.yaml
[root@xksmaster1 Others]# cat service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
[root@xksmaster1 Others]# kubectl apply -f service.yaml
service/myservice created
service/mydb created
[root@xksmaster1 Others]# kubectl get pods
NAME                               READY   STATUS     RESTARTS   AGE
myapp-pod                          0/1     Init:0/2   0          98s
nfs-provisioner-68d8f76665-cqftz   1/1     Running    0          4h21m
pod-secret-volume                  1/1     Running    0          26h
web-0                              1/1     Running    0          4h15m
web-1                              1/1     Running    0          4h12m
[root@xksmaster1 Others]# kubectl get pods
NAME                               READY   STATUS     RESTARTS   AGE
myapp-pod                          0/1     Init:1/2   0          99s
nfs-provisioner-68d8f76665-cqftz   1/1     Running    0          4h21m
pod-secret-volume                  1/1     Running    0          26h
web-0                              1/1     Running    0          4h15m
web-1                              1/1     Running    0          4h12m
[root@xksmaster1 Others]# kubectl get pods
NAME                               READY   STATUS            RESTARTS   AGE
myapp-pod                          0/1     PodInitializing   0          100s
nfs-provisioner-68d8f76665-cqftz   1/1     Running           0          4h21m
pod-secret-volume                  1/1     Running           0          26h
web-0                              1/1     Running           0          4h15m
web-1                              1/1     Running           0          4h12m
[root@xksmaster1 Others]# kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
myapp-pod                          1/1     Running   0          102s
nfs-provisioner-68d8f76665-cqftz   1/1     Running   0          4h21m
pod-secret-volume                  1/1     Running   0          26h
web-0                              1/1     Running   0          4h15m
web-1                              1/1     Running   0          4h12m

污点和容忍度

 

pause容器

 

探针

两种探针区别: ReadinessProbe 和 livenessProbe 可以使用相同探测方式,只是对 Pod 的处置方式不同:

readinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。

livenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。

LivenessProbe 探针使用示例 (1)、通过 exec 方式做健康探测

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: busybox
    args: #创建测试探针探测的文件
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      initialDelaySeconds: 10 #延迟检测时间
      periodSeconds: 5 #检测时间间隔
      exec:
        command:
        - cat
        - /tmp/healthy

容器启动设置执行的命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
容器在初始化后,首先创建一个 /tmp/healthy 文件,然后执行睡眠命令,睡眠 30 秒,到
时间后执行删除 /tmp/healthy 文件命令。而设置的存活探针检检测方式为执行 shell 命令,用
cat 命令输出 healthy 文件的内容,如果能成功执行这条命令,存活探针就认为探测成功,否则
探测失败。在前 30 秒内,由于文件存在,所以存活探针探测时执行 cat /tmp/healthy 命令成
功执行。30 秒后 healthy 文件被删除,所以执行命令失败,Kubernetes 会根据 Pod 设置的重
启策略来判断,是否重启 Pod。

(2)、通过 HTTP 方式做健康探测 示例文件 liveness-http.yaml

[root@xksmaster1 Others]# cat liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
  - name: liveness
    image: mydlqclub/springboot-helloworld:0.0.1
    livenessProbe:
      initialDelaySeconds: 20 #延迟加载时间
      periodSeconds: 5 #重试时间间隔
      timeoutSeconds: 10 #超时时间设置
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health

上面 Pod 中启动的容器是一个 SpringBoot 应用,其中引用了 Actuator 组件,提供了
/actuator/health 健康检查地址,存活探针可以使用 HTTPGet 方式向服务发起请求,请求 8081
端口的 /actuator/health 路径来进行存活判断:

任何大于或等于 200 且小于 400 的代码表示探测成功。
任何其他代码表示失败。

如果探测失败,则会杀死 Pod 进行重启操作。
httpGet 探测方式有如下可选的控制字段:
  scheme: 用于连接 host 的协议,默认为 HTTP。
  host:要连接的主机名,默认为 Pod IP,可以在 http request head 中设置 host 头部。
  port:容器上要访问端口号或名称。
  path:http 服务器上的访问 URI。
  httpHeaders:自定义 HTTP 请求 headers,HTTP 允许重复 headers。

 

(3)、通过 TCP 方式做健康探测

[root@xksmaster1 Others]# cat liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: nginx
    livenessProbe:
      initialDelaySeconds: 15
      periodSeconds: 20
      tcpSocket:
        port: 80

TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间
后,kubelet 将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将
杀死 Pod 重启容器。

ReadinessProbe 探针使用示例

 

[root@xksmaster1 Others]# cat readiness-exec.yaml
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

Pod 的 ReadinessProbe 探针使用方式和 LivenessProbe 探针探测方法一样,也是支持三种,只
是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。这里用一个 Springboot
项目,设置 ReadinessProbe 探测 SpringBoot 项目的 8081 端口下的 /actuator/health 接
口,如果探测成功则代表内部程序以及启动,就开放对外提供接口访问,否则内部应用没有成功
启动,暂不对外提供访问,直到就绪探针探测成功。

ReadinessProbe + LivenessProbe 配合使用示例

readinessProbe: 
  initialDelaySeconds: 20 
  periodSeconds: 5 
  timeoutSeconds: 10 
  httpGet: 
    scheme: HTTP 
    port: 8081 
    path: /actuator/health 
livenessProbe: 
  initialDelaySeconds: 30 
  periodSeconds: 10 
  timeoutSeconds: 5 
  httpGet: 
    scheme: HTTP 
    port: 8081 
    path: /actuator/health

 

Pod的终止流程

1创建pod完成调度流程
容器启动并执行postStart
实况调查
进入running状态
readinessProbe
服务关联pod
接受客尸端请求
2.删除pod
Pod被设置为”Terminating”状态、从service的Endpoints列表中删除并不再接受客户端请求
执行PreStop
Kubernetes向pod中的容器发送SIGTERM信号(正常终止信号)终止pod里面的主进程,这个信号让容器知道自己很快将会被关闭
terminationGracePeriodSeconds:60 #可选终止等待期,如果有设置删除宽限时间,则等待宽限时间到期,否则最多等待30s.
Kubernees等待指定的时间称为优雅终止宽限期,默认情况下是30秒,值得注意的是等待期与DreStop Hook和SIGTERM信号并行执行,
Kubernetes可能不会等待preStopHook完成(最长30秒之后主进程还没有结束就就强制终止pod)。
SIGKILL信号被发送到Pod,并删除Pod

 

posted @ 2023-12-18 23:15  しみずよしだ  阅读(200)  评论(0)    收藏  举报