pod生命周期/pod初始化容器

This commit is contained in:
huanqing.shao
2019-09-07 20:36:48 +08:00
parent f6a953ab07
commit bf6724bfb0
12 changed files with 373 additions and 92 deletions

View File

@ -17,6 +17,8 @@ description: Kubernetes 学习路径推荐
* [通过互联网访问您的应用](/learning/k8s-intermediate/ingress.html)
* 工作负载
* [Pod 容器组](/learning/k8s-intermediate/workload/pod.html)
* [Pod 生命周期](/learning/k8s-intermediate/workload/pod-lifecycle.html)
* [Pod 初始化容器](/learning/k8s-intermediate/workload/init-container.html)
* [使用 ConfigMap 配置您的应用程序](/learning/k8s-intermediate/config-map.html)
* [使用私有 registry 中的 docker 镜像](/learning/k8s-intermediate/private-registry.html)
* 持久化数据
@ -24,35 +26,14 @@ description: Kubernetes 学习路径推荐
* [存储卷 PV 和存储卷声明 PVC](/learning/k8s-intermediate/persistent/pv.html)
* [存储类 StorageClass](/learning/k8s-intermediate/persistent/storage-class.html)
## **课程推荐**
## **Kubernetes 实战**
作者认为,基础比较好的同学,在学完 **Kubernetes 入门** 部分的内容后,就可以根据 Kubernetes 的官网文档和 docker 的官网文档,结合实际项目将 Kubernetes 应用得很好。同时,作者也在逐步完善 **Kubernetes 进阶** 的学习内容,更好的帮助大家在项目中落地 Kubernetes。但是鉴于时间和进度的原因短期内仍然不能很好的通过 www.kuboard.cn 满足 Kubernetes 爱好者迫切的学习意愿。
在 Kubernetes 上部署 Spring Cloud 微服务:
在这种情况下,作者向大家推荐一份视频课程。该课程价格为 99 元,新注册用户享有 30 元现金优惠,也就是只需要 <font color="red">69 元</font> 即可购买该套课程。
点击此处购买 <span v-on:click="openRecommendation" style="cursor: pointer;"><a>深入剖析Kubernetes</a></span> ,或扫描图片中的二维码。
<div v-on:click="openRecommendation" style="cursor: pointer">
<img src="./k8s-intermediate/recommendation.assets/88302026c83b209ccc6261c63281a963.jpg" style="border: 1px solid #d7dae2; max-width: 600px;"></img>
</div>
<script>
export default {
methods: {
openRecommendation () {
window.open('https://time.geekbang.org/column/intro/100015201?code=MH1Wu456g0ZsrKtQI7QidivKV2hVvzerAUxDz5pOuQs%3D', '_blank');
console.log('尝试发送 ga event')
if (window.ga) {
window.ga('send', {
hitType: 'event',
eventCategory: 'Learning',
eventAction: 'click',
eventLabel: '深入剖析Kubernetes-learning'
});
console.log('发送成功 ga event')
} else {
console.log('开发环境,不发送 ga event')
}
}
}
}
</script>
* [概述](/micro-service/spring-cloud/index.html)
* [部署服务注册中心]
* [部署数据库]
* [部署微服务]
* [部署服务网关]
* [部署Web前端]
* [复制一套部署环境]

View File

@ -1,31 +0,0 @@
# Kubernetes 课程推荐
作者认为,基础比较好的同学,在学完 **Kubernetes 入门** 部分的内容后,就可以根据 Kubernetes 的官网文档和 docker 的官网文档,结合实际项目将 Kubernetes 应用得很好。同时,作者也在逐步完善 **Kubernetes 进阶** 的学习内容,例如 [通过互联网访问您的应用](./ingress.html),但是鉴于时间和进度的原因,短期内仍然不能很好的满足 Kubernetes 爱好者迫切的学习意愿。
在这种情况下,作者向大家推荐一份视频课程。该课程价格为 99 元,新注册用户享有 30 元现金优惠,也就是只需要 <font color="red">69 元</font> 即可购买该套课程。
点击此处购买 <span v-on:click="gotoRecommendation" style="cursor: pointer;"><a>深入剖析Kubernetes</a></span> ,或扫描图片中的二维码。
<img src="./recommendation.assets/88302026c83b209ccc6261c63281a963.jpg" style="border: 1px solid #d7dae2; max-width: 600px;" v-on:click="gotoRecommendation"></img>
<script>
export default {
methods: {
gotoRecommendation () {
window.open('https://time.geekbang.org/column/intro/100015201?code=MH1Wu456g0ZsrKtQI7QidivKV2hVvzerAUxDz5pOuQs%3D', '_blank');
console.log('尝试发送 ga event')
if (window.ga) {
window.ga('send', {
hitType: 'event',
eventCategory: 'Recommendation',
eventAction: 'click',
eventLabel: '深入剖析Kubernetes-k8s-intermediate'
});
console.log('发送成功 ga event')
} else {
console.log('开发环境,不发送 ga event')
}
}
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@ -0,0 +1,103 @@
---
description: 本文描述了 Kubernetes Pod 中的初始化容器的概念、使用场景和使用方法。初始化容器是容器组中 app 容器启动之前执行的容器。可能包含 setup 脚本,或其他工具进程
---
# Pod 初始化容器
参考文档: Kubernetes 官网 [Init Containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)
## 初始化容器介绍
Pod 可以包含多个工作容器,也可以包含一个或多个初始化容器,初始化容器在工作容器启动之前执行。
初始化容器与工作容器完全相同,除了如下几点:
* 初始化容器总是运行并自动结束
* kubelet 按顺序执行 Pod 中的初始化容器,前一个初始化容器成功结束后,下一个初始化容器才开始运行。所有的初始化容器成功执行后,才开始启动工作容器
* 如果 Pod 的任意一个初始化容器执行失败kubernetes 将反复重启该 Pod直到初始化容器全部成功除非 Pod 的 restartPolicy 被设定为 Never
* 初始化容器的 Resource request / limits 处理不同,请参考 [Resources](#Resources)
* 初始化容器不支持 [就绪检查 readiness probe](/learning/k8s-intermediate/workload/pod-lifecycle.html#container-probes),因为初始化容器必须在 Pod ready 之前运行并结束
## 使用初始化容器
初始化容器可以指定不同于工作容器的镜像,这使得初始化容器相较于直接在工作容器中编写启动相关的代码更有优势:
* 初始化容器可以包含工作容器中没有的工具代码或者自定义代码。例如:您无需仅仅为了少量的 setup 工作(使用 sed, awk, python 或 dig 进行环境设定)而重新从一个基础镜像制作另外一个镜像
* 初始化容器可以更安全地执行某些使工作容器变得不安全的代码
* 应用程序的镜像构建者和部署者可以各自独立地工作,而无需一起构建一个镜像
* 初始化容器相较于工作容器,可以以另外一个视角处理文件系统。例如,他们可以拥有访问 Secrets 的权限,而工作容器却不一定被授予该权限
* 初始化容器在任何工作容器启动之前结束运行,这个特性使得我们可以阻止或者延迟工作容器的启动,直到某些前提条件得到满足。一旦前提条件满足,所有的工作容器将同时并行启动
### Examples
下面是一些使用初始化容器的例子:
* 使用一行 shell 命令,等待某一个 Service 启动后再启动工作容器
``` sh
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
```
* 使用 Pod 的信息将其注册到某一个远程服务:
``` sh
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
```
* 等候一定时间再启动工作容器
```sh
sleep 60
```
* 将 Git repository 克隆到一个数据卷
* 根据某些参数,运行一个模板工具动态生成工作容器所需要的配置文件
### 在 Kuboard 中使用初始化容器
Kuboard 工作负载编辑器中支持定义初始化容器,如下图所示,左下角可 ***添加初始化容器*** 初始化容器按照添加的顺序显示在容器组中,且始终显示在工作容器的前面。
![image-20190907171451988](./init-container.assets/image-20190907171451988.png)
## 初始化容器的行为
* Pod 的启动时首先初始化网络和数据卷然后按顺序执行每一个初始化容器。任何一个初始化容器都必须成功退出才能开始下一个初始化容器。如果某一个容器启动失败或者执行失败kubelet 将根据 Pod 的 restartPolicy 决定是否重新启动 Pod。
* 只有所有的初始化容器全都执行成功Pod 才能进入 ready 状态。初始化容器的端口是不能够通过 kubernetes Service 访问的。Pod 在初始化过程中处于 Pending 状态,并且同时有一个 type 为 `initializing` status 为 `True` 的 [Condition](./pod-lifecycle.html#pod-conditions)
* 如果 Pod 重启,所有的初始化容器也将被重新执行。
* 您可以重启、重试、重新执行初始化容器,因此初始化容器中的代码必须是 **幂等** 的。具体来说,向 emptyDir 写入文件内容的代码应该考虑到该文件已经存在的情况。请参考 [幂等](/glossary/idempotent.html) 获得更多信息
* 您可以组合使用就绪检查和 activeDeadlineSeconds <Badge text="Kuboard 暂不支持" type="warn"/>,以防止初始化容器始终失败。
* Pod 中不能包含两个同名的容器(初始化容器和工作容器也不能同名)。
### Resources
在确定初始化容器的执行顺序以后,以下 resource 使用规则将适用:
* 所有初始化容器中最高的 resource request/limit 是最终生效的 request/limit
* 对于 Pod 来说,最终生效的 resource request/limit 是如下几个当中较高的一个:
* 所有工作容器某一个 resource request/limit 的和
* 最终生效的初始化容器的 request/limit 的和
* Kubelet 依据最终生效的 request/limit 执行调度,这意味着,在执行初始化容器时,就已经为 Pod 申请了其资源需求
<!-- The QoS (quality of service) tier of the Pods effective QoS tier is the QoS tier for init containers and app containers alike.
Quota and limits are applied based on the effective Pod request and limit.
Pod level control groups (cgroups) are based on the effective Pod request and limit, the same as the scheduler.
Pod restart reasons
A Pod can restart, causing re-execution of init containers, for the following reasons:
A user updates the Pod specification, causing the init container image to change. Any changes to the init container image restarts the Pod. App container image changes only restart the app container.
The Pod infrastructure container is restarted. This is uncommon and would have to be done by someone with root access to nodes.
All containers in a Pod are terminated while restartPolicy is set to Always, forcing a restart, and the init container completion record has been lost due to garbage collection. -->
### Pod 重启的原因
Pod 重启时所有的初始化容器都会重新执行Pod 重启的原因可能有:
* 用户更新了 Pod 的定义,并改变了初始化容器的镜像
* 改变任何一个初始化容器的镜像,将导致整个 Pod 重启
* 改变工作容器的镜像,将只重启该工作容器,而不重启 Pod
* Pod 容器基础设施被重启(例如 docker engine这种情况不常见通常只有 node 节点的 root 用户才可以执行此操作
* Pod 中所有容器都已经结束restartPolicy 是 Always且初始化容器执行的记录已经被垃圾回收此时将重启整个 Pod

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,9 +1,133 @@
---
description: Pod 容器组的生命周期
description: 本文描述了 Kubernetes 中 Pod 容器组的生命周期
---
# Pod 生命周期
参考文档: Kubernetes 官网文档 [Pod Lifecycle](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/)
进行中...
[[TOC]]
## Pod phase
Pod phase 代表其所处生命周期的阶段。Pod phase 并不是用来代表其容器的状态,也不是一个严格的状态机。
phase 的可能取值有:
| Phase | 描述 |
| ------------ | ------------------------------------------------------------ |
| Pending | Kubernetes 已经创建并确认该 Pod。此时可能有两种情况<li>Pod 还未完成调度(例如没有合适的节点)</li><li>正在从 docker registry 下载镜像</li> |
| Running | 该 Pod 已经被绑定到一个节点,并且该 Pod 所有的容器都已经成功创建。其中至少有一个容器正在运行,或者正在启动/重启 |
| Succeeded | Pod 中的所有容器都已经成功终止,并且不会再被重启 |
| Failed | Pod 中的所有容器都已经终止,至少一个容器终止于失败状态:容器的进程退出码不是 0或者被系统 kill |
| Unknown | 因为某些未知原因,不能确定 Pod 的状态,通常的原因是 master 与 Pod 所在节点之间的通信故障 |
## Pod conditions
每一个 Pod 都有一个数组描述其是否达到某些指定的条件。Pod condition 数组在 Kuboard 中的显示如下图所示:
![image-20190907122721669](./pod-lifecycle.assets/image-20190907122721669.png)
该数组的每一行可能有六个字段:
| 字段名 | 描述 |
| ---------------------------------------------------------- | ------------------------------------------------------------ |
| type | type 是最重要的字段,可能的取值有:<li><font color="#007af5">**PodScheduled**</font> Pod 已被调度到一个节点</li><li><font color="#007af5">**Ready**</font> Pod 已经可以接受服务请求,应该被添加到所匹配 Service 的负载均衡的资源池</li><li><font color="#007af5">**Initialized**</font>Pod 中所有初始化容器已成功执行</li><li><font color="#007af5">**Unschedulable**</font>不能调度该 Pod缺少资源或者其他限制</li><li><font color="#007af5">**ContainersReady**</font>Pod 中所有容器都已就绪</li> |
| status | 能的取值有:<li>True</li><li>False</li><li>Unknown</li> |
| reason <Badge text="Kuboard 暂不显示" type="warn"/> | Condition 发生变化的原因,使用一个符合驼峰规则的英文单词描述 |
| message <Badge text="Kuboard 暂不显示" type="warn"/> | Condition 发生变化的原因的详细描述human-readable |
| lastTransitionTime | Condition 发生变化的时间戳 |
| lastProbeTime <Badge text="Kuboard 暂不显示" type="warn"/> | 上一次针对 Pod 做健康检查/就绪检查的时间戳 |
## Container probes
Probe 是指 kubelet 周期性地探测容器的状况。有三种类型的 Probe
* <font color="#007af5">**ExecAction**</font> 在容器内执行一个指定的命令。如果该命令的退出状态码为 0则成功
* <font color="#007af5">**TCPSocketAction**</font> 探测容器的指定 TCP 端口,如果该端口处于 open 状态,则成功
* <font color="#007af5">**HTTPGetAction**</font> 探测容器指定端口/路径上的 HTTP Get 请求,如果 HTTP 响应状态码在 200 到 400不包含400之间则成功
Probe 有三种可能的结果:
* <font color="#007af5">**Success**</font> 容器通过检测
* <font color="#007af5">**Failure**</font> 容器未通过检测
* <font color="#007af5">**Unknown**</font> 检测执行失败,此时 kubelet 不做任何处理
Kubelet 可以在两种情况下对运行中的容器执行 Probe
* <font color="#007af5">**就绪检查 readinessProbe**</font> 确定容器是否已经就绪并接收服务请求。如果就绪检查失败kubernetes 将该 Pod 的 IP 地址从所有匹配的 Service 的资源池中移除掉。
* <font color="#007af5">**健康检查 livenessProbe**</font> 确定容器是否正在运行。如果健康检查失败kubelete 将结束该容器,并根据 restart policy重启策略确定是否重启该容器。
### 何时使用 健康检查/就绪检查?
* 如果容器中的进程在碰到问题时可以自己 crash您并不需要执行健康检查kubelet 可以自动的根据 Pod 的 restart policy重启策略执行对应的动作
* 如果您希望在容器的进程无响应后,将容器 kill 掉并重启,则指定一个健康检查 liveness probe并同时指定 restart policy重启策略为 Always 或者 OnFailure
* 如果您想在探测 Pod 确实就绪之后才向其分发服务请求,请指定一个就绪检查 readiness probe。此时就绪检查的内容可能和健康检查相同。就绪检查适合如下几类容器
* 初始化时需要加载大量的数据、配置文件
* 启动时需要执行迁移任务
* 其他
::: tip
如果您想在删除 Pod 前停止向其分发服务请求,您无需为此而指定就绪检查。在删除 Pod 时kubelete 自动将 Pod 置于 unready 状态,并等待其中的容器停止。
:::
### Kuboard 中配置健康检查/就绪检查
Kuboard 可以在工作负载编辑器中配置健康检查/就绪检查,界面如下所示:
![image-20190907141952059](./pod-lifecycle.assets/image-20190907141952059.png)
<!--
$$ Pod and Container status
-->
## Container States
一旦 Pod 被调度到节点上kubelet 便开始使用容器引擎(通常是 docker创建容器。容器有三种可能的状态Waiting / Running / Terminated
* <font color="#007af5">**Waiting**</font> 容器的初始状态。处于 Waiting 状态的容器,仍然有对应的操作在执行,例如:拉取镜像、应用 Secrets等。
* <font color="#007af5">**Running**</font> 容器处于正常运行的状态。容器进入 Running 状态之后,如果指定了 postStart hook该钩子将被执行。
* <font color="#007af5">**Terminated**</font> 容器处于结束运行的状态。容器进入 Terminated 状态之前,如果指定了 preStop hook该钩子将被执行。
在 Kuboard 的工作负载查看界面中可查看到容器的状态如下图所示:
![image-20190907143026772](./pod-lifecycle.assets/image-20190907143026772.png)
<!-- $$ Pod readiness gate
Kuboard 暂不支持 -->
## Restart policy
定义 Pod 或工作负载时,可以指定 restartPolicy可选的值有
* Always (默认值)
* OnFailure
* Never
restartPolicy 将作用于 Pod 中的所有容器。kubelete 将在五分钟内按照递延的时间间隔10s, 20s, 40s ......)尝试重启已退出的容器,并在十分钟后再次启动这个循环,直到容器成功启动,或者 Pod 被删除。
## Pod lifetime
通常,如果没有人或者控制器删除 PodPod 不会自己消失。只有一种例外,那就是 Pod 处于 Scucceeded 或 Failed 的 phase并超过了垃圾回收的时长在 kubernetes master 中通过 terminated-pod-gc-threshold 参数指定kubelet 自动将其删除。
<!--
Three types of controllers are available:
Use a Job for Pods that are expected to terminate, for example, batch computations. Jobs are appropriate only for Pods with restartPolicy equal to OnFailure or Never.
Use a ReplicationController, ReplicaSet, or Deployment for Pods that are not expected to terminate, for example, web servers. ReplicationControllers are appropriate only for Pods with a restartPolicy of Always.
Use a DaemonSet for Pods that need to run one per machine, because they provide a machine-specific system service.
All three types of controllers contain a PodTemplate. It is recommended to create the appropriate controller and let it create Pods, rather than directly create Pods yourself. That is because Pods alone are not resilient to machine failures, but controllers are.
If a node dies or is disconnected from the rest of the cluster, Kubernetes applies a policy for setting the phase of all Pods on the lost node to Failed.
$$ Examples
$$ What's next -->