k8s
前置工作: docker配置中“渡渡鸟”的国内镜像同步站配置镜像加速器
[root@k8s-master01 ~]# cat /etc/docker/daemon.json
{
"data-root": "/data/docker",
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "100"
},
"insecure-registries": ["harbor.fangpch.com"],
"registry-mirrors": [
"https://docker.aityp.com",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}
pod:
主进程(PID 1)不是指 Pod 里的某一个特定容器,而是指 Pod 中【每一个容器】内部自己的主进程。
为了让你彻底理清这个概念,我们从以下三个维度来拆解:
1. 什么是“主进程(PID 1)”?
在 Linux 系统(容器底层就是 Linux)中,当一个容器被启动时,它会运行你在 YAML 中配置的
command(或者 Dockerfile 中的 ENTRYPOINT)。- 这个启动命令在容器内部产生的第一个进程,就是主进程(PID 1)。
- 核心铁律:只要这个 PID 1 还在运行,容器就处于
Running状态;一旦这个 PID 1 退出了,K8s 就认为这个容器“死”了。
2. 多容器 Pod 中,restartPolicy 是如何工作的?
假设你的 Pod 里有 3 个容器(A、B、C)。
restartPolicy: Always 是作用在 Pod 级别的,但 Kubelet 在执行时,是分别盯着每一个容器的:- 如果容器 A 的 PID 1 崩溃退出了:Kubelet 发现 A 死了,就会只重启容器 A。容器 B 和 C 完全不受影响,继续正常运行。
- 如果容器 B 的 PID 1 也崩溃了:Kubelet 就会去重启容器 B。
- 如果 A、B、C 全都崩溃退出了:Kubelet 会把它们挨个重启。
所以,
restartPolicy 就像是 Kubelet 给每个容器派发的“独立监工”,谁挂了,Kubelet 就重启谁。进程突然挂掉(退出),是由
restartPolicy 触发重启的;而存活探针(Liveness Probe)和就绪探针(Readiness Probe)都不会因为进程挂掉而触发重启。为了让你彻底搞懂如何判断,我们需要理清它们三者的“管辖范围”和“判断方法”:
1. 到底是谁让它重启的?(职责划分)
restartPolicy(重启策略):负责“进程级”的兜底。
只要容器的主进程(PID 1)退出了(无论是正常退出还是崩溃退出),Kubelet 就会立刻介入,根据restartPolicy(如Always)来重启容器。- 存活探针(Liveness Probe):负责“应用级”的自救。
它只在进程还在运行,但应用卡死(假死/死锁)时发挥作用。如果存活探针失败,Kubelet 会主动杀死这个容器,然后触发restartPolicy进行重启。 - 就绪探针(Readiness Probe):绝对不负责重启。
就绪探针失败,只会把 Pod 从 Service 的 Endpoints 中剔除(切断流量),容器依然活着,绝对不会重启。
2. 我怎么判断到底是哪个触发的?(实战排查)
当 Pod 发生重启时,你可以通过以下两个命令来像“侦探”一样找出真凶:
第一步:看重启次数和当前状态
bash
1kubectl get pod <pod-name>
看
RESTARTS 列是否增加了。如果增加了,说明发生了重启。第二步:看 Pod 的详细事件(核心证据)
bash
1kubectl describe pod <pod-name>
重点看输出结果最下方的 Events(事件) 和 Containers(容器状态) 部分:
场景 A:进程自己挂掉的(restartPolicy 触发)
如果你看到类似这样的信息,说明是进程自己崩溃了,Kubelet 只是按规矩把它拉起来:
如果你看到类似这样的信息,说明是进程自己崩溃了,Kubelet 只是按规矩把它拉起来:
text
1Containers:
2 myapp:
3 State: Waiting
4 Reason: CrashLoopBackOff
5 Last State: Terminated
6 Reason: Error
7 Exit Code: 137 (或 1, 139 等)
注:
Exit Code 非 0 表示异常退出,Kubelet 根据 Always 策略自动重启。Events 中通常没有 Unhealthy 警告。场景 B:存活探针失败导致的重启(Liveness Probe 触发)
如果你看到类似这样的信息,说明应用假死了,被探针“处决”了:
如果你看到类似这样的信息,说明应用假死了,被探针“处决”了:
text
1Events:
2 Type Reason Age From Message
3 ---- ------ ---- ---- -------
4 Warning Unhealthy 2m kubelet, node-01 Liveness probe failed: HTTP probe failed with statuscode: 500
5 Normal Killing 2m kubelet, node-01 Container myapp failed liveness probe, will be restarted
注:明确出现了
Liveness probe failed 和 will be restarted,这是存活探针杀人的铁证。场景 C:就绪探针失败(Readiness Probe 触发)
如果你看到类似这样的信息,说明应用没准备好,被切断了流量,但没有重启:
如果你看到类似这样的信息,说明应用没准备好,被切断了流量,但没有重启:
text
1Events:
2 Type Reason Age From Message
3 ---- ------ ---- ---- -------
4 Warning Unhealthy 2m kubelet, node-01 Readiness probe failed: HTTP probe failed with statuscode: 503
注:只有
Readiness probe failed,没有 will be restarted,且 RESTARTS 次数不会增加。总结
- 进程没了 -> 找
restartPolicy。 - 进程还在但卡死 -> 找
Liveness Probe。 - 进程还在但还没准备好接客 -> 找
Readiness Probe。
通过
kubectl describe pod 看 Events 里的 Reason 和 Message,你就能百分之百确定是谁在背后操纵了容器的生死!K8s 控制平面(API Server)只负责下发“期望状态”,而真正干活的是运行在每个节点上的 Kubelet。
- 自动接管:Kubelet 会持续监听并对比 Pod 的期望状态和实际状态。如果某个容器崩溃了,Kubelet 会自动调用容器运行时(如 containerd)把它重启起来,根本不需要人工干预。
- 同生共死:当用户执行
kubectl delete pod时,Kubelet 会接管这个删除指令,向 Pod 内的所有容器发送终止信号(SIGTERM),并在优雅期过后强制清理它们,最后释放网络和存储资源。
一句话总结你的感悟:
在 K8s 的世界里,不要试图去“微操”单个容器。把 Pod 当作一个不可分割的“命运共同体”,把容器的生老病死交给 Kubelet 去自动兜底,这才是云原生时代正确的运维姿势!
在 K8s 的世界里,不要试图去“微操”单个容器。把 Pod 当作一个不可分割的“命运共同体”,把容器的生老病死交给 Kubelet 去自动兜底,这才是云原生时代正确的运维姿势!
labels加载容器上还是pod上
在 Kubernetes 中,标签(Labels)是加载在 Pod 级别(以及 Node、Service 等其他 K8s 对象上),而不是加载在单个容器(Container)上的。
为什么标签加在 Pod 上?
这与我们之前讨论过的 K8s 核心设计哲学完全一致:
- Pod 是最小逻辑单元:标签的作用是对资源进行分类、分组和关联(例如让 Service 通过选择器找到对应的 Pod,或者让 Node 亲和性规则决定 Pod 调度到哪台机器)。
- 容器只是执行单元:Pod 内的所有容器共享同一个网络 IP 和存储卷。K8s 把 Pod 作为一个整体来管理,因此用来标识和选择资源的标签自然也是打在 Pod 这个“逻辑外壳”上的。
如何在 YAML 中配置?
在编写 YAML 清单时,标签(
labels)是写在 Pod 的 metadata 字段下的,而不是写在 spec.containers 里面:yaml
1apiVersion: v1
2kind: Pod
3metadata:
4 name: my-pod
5 labels: # <--- 标签写在这里,属于 Pod 级别
6 app: nginx
7 environment: prod
8spec:
9 containers: # <--- 容器配置里没有 labels 字段
10 - name: nginx
11 image: nginx:1.14.2
补充说明
虽然标签是打在 Pod 上的,但一个 Pod 可以包含多个容器。当你通过标签(如
app: nginx)选中了这个 Pod 时,实际上也就间接选中了它里面的所有容器。此外,除了 Pod,Kubernetes 中的其他资源对象(如 Node 节点、Service、Deployment 等)也都拥有自己的标签系统,它们各自独立,互不干扰。
7篇来源
钩子执行失败对业务容器有什么影响,这两个是并行启动的,会不会不相干
这是一个非常关键且容易让人产生误解的问题!
你的直觉很敏锐,它们确实是“并行启动”的(即容器主进程和
postStart 钩子同时被触发),但这绝对不意味着它们“不相干”。如果钩子执行失败,对业务容器有着极其致命的直接影响:业务容器会被直接杀死(终止),并根据重启策略决定是否重启。
为了让你彻底理清这个逻辑,我们需要从官方文档的定义和底层的执行机制来剖析:
1. 为什么“并行”还会互相影响?
Kubernetes 官方文档对
postStart 的描述是:“postStart 处理函数与容器的代码是异步执行的,但 Kubernetes 的容器管理逻辑会一直阻塞等待 postStart 处理函数执行完毕”。这句话听起来很矛盾,但它的真实含义是:
- 异步执行:容器的主进程(ENTRYPOINT)和
postStart钩子是被同时触发启动的。 - 管理逻辑阻塞:虽然主进程在跑,但 Kubelet(容器管理逻辑)在底层会一直盯着
postStart。如果postStart挂起或执行时间过长,Pod 会一直卡在ContainerCreating状态,无法进入Running状态。
2. 钩子失败的具体影响
无论是
postStart(启动后钩子)还是 preStop(停止前钩子),只要它们执行失败(比如脚本报错、HTTP 请求超时等),Kubernetes 的处理机制都非常简单粗暴:- 直接杀死容器:Kubelet 会立即终止该容器的主进程。
- 触发重启:如果 Pod 的
restartPolicy是Always(默认值),容器被杀死后会被重新拉起,这就可能导致容器陷入反复启动又失败的死循环(CrashLoopBackOff)。
3. 一个形象的比喻
你可以把
postStart 钩子看作是容器启动时的“入职安检”。- 容器的主进程就像是“新员工”,安检(钩子)和员工上班(主进程)是同时开始的。
- 但是,如果新员工在安检时被发现违规(钩子执行失败),虽然他已经坐在了工位上(主进程可能在跑),但公司保安(Kubelet)会立刻把他赶出公司(杀死容器),让他重新走入职流程(重启)。
总结与最佳实践
虽然它们是并行触发的,但
postStart 钩子拥有对容器生死的“一票否决权”。因此,在实际生产环境中,Kubernetes 官方强烈建议:
- 保持钩子轻量级:钩子处理程序应该尽可能轻量,避免执行耗时过长的操作。
- 重型初始化用 Init Container:如果你有需要长时间运行、且必须在主业务进程启动前完成的初始化任务,千万不要放在
postStart里,而应该使用Init Container(初始化容器)。Init 容器是串行执行的,只有它成功退出了,主容器才会被创建。
海纳百川 ,有容乃大

浙公网安备 33010602011771号