kubernetes pod 深度解析
目录
- 什么是Pod
- 1:从使用角度来看
- 2:从kubernetes的角度来看
- 3:pod的状态
- 1.kubectl命令创建pod
- 2.查看pod
- 3.显示指定pod的更多信息
- 4.查看日志
- 5.以yaml格式显示指定pod的详细信息
- 6.显示资源的详细描述信息
- 7.登录到Pod中的容器
- 8.将pod端口映射到宿主机
- 9.在宿主机和pod容器之间拷贝文件
- 10.pod的状态
- 11.删除pod
- Pod探针
- 1:Pod探针的实现方式
- 2:容器状态
- 3:Pod探针类型
- 1.livenessProbe(存活探针)
- 2.readinessProbe(就绪探针)
- 3.startupProbe(启动探针)
- Pod镜像拉取策略和重启策略
- 1:镜像拉取策略
- 2:Pod重启策略
- 创建一个简单Pod
- 1:编写一个简单的Pod
- 2:编写pod配置文件
- 3:pod文件语法
- 1.pod文件的一级属性
- 2.spec(规格)属性
- 3.通过kubectl explain命令来查看每种资源的可配置项
- 4:运行kubectl create命令创建此pod
- 5:查看已经创建的pod
- 6:查看pod详细的创建信息
- 7:删除pod
- Pod的基本用法
- 1:编写pod文件,将两个容器放在同一个pod中
- 2:部署nginx的pod文件
- 3:暴露端口
- 4:查看端口映射
- 5:测试访问
- 静态pod
- Pod启动过程与运行状态
- 1:pod的启动过程包含的步骤
- 1.用户提交 Pod 定义
- 2.API Server 接收请求
- 3.scheduler 调度 Pod
- 4.kubelet 创建 Pod
- 5.容器运行时启动容器
- 6.kubelet更新pod状态
- 7.pod进入运行状态
- 8.探针检查(可选)
- 9.Pod可用
- 10.持续监控
- 2:pod运行状态
- 1.Pending
- 2.Running
- 3.Succeeded
- 4.Failed
- 5.Unknown
- 故障排除步骤
- 1:查看pod状态
- 2:查看Pod日志(Failed状态下)
- 3:Pod处于Pending状态
- 4:Pod处于ImagePullBackoff状态
- 5:Pod处于CrashLoopBackoff状态
- 6:Pod处于ErrImagePull状态
- 7:Pod处于ContainerCreating状态
- 8:检查网络和存储
- 9:检查资源限制
什么是Pod
Pod 是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及运行规范。在 Pod 中,所有容器都被统一安排和调度。对于具体应用而言,Pod 是它们的逻辑主机,Pod 包含业务相关的多个应用容器。所以,Pod 是一组具有共享命名空间、IP地址和端口的容器的集合。
1:从使用角度来看
在实际的使用时,单个容器是无法单独来支撑我们的应用的,往往需要很多微服务才能组成一个系统,并且还会存在A服务依赖B服务,B服务需要和C服务共用某个目录。另外,在使用裸容器时,很难实现对容器内进行健康检査以及横向扩容等操作,而Pod 可以轻松解决这些问题。
2:从kubernetes的角度来看
Docker 只是容器 Runtime(运行时)的一种们还有很多容器 Runtime,比如 Rkt、CRI-0等,而Kubernetes 作为目前最流行的容器编排工具,需要文持各个 Runtime 并且不依赖于底层 Runtime 的实现技术,于是就抽象出了 Pod 这个概念,用于管理多个紧密相连的符合 CRI 标准的容器
Pod 可以简单的理解为一组、一个或多个容器,每个 Pod 还包含一个 Pause 容器,Pause 容器是 Pod的父容器,主要负责僵尸进程的回收管理。同时,通过 Pause 容器可以使同一个 Pod 里面的不同容器其享存储、网络、PID、IPC(进程间通信)等,容器之间可以使用 Localhost:Port 的方式相互访问,可以使用 volume 实现数据共享。根据 Docker 的构造,Pod 可以被创建为一组具有共享命名空间、IP 地址和端口的容器。
Pod 有两个必须知道的特点:
网络:每一个Pod 都会被指派一个唯一的 Ip地址,在 Pod 中的每一个容器共享网络命名空间,包括Ip 地址和网络端口。在同一个 Pod 中的容器可以同 1oca1host 进行互相通信。当 Pod 中的容器需要与Pod 外的实体进行通信时,则需要通过端口等共享的网络资源。
存储:Pod能够被指定共享存储卷的集合,在 Pod 中所有的容器能够访问共享存储卷,允许这些容器共享数据。存储卷也允许在一个 Pod 持久化数据,以防止其中的容器需要被重启。
3:pod的状态
1.kubectl命令创建pod
2.查看pod
创建时没有指定其他的命名空间则不需要-n default,默认就是default
查看所有命名空间的pod
3.显示指定pod的更多信息
4.查看日志
首先需要访问
才能生成日志
5.以yaml格式显示指定pod的详细信息
6.显示资源的详细描述信息
一般查询错误都是从这里查看
备注:
kubectl get:常用于査看同一资源类型的一个或多个资源对象,可以使用-o 参数自定义输出格式。
kubectl describe:侧重于描述指定资源的各方面的详细信息,不仅会返回节点信息,还会返回在其上运行的 Pod 的摘要、节点事件等信息。
7.登录到Pod中的容器
第一个nginx是pod名,-c指定的是pod中的容器名。如果登录的时候不指定容器,就会登录到第一个容器
8.将pod端口映射到宿主机
注意:
此命令会在前台运行,此时就可以在其他客户端用该k8s 主机的 IP 地址和 8080 的端口号进行访问了,Ctrl+c 停止,但停止后就没有这个映射了。只适用于测试
9.在宿主机和pod容器之间拷贝文件
10.pod的状态
pod的状态不仅仅只有running,常见的状态如下:
状态 | 说明 |
---|---|
Pending(挂起) | Pod 已经被 Kubernetes 系统接收,但是仍有一个或多个容器未被创建,可以通过kubectl describe 查看处于Pending 状态的原因 |
Running(运行中) | Pod 已经被绑定到一个节点上,并且所有的容器都已经被创建,而且至少有一个是运行的状态、正在启动或者重启,可以通过 kubectl logs 査看 Pod 的日志 |
Succeeded | 所有容器执行成功,并终止,并且不会再次重启,可以通过kubectl logs 査看 Pod 的日志 |
Failed(失败) | 所有容器都已终止,并且至少一个容器以失败的方式终止,也就是说这个容器要么以非零状态退出,要么被系统终止可以通过 logs 和 describe 査看 Pod 的日志和状态 |
Unknown(未知) | 通常是由于通信问题造成的无法获得 Pod 的状态 |
ImagePullBackOff ErrImagePull | 镜像拉取失败,一般是由于镜像不存在、网络不通或者需要登录认证引起的,可以使用 describe 命令查看具体的原因 |
CrashLoopBackOff | 容器启动失败,可以通过 logs 命令查看具体的原因,一般为启动命令不正确、健康检查不通过等原因 |
OOMKilled | 容器内存溢出,一般是容器的内存 Limit 设置的过小,或者程序本身有内存溢出,可以通过 logs 查看程序的启动日志 |
Terminating | Pod 正在被删除,可以通过 describe 查看状态 |
SysctlForbiden | Pod 自定义了内核配置,但 kubectl 没有添加内核配置或配置的内核参数不支持,可以通过 describe 查看具体原因 |
Completed | 容器内部主进程退出,一般计划任务执行结束会显示该该状态,此时可以通过 logs 查看容器日志 |
Containercreating | Pod 正在创建,一般正在下载镜像,或者有配置不当的地方,可以通过 describe 查看具体原因 |
11.删除pod
Pod探针
在生产环境中,进程正常启动并不代表应用能正常处理请求,所以合理的设计应用的健康检查尤其重要。在使用裸机或裸容器部署时,一般很难对应用做很完善的健康检査,而 Pod 提供的探针可以很方便的用来检测容器的应用是否正常。
1:Pod探针的实现方式
目前探针有3种检测方式,可以根据不同的场景选择合适的健康检查方式,分别是ExecAction、TCPSocketAction 和 HTTPGetAction。具体实现方式如表
实现方式 | 说明 |
---|---|
ExecAction | 在容器内执行一个指定命令,如果命令返回值为0,则认为容器健康 |
TCPSocketAction | 通过TCP连接检查容器指定的端口,如果端口开放,则认为容器健康 |
HTTPGetAction | 对指定的URL进行Get请求,如果状态码在200-400之间,则认为容器健康 |
2:容器状态
通过上述的检查方式可以被周期性的执行,每次检查容器后可能得到的容器状态
状态 | 说明 |
---|---|
Success(成功) | 容器通过检查 |
Failure(失败) | 容器检查失败 |
Unknown | 诊断失败,因此不采取任何措施 |
3:Pod探针类型
Pod 探针有三类,分别是: livenessProbe(存活探针)、readinessProbe(就绪探针)、startupProbe(启动探针)。
1.livenessProbe(存活探针)
它被用来知道一个容器是否在正常运行。如果容器未能通过存活探针的检查,则系统会认为该容器已经进入了一个必须被重启的状态,从而自动重启这个容器。这种机制可以确保容器在出现问题后能够自动恢复到可用状态。
存活探针支持以下几种类型:
HTTP GET请求 - 通过发送HTTP请求到容器内的某个URL来检测容器是否处于健康状态
Exec 执行命令 - 在容器内执行一个自定义命令或可执行文件,并根据其退出码判断容器是否健康
TCP Socker - 尝试打开一个TCP socket连接到容器的指定端口,如果成功则认为容器是健康的
2.readinessProbe(就绪探针)
判断容器是否能够进入ready 状态,用于确定Pod 中的容器是否已准备好接收流量。与livenessProbe 不同,readinessProbe 主要关注的是容器是否已经准备好为服务提供者处理请求。如果容器没有通过就绪探针的检査,Kubernetes 将不会把任何新的网络流量路由到这个容器上。
当一个容器报告自己尚未准备好时,Kubernetes可能会采取以下行动:
服务(Service)不会将流量路由到未准备好的Pod。
如果 Pod 是副本集(Replicaset)、部署(Deployment)、状态集(statefulset)等的一部分,
控制器会认为这个实例不可用。
对于使用 Pod 的滚动更新策略的情况,就绪探针可以帮助确保新版本的 Pod 在旧版本被终止之前就已经准备好了。
readinessProbe也支持多种类型的探测方法:
HTTP GET请求 - 通过发送HTTP请求到容器内的某个URL来检测容器是否处于健康状态
Exec 执行命令 - 在容器内执行一个自定义命令或可执行文件,并根据其退出码判断容器是否健康
TCP Socker - 尝试打开一个TCP socket连接到容器的指定端口,如果成功则认为容器是健康的
3.startupProbe(启动探针)
判断容器内的应用是否启动成功,在 success 状态前,其它探针都处于无效状态。它专门用于检测容器是否完成了初始化并进入了预期的运行状态。与 1ivenessProbe(存活探针)和 readinessProbe(就绪探针)不同,startupProbe 专注于容器启动阶段,并且仅在容器启动过程中使用。startupProbe 的主要作用是在容器启动期间持续检査容器是否已经完成启动。一旦容器通过了startupProbe 的检査,Kubernetes 就会认为容器已经成功启动,并停止对该容器的启动探针检查。如果容器始终无法通过启动探针的检査,那么 Kubernetes 将会根据配置重试一定的次数,超过重试次数后可能会采取进一步的措施,如重启容器。
Pod镜像拉取策略和重启策略
1:镜像拉取策略
在发布应用或者更改控制器配置时,会触发 Pod 的滚动更新,此时针对容器的镜像有不同的拉取方式。
操作方式 | 说明 |
---|---|
Always | 总是拉取,无论镜像是否存在,总是拉取 |
Never | 无论是否存在都不拉取 |
IfNotPresent | 镜像不存在时拉取镜像,是k8s默认策略,但如果tag为latest,则总是拉取 |
指定拉取策略
2:Pod重启策略
在 Kubernetes 中,Pod 的重启策略(Restart Policy)定义了当容器退出或失败时,kubelet 如何处理容器。重启策略是Pod 级别的配置,适用于Pod 中的所有容器
在 Always 策略中,只要容器退出(无论退出码是什么),kubelet 都会自动重启容器。适用于需要持续运行的服务(如 web 服务器、数据库等)。
在 OnFailure 策略中,只有当容器以非零退出码退出时,kubelet 才会重启容器,如果容器正常退出(退出码为 0),则不会重启。适用于任务型 Pod(如批处理任务),任务完成后不需要重启。在 Never 策略中,无论容器以何种方式退出,kubelet 都不会重启容器。适用于一次性任务,任务完成后不需要重启。
操作方式 | 说明 |
---|---|
Always | 容器退出即重启,适合长期运行的服务 |
OnFailure | 容器失败则退出,适合任务型工作负载 |
Never | 容器退出后不重启,适合一次性任务 |
指定重启策略
创建一个简单Pod
1:编写一个简单的Pod
2:编写pod配置文件
备注:
apiVersion:v1 必选,版本号
kind: Pod 必选,资源类型
metadata: 必选,元数据
name: redis-php 必选,Pod 名称
labels 自定义的 pod 标签列表
name: redis-php 标签值
spec 必选,Pod 中容器的详细信息
containers 必选,Pod 中的容器列表
-name: frontend 必选,自定义的容器名称
-image:kubeguide/guestbook-php-frontend:localredis 容器的镜像名称
-imagePullPolicy IfNotPresent 镜像拉取策略i
livenessProbe 设置存活探针
tcpsocket 测试某端口是否可以连接
port:80 指定要测试的端口
initialDelaySeconds:1 指定 kubelet 在执行第一次探测前应该等待1秒,即第一次探测是在容器启动后的第2秒才开始执行。默认是0秒,最小值是0
periodseconds:3 指定了 kubelet 应该每 3 秒执行一次存活探测。默认是 10秒。最小值是 1
timeoutseconds:1 当探测失败时,Kubernetes 在超时之前等待的时间。存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
ports 需要暴露的端口号列表
-containerPort:80 容器需要监听的端口号
name: redis 另一个容器的名字
image: kubeguide/redis-master 另一个容器的镜像
ports 需要暴露的另一个容器的端口列表
-containerPort:6379 容器需要监听的端口号
restartPolicy:onFailure 重启策略
3:pod文件语法
1.pod文件的一级属性
一级属性主要包含五部分:
apiversion <string>版本,由 kubernetes 内部定义,版本号必须可以用 kubectl api-versions查询到
kind <string>类型,由 kubernetes 内部定义,版本号必须可以用 kubectl api-resources 查询到
metadata<Object>元数据,主要是资源标识和说明,常用的有 name、namespace、labels 等
spec<Object>描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
status<0bject>状态信息,里面的内容不需要定义,由kubernetes 自动生成
2.spec(规格)属性
在一级属性中,spec是研究的重点,它的常见子属性有:
containers< [ ]0bject>容器列表,用于定义容器的详细信息
nodeName <string>根据 nodeName 的值将 pod 调度到指定的 Node 节点上nodeSelector <map[ ]>根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的 Node 上
hostNetwork<boolean>是否使用主机网络模式,默认为 false,如果设置为 true,表示使用宿主机网络
volumes<[ ]object>存储卷,用于定义 Pod 上面挂在的存储信息restartPolicy<string>重启策略,表示 Pod 在遇到故障的时候的处理策略
3.通过kubectl explain命令来查看每种资源的可配置项
4:运行kubectl create命令创建此pod
5:查看已经创建的pod
6:查看pod详细的创建信息
7:删除pod
Pod的基本用法
1:编写pod文件,将两个容器放在同一个pod中
2:部署nginx的pod文件
注:
create和apply同样是创建,但是apply可以反复执行而create不行
3:暴露端口
4:查看端口映射
5:测试访问
用外部主机,访问master 的ip地址:映射的端口
静态pod
静态 Pod 是由 kubelet 进行管理的仅存在于各个 Node 上的 Pod。他们不能通过 API Server 进行管理,无法于 Replicationcontroller、Deployment 或者 DaemonSet 进行关联,并且 kubelet 无法对他们进行健康检査。静态 Pod 总是由 kubelet 创建的,并且总在 kubelet 所在的 Node 上运行。
删除静态pod的方法
备注:
不能用如下语句删除
kubectl delete pod nginx-k8s-master 这样删除,会让 pod 处于 pending 状态,但无法删除,过后还会自动开启
Pod启动过程与运行状态
Pod 创建完之后,一直到持久运行起来,中间有很多步骤,也就有很多出错的可能,因此会有很多不同的状态。
在 Pod 的启动过程中,会涉及到多个关键组件,保证 Pod 能够顺利的启动完成,这些关键组件和作用如下所示:
API Server:接收和处理 Pod 创建请求。
etcd:存储集群状态和 Pod 定义。
Scheduler:将 Pod 调度到合适的节点。
kubelet:在节点上管理 Pod 的生命周期。
容器运行时:负责容器的创建和运行。
通过这些步骤,Kubernetes确保Pod 能够按照预期启动并运行
1:pod的启动过程包含的步骤
Pod 的启动过程是 Kubernetes 中一个关键的操作,涉及多个步骤和组件协同工作。以下是 Pod 启动的主要过程:
1.用户提交 Pod 定义
用户通过 kubectl 或其他工具提交 Pod 的 YAML 或 JSON 定义文件到 Kubernetes API Server。
2.API Server 接收请求
API Server 接收到 Pod 创建请求后,会进行身份验证和授权检查,确保请求合法。
通过检査后,API Server 将 Pod 的定义信息存储到 etcd 中。
3.scheduler 调度 Pod
Scheduler 监控 API Server,发现有待调度的 Pod。
Scheduler 根据 Pod 的资源需求、节点亲和性、污点容忍等策略,选择一个合适的节点。
Scheduler 将 Pod 与节点绑定,并将绑定信息更新到 etcd。
4.kubelet 创建 Pod
目标节点上的 kubelet 监控 API Server,发现有新的 Pod 被调度到本节点。
kubelet 根据 Pod 定义,调用容器运行时(如 Docker、containerd)创建容器kubelet 还会为 Pod 设置网络(通过 CNI 插件)和存储卷(如 emptyDir、hostPath 或持久卷)
5.容器运行时启动容器
容器运行时根据 kubelet 的指令,拉取镜像(如果本地没有)并启动容器容器启动后,运行时向 kubelet 报告容器状态
6.kubelet更新pod状态
kubelet 监控容器的运行状态,并将 Pod 的状态更新到 API Server。
API Server 将状态信息存储到 etcd
7.pod进入运行状态
当所有容器成功启动并运行后,Pod 进入 Running 状态。如果容器启动失败,kubelet 会根据重启策略(如 Always、OnFailure)决定是否重启容器
8.探针检查(可选)
如果 Pod 定义了存活探针(Liveness Probe)或就绪探针(Readiness Probe),kubelet 会定期执行这些探针。
探针检查失败可能导致容器重启或Pod 从服务端点移除
9.Pod可用
当 Pod 的所有容器正常运行并通过就绪探针检査后,Pod 被视为可用,可以接收流量或执行任务。
10.持续监控
kubelet持续监控Pod状态,确保其正常运行
如果pod或容器出现问题,kubelet会根据配置采取相应措施
2:pod运行状态
1.Pending
表示 APIServer 创建了 Pod 资源对象并已经存入了 etcd 中,但是它并未被调度完成(比如还没有调度到某台 node上),或者仍然处于从仓库下载镜像的过程中
2.Running
Pod 已经被调度到某节点之上,并且 Pod 中所有容器都已经被 kubelet 创建。至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说 Running 状态下的 Pod 不一定能被正常访问)
3.Succeeded
有些 pod 不是长久运行的,比如 job、cronjob,一段时间后 Pod 中的所有容器都被成功终止,并且不会再重启。需要反馈任务执行的结果
4.Failed
Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非。状态退出或者被系统终止,比如command 写的有问题
5.Unknown
表示无法读取 Pod 状态,通常是 kube-controller-manager 无法与 Pod 通信
故障排除步骤
当一个 Pod 无法正常启动时,可能是由于多种原因导致的。以下是故障排除的详细步骤,帮助你定位和解决问题。
1:查看pod状态
kubelet get pods
2:查看Pod日志(Failed状态下)
kubelet logs <pod-name> -n <namespace>
如果Pod中有多个容器,使用-c指定容器名称
如果容器不断重启,可以查看上一次崩溃日志
kubectl logs <pod-name> -n <namespace> --previous
3:Pod处于Pending状态
可能原因:
资源不足(CPU、内存)
没有可用节点满足调度条件(如节点亲和性、污点容忍)持久卷声明(PVC)未绑定。
排查方法:
检查节点资源:kubectldescribe node<node-name>
检查 PVC 状态:kubectl get pvc -n<namespace>
查看调度器日志(如果启用了调度器日志)
检查节点资源是否充足(CPU、内存)
检查节点是否有污点(Taint)导致 Pod 无法调度,
检查节点是否处于 NotReady 状态。
4:Pod处于ImagePullBackoff状态
可能原因:
镜像名称错误或镜像不存在。
私有镜像未配置正确的镜像拉取密钥(imagePullsecrets)
镜像仓库不可访问(网络问题或认证失败)
排查方法:
检查镜像名称和标签是否正确。
确保 imagePullsecrets 配置正确。
手动尝试拉取镜像:docker pull<image-name>。
5:Pod处于CrashLoopBackoff状态
可能原因:
容器启动后立即崩溃(应用程序错误、配置错误)
资源限制过低(如内存不足导致 OOM)。
依赖服务未就绪。
排查方法:
查看容器日志
检查资源限制:kubectl describe pod<pod-name>-n<namespace>
检查应用程序配置和依赖服务。
6:Pod处于ErrImagePull状态
可能原因:
镜像拉取失败(镜像不存在或权限问题)
排查方法:
检查镜像名称和权限。确保镜像仓库可访问
7:Pod处于ContainerCreating状态
可能原因:
容器正在创建,但耗时较长。
可能由于网络问题(如CNI 插件未正确配置)或存储卷未准备好。
排查方法:
检查节点网络和CNI 插件状态
检查存储卷(PVC)是否已绑定
8:检查网络和存储
网络问题:
检查CNI 插件是否正常运行。
检査 Pod 的 DNS 配置是否正确。
存储问题:
检查 PVC 是否已绑定:kubectlgetpvc-n
检查存储类(storageclass)配置是否正确。
9:检查资源限制
确保资源请求不超过节点可用资源。如果资源限制过低,可能导致容器崩溃(如OOM)如果 Pod 因资源不足无法启动,检查资源请求和限制:
resources:
requests:
memory:“64Mi”
cpu:“250m”
limits:
memory:“128Mi”
cpu:“500m”
通过以上步骤,可以逐步定位 Pod 无法启动的原因。常见问题包括镜像拉取失败、资源不足、配置错误、网络或存储问题等。根据具体错误信息,结合日志和事件描述,可以快速解决问题。