我有一个基于Node.JS的应用程序,由三个服务组成。一个是 Web 应用程序,两个是内部 API。Web 应用程序需要与 API 通信才能完成其工作,但我不想将其他服务的 IP 地址和端口硬编码到代码库中。
在我的本地环境中,我正在使用漂亮的envify
Node.JS 模块来解决此问题。基本上,我可以在编写代码时假装我有权访问环境变量,然后使用envify
CLI 工具将这些变量转换为最终浏览器化文件中的硬编码字符串。
我想将此解决方案容器化并将其部署到 Kubernetes。这就是我遇到问题的地方...
我已经在我的 Docker 镜像模板中定义了几个ARG
变量。这些通过RUN export FOO=${FOO}
转换为环境变量,运行npm run-script build
后,我有了我需要的容器。好的,所以我可以运行:
docker build . -t residentmario/my_foo_app:latest --build-arg FOO=localhost:9000 BAR=localhost:3000
然后用docker push
将其推送到注册表。
我对这种方法的疑虑是,我只成功地将硬编码变量撑入容器映像。我真正想要的是在 pod 初始化时定义路径。这可能吗?
编辑:这里有两个解决方案。
启动后
Kubernetes 带有一个名为PostStart
的生命周期钩子。这在"容器生命周期钩子"中有简要描述。
一旦容器达到ContainerCreated
状态,此钩子就会触发,例如,容器被拉出并完全初始化。然后,您可以使用挂钩跳转到容器并运行任意命令。
在我们的例子中,我可以创建一个PostStart
事件,该事件在触发时,使用正确的路径重建应用程序。
除非您创建了一个实际上不运行任何内容的 Docker 映像(这对我来说似乎是错误的,但让我知道这是否被认为是一种正常的做法),否则这确实需要一些重复的工作:停止应用程序、重新运行构建过程并重新启动应用程序。
命令
根据下面的评论,此事件不一定在正确的时间触发。这是另一种保证有效的方法(因此,优越)。
一个有用的 Docker 容器以为应用程序提供服务的CMD
上的一些变体结束。您可以在 Kubernetes 中覆盖此运行命令,如文档的"定义容器的命令和参数"部分所述。
因此,我在 pod 定义中添加了一个运行 shell 脚本的command
,该脚本 (1) 使用正确的路径重建应用程序,作为 pod 的环境变量提供,以及 (2) 开始为应用程序提供服务:
command: ["/bin/sh"]
args: ["./scripts/build.sh"]
像魅力一样工作。