控制 Pod 内容器的启动顺序

背景

众所周知, Kubernetes Pod 内有两种容器: 初始化容器(init container)和应用容器(app container). 其中初始化容器的执行先于应用容器, 并且初始化容器和应用容器的个数分别为 0~n1~n.

初始化容器会按照顺序执行, 顺序执行的前提是初始化容器始终会运行到完成(completed)状态. 而应用容器恰好相反: 启动顺序随机, 并始终保持运行(running)状态.

问题

工作中有个架构的方案使用到了 sidecar 容器: 将基础组件功能从容器转移到 sidecar 容器中, 其中有个功能是从远程配置中心获取配置并保持实时更新. 保证实时更新没有问题, 但是配置文件需要在 app 启动之前完成初始化.

对于同为"应用容器"类型的 sidecar 容器来说, 由于容器启动顺序随机而无法做到这一点.

当时我们给定的方案是增加一个初始化容器进行配置的初始化, 不可避免的我们需要增加一个额外的容器, 即使是这个容器的生命周期非常短.

追求极致的我们总是对这个额外增加的容器耿耿于怀: 假如能控制应用容器的启动顺序…

新发现

近期在研究 CDF (Continuous Delivery Foundation)下的 Tekton, 其中有个概念是其将流水线(pipeline)中的各个步骤(step)作为应用容器在同一个 Pod 中运行.

我们都知道流水线中的步骤是按照定义的顺序执行的, 那么 Tekton 是如何保证应用容器的执行顺序的?

查看 pod 的 manifest 之后发现了下面的容器配置 (这个容器的作用从 git 仓库克隆代码)

spec:
  containers:
  - args:
    - -wait_file
    - /tekton/downward/ready
    - -wait_file_content
    - -post_file
    - /tekton/tools/0
    - -termination_path
    - /tekton/termination
    - -entrypoint
    - /ko-app/git-init
    - --
    - -url
    - http://gitlab.nip.io:8088/addozhang/tekton-test
    - -revision
    - develop
    - -path
    - /workspace/git-source
    command:
    - /tekton/tools/entrypoint

克隆代码的命令是:

git-init -url http://gitlab.nip.io:8088/addozhang/tekton-test -revision develop -path /workspace/git-source

但是容器的启动命令是/tekton/tools/entrypoint并带上了一坨的参数(此处略过, 后面分析).

翻看了下文档:

This binary is used to override the entrypoint of a container by wrapping it. In tektoncd/pipeline this is used to make sure Task’s steps are executed in order, or for sidecars.

这个二进制文件被用于通过包装的方式来覆盖容器的入口点. 在 tektoncd/pipeline 中确保任务中的步骤或者 sidecar 被顺序地执行.

  • -entrypoint: 原始的容器启动命令, 作为 entrypoint 的子进程运行. 即上面的 git-init XXXX
  • -post_file: 子进程运行结束后写的文件路径(即上面的/tekton/tools/0). 如果子进程执行失败, 则写一个{{post_file}}.err文件, 而不是{{post_file}}
  • -wait_file: 启动子进程监控的文件路径(即上面的/tekton/downward/ready). 通过监控到的{{watch_file}}或者{{watch_file}}.err文件来决定执行子进程, 还是跳过执行然后写入{{post_file}}.err文件并返回错误码(exitCode >= 0)
  • -wait_file_content: 等待wait_file有实际内容写入, 持续监控wait_file直到有内容写入.

回头看上面容器配置:

  1. 容器的entrypoint启动进程
  2. 监控到/tekton/downward/ready文件的创建, 并等待文件内容的写入
  3. 执行git-init子进程, 从 git 仓库克隆源码
  4. 创建/tekton/tools/0文件

实际应用

这个方案是否能解决我们的问题, 还是有一定的局限性的.

首先需要应用容器的启动命令进行重新的编排, 这个存在一定的挑战. 需要统一应用的启动命令才能做到规模化+自动化.

其次引入可用于监控的文件, 需要额外增加Volume用于跨容器的文件访问. 当然通过增加emptyDirVolume即可.

同时 sidecar 容器需要在完成启动后创建post_file, 应用容器可以使用这个entrypoint进行包装.

如果要突破这个局限, CRD 无非是个优秀的方案. 下一篇, 我们通过一个简单的 CRD 来实现.


文章同步发送到公众号:云编码 (微信号:sevenfeet)。

qrcode

comments powered by Disqus