Kubernetes 设计模式笔记 —— Init Contai

2023-09-08  本文已影响0人  rollingstarky

Init Container 为初始化相关的任务提供了区别于主应用程序的独立的生命周期,从而实现关注点分离。

初始化在很多编程语言中都备受关注。比如在 Java 中,为了初始化某个需要配置的对象,我们使用 constructor。
Constructor 会保证在对象中是第一个运行的,且只被 runtime 运行一次。此外,还可以使用构造函数验证强制参数之类的先决条件,传入参数或默认值以初始化实例字段。

Init Container 与构造函数是类似的,只不过是在 Pod 级别而不是类级别。
假如 Pod 中有一个或多个容器代表主应用程序,这些容器可能需要一些启动前的先决条件。比如为文件系统设置特殊的权限,设置数据库 schema,应用程序种子数据的安装等。同时,这些初始化逻辑可能需要主容器镜像中不包含的工具和库。
又或者,用户想要延迟应用的启动,直到可以确认某个外部的依赖满足条件。
所有上述需求都可以通过 Kubernetes 提供的 Init Container 实现。

Kubernetes 中的 Init Container 属于 Pod 定义的一部分,可以将容器划分成两组:init containers 和 application containers。
所有的 init container 会以串行的顺序一个接一个地执行,在应用容器开始启动之前,所有 init container 的执行必须成功完成。
而应用容器是可以并行运行的,启动顺序也是任意的。


Init and application containers

通常情况下,init container 应该是小型快速且能成功完成的,除非它是用来延迟 Pod 的启动以等待某个依赖符合要求。
当 init container 失败时,整个 Pod 会重新启动(除非配置了 RestartNever),导致所有 init container 重新执行一遍。因而令它们符合幂等原则可以避免副作用。
一方面,init container 有着和应用容器一样的能力:位于同一个 Pod 中,共享资源限制、存储卷和安全设置。另一方面,它们的健康检查和资源处理在语义上有些许不同。它们不存在 rediness check,因为只有当所有的 init container 成功结束之后应用容器才会继续启动。

在容器调度、自动伸缩、配额管理方面,Init container 会影响 Pod 请求和计算资源的方式。由于所有的 init container 会先串行执行到终止,接着应用容器并行运行。因而高效的 Pod 级别的资源分配取决于以下两组值中较大的那个:

上述行为的限制在于,当 init container 的资源需求非常高而应用容器相对很低时,这种配置对于资源的利用就很低效。因为 init container 一般只运行很短的一段时间,其他 Pod 无法使用 init container 运行结束后空闲下来的资源。

Init container 能够实现关注点分离,从而使容器保持 single-purposed。应用容器可以由只关注应用逻辑的开发工程师创建,而部署工程师可以为其添加 init container 并只关注配置和初始化任务。比如下面的例子。

apiVersion: v1
kind: Pod
metadata:
  name: www
  labels:
    app: www
spec:
  initContainers:
  - name: download
    image: axeclbr/git
    command:
    - git
    - clone
    - https://github.com/mdn/beginner-html-site-scripted
    - /var/lib/data
    volumeMounts:
    - mountPath: /var/lib/data
      name: source
  containers:
  - name: run
    image: docker.io/centos/httpd
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /var/www/html
      name: source
  volumes:
  - emptyDir: {}
    name: source

Init container 克隆外部 Git repo 到挂载的路径,该路径通过 emptyDir 挂载卷实现 init 容器和应用容器间的数据共享。

总结

Init container 将 Pod 中的容器分成两组,拥有不同的生命周期、目的甚至作者。
Init 容器分阶段地执行,且只有当前容器成功完成后才继续进行下一阶段,意味着我们可以确保应用初始化的每一个阶段都是有保障的。
应用容器则可以并行运行,没有提供 init 容器那样的保证。我们可以根据目的在 Pod 中合理地组织关注初始化的 init 容器和关注应用本身的应用容器。

参考资料

Kubernetes Patterns

上一篇 下一篇

猜你喜欢

热点阅读