原文連結:https://bbs.huaweicloud.com/blogs/312634
背景
配置中心問題:
對於在雲原生中配置中心,例如configmap和secret物件,雖然可以進行直接更新資源物件
對於參照這些有些不變的配置是可以打包到映像中的,那可變的配置呢?
資訊泄漏,很容易引發安全風險,尤其是一些敏感資訊,比如密碼、金鑰等。
每次配置更新後,都要重新打包一次,升級套用。映像版本過多,也給映像管理和映像中心儲存帶來很大的負擔。
客製化太嚴重,可延伸能力差,且不容易復用。
使用方式:
Configmap或Secret使用有兩種方式,一種是env系統變量賦值,一種是volume掛載賦值,env寫入系統的configmap是不會熱更新的,而volume寫入的方式支持熱更新!
對於env環境的,必須要捲動更新pod才能生效,也就是刪除老的pod,重新使用映像拉起新pod載入環境變量才能生效。
對於volume的方式,雖然內容變了,但是需要我們的套用直接監控configmap的變動,或者一直去更新環境變量才能在這種情況下達到熱更新的目的。
套用不支持熱更新,可以在業務容器中啟動一個sidercar容器,監控configmap的變動,更新配置檔,或者也捲動更新pod達到更新配置的效果。
解決方案
ConfigMap 和 Secret 是 Kubernetes 常用的保存配置數據的物件,你可以根據需要選擇合適的物件儲存數據。透過 Volume 方式掛載到 Pod 內的,kubelet 都會定期進行更新。但是透過環境變量註入到容器中,這樣無法感知到 ConfigMap 或 Secret 的內容更新。
目前如何讓 Pod 內的業務感知到 ConfigMap 或 Secret 的變化,還是一個待解決的問題。但是我們還是有一些 Workaround 的。
如果業務自身支持 reload 配置的話,比如nginx -s reload,可以透過 inotify 感知到檔更新,或者直接定期進行 reload(這裏可以配合我們的 readinessProbe 一起使用)。
如果我們的業務沒有這個能力,考慮到不可變基礎設施的思想,我們是不是可以采用捲動升級的方式進行?沒錯,這是一個非常好的方法。目前有個開源工具Reloader,它就是采用這種方式,透過 watch ConfigMap 和 Secret,一旦發現物件更新,就自動觸發對 Deployment 或 StatefulSet 等工作負載物件進行捲動升級。
reloader簡介
reloader簡介:
Reloader 可以觀察 ConfigMap 和 Secret 中的變化,並透過相關的 deploymentconfiggs、 deploymentconfiggs、 deploymonset 和 statefulset 對 Pods 進行捲動升級。
reloader安裝:
helm安裝:
helm repo add stakater https://stakater.github.io/stakater-charts
helm repo update
helm install stakater/reloader
Kustomize:
kubectl apply -k https://github.com/stakater/Reloader/deployments/kubernetes
資源清單安裝:
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
# 在此安裝在common-service 名稱空間下,
[root@master reloader]# kubectl apply -f reloader.yaml
clusterrole.rbac.authorization.k8s.io/reloader-reloader-role created
clusterrolebinding.rbac.authorization.k8s.io/reloader-reloader-role-binding created
deployment.apps/reloader-reloader created
serviceaccount/reloader-reloader created
[root@master reloader]# kubectl get all -n common-service
NAME READY STATUS RESTARTS AGE
pod/reloader-reloader-66d46d5885-nx64t 1/1 Running 0 15s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/reloader-reloader 1/1 1 1 16s
NAME DESIRED CURRENT READY AGE
replicaset.apps/reloader-reloader-66d46d5885 1 1 1 16s
配置忽略:
reloader能夠配置忽略cm或者secrets資源,可以透過配置在reader deploy中的spec.template.spec.containers.args,如果兩個都忽略,那就縮小deploy為0,或者不部署reoader。
Args | Description |
---|---|
–resources-to-ignore=configMaps | To ignore configMaps |
–resources-to-ignore=secrets | To ignore secrets |
配置:
自動更新:
reloader.stakater.com/search 和 reloader.stakater.com/auto 並不在一起工作。如果你在你的部署上有一個 reloader.stakater.com/auto : 「 true」的註釋,該資源物件參照的所有configmap或這secret的改變都會重新開機該資源,不管他們是否有 reloader.stakater.com/match : 「 true」的註釋。
kind:Deployment
metadata:
annotations:
reloader.stakater.com/auto:"true"
spec:
template: metadata:
制定更新:
指定一個特定的configmap或者secret,只有在我們指定的配置圖或秘密被改變時才會觸發捲動升級,這樣,它不會觸發捲動升級所有配置圖或秘密在部署,後台登入或狀態設定中使用。
一個制定deployment資源物件,在參照的configmap或者secret種,只有
reloader.stakater.com/match: "true"
為true才會出發更新,為false或者不進行標記,該資源物件都不會監視配置的變化而重新開機。
kind:Deployment
metadata:
annotations:
reloader.stakater.com/search:"true"
spec:
template:
cm配置:
kind:ConfigMap
metadata:
annotations:
reloader.stakater.com/match:"true"
data:
key:value
指定cm:
如果一個deployment掛載有多個cm或者的場景下,我們只希望更新特定一個cm後,deploy發生捲動更新,更新其他的cm,deploy不更新,這種場景可以將cm在deploy中指定為單個或著列表實作。
例如:一個deploy有掛載nginx-cm1和nginx-cm2兩個configmap,只想nginx-cm1更新的時候deploy才發生捲動更新,此時無需在兩個cm中配置註解,只需要在deploy中寫入configmap.reloader.stakater.com/reload:nginx-cm1,其中nginx-cm1如果發生更新,deploy就會觸發捲動更新。
如果多個cm直接用逗號隔開
# configmap物件
kind:Deployment
metadata:
annotations:
configmap.reloader.stakater.com/reload:"nginx-cm1"
spec:
template: metadata:
# secret物件
kind:Deployment
metadata:
annotations:
secret.reloader.stakater.com/reload:"foo-secret"
spec:
template: metadata:
無需在cm或secret中添加註解,只需要在參照資源物件中添加註解即可。
測試驗證
deploy:
apiVersion:apps/v1
kind:Deployment
metadata:
annotations:
# reloader.stakater.com/auto: "true"
reloader.stakater.com/search:"true"
labels:
run:nginx
name:nginx
namespace:default
spec:
replicas:1
selector:
matchLabels:
run:nginx
template:
metadata:
labels:
run:nginx
spec:
containers:
-image:nginx
name:nginx
volumeMounts:
# 必須匹配volumes的名稱,定義configmap
-name:nginx-cm
mountPath:/data/cfg
readOnly:true
volumes:
# 定義邏輯卷的名稱
-name:nginx-cm
configMap:
# 使用configmap資源的名稱
name:nginx-cm
items:
# 使用configmap中到那個key
-key:config.yaml
# 使用configmap中到key對映到容器中到檔名稱
path:config.yaml
mode:0644
configmap:
apiVersion:v1
data:
config.yaml:|
# project settings
# go2cloud_api service config
DEFAULT_CONF:
port:8888
# data disk api
UNITTEST_TENCENT_ZONE:ap-chongqing-1
kind:ConfigMap
metadata:
name:nginx-cm
annotations:
reloader.stakater.com/match:"true"
測試:
[root@master ns-default]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-68c9bf4ff7-9gmg6 1/1 Running 0 10m
[root@master ns-default]# kubectl get cm
NAME DATA AGE
nginx-cm 1 28m
# 更新cm內容
[root@master ns-default]# kubectl edit cm nginx-cm
configmap/nginx-cm edited
# 檢視po發生了捲動更新,重新載入配置檔
[root@master ns-default]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-66c758b548-9dllm 0/1 ContainerCreating 0 4s
nginx-68c9bf4ff7-9gmg6 1/1 Running 0 10m
註意事項
reloader為全域資源物件,建議部署在一個公共服務的ns下,然後其他ns也可以正常使用reloader特性。
Reloader.stakater.com/auto : 如果配置configmap或者secret在 deploymentconfigmap/deployment/daemonsets/Statefulsets
secret.reloader.stakater.com/reload 或者 configmap.reloader.stakater.com/reload 註釋中被使用,那麽 true 只會重新載入 pod,不管使用的是 configmap 還是 secret。
reloader.stakater.com/search 和 reloader.stakater.com/auto 不能同時使用。如果你在你的部署上有一個 reloader.stakater.com/auto : 「 true」的註釋,那麽它總是會在你修改了 configmaps 或者使用了機密之後重新啟動,不管他們是否有 reloader.stakater.com/match : 「 true」的註釋。
反思
Reloader透過 watch ConfigMap 和 Secret,一旦發現物件更新,就自動觸發對 Deployment 或 StatefulSet 等工作負載物件進行捲動升級。
如果我們的套用內部沒有去即時監控配置檔,利用該方式可以非常方便的實作配置的熱更新。
參考連結
https://github.com/stakater/Reloader
往期推薦
點亮,伺服器三年不宕機