天天看點

用 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 等都可以使用這種方式來完成配置重新整理工作。能夠有效的避免重新開機或修改業務應用的老大難問題。