背景
K8s中部署的工作負載使用ConfigMap
或Secret
時,存在兩種方式:
- 環境變量 Env 方式掛載
- 文件方式掛載
當更新ConfigMap
或Secret
時,掛載到Pod中的數據存在兩種情況:
- Env 方式掛載的環境變量不會同步更新
- 文件方式掛載的數據會同步更新(存在秒級延時)
大部分場景下,在更新了ConfigMap
或Secret
中的信息后,都希望Pod內業務能讀取到最新的值。通常都會手動去滾動更新一下Pod,重新讀取環境變量或文件內容。當前社區已經有對應的開源工具Reloader實現了ConfigMap
/Secret
更新時自動觸發Pod的滾動更新。
Reloader介紹
Reloader 通過watch ConfigMap
和 Secret
中的變化,對 Deployment
、 DaemonSet
和 StatefulSet
等負載的 Pod
進行滾動升級。
兼容性
Reloader 兼容的 K8s 版本為>=1.9。
常用配置
以下使用Deployment舉例:
-
Deployment 中使用的所有 ConfigMap 和 Secret 變動都會觸發 Pod 滾動更新
在Deployment 的metadata.annotations
中添加reloader.stakater.com/auto: "true"
kind: Deployment metadata: annotations: reloader.stakater.com/auto: "true" spec: template:
-
Deployment 中的部分 ConfigMap 和 Secret 變動會觸發 Pod 滾動更新
在Deployment 的metadata.annotations
中添加reloader.stakater.com/search: "true"
同時在需要觸發 Pod 更新的 ConfigMap 或 Secret 中的kind: Deployment metadata: annotations: reloader.stakater.com/search: "true" spec: template:
metadata.annotations
中添加reloader.stakater.com/match: "true"
kind: ConfigMap metadata: annotations: reloader.stakater.com/match: "true" data: key: value
-
Deployment 中指定 ConfigMap 或 Secret 的變動觸發 Pod 滾動更新
在Deployment 的metadata.annotations
中添加configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap"
,指定這些 ConfigMap 才會觸發 Pod 的更新。多個 ConfigMap 使用逗號分隔
在Deployment 的kind: Deployment metadata: annotations: configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap" spec: template: metadata:
metadata.annotations
中添加secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret"
,指定這些 Secret 才會觸發 Pod 的更新。多個 Secret 使用逗號分隔kind: Deployment metadata: annotations: secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret" spec: template: metadata:
其他配置
-
忽略 ConfigMap 或 Secret 變動(全局)
在 Reloader deployment的spec.template.spec.container.args
中添加參數:參數 描述 --resources-to-ignore=configMaps 忽略 configMaps 變動 --resources-to-ignore=secrets 忽略 secrets 變動 --resources-to-ignore
參數只支持忽略一種資源,若要同時忽略 configMaps 和 secrets 的變動,則只需要把 Reloader 副本數降為0。 忽略 Namespace 中的變動
在 Reloader deployment的spec.template.spec.container.args
中配置參數--namespaces-to-ignore={namespace}
-
覆蓋默認相關annotation
參數 描述 --auto-annotation 覆蓋默認的annotation reloader.stakater.com/auto
--auto-search-annotation 覆蓋默認的annotation reloader.stakater.com/search
--search-match-annotation 覆蓋默認的annotation reloader.stakater.com/match
--configmap-annotation 覆蓋默認的annotation configmap.reloader.stakater.com/reload
--secret-annotation 覆蓋默認的annotation secret.reloader.stakater.com/reload
更多信息參考:https://github.com/stakater/Reloader
實戰驗證
測試環境準備
- 創建namespace
輸入命令,創建一個namespace,名為ns1
。
kubectl create ns ns1
- 安裝reloader
輸入如下命令,安裝reloader相關deployment。
$ kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
- 創建configmap
使用kubectl apply -f cm.yaml
命令創建configmap。cm.yaml
文件內容如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: test-config-file
namespace: ns1
annotations:
# reloader.stakater.com/match: "true"
data:
info.yaml: |
user=aliens
age=22
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-config-env
namespace: ns1
annotations:
# reloader.stakater.com/match: "true"
data:
COUNTRY: china
CITY: beijing
- 創建deployment
使用kubectl apply -f nginx-deploy.yaml
命令創建configmap。nginx-deploy.yaml
文件內容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: ns1
annotations:
# configmap.reloader.stakater.com/reload: "test-config-file"
# reloader.stakater.com/search: "true"
reloader.stakater.com/auto: "true"
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
env:
# Define the environment variable
- name: COUNTRY
valueFrom:
configMapKeyRef:
name: test-config-env
key: COUNTRY
- name: CITY
valueFrom:
configMapKeyRef:
name: test-config-env
key: CITY
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: test-config-file
Reloader功能驗證
- 更新configmap(以文件方式掛載)
使用命令kubectl -nns1 edit cm test-config-file
編輯configmap,設置user
的值為ted
。查看pod已經滾動更新。
? kubectl edit cm -nns1 test-config-file
configmap/test-config-file edited
? kubectl get pods -nns1
NAME READY STATUS RESTARTS AGE
nginx-5dff48f5dd-m528h 0/1 ContainerCreating 0 6s
nginx-6f455f8cd5-9h7pp 1/1 Running 0 34m
查看新啟動pod中configmap所掛載的文件內容,發現user
的值已經變為ted
。
? kubectl exec -it nginx-5dff48f5dd-m528h -nns1 -- cat /etc/foo/info.yaml
user=ted
age=22
- 更新configmap(以環境變量方式注入)
使用命令kubectl -nns1edit cm test-config-env
編輯configmap,設置CITY
的值為shenzhen
。查看pod已經滾動更新。
? kubectl edit cm -nns1 test-config-env
configmap/test-config-env edited
? kubectl get pods -nns1
NAME READY STATUS RESTARTS AGE
nginx-5b4cb86669-9cv6k 0/1 ContainerCreating 0 6s
nginx-5dff48f5dd-m528h 1/1 Running 0 9m35s
查看新啟動pod中configmap所注入的環境變量,發現CITY
的值已經變為shenzhen
。
? kubectl exec -it nginx-5b4cb86669-9cv6k -nns1 -- env|grep CITY
CITY=shenzhen
注意事項
- Reloader自動觸發滾動更新,可能會導致業務中斷。使用該功能時需要評估pod滾動更新對業務帶來的影響。
-
reloader.stakater.com/auto
的優先級高于reloader.stakater.com/search
。