作者:半身风雪
上一节: K8S 应用pod结点
简介:上一节我们一起学习了,Kubernetes 应用中pod工作节点的详细使用,那么pod 是否有生命周期呢?本节我将和大家共同学习,pod 生命周期。
Pod 生命周期的流程 Pending
-> Running
-> Succeeded
/Failed
。
在pod 中,生命周期主要分为三个状态,开始阶段Pending
,如果有容器启动,进入运行Running
状态,然后进入成功或者失败状态Succeeded
/Failed
。
在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态,并使 Pod 重新运行所采取的动作。
在 Kubernetes 中,Pod 包含规定约束部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。
Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。
和其它独立的应用容器一样,Pod 也是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。
如果一个节点kill了,该节点 的 Pod 也会被计划在给定超时期限结束后删除。
Pod 不能像其它语言一样,去调节自身的状态。如果 Pod 所在节点失效,Pod 就会被删除;同样,Pod 也无法在节点资源耗尽或者节点维护而被驱逐期间继续存活。Kubernetes 使用一种高级抽象来管理这些相对而言可随时丢弃的 Pod 实例,称作 控制器(控制器通过 apiserver监控集群 的公共状态,并将当前状态转变为期望的状态。)。
任何给定的 Pod (由 UID 定义)从不会被“重新调度(rescheduled)”到不同的节点; 相反,这一 Pod 可以被一个新的、几乎完全相同的 Pod 替换掉。 如果需要,新 Pod 的名字可以不变,但是其 UID 会不同。
如果某物声称其生命期与某 Pod 相同,例如存储卷, 这就意味着该对象在此 Pod (UID 亦相同)存在期间也一直存在。 如果 Pod 因为任何原因被删除,甚至某完全相同的替代 Pod 被创建时, 这个相关的对象(例如这里的卷)也会被删除并重建。
下面来看一个Pod 结构图:
一个包含多个容器的 Pod 中包含一个用来拉取文件的程序和一个 Web 服务器, 均使用持久卷作为容器间共享的存储。
Pod 的 status
字段是一个 PodStatus 对象,其中包含一个 phase
字段。
如果某节点死掉或者与集群中其他节点失联,Kubernetes 会将失去的节点上运行的所有 Pod 的 phase 设置为 Failed。
Kubernetes 会跟踪 Pod 中每个容器的状态,可以使用容器生命周期回调 来在容器生命周期中的特定时间点触发事件。
一旦调度器将 Pod 分派给某个节点,kubelet 就通过 容器运行时 开始为 Pod 创建容器。 容器的状态有三种:Waiting(等待)、Running(运行中)和 Terminated(已终止)。
检查 Pod 中容器的状态,可以执行下面的命令。
$ kubectl describe pod
提示
:如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。
Pod 的 spec
中包含一个 restartPolicy
字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
restartPolicy
适用于 Pod 中的所有容器。restartPolicy
仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、…),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作。
Pod 有一个 PodStatus 对象,其中包含一个 PodConditions 数组。Pod 可能通过也可能未通过其中的一些状况测试。
字段名称 | 描述 |
---|---|
type | Pod 状况的名称 |
status | 表明该状况是否适用,可能的取值有 “True”, “False” 或 “Unknown” |
lastProbeTime | 上次探测 Pod 状况时的时间戳 |
lastTransitionTime | Pod 上次从一种状态转换到另一种状态时的时间戳 |
reason | 机器可读的、驼峰编码(UpperCamelCase)的文字,表述上次状况变化的原因 |
message | 可读的消息,给出上次状态转换的详细信 |
应用可以向 PodStatus 中注入额外的反馈或者信号:Pod Readiness(Pod 就绪态)。 要使用这一特性,可以设置 Pod 规约中的 readinessGates
列表,为 kubelet 提供一组额外的状况供其评估 Pod 就绪态时使用。
就绪态门控基于 Pod 的 status.conditions
字段的当前值来做决定。 如果 Kubernetes 无法在 status.conditions
字段中找到某状况,则该状况的 状态值默认为 “False
”。
一起来看一段代码:
status:
phase: Running
conditions:
- type: Initialized # 内置的 Pod 状况
status: 'True'
lastProbeTime: null
lastTransitionTime: '2022-07-01T06:36:04Z'
- type: Ready
status: 'True'
lastProbeTime: null
lastTransitionTime: '2022-07-01T06:36:05Z'
- type: ContainersReady
status: 'True'
lastProbeTime: null
lastTransitionTime: '2022-07-01T06:36:05Z'
- type: PodScheduled
status: 'True'
lastProbeTime: null
lastTransitionTime: '2022-07-01T06:36:04Z'
直接使用命令
$ kubectl patch
并不能修改对象的状态。 如果需要设置 Pod 的 status.conditions
,应用或者 Operators 需要使用 PATCH
操作。 你可以使用 Kubernetes 客户端库 之一来编写代码,针对 Pod 就绪态设置定制的 Pod 状况。
对于使用定制状况的 Pod 而言,只有当下面的陈述都适用时,该 Pod 才会被评估为就绪:
当 Pod 的容器都已就绪,但至少一个定制状况没有取值或者取值为 False, kubelet 将 Pod 的状况设置为 ContainersReady
。
probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。
使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:
每次探测都将获得以下三种结果之一:
针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:
如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet 将根据 Pod 的 restartPolicy
自动执行修复操作。
如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 restartPolicy 为 “Always” 或 “OnFailure”。
如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是规约中的就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。
如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针,检查某个特定于 就绪态的因此不同于存活态探测的端点。
如果你的应用程序对后端服务有严格的依赖性,你可以同时实现存活态和就绪态探针。 当应用程序本身是健康的,存活态探针检测通过后,就绪态探针会额外检查每个所需的后端服务是否可用。 这可以帮助你避免将流量导向只能返回错误信息的 Pod。
如果你的容器需要在启动期间加载大型数据、配置文件或执行迁移,你可以使用 启动探针。 然而,如果你想区分已经失败的应用和仍在处理其启动数据的应用,你可能更倾向于使用就绪探针。
如果你只是想在 Pod 被删除时能够排空请求,则不一定需要使用就绪态探针; 在删除 Pod 时,Pod 会自动将自身置于未就绪状态,无论就绪态探针是否存在。 等待 Pod 中的容器停止期间,Pod 会一直处于未就绪状态。
对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。
如果你的容器启动时间通常超出 initialDelaySeconds + failureThreshold × periodSeconds
总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds 的默认值是 10 秒。你应该将其 failureThreshold 设置得足够高, 以便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。
由于 Pod 所代表的是在集群中节点上运行的进程,当不再需要这些进程时允许其体面地 终止是很重要的。一般不应武断地使用 KILL 信号终止它们,导致这些进程没有机会 完成清理操作。
设计的目标是令你能够请求删除进程,并且知道进程何时被终止,同时也能够确保删除 操作终将完成。当你请求删除某个 Pod 时,集群会记录并跟踪 Pod 的体面终止周期, 而不是直接强制地杀死 Pod。在存在强制关闭设施的前提下, kubelet 会尝试体面地终止 Pod。
通常情况下,容器运行时会发送一个 TERM 信号到每个容器中的主进程。 很多容器运行时都能够注意到容器镜像中 STOPSIGNAL 的值,并发送该信号而不是 TERM。 一旦超出了体面终止限期,容器运行时会向所有剩余进程发送 KILL 信号,之后 Pod 就会被从 API 服务器 上移除。如果 kubelet 或者容器运行时的管理服务在等待进程终止期间被重启, 集群会从头开始重试,赋予 Pod 完整的体面终止限期。
在这里,我们不得不再来复习一下 kubectl 命令行,因为在下面的实例中,我们会使用到。
$ kubectl help
kubectl controls the Kubernetes cluster manager.
Find more information at:
https://kubernetes.io/docs/reference/kubectl/overview/
Basic Commands (Beginner):
create Create a resource from a file or from stdin
expose Take a replication controller, service, deployment or pod and
expose it as a new Kubernetes service
run 在集群中运行一个指定的镜像
set 为 objects 设置一个指定的特征
Basic Commands (Intermediate):
explain Get documentation for a resource
get 显示一个或更多 resources
edit 在服务器上编辑一个资源
delete Delete resources by file names, stdin, resources and names, or
by resources and label selector
Deploy Commands:
rollout Manage the rollout of a resource
scale Set a new size for a deployment, replica set, or replication
controller
autoscale Auto-scale a deployment, replica set, stateful set, or
replication controller
Cluster Management Commands:
certificate 修改 certificate 资源.
cluster-info Display cluster information
top Display resource (CPU/memory) usage
cordon 标记 node 为 unschedulable
uncordon 标记 node 为 schedulable
drain Drain node in preparation for maintenance
taint 更新一个或者多个 node 上的 taints
Troubleshooting and Debugging Commands:
describe 显示一个指定 resource 或者 group 的 resources 详情
logs 输出容器在 pod 中的日志
attach Attach 到一个运行中的 container
exec 在一个 container 中执行一个命令
port-forward Forward one or more local ports to a pod
proxy 运行一个 proxy 到 Kubernetes API server
cp Copy files and directories to and from containers
auth Inspect authorization
debug Create debugging sessions for troubleshooting workloads and
nodes
Advanced Commands:
diff Diff the live version against a would-be applied version
apply Apply a configuration to a resource by file name or stdin
patch Update fields of a resource
replace Replace a resource by file name or stdin
wait Experimental: Wait for a specific condition on one or many
resources
kustomize Build a kustomization target from a directory or URL.
Settings Commands:
label 更新在这个资源上的 labels
annotate 更新一个资源的注解
completion Output shell completion code for the specified shell (bash,
zsh or fish)
Other Commands:
alpha Commands for features in alpha
api-resources Print the supported API resources on the server
api-versions Print the supported API versions on the server, in the form of
"group/version"
config 修改 kubeconfig 文件
plugin Provides utilities for interacting with plugins
version 输出 client 和 server 的版本信息
Usage:
kubectl [flags] [options]
Use "kubectl > --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all
commands).
再来看一个例子:
默认情况下,所有的删除操作都会附有 30 秒钟的宽限期限。 kubectl delete
命令支持 --grace-period=
选项,允许你重载默认值, 设定自己希望的期限值。
将宽限期限强制设置为 0 意味着立即从 API 服务器删除 Pod。 如果 Pod 仍然运行于某节点上,强制删除操作会触发 kubelet 立即执行清理操作。
你必须在设置
--grace-period=0
的同时额外设置--force
参数才能发起强制删除请求。
执行强制删除操作时,API 服务器不再等待来自 kubelet 的、关于 Pod 已经在原来运行的节点上终止执行的确认消息。 API 服务器直接删除 Pod 对象,这样新的与之同名的 Pod 即可以被创建。 在节点侧,被设置为立即终止的 Pod 仍然会在被强行杀死之前获得一点点的宽限时间。
对于已失败的 Pod 而言,对应的 API 对象仍然会保留在集群的 API 服务器上,直到 用户或者控制器进程显式地 将其删除。
控制面组件会在 Pod 个数超出所配置的阈值 (根据 kube-controller-manager
的 terminated-pod-gc-threshold
设置)时 删除已终止的 Pod(阶段值为 Succeeded 或 Failed)。 这一行为会避免随着时间演进不断创建和终止 Pod 而引起的资源泄露问题。
本次的文章,全文差不多一万字了,文章参考 Kubernetes 生命周期部分。