跳到主要内容

ConfigMap

Reloader

监听 configmap 更新

https://github.com/stakater/Reloader

kubectl apply -k https://github.com/stakater/Reloader/deployments/kubernetes
## kind: Deployment
## metadata:
## annotations:
## #------ all(ConfigMap and/or Secret)
## reloader.stakater.com/auto: "true"
## #------ only configmap for name: "foo-configmap"
## configmap.reloader.stakater.com/reload: "foo-configmap"
## #------ many configmaps
## configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap"
## #------ only secret for name: "foo-secret"
## secret.reloader.stakater.com/reload: "foo-secret"
## #------ many secrets
## secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret"
## spec:
## template:
## metadata:

ConfigMap

# 从文件创建配置,redis保存到k8s的etcd;
kubectl create cm redis-conf --from-file=redis.conf

ConfigMap yaml

apiVersion: v1
data: #data是所有真正的数据,key:默认是文件名 value:配置文件的内容
redis.conf: |
appendonly yes
kind: ConfigMap
metadata:
name: redis-conf
namespace: default

使用

apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
command:
- redis-server
- "/redis-master/redis.conf" #指的是redis容器内部的位置
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: redis-conf
items:
- key: redis.conf
path: redis.conf

完整练习文件

---
# configmap
# kubectl create configmap localconfig-env --from-literal=log_level_test=TEST --from-literal=log_level_produce=PRODUCE
apiVersion: v1
kind: ConfigMap
metadata:
name: localconfig-env
data:
log_level_test: TEST
log_level_produce: PRODUCE

---
# configmap
# kubectl create configmap localconfig-file --from-file=localconfig-test=localconfig-test.conf --from-file=localconfig-produce=localconfig-produce.conf
apiVersion: v1
kind: ConfigMap
metadata:
name: localconfig-file
data:
localconfig-produce: |
TEST_RELEASE = False
PORT = 80
PROCESSES = 0
MESSAGE = Produce
localconfig-test: |
TEST_RELEASE = True
PORT = 8080
PROCESSES = 1
MESSAGE = Test

---
# secret
# kubectl create secret generic mysecret --from-literal=mysql-root-password='BogeMysqlPassword' --from-literal=redis-root-password='BogeRedisPassword' --from-file=my_id_rsa=/root/.ssh/id_rsa --from-file=my_id_rsa_pub=/root/.ssh/id_rsa.pub
apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: default
type: Opaque
data:
my_id_rsa: bXlfaWRfcnNhCg==
my_id_rsa_pub: bXlfaWRfcnNhX3B1Ygo=
mysql-root-password: Qm9nZU15c3FsUGFzc3dvcmQ=
redis-root-password: Qm9nZVJlZGlzUGFzc3dvcmQ=

---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: test-busybox
name: test-busybox
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: test-busybox
template:
metadata:
labels:
run: test-busybox
spec:
containers:
- name: test-busybox
image: registry.cn-shanghai.aliyuncs.com/acs/busybox:v1.29.2

args:
- /bin/sh
- -c
- >
echo "-------------------------------------------------";
echo "TEST_ENV is:$(TEST_ENV)";
echo "-------------------------------------------------";
echo "PRODUCE_ENV is:$(PRODUCE_ENV)";
echo "-------------------------------------------------";
echo "secret MYSQL_ROOT_PASSWORD is:$(MYSQL_ROOT_PASSWORD)";
echo "-------------------------------------------------";
echo "secret REDIS_ROOT_PASSWORD is:$(REDIS_ROOT_PASSWORD)";
echo "-------------------------------------------------";
echo "/etc/local_config_test.py body is:";
cat /etc/local_config_test.py;
echo "-------------------------------------------------";
echo "/etc/local_config_produce.py body is:";
cat /etc/local_config_produce.py;
echo "-------------------------------------------------";
echo "/etc/id_rsa body is:";
cat /etc/id_rsa;
echo "-------------------------------------------------";
echo "/etc/id_rsa.pub body is:";
cat /etc/id_rsa.pub;
echo "-------------------------------------------------";
ls -ltr /etc;
sleep 30000;
env:
- name: TEST_ENV
valueFrom:
configMapKeyRef:
name: localconfig-env
key: log_level_test
- name: PRODUCE_ENV
valueFrom:
configMapKeyRef:
name: localconfig-env
key: log_level_produce
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: mysql-root-password
- name: REDIS_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: redis-root-password
volumeMounts:
- name: testconfig
mountPath: "/etc/local_config_test.py"
subPath: localconfig-test
- name: testconfig
mountPath: "/etc/local_config_produce.py"
subPath: localconfig-produce
readOnly: true
- name: testsecret
mountPath: "/etc/id_rsa"
subPath: my_id_rsa
readOnly: true
- name: testsecret
mountPath: "/etc/id_rsa.pub"
subPath: my_id_rsa_pub
readOnly: true

volumes:
- name: testconfig
configMap:
name: localconfig-file
defaultMode: 0660
- name: testsecret
secret:
secretName: mysecret
defaultMode: 0600


介绍 K8S 中常见的 ConfigMap 存储机制!

ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象

ConfigMap 的创建
使用目录创建
--from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容。

$ ls docs/user-guide/config-map/kubectl/
game.properties
ui.properties

# game.properties
$ cat docs/user-guide/config-map/kubectl/game.properties
enemies=aliens
lives= 3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives= 30

# ui.properties
$ cat docs/user-guide/config-map/kubectl/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

# 创建名称为game-config的ConfigMap配置
$ kubectl create configmap game-config \
--from-file=docs/user-guide/config-map/kubectl

# 查看存储的ConfigMap列表
$ kubectl get configmap
NAME DATA AGE
game-config 2 22s

# 查看对应内容
$ kubectl describe configmap game-config
$ kubectl get configmap game-config -o yaml
使用文件创建
只要指定为一个文件就可以从单个文件中创建 ConfigMap。--from-file 这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的。

# 创建名称为game-config-2的ConfigMap配置
$ kubectl create configmap game-config-2 \
--from-file=docs/user-guide/config-map/kubectl/game.properties

# 查看存储的ConfigMap列表
$ kubectl get configmap
NAME DATA AGE
game-config 2 34s
game-config-2 1 2s

# 查看对应内容
$ kubectl describe configmap game-config-2
$ kubectl get configmap game-config-2 -o yaml
使用字面值创建
使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下。

# 创建名称为special-config的ConfigMap配置
$ kubectl create configmap special-config \
--from-literal=special.how=very \
--from-literal=special.type=charm

# 查看对应内容
$ kubectl get configmaps special-config -o yaml
ConfigMap 的使用
使用 ConfigMap 来替代环境变量
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-test-pod
spec:
restartPolicy: Never
containers:
- name: test-container
image: hub.escape.com/library/myapp:v1
command: ["/bin/sh", "-c", "env"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how

- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
用 ConfigMap 设置命令行参数
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-test-pod
spec:
restartPolicy: Never
containers:
- name: test-container
image: hub.escape.com/library/myapp:v1
command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
通过数据卷插件使用 ConfigMap
在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。

apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-test-pod
spec:
restartPolicy: Never
containers:
- name: test-container
image: hub.escape.com/library/myapp:v1
command: ["/bin/sh", "-c", "cat /etc/config/special.how"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
ConfigMap 热更新
正常情况下,我们可以通过如下配置,在启动的 Pod 容器里面获取到 ConfigMap 中配置的信息。

apiVersion: v1
kind: ConfigMap
metadata:
name: log-config
namespace: default
data:
log_level: INFO

---
apiVersion: extensions/v1beta
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: hub.escape.com/library/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: log-config
# 查找对应信息
$ kubectl exec \
`kubectl get pods -l run=my-nginx -o=name | cut -d "/" -f2` \
cat /etc/config/log_level
INFO
修改 ConfigMap 配置,修改 log_level 的值为 DEBUG 等待大概 10 秒钟时间,再次查看环境变量的值。

# 修改ConfigMap配置
$ kubectl edit configmap log-config

# 查找对应信息
$ kubectl exec \
`kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` \
cat /etc/config/log_level
DEBUG
ConfigMap 更新后滚动更新 Pod,更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新。这个例子里我们在 .spec.template.metadata.annotations 中添加 version/config,每次通过修改 version/config 来触发滚动更新。

$ kubectl patch deployment my-nginx \
--patch '{"spec": {"template": {"metadata": {"annotations": \
{"version/config": "20190411" }}}}}'
更新 ConfigMap 后:

使用该 ConfigMap 挂载的 Env 不会同步更新

使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概 10 秒)才能同步更新