在学习k8s是有关Pod很容易卡住的几个点:
-
为什么我的 Pod 一直卡在
Init状态不动了? -
什么是 Sidecar?它和普通容器有啥区别?
-
我删了一个 Pod,过一会它自己又冒出来了?删不掉?
一、Init 容器:为什么我的 Pod 一直卡 Init?
我经常碰到这种情况:创建了一个 Pod,查看状态的时候,它一直显示Init:0/2,半天不动,也不知道为啥?
这就是 Init 容器 ("前置容器" )在搞鬼
它是干嘛的
Init 容器,就是业务容器启动之前,先跑的 "初始化任务"。
举个最常见的例子:你的业务程序要连数据库,但是数据库启动比较慢,如果你直接启动业务容器,业务程序一启动就去连数据库,大概率会连不上,直接报错退出。
这时候你就可以加一个 Init 容器:让它先去等数据库启动,等数据库能连上了,Init 容器的任务就完成了,退出了,这时候 K8s 才会启动你的业务容器,完美解决依赖问题。
运行规则
Init 容器有几个很关键的特点:
-
按顺序跑,一个都不能少 Init 容器会按你写的顺序,一个接一个运行,必须所有的 Init 容器都成功跑完退出了,后面的业务容器才能启动。 比如你写了两个 Init 容器,第一个睡 20 秒,第二个睡 20 秒,那就要等 40 秒,两个都跑完,业务容器才会启动。
-
失败了就一直重试 如果 Init 容器运行失败了,K8s 会不断重启它,直到它成功为止 ------ 这就是为什么你的 Pod 会一直卡在 Init 状态不动,因为 Init 容器一直失败,一直在重试。
这时候你看到的状态Init:0/2,意思就是:2 个 Init 容器,0 个跑完了;如果是Init:1/2,就是第一个跑完了,第二个还在跑。
碰到卡 Init 怎么排查?
查看 Init 容器的日志就行:
kubectl logs 你的Pod名 -c Init容器的名字
看看到底是哪里出错了,是连不上数据库?还是初始化命令写错了,改了就好。
二、Sidecar 容器:不用改业务代码,就能给程序加功能?
那 Sidecar 容器是什么?它和 Init 有啥区别?
如果说 Init 容器是 "前置临时工",干完活就走;那 Sidecar 容器就是 "常驻辅助工",它和你的业务容器一起启动、一起运行,一辈子陪着业务容器,帮它干活。
它最神奇的地方:不用改业务代码
Sidecar 最牛的地方就是,你不用动业务程序的一行代码,就能给你的程序加一堆功能。
比如最常见的日志收集: 你的业务程序只需要把日志写到本地文件就行,剩下的事交给 Sidecar 容器 ------ 它会帮你把这些日志收集起来,转发到日志中心,业务程序根本不用管日志要存到哪、要发给谁。
再比如现在很火的服务网格 Istio: 它就是把一个代理容器作为 Sidecar,插到你的 Pod 里,拦截你业务容器的所有流量,帮你做流量治理、监控、安全控制,你的业务代码完全不用改,就能拥有这些能力。
它怎么和业务容器配合?
最常见的就是共享存储,比如: 我们搞了一个临时的共享目录,业务 web 容器把这个目录当成自己的网页根目录,Sidecar 容器把内容写到这个目录里,web 容器直接就能读到,对外提供访问,两个容器配合得天衣无缝。
这也是为什么 Sidecar 要和业务容器放同一个 Pod 里 ------ 它们要共享网络、共享存储,紧密配合,分开的话就没这么方便了。
三、静态 Pod:为什么我删了 Pod,它又自己回来了?
在我开始学 K8s时,有次碰到一个 Pod,我用kubectl delete pod删了,结果过了一会,用kubectl get pod一看,这个 Pod 又回来了!删了好几次,删了又冒出来,我还以为是 K8s 出 bug 了
其实这就是静态 Pod 在搞鬼。
普通 Pod 和静态 Pod,谁在管它们?
我们平时用的普通 Pod,是 K8s 的 API 服务器、控制器来管的,你用kubectl发命令给 API 服务器,让它删 Pod,它就删了。
但静态 Pod 不一样 ------ 它根本不归 API 服务器管,它是节点上的 kubelet(就是节点上的 K8s 代理)自己直接管的。
kubelet 会盯着一个指定的目录,只要你把 Pod 的配置文件放到这个目录里,它就自动帮你创建 Pod;你把文件删了,它就删 Pod;你改了文件,它就更新 Pod。
而且 kubelet 会给 API 服务器同步一个 "镜像 Pod",让你能通过kubectl看到这个 Pod 的状态,但是你不能通过kubectl来改它、删它 ------ 你删了,kubelet 发现配置文件还在,就又给你建回来了,这就是为什么你删了它又冒出来了
那怎么正确删静态 Pod?
很简单,你要去节点上,把那个目录里的配置文件删掉,kubelet 检测到文件没了,就会把 Pod 删掉了,这才是正确的删除方式。
那什么时候用静态 Pod?其实你现在用的 K8s 集群,核心组件比如kube-apiserver、etcd这些,都是静态 Pod------ 因为集群刚启动的时候,API 服务器还没工作,普通 Pod 根本创建不了,只能用静态 Pod,由 kubelet 直接把这些核心组件跑起来。
四、多容器 Pod:什么时候该把多个容器塞到一个 Pod 里?
我在学了多容器 Pod 之后,就啥都往一个 Pod 里塞:把数据库、业务程序、日志收集全放一个 Pod 里,这完全是用错了。
多容器 Pod,只适合紧密耦合、必须同机部署、需要共享资源的程序,比如:
-
业务程序 + 日志收集的 Sidecar
-
业务程序 + 服务网格的代理
-
两个需要共享文件、共享网络的配合程序
除此之外,独立的程序,都应该单独做 Pod,分开调度,不然你把不相关的程序塞到一个 Pod 里,它们的生命周期绑在一起,一个挂了全 Pod 重启,反而会出问题。
最后,总结
-
Pod 一直卡 Init? 别慌,查看 Init 容器的日志,看看初始化任务哪里出错了,改了就好。
-
进入容器改了内容,重启就没了? 因为你改的是容器的临时可写层,镜像本身没变,容器重建就会丢,要永久改的话,要么改镜像,要么用持久化存储。
-
Pod 删了又回来? 大概率是静态 Pod,别用 kubectl 删了,去节点上把配置文件删掉才行。
-
别啥容器都往一个 Pod 里塞! 只有紧密耦合的才放一起,独立的程序分开做 Pod。
。