文章目录
四、Pod 状态与生命周期管理
Pod是kubernetes中最重要的基本概念,在kubernetes中最小的管理元素不是一个个独立的容器,而是pod,pod是最小的单元。
其中组件kube-controller-manage就是用来控制Pod的状态和生命周期
1.Pod概念
Pod 中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络 IP,管理容器的运行策略。
常见的用法是一个pod中运行一个容器。还有就是一个pod中同时运行多个容器,他们之间共享资源(网络和存储)。
每个pod都是一个应用的实例,我们可以水平扩展运行多些pod。
- metadata: 关于 Pod 的元数据信息,包括名称,命名空间,标签和注解等
- spec: 描述 Pod 期望的运行状态,比如要运行的容器,运行参数,需要挂载的卷等
- status: 描述 Pod 当前的运行状态,如运行容器,容器的状态,Pod的IP等
可以通过 kubectl explain pods
和 kubectl explain pod.spec
查看对象包含的详细信息,添加参数 --recursive
递归列出简化的信息。
网络
每个pod都会给分配一个集群唯一的ip地址。pod中所有容器共享网络空间,包括ip地址和端口。pod内部的容器可以使用loaclhost互相通信。pod中容器于外界通信时,必须分配网络资源(例如使用宿主机的端口映射)
存储
可以为一个pod指定多个共享的Volume。pod中的所以容器都可以访问共享的Volume。Volume可以持久化存储资源,防止容器重启后数据丢失。
用法
在实际使用中很好创建单个pod。因为pod的生命周期是短暂的,用后即焚。pod自身是不会自愈的,如果pod运行的node故障,或者调度器本身故障,这个pod就会被删除。如果pod所在node缺少资源或者处于维护状态,pod也会被驱逐。kubernetes使用controller(控制器)来管理pod,这是我们通常使用的。
pod的终止
优雅的退出很重要,这个想必众所周知,当发送删除pod的请求时,在被枪毙之前会有一个30s的宽限期,会发送一个TERM请求到每个容器的主进程,在这之前Pod不允许被强制的杀死,TERM信号会发送给容器主要的进程。一旦优雅退出的期限过了,KILL信号会送到这些进程,pod会从API服务器其中被删除。如果在等待进程结束的时候,Kubelet或者容器管理器重启了,结束的过程会带着完整的优雅退出时间段进行重试。
流程如下:
-
发送命令删除pod,默认宽限期30s
-
在Pod超过该宽限期后API server就会更新Pod的状态为“dead”
-
在客户端命令行上显示的Pod状态为“terminating”(退出中)
-
(与第3同时)当kubelet发现pod被标记为“terminating”状态时,开始停止pod进程
1)、如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
2)、向Pod中的进程发送TERM信号;
-
(与第3同时)该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量
-
过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。
-
Kubelet会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。
kubectl delete
命令支持 —grace-period=<seconds>
选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force
和 --grace-period=0
来强制删除pod。 在 yaml 文件中可以通过 {{ .spec.spec.terminationGracePeriodSeconds }}
来修改此值。
2.Init容器
这是一种专用的容器,Init 容器会按顺序在网络和数据卷初始化之后启动。在应用程序启动之前运行,可以有一个或多个,init容器总是运行到成功完成为止,每个init容器都必须在下一个init容器启动之前成功完成。
如果pod的init容器失败,restartPolicy=Always时,k8s会不断重启该pod,直到init容器成功为止;如果restartPolicy为Never,则不会重新启动。
init模板
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
用途
- 等待一个service创建完成
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
- 将pod注册到远程服务器,通过在命令中调用API
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
-
在启动容器之前等待一段时间,使用类似sleep 60
-
克隆Git仓库到数据卷
-
将配置值放到配置文件中,例如,在配置文件中设置POD_IP
3.Pause容器
Pause容器又叫Infra容器,全称infrastucture container基础容器,俗称“根容器”
在kubelet配置中有个默认参数来指定根容器的镜像,也可自定义。其镜像非常小,大约700KB左右,每个pod都对应一个根容器且永远处于Pause(暂停)状态。他的生命周期就是pod的生命周期,在pod中担任Linux命名空间共享的基础,启用pid命名空间,开启init进程。
KUBELET_POD_INFRA_CONTAINER=--pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.0
4.Pod的生命周期
Pod phase(阶段)
以下是Pod 在其生命周期中的简单宏观概述,不应该再假定 Pod 有其他的 phase
值。
描 述 | 状态值 |
---|---|
Pending | Api-server已经常见该pod,但有一个或多个容器尚未创建,包括调度pod的时间和下载镜像的时间 |
Running | Pod内的容器都已创建,且至少有一个 容器处于运行常态、启动状态和重启状态 |
Succeeded | Pod内所有容器均成功执行后退出,且不会再重启 |
Failed | Pod内所有容器均退出,但至少有一个容器退出为失败状态 |
Unknown | 无法获取该Pod的状态,可能网络不畅 |
Pod生命周期示意图
Pod 状态
Pod 有一个 PodStatus 对象,其中包含一个 PodCondition 数组。 PodCondition 数组的每个元素都有一个 type
字段和一个 status
字段。type
字段是字符串,可能的值有 PodScheduled、Ready、Initialized、Unschedulable和ContainersReady。status
字段是一个字符串,可能的值有 True、False 和 Unknown。
5.Pod健康-容器探针(Probe)
概念
探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:
- ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
- TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
- HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
- 成功:容器通过了诊断。
- 失败:容器未通过诊断。
- 未知:诊断失败,因此不会采取任何行动。
Kubelet 可以选择是否执行在容器上运行的两种探针执行和做出反应:
livenessProbe
:指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其 重启策略 的影响。如果容器不提供存活探针,则默认状态为 Success
。
readinessProbe
:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure
。如果容器不提供就绪探针,则默认状态为 Success
。
下面以livenessProbe为例,如果想使用readinessProbe,将livenessProbe换成readinessProbe即可
对每一个Container都可以设置不同的restartpolicy,有三种值可以设置:
- Always: 只要container退出就重新启动
- OnFailure: 当container非正常退出后重新启动
- Never: 从不进行重新启动
EXEC探针
exec类型的探针通过在目标容器中执行由用户自定义的命令来判断容器的监控状态,若命令状态返回值为0则表示“成功”通过检测,其他值则均为“失败”状态。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness-exec
name: liveness-exec
spec:
restartPolicy: OnFailure
containers:
- name: liveness-exec
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command: ["test","-e","/tmp/healthy"]
initialDelaySeconds: 5 #探测延时时长,第一次探测前等待5秒,默认为0
periodSeconds: 5 #每5秒执行一次liveness探测,默认值10秒,最小1秒
timeoutSeconds: 2 #超长时长,默认为1s,最小值也为1s
failureThreshold: 3 #处于成功状态时,探测操作至少连续多少次的失败才被视为检测不通过,默认为3,最小为1
HTTP探针
基于HTTP的探测(HTTPGetAction)向目标容器发起一个HTTP请求,根据其相应码进行结果判定,响应码如2xx或3xx时表示检测通过。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: googlecontainer/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
TCPSocket探针
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
spec:
containers:
- name: nginx
image: nginx
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 80
initialDelaySeconds:容器启动后首次进行健康检查的等待时间
timeoutSeconds: 探测超时时间。默认1秒,最小1秒
periodSeconds: 每个多少秒执行一次探针
successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。