一、init 初始化容器 ------ "开工前的准备工作"
1. 它是干啥的?
就像咱们做饭前要先洗菜、切菜一样,init 容器是在主容器(真正的应用)启动之前,先跑起来干一些准备工作的容器。可以有一个或多个,按顺序一个一个执行,全部干完了,主容器才会启动。
2. 和普通容器有啥不同?
-
必须成功完成:每个 init 容器都得正常退出(成功),下一个才能开始。如果中途失败了,K8S 就会反复重启这个 Pod,直到它成功(除非你设置了不重启)。
-
独立于主容器之外:它不属于主容器的生命周期,更像是一个前置阶段。
-
共享数据卷和网络:init 容器里产生的文件、配置,主容器都能用。
3. 有啥好处?
-
可以在 init 容器里放一些工具(比如测试网络、处理配置文件),不用把这些工具塞进主容器里,主容器可以更精简、更安全。
-
能用不同的镜像,比如专门用来执行安装脚本。
-
可以阻塞主容器启动,直到某些条件满足(比如数据库准备好了)。
4. 实际用来干嘛?
-
等待别人就绪:比如你的 Web 应用依赖数据库,可以在 init 容器里不断检查数据库能不能连上,连上了才启动 Web 应用,避免启动后连不上报错。
-
做初始化配置:比如提前把集群的成员信息写好,主容器起来直接用。
-
注册到配置中心:比如把 Pod 的信息注册到 Nacos 等。
5. 举个栗子(简化版)
yaml
spec:
containers: # 主容器
- name: myapp
image: busybox
command: ['sh', '-c', 'echo 应用跑起来了 && sleep 3600']
initContainers: # 初始化容器,按顺序执行
- name: check-db
image: busybox
command: ['sh', '-c', '直到能解析到 mysql 服务才退出']
- name: check-cache
image: busybox
command: ['sh', '-c', '直到能解析到 redis 服务才退出']
一开始 Pod 状态是 Init:0/2,等两个 init 容器都成功了,主容器才变成 Running。
二、临时容器(Ephemeral Containers)------"救急的调试工具"
1. 它是干啥的?
临时容器就像一个一次性的、随用随开的小窗口 ,专门用来进到 Pod 里排查问题。尤其是当你的主容器因为崩溃、或者镜像里没有 bash、curl 等调试工具时,用 kubectl exec 进不去,这时候临时容器就派上用场了。
2. 它有什么特别?
-
不会自动重启:它只是个"临时工",任务完成就没了,不会像普通容器那样挂了还被拉起来。
-
功能受限:没有端口、没有健康检查、不能单独分配资源(和 Pod 里的其他容器共用)。
-
创建后不能修改或删除:要么留着,要么整个 Pod 重建。
-
通过特殊 API 创建 :不能用
kubectl edit直接加,一般用kubectl debug命令来生成。
3. 典型使用场景
-
你的主容器用的是极简镜像(distroless) ,里面连
sh都没有,崩溃了根本没法进去看。 -
这时候执行
kubectl debug -it my-pod --image=busybox --target=my-container,就能启动一个临时容器(比如 busybox),并"附身"到主容器的命名空间上,让你执行ps、netstat等命令来排查问题。
4. 举个栗子
bash
# 先跑一个普通的 nginx Pod
kubectl run nginx-test --image=nginx
# 然后添加一个临时容器,用 busybox 镜像,并“进入”它的终端
kubectl debug -it nginx-test --image=busybox --target=nginx
# 现在你就在临时容器里了,可以执行 ps、curl 等操作
/ # ps -ef | grep nginx
用 kubectl describe pod nginx-test 能看到 Ephemeral Containers 字段里多了这个临时容器。
大白话总结
| 类型 | 一句话概括 | 执行时机 | 失败处理 | 主要用途 |
|---|---|---|---|---|
| init 容器 | 主容器启动前的"准备工作",必须全部成功 | 主容器之前,按顺序 | 反复重启直到成功 | 检查依赖、初始化配置、注册服务 |
| 临时容器 | 故障排查时的"急救工具",随用随开 | Pod 运行中,手动创建 | 不会重启,用完拉倒 | 进入崩溃或精简镜像的容器里调试 |
希望这样一说,你就清楚这两种"特殊容器"到底是干嘛的了~
一、把 Pod 安排到指定节点
1. 直接点名(nodeName)
就像你打车直接告诉司机"去某某小区",Pod 也能指定要跑到哪台机器上干活。
- 例子:配置里写
nodeName: k8s-node1,这 Pod 就只去 node1。
2. 贴标签筛选(nodeSelector)
先给机器贴上标签(比如 node=worker01),然后在 Pod 里声明"我要找带有 node=worker01 标签的机器"。
- 相当于:我要一台"运维专用"的机器,你帮我挑一台符合条件的。
二、Pod 之间的亲疏关系
亲和性(喜欢腻在一起)
让两个 Pod 尽量待在同一台机器或同一个机柜上,方便它们快速通信。
- 比如 Nginx 和 Tomcat 放在一起,减少网络延迟。
反亲和性(不喜欢挨着)
让两个 Pod 尽量分开,避免互相影响,或者提高容灾能力。
- 比如同一个应用的两个副本,最好在不同机器上,一台坏了另一台还能顶住。
硬性要求 vs 软性建议
-
requiredDuringScheduling...:必须满足,不满足就不安排(硬性)。 -
preferredDuringScheduling...:尽量满足,实在不行也可以将就(软性)。
关键概念:topologyKey(位置依据)
-
kubernetes.io/hostname:按机器名判断是否"同一个位置"(同一台机器)。 -
topology.kubernetes.io/zone:按可用区判断(同一个机房区域)。 -
想分散 Pod 就按 hostname 做反亲和,想集中在同一区域就按 zone 做亲和。
三、资源限制(文档只提了个标题)
就是给 Pod 设置能用多少 CPU、内存,避免一个 Pod 把机器资源吃光。
(原文档无详细内容,这里点一下即可)
四、污点和容忍(节点"嫌弃"Pod 与 Pod"忍气吞声")
污点(Taints):节点给自己贴个"嫌弃脸",不让普通 Pod 进来。
-
三种嫌弃程度:
-
NoSchedule:新 Pod 不准来。 -
PreferNoSchedule:最好不要来,但实在没地方了也能来。 -
NoExecute:新 Pod 不准来,已经在上面跑的不容忍就立刻撵走。
-
-
例子:Master 节点默认有个污点,所以普通 Pod 不会跑上去。
容忍(Tolerations):Pod 说"我不怕你的嫌弃,让我进去吧"。
-
在 Pod 里配置容忍,匹配节点的污点,才能被调度到有污点的节点上。
-
还可以给
NoExecute污点设置一个"忍耐时间"(如 60 秒),时间到了才被撵走。
配合使用:
-
如果一个节点有污点,但 Pod 容忍了它,然而另一个节点没有污点,Pod 还是会优先选没污点的节点。
-
想让 Pod 必须去那个有污点的节点?那就再配上节点亲和性,强迫它过去。
小提醒:
-
operator: Exists表示只看 key 是否存在,不管 value 是什么;Equal则需要 key 和 value 完全一样。 -
生产环境不要用"容忍所有污点"(空 key + Exists),太危险。
一句话总结:
-
想指定 Pod 去哪台机器 → 用
nodeName或nodeSelector。 -
想控制 Pod 之间的"抱团"或"分散" → 用亲和/反亲和。
-
想不让 Pod 来某台机器 → 给节点打污点。
-
想让 Pod 硬闯有污点的机器 → 给 Pod 加容忍。