Kubernetes Pod深度理解
Kubernetes Pod深度理解
- 一、Pod
- 从使用角度看
- 从kubernetes角度看
- 有关pod基础命令
- kubectl命令创建pod
- 查看pod
- 显示pod更多信息
- 查看pod日志
- 以yaml格式显示pod详细信息
- 显示资源的详细描述信息
- 在pod容器中执行命令
- 登录到pod中容器中
- 将pod的端口映射到宿主机
- 在宿主机和pod的容器间拷贝文件
- pod状态
- 删除pod
- 二、pod探针
- 1.探针的实现方式
- 2.容器状态
- 3.pod探针类型
- (1)livenessProbe(存活探针)
- (2)readinessProbe(就绪探针)
- (3)startupProbe (启动探针)
- 三、pod镜像拉取策略和重启策略
- 1:镜像拉取策略
- 2.pod重启策略
- 四、创建一个简单pod
- 1.编写一个简单的pod
- 2.编写pod配置文件frontend-localredis-pod.yaml
- 3、Pod 文件语法
- 五、Pod的基本用法
- 六、静态pod
- 七、pod启动过程与运行状态
- 1、pod 的启动过程包含的步骤
- 八、故障排除步骤
- 1、查看 Pod 事状态
- 2、查看 Pod 日志(Failed 状态下)
- 3、Pod 处于 Pending 状态
- 4、Pod 处于 ImagePullBackOff 状态
- 5、Pod 处于 CrashLoopBackOff 状态
- 6、Pod 处于 ErrImagePull 状态
- 7、Pod 处于 ContainerCreating 状态
- 8、检查网络和存储
一、Pod
Pod 是一个或多个容器的组合。这些容器共享存储、网络和命名空间,以及运行规范。在 Pod 中,所有容器都被统一安排和调度。对于具体应用而言,Pod 是它们的逻辑主机,Pod 包含业务相关的多个应用容器。所以,Pod 是一组具有共享命名空间、IP地址和端口的容器的集合。
从使用角度看
在实际的使用时,单个容器是无法单独来支撑我们的应用的,往往需要很多微服务才能组成一个系统,并且还会存在A服务依赖B服务,B服务需要和C服务共用某个目录。另外,在使用裸容器时,很难实现对容器内进行健康检査以及横向扩容等操作,而 Pod 可以轻松解决这些问题。
从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 中的容器可以同 localhost 进行互相通信。当 Pod 中的容器需要与Pod 外的实体进行通信时,则需要通过端口等共享的网络资源。
存储:Pod 能够被指定共享存储卷的集合,在 Pod 中所有的容器能够访问共享存储卷,允许这些容器共享数据。存储卷也允许在一个 Pod 持久化数据,以防止其中的容器需要被重启。
有关pod基础命令
kubectl命令创建pod
ku run nginx --image=nginx:1.7.9 --labels="app=nginx"
查看pod
ku get pod -n default
显示pod更多信息
ku get pod nginx -o wide
查看pod日志
curl 10.244.58.209
ku logs nginx
以yaml格式显示pod详细信息
ku get pod nginx -o yaml
显示资源的详细描述信息
关键点在末尾事件
备注:
kubectl get:常用于査看同一资源类型的一个或多个资源对象,可以使用-0 参数自定义输出格式。
kubectl describe:侧重于描述指定资源的各方面的详细信息,不仅会返回节点信息,还会返回在其上运行的 Pod 的摘要、节点事件等信息。
在pod容器中执行命令
ku exec nginx -c nginx -- ls
备注:
-c:指定 Pod 中容器的名字
登录到pod中容器中
ku exec -it nginx -c nginx -- bash
备注:
kubectl exec -it nginx - - bash
如果登录的时候不指定容器,就登录到Pod 中的第一个容器中。
将pod的端口映射到宿主机
此方式不建议在真正生成环境中使用,可在测试环境中使用,此方法是临时性的映射占用前端屏幕。
ku port-forward --address 0.0.0.0 pod/nginx 8080:80
注意:
此命令会在前台运行,此时就可以在其他客户端用该k8s 主机的 IP 地址和 8080 的端口号进行访问了,Ctrl+c停止,但停止后就没有这个映射了。
在宿主机和pod的容器间拷贝文件
echo "aaa" >aaa.txt
ku cp aaa.txt nginx:/opt/bbb.txt
ku exec -it nginx -- bash
pod状态
ku get pods -n default
可以看到此时的 Pod 的状态是 Running,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 查看具体原因 |
删除pod
ku delete pod nginx
二、pod探针
在生产环境中,进程正常启动并不代表应用能正常处理请求,所以合理的设计应用的健康检査尤其重要。在使用裸机或裸容器部署时,一般很难对应用做很完善的健康检査,而 Pod 提供的探针可以很方便的用来检测容器的应用是否正常。
1.探针的实现方式
目前探针有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 Socket - 尝试打开一个 TCP socket 连接到容器上的指定端口,如果连接成功则认为容器是健康的。
(2)readinessProbe(就绪探针)
判断容器是否能够进入ready 状态,用于确定 Pod 中的容器是否已准备好接收流量。与livenessProbe 不同,readinessProbe 主要关注的是容器是否已经准备好为服务提供者处理请求。如果容器没有通过就绪探针的检査,Kubernetes 将不会把任何新的网络流量路由到这个容器上。
当一个容器报告自己尚未准备好时,Kubernetes 可能会采取以下行动:
- 服务(Service)不会将流量路由到未准备好的Pod。
- 如果 Pod是副本集(Replicaset)、部署(Deployment)、状态集(statefulset)等的一部分控制器会认为这个实例不可用。
- 对于使用 Pod 的滚动更新策略的情况,就绪探针可以帮助确保新版本的 Pod 在旧版本被终止之前就已经准备好了。
就像 livenessProbe 一样,readinessProbe 也支持多种类型的探测方法:
- HTTP GET 请求 -发送 HTTP 请求到容器内的某个 URL
- Exec执行命令-在容器内执行一个自定义命令或可执行文件
- TCP Socket -尝试建立一个到容器上的指定端口的 TCP 连接。
(3)startupProbe (启动探针)
判断容器内的应用是否启动成功,在 success 状态前,其它探针都处于无效状态。它专门用于检测容器是否完成了初始化并进入了预期的运行状态。与livenessProbe(存活探针)和 readinessProbe(就绪探针)不同,startupProbe专注于容器启动阶段,并且仅在容器启动过程中使用。
startupProbe 的主要作用是在容器启动期间持续检査容器是否已经完成启动。一旦容器通过了startupProbe 的检査,Kubernetes 就会认为容器已经成功启动,并停止对该容器的启动探针检査。如果容器始终无法通过启动探针的检査,那么 Kubernetes 将会根据配置重试一定的次数,超过重试次数后可能会采取进一步的措施,如重启容器。
三、pod镜像拉取策略和重启策略
1:镜像拉取策略
在发布应用或者更改控制器配置时,会触发 Pod 的滚动更新,此时针对容器的镜像有不同的拉取方式。
如表所示。
操作方式 | 说明 |
---|---|
Always | 总是拉取,无论镜像是否存在,总是拉取 |
Never | 无论是否存在都不会拉取 |
IfNotPresent | 镜像不存在时拉取镜像,是 k8s 默认的策略,但是如果 tag 为 latest,则总是拉取 |
指定拉取策略:
ku run nginx --image=nginx:1.7.9 --labels="app=nginx" --image-pull-policy=Never
2.pod重启策略
在 Kubernetes 中,Pod 的重启策略(Restart Policy)定义了当容器退出或失败时,kubelet 如何处理容器。重启策略是 Pod 级别的配置,适用于Pod 中的所有容器。
在 Always 策略中,只要容器退出(无论退出码是什么),kubelet 都会自动重启容器。适用于需要持续运行的服务(如 web 服务器、数据库等)。
在 OnFailure 策略中,只有当容器以非零退出码退出时,kubelet 才会重启容器,如果容器正常退出(退出码为 ),则不会重启。适用于任务型 Pod(如批处理任务),任务完成后不需要重启。
在 Never 策略中,无论容器以何种方式退出,kubelet 都不会重启容器。适用于一次性任务,任务完成后不需要重启。
操作方式 | 说明 |
---|---|
Always | 容器退出即重启,适用于长期运行的服务 |
OnFailure | 容器失败时重启,适用于任务型工作负载 |
Never | 容器退出后不重启,适用于一次性任务 |
指定重启策略:
ku delete pod nginx
ku run nginx --image=nginx:1.7.9 --labels="app=nginx" --restart=OnFailure
四、创建一个简单pod
1.编写一个简单的pod
apiVersion: v1
kind: Pod
metadata:name: nginxlabels:name: nginx
spec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80
2.编写pod配置文件frontend-localredis-pod.yaml
cat <<EOF>frontend-localredis-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: redis-phplabels:name: redis-php
spec:containers:- name: frontendimage: kubeguide/guestbook-php-frontend:localredisimagePullPolicy: IfNotPresentlivenessProbe:tcpSocket:port: 80initialDelaySeconds: 1periodSeconds: 3timeoutSeconds: 1ports:- containerPort: 80- name: redisimage: kubeguide/redis-masterimagePullPolicy: IfNotPresentports:- containerPort: 6379restartPolicy: OnFailure
EOF
命令 | 含义 |
---|---|
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 | 镜像拉取策略 |
livenessProbe | 设置存活探针 |
tcpsocket | 测试某端口是否可以连接 |
port:80 | 指定要测试的端口 |
initialDelaySeconds:1 | 指定 kubelet 在执行第一次探测前应该等待1秒,即第一次探测是#在容器启动后的第2秒才开始执行。默认是8秒,最小值是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 | 重启策略 |
ku apply -f frontend-localredis-pod.yaml
3、Pod 文件语法
(1) Pod 文件的一级属性
一级属性主要包含 5 部分:
(2) spec(规格)属性
在一级属性中,spec 是研究的重点,它的常见子属性有:
五、Pod的基本用法
1、将两个容器放入一个Pod中
vim nginx-php.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx-phplabels:name: nginx
spec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80- name: php-appimage: bitnami/php-fpmimagePullPolicy: Neverports:- containerPort: 9000
部署nginx的php文件
ku apply -f nginx-php.yaml
ku get pods
备注:
此时可以看到 pod 中有两个容器处于 running 状态中
查看pod详细信息
ku describe pod nginx-php
暴露端口
ku expose pod nginx-php --port=8080 --target-port=80 --type=NodePort --name=nginx-php###参数说明###pod nginx-php ##指定要暴露的资源类型为 Pod,并给出 Pod 的名称 nginx-php。--port=8080 ##服务(Service)对外暴露的端口号。客户端将通过这个端口访问服务。--target-port=80 ##Pod 内部应用实际监听的端口号。服务接收到的请求会被转发到 Pod 的这个端口。--type=NodePort ##服务的类型为 NodePort。这种类型会在集群每个节点的 IP 上开放一个静态端口(默认范围 30000-32767),外部可以通过 节点IP:NodePort 访问服务。--name=nginx-php ##指定创建的服务名称为 nginx-php。
查看端口映射
ku get pod,svc nginx-php -o wide
测试访问
删除pod
ku delete -f nginx-php.yaml
六、静态pod
静态 Pod 是由 kubelet 进行管理的仅存在于各个 Node 上的 Pod。他们不能通过 API Server 进行理,无法于 ReplicationController、Deployment 或者 DaemonSet 进行关联,并且 kubelet 无法对们进行健康检査。静态 Pod 总是由 kubelet 创建的,并且总在 kubelet 所在的 Node 上运行。
编写yaml文件
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nginxlabels:name: nginx
spec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80
cp nginx-pod.yaml /etc/kubernetes/manifests/
不需执行部署命令,过一会,查看 pod
自动部署成功
删除静态Pod
rm -rf /etc/kubernetes/manifests/nginx-pod.yaml
备注:
不能用如下语句删除
kubectl delete pod static-web-k8s-master01这样删除,会让 pod 处于 pending 状态,但无法删除
七、pod启动过程与运行状态
Pod 创建完之后,一直到持久运行起来,中间有很多步骤,也就有很多出错的可能,因此会有很多不同的状态。
在 Pod 的启动过程中,会涉及到多个关键组件,保证 Pod 能够顺利的启动完成,这些关键组件和作用如下所示:
1、pod 的启动过程包含的步骤
Pod 的启动过程是 kubernetes 中一个关键的操作,涉及多个步骤和组件协同工作。以下是 Pod 启动的主要过程:
八、故障排除步骤
当一个 Pod 无法正常启动时,可能是由于多种原因导致的。以下是故障排除的详细步骤,帮助你定位和解决问题。
1、查看 Pod 事状态
kubectl logs <pod - name> -n <namespace>
2、查看 Pod 日志(Failed 状态下)
kubectl logs <pod - name> -n <namespace>
如果 Pod 中有多个容器,使用 -c 指定容器名称:
kubectl logs <pod - name> -n <namespace> -c <container - name>
如果容器不断重启,可以查看上一次崩溃的日志:
kubectl logs <pod - name> -n <namespace> --previous
3、Pod 处于 Pending 状态
可能原因:
资源不足(CPU、内存)。
没有可用节点满足调度条件(如节点亲和性、污点容忍)。
持久卷声明(PVC)未绑定。
排查方法:
检查节点资源:
kubectl describe 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 是否已绑定:
kubectl get pvc -n <namespace>
检查存储类(StorageClass)配置是否正确。