本系列教程目录(已发布):

图解 K8S(01):基于ubuntu 部署最新版 k8s 集群
图解 K8S(02):认识 K8S 中的资源对象
图解 K8S(03):从 Pause 容器理解 Pod 的本质
图解 K8S(04):吃透 Pod 中的第三类容器 – init 容器

以下是本篇正文

从上一篇文章,我们已经知道了一个 Pod 至少会有两种容器, pause 容器和 应用容器。

注意我的表述是 至少,这其实已经在暗示 Pod 里还存在其他类型的容器,这就是我们本篇文章的主角 – init 容器

init 容器和 pause 容器有相同点,也有不同点

  • 相同点在于:它们都有固定用途,是专用的特殊容器

  • 不同点在于: init容器是用户级的容器,它是由用户来定义的,而 pause 容器是系统级容器,它不是由用户定义的。

init 容器会在应用(业务)容器启动之前运行,用来包含一些应用镜像中不存在的实用工具或安装脚本。

1. init 容器的运行机制

init 容器,从名字上来看,也能看出是的用途就是运行一些初始化任务,来保证应用容器运行环境。

这就决定了:

  • init 容器必须先于 应用容器启动
  • 仅当 init 容器完成后,才能运行应用容器
  • 一个 Pod 允许有多个 init 容器,做不同的初始化任务

当一个 Pod 有多个 init 容器时,这些 init 容器是顺序运行的,一个 init 容器完成之后,才会运行一个 init 容器。

因此如果你在 kubectl get po 时加一个 -w 参数,就能看到 Pod 状态的变化过程

在正常情况下(默认 Pod 的 restartPolicy 为 Never),只要有一个 init 容器运行失败,整个 Pod 便会不停地重启,直到 init 容器全部运行完成为止。

而只要一个 Pod 重启,不管init 容器之前有没有执行过,所有的 init 容器都要重新执行一遍。

2. init 容器与应用容器

init 容器与应用容器,除个别配置之外,基本一致,不用付出太多额外的学习成本。

不一样的地方有哪些呢?

第一点不同

定义位置不同。

应用容器定义在 Pod.Spec.Containers,是必填字段,而 init 是定义在 Pod.Spec.initContainers 中,是可选字段。

第二点不同

部分配置不同。

init 容器没有 Lifecycle actions, Readiness probes, Liveness probes 和 Startup probes,而这些应用容器都有。

另外,虽然 init 容器与应用容器是两个类别的容器,但由于属于同一个 Pod ,因此容器的名字,是不能重复的。

3. init 容器的资源问题

当一个 Pod 只有应用容器时,那么在 kube-scheduler 调度该 Pod 时,会将所有的应用容器的 requests/limits 资源进行相加,得到一个requests/limits 的总量。

然后拿这个总量,去跟 node 上的可用资源进行比较,若 node 上的资源充足,则允许调度过去,反之则不允许。

而现在有了 init 容器后,情况会稍微复杂一点。

我以 requests.cpu 为例,来实践一下 kube-scheduler 到底是如何请求的资源问题的。

而 limits 以及其他资源类型(如 memory)都是一样的道理。

下面是一个包含一个应用容器和两个 init 容器的 Pod 的配置文件。

# init-pod.yml
apiVersion: v1
kind: Pod
metadata:name: test-init-podlabels:app: init
spec:containers:- name: myappimage: busyboxresources:requests:cpu: 100mcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']initContainers:- name: init-01image: busyboxcommand: ['sh', '-c', 'sleep 10']resources:requests:cpu: 20m- name: init-02image: busyboxcommand: ['sh', '-c', 'sleep 10']resources:requests:cpu: 30m

我们只是想实践看看这些 resources 的资源是如何计算的,因此容器里的 command 内容可以不用关注,怎么简单怎么来,全都是 sleep 。

使用 kubectl apply -f init-pod.yml 创建该 pod 之后,再使用 kubectl get po -o wide 查看一下创建到哪一台 node 上。

假设创建到 worker01 上,使用 kubectl describe node worker01 就可以看到该 node 上的所有 pod 的详情,包括资源占用情况。

可以看到 requests.cpu 总量计算为 100m,这刚好是应用容器的 requests.cpu

在此你可能会认为,调度参考的资源总量只考虑了应用容器。

实际上,并不是这样,可以尝试把上面的配置文件里,应用容器 cpu 数据下调为 10m,小于其他任意容器的值。

# init-pod.yml
apiVersion: v1
kind: Pod
metadata:name: test-init-podlabels:app: init
spec:containers:- name: myappimage: busyboxresources:requests:cpu: 10mcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']initContainers:- name: init-01image: busyboxcommand: ['sh', '-c', 'sleep 10']resources:requests:cpu: 20m- name: init-02image: busyboxcommand: ['sh', '-c', 'sleep 10']resources:requests:cpu: 30m

再次使用 describe 查看 node,发现该 pod 的 requests.cpu 只剩下 30m,这不刚好是 init-02 请求的资源值吗?

善于总结规律的你,应该已经想到了 kube-scheduler 的套路,我这里再补充总结一下:

1. 当只有应用容器时

由于应用容器是同时运行的,因此为了保证应用容器的正常运行,请求的资源总量应当是所有应用容器的各自请求的资源之和。

2. 当有 init 容器时

由于 init 容器会先于应用容器运行,只有当 init 运行成功并且退出后,应用容器才会运行,因此为了保证所有的容器(不仅包括应用容器,还包括 init 容器)的运行,pod 的资源总量的计算公式如下

max(应用容器请求资源之和,max(所有的 init 容器请求资源))

4. init 容器的应用场景

上面我们以简单的例子来理解 init 容器的运行机器和资源计算,每个容器都运行简单的 sleep 命令,并没有代入实际的业务场景,也许会让你以为 init 容器和普通的应用容器没什么区别。

实际上并不是那样子的,那 init 容器到底有什么用呢?它的应用场景又有哪些呢?

举一个最简单的例子,假设我们有一个 Web 服务,该服务又依赖于另外一个数据库服务。

但是在在启动这个 Web 服务的时候,我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内 Web 服务连接数据库异常。

要解决这个问题的话我们就可以在 Web 服务的 Pod 中使用一个InitContainer,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们的主容器 Web 服务被启动起来,这个时候去连接数据库就不会有问题了。

但其实不用 initContainer 的话,这部分依赖的检查实际也可以移入应用容器的程序中,确实是如此。

那为什么 K8S 还要提供一个 initContainer 的入口呢?

这就好像,你使用计算器计算 5 个 88 相加的结果是使用 88+88+88+88+88,还是使用 88*5 是一个道理。

计算器提供这个功能,至于你用不用?怎么用?都取决于用户自己。

但从 K8S 这个平台来考虑,提供了这个接口,就可以把一个大而重的程序分割成多个小的细分模块,不仅有利于编码和维护,还能让应用程序的之间的依赖关系更加清晰。

图解 K8S(04):吃透 Pod 中的第三类容器 -- init 容器相关推荐

  1. 图解 K8S(06):调度利器之污点与容忍度(压力驱逐)

    本系列教程目录(已发布): 图解 K8S(01):基于ubuntu 部署最新版 k8s 集群 图解 K8S(02):认识 K8S 中的资源对象 图解 K8S(03):从 Pause 容器理解 Pod ...

  2. 图解 K8S(07):调度利器之亲和与反亲和(服务容灾)

    本系列教程目录(已发布): 图解 K8S(01):基于ubuntu 部署最新版 k8s 集群 图解 K8S(02):认识 K8S 中的资源对象 图解 K8S(03):从 Pause 容器理解 Pod ...

  3. 图解 K8S(05):调度利器之标签与选择器(分组调度)

    本系列教程目录(已发布): 图解 K8S(01):基于ubuntu 部署最新版 k8s 集群 图解 K8S(02):认识 K8S 中的资源对象 图解 K8S(03):从 Pause 容器理解 Pod ...

  4. K8S!之Pod概念与网络通讯方式详解!

    文章目录 前言 一:pod概念 1.1 pod的种类 1.11特点: 1.2 pod网络 1.3 pod存储 1.4 使用pod 1.5 pod控制器类型 1.6 服务发现 二:网络通讯方式 2.1: ...

  5. 图解k8s中pod的创建流程

    什么是pod Pod 是 k8s 系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支撑或者扩展 P ...

  6. K8S configmap详解:从文件创建、从文件夹创建及以volume、env环境变量的方式在pod中使用

    K8S configmap详解:从文件创建.从文件夹创建及以volume.env环境变量的方式在pod中使用 ConfigMap是用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在 ...

  7. k8s 从pod中下载文件到本地

    获取pod或者deployments信息 获取pod信息 kubectl get pod -n 命名空间 我的k8s是封装过的,取名为tess,我的命名空间是xxxx-qa-ns tess kubec ...

  8. K8S在一个Pod中创建多个容器

    参考书籍:<Kubernetes权威指南第4版从Docker到Kubernetes实践全接触> YAML文件内容(把tomcat和mysql放到同一个Pod中) apiVersion: v ...

  9. k8s查看容器日志---查看运行中指定pod以及指定pod中容器的日志

    1.查看指定pod的日志 kubectl logs <pod_name> kubectl logs -f <pod_name> #类似tail -f的方式查看(tail -f ...

最新文章

  1. android launcher
  2. Android--GridView实现动态文字排版
  3. 基于协同过滤算法的在线鲜花店推荐系统详解及GitHub下载
  4. 简单的Gradle Java插件自定义
  5. beautifulsoup网页爬虫解析_Python爬虫神器:PyQuery,解析网页更简单,小白也能学会
  6. [LAMP]——mod_security和mod_evasive模块的安装
  7. sql取上个月年月_sql 查询本年、本月、本日记录的语句,附SQL日期函数
  8. 手机归属地查询接口,手机号查3大运营商的归属地信息接口
  9. html语言隔开的代码,2、HTML(示例代码)
  10. iOS 人脸识别功能
  11. android设计个人简历页面_Android程序员个人简历模板下载(Word格式)
  12. [MATLAB]--曲线拟合(polyfit/polyval)
  13. 初探一个0代码开发—iVX平台
  14. oracle查看登录失败次数,Oracle取消用户连续登录失败次数限制
  15. 解决qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in ““ even though it was found.问题
  16. spark使用之ALS版本对比
  17. chrony配置外部时钟源后stratum=16
  18. 设置计算机电源线,小技巧get 主机内凌乱线材如何轻松搞定
  19. 6年拉力工作经验,学了阿里P8级架构师的7+1+1落地项目,跳槽阿里年薪直接40W+
  20. 知识图谱学习思维导图

热门文章

  1. list-style无效
  2. Charles安装后无法抓取https请求,显示 unknow
  3. Ubuntu安装deb及依赖
  4. #557. 蒟蒻KC的垃圾数列
  5. 51Nod 欢乐手速场1 A Pinball[DP 线段树]
  6. 什么是数字签名?什么是数字证书?密码学知识?
  7. 微服务治理-含服务线上稳定性保障建设治理
  8. springboot操作以太坊(eth),使用web3j,转账等
  9. 深圳IT白领猝死家中 前员工称连续加班5通宵
  10. 不知道新的行业资讯?要想技术不落伍程序员必看!