天天看点

用 Sidecar 刷新应用配置

在 Kubernetes 的使用过程中,很多人会使用 Configmap 资源来进行配置文件的加载。Configmap 对象是支持热更新的,也就是说,对 Configmap 的变更,会同时反应到加载该 Configmap 的 Pod 之中。但美中不足的是,很多应用都不会检测配置文件的更新,因此就算是通过对 Configmap 的变更,完成了配置文件的修改,应用还是无法做出即时的响应的。可以在外部进行滚动更新;或者改写业务容器,监控文件变化之后重新启动业务进程。

在 Kubernetes 1.10 中新增的 Pod 内共享进程命名空间的功能,给这个问题带来了一点新思路:做一个 Sidecar 用于对配置文件进行监控,发现文件变化之后,发送重新载入的信号给业务进程,要求业务进程自行刷新。这样就无需对业务容器所在镜像进行修改了。

这种方法当然也有个局限性,需要业务进程支持这种信号。

下面以 Apache 为例,看看这种方式的用法。

用一个简化的 <code>httpd.conf</code> 文件,生成 Configmap,例如:

如此就生成了一个名为 apache 的 Configmap。

这个镜像要完成的任务有两个:监控文件变化,如果内容变化,则发送信号给业务进程。文件内容变化的监控,可以用哈希码或者 inotify 调用来完成,这里使用 <code>inotifywait</code>命令做一个死循环,发现特定事件后,则发出信号:

这里没有用监控本地文件的 <code>-m</code> 或者 <code>-e modify</code> 事件,而是用了 <code>delete_self</code>,这是 Configmap 加载生成文件的差异,也可以考虑用环境变量来替换这一事件。

然后构建镜像:

这里假设镜像名称为 <code>dustise/inotify:latest</code>。

我们选择 Apache 作为业务应用的示范,它能够接受 <code>USR1</code> 信号进行重新载入。

这段代码:

在 <code>template.spec</code> 中加入了 <code>shareProcessNamespace: true</code>,表示启用进行命名空间共享功能;

新建了一个伴行的 Sidecar 容器;

Apache 和 Sidecar 共享来自同一个 Configmap 的配置文件,根据加载情况为 Sidecar 定义了环境变量。

接下来可以使用 <code>kubectl logs</code> 命令来监控两个容器的日志输出:

然后使用 <code>kubectl edit cm apache</code>,修改配置文件(例如删除点注释)。稍候片刻,发现两个容器的输出都发生了变化:

脚本检测到了配置文件发生了删除事件,发送信号,并重新启动监控。

Apache 收到了 USR1 信号,进行了优雅重启。

对于支持信号控制的软件,例如 Nginx、Gunicorn、HA-Proxy 等都可以使用这种方式来完成配置刷新工作。能够有效的避免重启或修改业务应用的老大难问题。