背景
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
。