揭秘Pod状态与生命周期管理的秘密(上)
写在前面
前几篇文章中主要分享了k8s的几种控制器,本文将着重分享一下k8s最小的创建和部署单位pod的状态与生命周期管理。
点击 这里 可以查看所有相关文章。
Pod 概览
Pod 是 kubernetes 中你可以创建和部署的最小也是最简的单位。Pod 代表着集群中运行的进程。
Pod 中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络 IP,管理容器如何运行的策略选项。Pod 代表着部署的一个单位:kubernetes 中应用的一个实例,可能由一个或者多个容器组合在一起共享资源。
在 Kubernetes 集群中 Pod 有如下两种使用方式:
- 一个 Pod 中运行一个容器。“每个 Pod 中一个容器” 的模式是最常见的用法;在这种使用方式中,你可以把 Pod 想象成是单个容器的封装,kuberentes 管理的是 Pod 而不是直接管理容器。
- 在一个 Pod 中同时运行多个容器。一个 Pod 中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个 Pod 中的容器可以互相协作成为一个 service 单位 —— 一个容器共享文件,另一个 “sidecar” 容器来更新这些文件。Pod 将这些容器的存储资源作为一个实体来管理。
Pod 中如何管理多个容器
Pod 中可以同时运行多个进程(作为容器运行)协同工作。同一个 Pod 中的容器会自动的分配到同一个 node 上。同一个 Pod 中的容器共享资源、网络环境和依赖,它们总是被同时调度。
Pod 中可以共享两种资源:网络和存储。
网络
每个 Pod 都会被分配一个唯一的 IP 地址。Pod 中的所有容器共享网络空间,包括 IP 地址和端口。Pod 内部的容器可以使用 localhost 互相通信。 Pod 中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
存储
可以为一个 Pod 指定多个共享的 Volume。Pod 中的所有容器都可以访问共享的 volume。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失。
使用 Pod
很少会直接在 kubernetes 中创建单个 Pod。因为 Pod 的生命周期是短暂的,用后即焚的实体。当 Pod 被创建后(不论是由你直接创建还是被其他 Controller创建),都会被 Kubernetes 调度到集群的 Node 上。直到 Pod 的进程终止、被删掉、因为缺少资源而被驱逐、或者 Node 故障之前这个 Pod 都会一直保持在那个 Node 上。
注意:重启 Pod 中的容器跟重启 Pod 不是一回事。Pod 只提供容器的运行环境并保持容器的运行状态,重启容器不会造成 Pod 重启。
Pod 不会自愈。如果 Pod 运行的 Node 故障,或者是调度器本身故障,这个 Pod 就会被删除。 同样的,如果 Pod 所在 Node 缺少资源或者 Pod 处于维护状态,Pod 也会被驱逐。Kubernetes 使用更高级的称为 Controller 的抽象层,来管理 Pod 实例。虽然可以直接使用 Pod,但是在 Kubernetes 中通常是使用 Controller 来管理 Pod 的。
Pod 解析
Pod 就像是豌豆荚一样,它由一个或者多个容器组成(例如 Docker 容器),它们共享容器存储、网络和容器运行配置项。Pod 中的容器总是被同时调度,有共同的运行环境。你可以把单个 Pod 想象成是运行独立应用的 “逻辑主机”—— 其中运行着一个或者多个紧密耦合的应用容器 —— 在有容器之前,这些应用都是运行在几个相同的物理机或者虚拟机上。
根据 Docker 的结构,Pod 中的容器共享 namespace 和 volume,不支持共享 PID 的 namespace。
就像每个应用容器,pod 被认为是临时(非持久的)实体。在 Pod 的生命周期中讨论过,pod 被创建后,被分配一个唯一的 ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果 node 死掉了,分配到了这个 node 上的 pod,在经过一个超时时间后会被重新调度到其他 node 节点上。一个给定的 pod(如 UID 定义的)不会被 “重新调度” 到新的节点上,而是被一个同样的 pod 取代,如果期望的话甚至可以是相同的名字,但是会有一个新的 UID。
资源共享和通信
Pod 中的应用可以共享网络空间(IP 地址和端口),因此可以通过 localhost 互相发现。因此,pod 中的应用必须协调端口占用。每个 pod 都有一个唯一的 IP 地址,跟物理机和其他 pod 都处于一个扁平的网络空间中,它们之间可以直接连通。
Pod 中应用容器的 hostname 被设置成 Pod 的名字。
Pod 中的应用容器可以共享 volume。Volume 能够保证 pod 重启时使用的数据不丢失。
Pod使用
Pod 也可以用于垂直应用栈(例如 LAMP),这样使用的主要动机是为了支持共同调度和协调管理应用程序,例如:
- 内容管理系统、文件和数据加载器、本地换群管理器等。
- 日志和检查点备份、压缩、旋转、快照等。
- 数据变更观察者、日志和监控适配器、活动发布者等。
- 代理、桥接和适配器等。
- 控制器、管理器、配置器、更新器等。
通常单个 pod 中不会同时运行一个应用的多个实例。
Pod 的终止
因为 Pod 作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送 KILL 信号这种暴力的方式)。用户需要能够发起一个删除 Pod 的请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除 pod 的请求,在 pod 可以被强制删除前会有一个宽限期,会发送一个 TERM 请求到每个容器的主进程。一旦超时,将向主进程发送 KILL 信号并从 API server 中删除。如果 kubelet 或者 container manager 在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。
示例流程如下:
- 用户发送删除 pod 的命令,默认宽限期是 30 秒;
- 在 Pod 超过该宽限期后 API server 就会更新 Pod 的状态为 “dead”;
- 在客户端命令行上显示的 Pod 状态为 “terminating”;
- 跟第三步同时,当 kubelet 发现 pod 被标记为 “terminating” 状态时,开始停止 pod 进程:
- 如果在 pod 中定义了 preStop hook,在停止 pod 前会被调用。如果在宽限期过后,preStop hook 依然在运行,第二步会再增加 2 秒的宽限期;
- 向 Pod 中的进程发送 TERM 信号;
- 跟第三步同时,该 Pod 将从该 service 的端点列表中删除,不再是 replication controller 的一部分。关闭的慢的 pod 将继续处理 load balancer 转发的流量;
- 过了宽限期后,将向 Pod 中依然运行的进程发送 SIGKILL 信号而杀掉进程。
- Kubelet 会在 API server 中完成 Pod 的的删除,通过将优雅周期设置为 0(立即删除)。Pod 在 API 中消失,并且在客户端也不可见。
删除宽限期默认是 30 秒。 kubectl delete 命令支持 —grace-period= 选项,允许用户设置自己的宽限期。如果设置为 0 将强制删除 pod。在 kubectl>=1.5 版本的命令中,必须同时使用 --force 和 --grace-period=0 来强制删除 pod。 在 yaml 文件中可以通过 {{ .spec.spec.terminationGracePeriodSeconds }} 来修改此值。
本文中主要介绍了pod的概念以及使用、删除等介绍,下文中将会继续介绍Pod中的各种容器以及Hook。
同时为了大家更好的学习云原生,熬夜整理了关于Go语言基础的学习文档:
关注公众号:云原生实战指南,回复Go语言资料即可免费获取。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!