目录
k8sday05深入Pod
Ⅰ、提示无法从 Docker Hub 拉取 Nginx 镜像,并且错误明确指向 网络连接超时 (i/o timeout)
Ⅱ、尽管镜像已拉取到宿主机,但 Kind 集群仍无法使用该镜像
一、探针
探针是 kubelet 对容器周期性做的一种健康检查动作,可以看作类似一个一直监视你的容器状态的东西。
1、探针类型
关于探针的类型可分三种:
-
启动探针(startupProbe)—— 容器刚创建时,给它一段“启动宽限期”,验证它是否真的启动成功。
-
存活探针(livenessProbe)——容器已经启动后,长期运行时的“心跳”检查,判断进程是否还活着。
-
就绪探针(readinessProbe)——判断容器是否已经准备好对外提供服务(例如完成初始化、加载完数据)
其中可知,启动探针是启动成功前进行的,存活探针和就绪探针是启动成功后进行的。
2、探针探测方式
探针的探测方式也可分为三种:
-
exec —— 在容器里执行一条命令,返回码为 0 视为成功。
-
-
跑脚本
-
-
httpGet —— 对容器指定端口和路径发 HTTP GET,返回 [200,400) 视为成功。
-
-
调用接口
-
-
tcpSocket —— 尝试连接容器指定端口,能连上就成功。
-
-
连接端口
-
这三种探测方式,根据你的服务应用不同而选择不同的探测方式更高效。如:
①、检测Nginx进程是否运行,使用exec探测
②、Web应用(如Nginx、Spring Boot)的健康检查,使用httpGet 探测
③、非HTTP应用(如数据库、Redis、SSH)的健康检查,使用tcpSocket 探测
3、常见探针的参数配置
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
initialDelaySeconds | 整数 | 0 | 容器启动后,第一次探测的延迟时间(秒)。例如,Java应用启动需要30秒,设为30。 |
periodSeconds | 整数 | 10 | 探测的间隔时间(秒)。默认每10秒探测一次。 |
timeoutSeconds | 整数 | 1 | 探测的超时时间(秒)。超过这个时间视为探测失败。 |
successThreshold | 整数 | 1 | 探测成功多少次后,视为容器状态正常。例如,失败后需要2次成功才恢复。 |
failureThreshold | 整数 | 3 | 探测失败多少次后,视为容器状态异常。例如,连续3次失败触发重启。 |
4、Pod创建配置文件
以下以一个配置nginx的Pod的yaml文件为例:
每个Pod都可以包含1个或多个容器,每个Pod都有根容器Pause容器
每一步都给出了解释,注意其中的缩进已经配置好了,不要随便添加或减少,否则在应用这个配置文件的时候会提示报错
注意:我只在配置文件列出常用的,部分其他命令我没有写,比如重启策略(restartPolicy)等等,大家如果有需要,可以查看官方文档进行补充。
基本可分为:Pod基本配置、镜像的拉取、启动命令、环境变量、端口、资源分配等等
# kind之后写Pod表示该配置文件是用来创建Pod,注意:区分大小写!!!
kind: Pod
apiVersion: v1 #此处写你的Pod的API版本
metadata: # 元数据
name: nginx-pod1 # 【可改】这是你创建的 Pod 名称,注意全小写
labels:
app: nginx-pod1 # 【可改】标签,这里面的键值对可以自定义
spec: # ← Pod 期望状态(Spec)的开始
containers: # ← 真正要运行的容器列表(数组,可写多个)
- name: nginx # 容器名字,随便起,必须唯一
image: nginx # 镜像名;如果本地没有,kubelet 会去仓库拉取
#imagePullPolicy: IfNotPresent
# 拉取镜像的策略有IfNotPresent(默认)本地没有再从远处拉、
# Always(每次都从远处拉)、Never(从不去远处拉,一直是本地拉,本地没有就报错)
ports:
- containerPort: 80 # 容器内部打开 80 端口(声明用,不会真正“暴露”到宿主机)
env:
- name: ENV # 把 ENV=prod 注入到容器的环境变量
value: "prod"
resources:
requests: # 容器“最低”需要多少资源
cpu: 100m # 100 毫核 ≈ 0.1 核
memory: 64Mi # 64 MiB 内存
limits: # 容器“最多”只能用到多少
cpu: 200m # 超过会被 CPU 限流
memory: 128Mi # 超过会被 OOMKill
# 启动探针:
startupProbe:
httpGet: # 当然也可以改为exec或tcp测试
path: / # 【可改】探测路径
port: 80
initialDelaySeconds: 5 # 【可改】首次探测延迟,即容器启动 5 s 后开始探测
periodSeconds: 10 # 【可改】探测间隔,这里是10s间隔
failureThreshold: 4 # 即连续失败4次后视为容器异常,启动失败
# 5×4 = 20 s 内成功即视为启动成功(periodSeconds x failureThreshold)
# 存活探针:一旦启动成功,持续检查是否 “活着“
livenessProbe:
httpGet: # 当然也可以改为exec或tcp测试
path: / # 【可改】探测路径
port: 80
initialDelaySeconds: 10 # 【可改】首次探测延迟,即容器启动 10 s 后开始探测
periodSeconds: 10 # 【可改】探测间隔,这里是10s间隔
timeoutSeconds: 5 # 【可改】探测超时时间,这里是5s超时
failureThreshold: 3 # 即连续失败3次后视为容器异常,启动失败
# 就绪探针:决定 Service 是否把流量打到该 Pod
readinessProbe:
httpGet: # 当然也可以改为exec或tcp测试
path: / # 【可改】探测路径
port: 80
initialDelaySeconds: 5 # 【可改】首次探测延迟,即容器启动 5 s 后开始探测
periodSeconds: 10 # 【可改】探测间隔,这里是10s间隔
timeoutSeconds: 3 # 【可改】探测超时时间,这里是3s超时
successThreshold: 1 # 【可改】成功阈值,即1次成功视为容器正常
failureThreshold: 3 # 【可改】失败阈值,即连续3次失败视为容器异常
注意:你在之前搭建集群使用的API和现在创建Pod的API是不相等的,不要将搭建集群使用的API复制到这(不要问我怎么知道的,我就是这样做的O.O)
可使用:
kubectl api-resources --verbs=list
来查看你的Pod的API,输出示例类似如下:
配置好文件,记得以yaml后缀形式保存,且你的文件内部要遵循 RFC 1123 子域名规则,Kubernetes 要求名称必须全小写。
-
允许的字符:
a-z(小写字母)、0-9(数字)、-(连字符)、.(点) -
不能以 . 或 - 开头或结尾,比如
-nginx或nginx-都是无效的。 -
不能有连续 . 或 -,比如
nginx..pod或nginx--pod也是无效的 -
长度限制:最多 253 个字符
创建成功,输入:
kubectl get pods
得到类似结果即创建Pod成功:
5、创建Pod可能遇到的问题
核心查看问题日志代码:
kubectl describe po <你创建的Pod名称>
这个代码会返回你的Events信息,从中可以看到很多日志信息
Ⅰ、提示无法从 Docker Hub 拉取 Nginx 镜像,并且错误明确指向 网络连接超时 (i/o timeout)
Warning Failed 8s kubelet Failed to pull image "nginx": failed to pull and unpack image "docker.io/library/nginx:latest"
解决方案:
①配置 Docker 镜像加速器
②手动预加载镜像(无外网时适用)
将 imagePullPolicy: IfNotPresent # 优先使用本地镜像 加入配置文件中
Ⅱ、尽管镜像已拉取到宿主机,但 Kind 集群仍无法使用该镜像
根本原因: Kind 默认使用
containerd作为容器运行时,而docker images中的镜像 不会自动同步到 containerd**,导致 Kubernetes 无法找到镜像。
解决方案:
将本地 Docker 镜像加载到 Kind 集群
kind load docker-image nginx:latest --name my-multi-node-cluster1
6、测试探针反应
修改探针路径
# 修改存活探针路径
livenessProbe:
httpGet:
path: /healthz #这是随便编的路径哈,原文件内没有这个
# ......剩下的不改
# 修改就绪探针路径
readinessProbe:
httpGet:
path: /readyz #这是随便编的路径哈,原文件内没有这个
# ......剩下的不改
查看最新日志:
kubectl discribe po <你的Pod创建的名称>
输出类似这种信息提示你绪探针(Readiness Probe)和存活探针(Liveness Probe)因返回 HTTP 404 状态码而失败
Warning Unhealthy 10s (x3 over 29s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
Warning Unhealthy 10s (x2 over 20s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 404
解决方案:修改探针路径为 Nginx 默认支持的路径(Nginx 默认只响应根路径 / 的请求)
二、生命周期
1、生命周期主要过程
-
Pod创建
-
运行初始化容器(init container)
-
运行主容器(main container)
-
容器启动后钩子(post start)、容器终止前钩子(pre stop)
-
探针存活探测、就绪探测
-
-
Pod终止(默认宽限期30s)
Pod在整个生命周期的五种状态:
| 状态 | 含义 |
|---|---|
| Pending(挂起) | Pod 已创建,但尚未被调度到节点,或镜像正在拉取。 |
| Running(运行中) | 至少有一个容器已启动;Pod 已绑定节点。 |
| Succeeded(成功) | 所有主容器正常退出(exit 0),不再重启。常用于 Job/CronJob。 |
| Failed(失败) | 至少一个主容器异常退出或启动失败,且不再重启。 |
| Unknown(未知) | 无法与节点通信,状态未知(通常节点失联、网络通信失败)。 |
2、主要使用
主要演示运行初始化容器和运行主容器
①、运行初始化容器
和容器平级,内容也差不多
②、运行主容器
钩子的使用和探针探测方式都是同样的三种:
-
exec —— 在容器里执行一条命令,返回码为 0 视为成功。
-
-
跑脚本
-
-
httpGet —— 对容器指定端口和路径发 HTTP GET,返回 [200,400) 视为成功。
-
-
调用接口
-
-
tcpSocket —— 尝试连接容器指定端口,能连上就成功。
-
-
连接端口
-
区别:钩子的使用是在lifecycle中使用,探针的使用是在探针内使用,举例和对比如下:
# 容器启动后钩子和容器停止前钩子的exec方法
#......
lifecycle:
postStart:
exec:
command:
<你要执行的命令>
preStop:
exec:
command:
<你要执行的命令>
#......
# 探针的exec方法
#......
livenessProbe: # 或startupProbe: 或readinessProbe:
exec:
command:
<你要执行的命令>
#......
# 容器启动后钩子和容器停止前钩子的TCP方法(tcpSocket)
#......
lifecycle:
postStart:
tcpSocket:
port: 80
preStop:
tcpSocket:
port: 80
#......
# 探针的TCP方法(tcpSocket)
#......
livenessProbe: # 或startupProbe: 或readinessProbe:
tcpSocket:
port: 80
#......
# 容器启动后钩子和容器停止前钩子的http方法(httpGet)
#......
lifecycle:
postStart:
httpGet:
path: /healthz
port: 8080
preStop:
httpGet:
path: /healthz
port: 8080
#......
# 探针的http方法(httpGet)
#......
livenessProbe: # 或startupProbe: 或readinessProbe:
httpGet:
path: /healthz
port: 8080
#......
3、重启策略
| 策略 | 含义 | 适用场景 |
|---|---|---|
| Always(默认) | 只要容器退出就自动重启,无限拉。 | 长期运行的服务(Deployment、StatefulSet、DaemonSet)。 |
| OnFailure | 仅当容器退出码 非 0 时重启。 | 一次性任务(Job、CronJob)。 |
| Never | 无论退出码如何都不重启。 | 批处理或调试(一次性 Job、调试 Pod)。 |
在spec期望中用字段 restartPolicy 声明即可
751

被折叠的 条评论
为什么被折叠?



