ConfigMap
1 创建
ConfigMap
资源对象使用key-value
形式的键值对来配置数据,这些数据可以在Pod
里面使用,ConfigMap
和我们后面要讲到的Secrets
比较类似,一个比较大的区别是ConfigMap
可以比较方便的处理一些非敏感的数据,比如密码之类的还是需要使用Secrets
来进行管理。我们来举个例子说明下ConfigMap
的使用方法:
kind: ConfigMap
apiVersion: v1
metadata:
name: cm-demo
namespace: default
data:
data.1: hello
data.2: world
config: |
property.1=value-1
property.2=value-2
property.3=value-3
其中配置数据在data
属性下面进行配置,前两个被用来保存单个属性,后面一个被用来保存一个配置文件。
当然同样的我们可以使用kubectl create -f xx.yaml
来创建上面的ConfigMap
对象,但是如果我们不知道怎么创建ConfigMap
的话,不要忘记kubectl
是我们最好的老师,可以使用kubectl create configmap -h
来查看关于创建ConfigMap
的帮助信息,
Examples:
# Create a new configmap named my-config based on folder bar
kubectl create configmap my-config --from-file=path/to/bar
# Create a new configmap named my-config with specified keys instead of file basenames on disk
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
# Create a new configmap named my-config with key1=config1 and key2=config2
kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
我们可以看到可以从一个给定的目录来创建一个ConfigMap
对象,比如我们有一个testcm
的目录,该目录下面包含一些配置文件,redis
和mysql
的连接信息,如下:
$ ls testcm
redis.conf
mysql.conf
$ cat testcm/redis.conf
host=127.0.0.1
port=6379
$ cat testcm/mysql.conf
host=127.0.0.1
port=3306
然后我们可以使用from-file
关键字来创建包含这个目录下面所以配置文件的ConfigMap
:
$ kubectl create configmap cm-demo1 --from-file=testcm
configmap "cm-demo1" created
其中from-file
参数指定在该目录下面的所有文件都会被用在ConfigMap
里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
创建完成后,同样我们可以使用如下命令来查看ConfigMap
列表:
$ kubectl get configmap
NAME DATA AGE
cm-demo1 2 17s
可以看到已经创建了一个cm-demo1
的ConfigMap
对象,然后可以使用describe
命令查看详细信息:
kubectl describe configmap cm-demo1
Name: cm-demo1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
mysql.conf:
----
host=127.0.0.1
port=3306
redis.conf:
----
host=127.0.0.1
port=6379
Events: <none>
我们可以看到两个key
是testcm
目录下面的文件名称,对应的value
值的话就是文件内容,这里值得注意的是如果文件里面的配置信息很大的话,describe
的时候可能不会显示对应的值,要查看键值的话,可以使用如下命令:
$ kubectl get configmap cm-demo1 -o yaml
apiVersion: v1
data:
mysql.conf: |
host=127.0.0.1
port=3306
redis.conf: |
host=127.0.0.1
port=6379
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:24:36Z
name: cm-demo1
namespace: default
resourceVersion: "3109975"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo1
uid: 6e0f4d82-6fef-11e8-a101-525400db4df7
除了通过文件目录进行创建,我们也可以使用指定的文件进行创建ConfigMap
,同样的,以上面的配置文件为例,我们创建一个redis
的配置的一个单独ConfigMap
对象:
$ kubectl create configmap cm-demo2 --from-file=testcm/redis.conf
configmap "cm-demo2" created
$ kubectl get configmap cm-demo2 -o yaml
apiVersion: v1
data:
redis.conf: |
host=127.0.0.1
port=6379
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:34:29Z
name: cm-demo2
namespace: default
resourceVersion: "3110758"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo2
uid: cf59675d-6ff0-11e8-a101-525400db4df7
我们可以看到一个关联redis.conf
文件配置信息的ConfigMap
对象创建成功了,另外值得注意的是--from-file
这个参数可以使用多次,比如我们这里使用两次分别指定redis.conf
和mysql.conf
文件,就和直接指定整个目录是一样的效果了。
另外,通过帮助文档我们可以看到我们还可以直接使用字符串进行创建,通过--from-literal
参数传递配置信息,同样的,这个参数可以使用多次,格式如下:
$ kubectl create configmap cm-demo3 --from-literal=db.host=localhost --from-literal=db.port=3306
configmap "cm-demo3" created
$ kubectl get configmap cm-demo3 -o yaml
apiVersion: v1
data:
db.host: localhost
db.port: "3306"
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:43:12Z
name: cm-demo3
namespace: default
resourceVersion: "3111447"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo3
uid: 06eeec7e-6ff2-11e8-a101-525400db4df7
2 使用
ConfigMap
创建成功了,那么我们应该怎么在Pod
中来使用呢?我们说ConfigMap
这些配置数据可以通过很多种方式在Pod
里使用,主要有以下几种方式:
设置环境变量的值
在容器里设置命令行参数
在数据卷里面创建config文件
首先,我们使用ConfigMap
来填充我们的环境变量:
apiVersion: v1
kind: Pod
metadata:
name: testcm1-pod
spec:
containers:
- name: testcm1
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.port
envFrom:
- configMapRef:
name: cm-demo1
这个Pod运行后会输出如下几行:
$ kubectl logs testcm1-pod
......
DB_HOST=localhost
DB_PORT=3306
mysql.conf=host=127.0.0.1
port=3306
redis.conf=host=127.0.0.1
port=6379
......
我们可以看到DB_HOST
和DB_PORT
都已经正常输出了,另外的环境变量是因为我们这里直接把cm-demo1
给注入进来了,所以把他们的整个键值给输出出来了,这也是符合预期的。
另外我们可以使用ConfigMap
来设置命令行参数,ConfigMap
也可以被用来设置容器中的命令或者参数值,如下Pod
:
apiVersion: v1
kind: Pod
metadata:
name: testcm2-pod
spec:
containers:
- name: testcm2
image: busybox
command: [ "/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)" ]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.port
运行这个Pod
后会输出如下信息:
$ kubectl logs testcm2-pod
localhost 3306
另外一种是非常常见的使用ConfigMap
的方式:通过数据卷使用,在数据卷里面使用ConfigMap
,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容:
apiVersion: v1
kind: Pod
metadata:
name: testcm3-pod
spec:
containers:
- name: testcm3
image: busybox
command: [ "/bin/sh", "-c", "cat /etc/config/redis.conf" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo2
运行这个Pod
的,查看日志:
$ kubectl logs testcm3-pod
host=127.0.0.1
port=6379
当然我们也可以在ConfigMap
值被映射的数据卷里去控制路径,如下Pod
定义:
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
spec:
containers:
- name: testcm4
image: busybox
command: [ "/bin/sh","-c","cat /etc/config/path/to/msyql.conf" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo1
items:
- key: mysql.conf
path: path/to/msyql.conf
运行这个Pod
的,查看日志:
$ kubectl logs testcm4-pod
host=127.0.0.1
port=3306
另外需要注意的是,当ConfigMap
以数据卷的形式挂载进Pod
的时,这时更新ConfigMap
(或删掉重建ConfigMap
),Pod
内挂载的配置信息会热更新。这时可以增加一些监测配置文件变更的脚本,然后reload
对应服务。
3 实践
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: {{ template "xdb.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
data:
{{ toYaml .Values.mysql.configFiles | indent 2 }}
server-id.cnf: |
[mysqld]
server-id=@@SERVER_ID@@
create-peers.sh: |
#!/bin/sh
set -eu
i=0
while [ $i -lt {{ .Values.replicaCount }} ]
do
if [ $i = 0 ]
then
echo -n "{{ template "fullname" . }}-${i}.{{ template "fullname" . }}.{{ .Release.Namespace }}:8801"
else
echo -n ",{{ template "fullname" . }}-${i}.{{ template "fullname" . }}.{{ .Release.Namespace }}:8801"
fi
i=$((i+1))
done
leader-start.sh: |
#!/usr/bin/env bash
for i in `seq 1 10`;do
if curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -H "Content-Type: application/json-patch+json" \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/{{ .Release.Namespace }}/pods/$HOSTNAME \
-d '[{"op": "replace", "path": "/metadata/labels/role", "value": "leader"}]' ;then
echo "label role to leader successs."
break
else
echo "label role to leader failed, retry times ${i}/10, interval 10s".
sleep 10
fi
done
leader-stop.sh: |
#!/usr/bin/env bash
for i in `seq 1 10`;do
if curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -H "Content-Type: application/json-patch+json" \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/{{ .Release.Namespace }}/pods/$HOSTNAME \
-d '[{"op": "replace", "path": "/metadata/labels/role", "value": "follower"}]' ;then
echo "label role to follower successs."
break
else
echo "label role to leader failed, retry times ${i}/10, interval 5s".
sleep 5
fi
done
server-id.cnf
:一个配置文件,用于设置 MySQL 的server-id
。@@SERVER_ID@@
是一个占位符,通常在部署时会被替换为具体的值。
create-peers.sh
:一个 Shell 脚本,用于生成集群中所有节点的连接字符串。使用
while
循环遍历副本数({{ .Values.replicaCount }}
),生成每个节点的地址。
leader-start.sh
和leader-stop.sh
:用于在 Kubernetes 中动态更改 Pod 的标签,以实现主从切换。使用
curl
命令向 Kubernetes API 发送 PATCH 请求,修改 Pod 的role
标签。leader-start.sh
将 Pod 标签设置为leader
,而leader-stop.sh
将其设置为follower
。
3.1 configmap 列表
kubectl get configmap
xdbmysql57001 5 7d4h
xdbmysql57001-xdbzookeeper 3 7d4h
3.2 configmap 详情
kubectl describe configmap xdbmysql57001
Name: xdbmysql57001
Namespace: default
Labels: app=xdbmysql57001
app.kubernetes.io/managed-by=Helm
chart=xdbmysql57-2.0.3
heritage=Helm
release=xdbmysql57001
Annotations: meta.helm.sh/release-name: xdbmysql57001
meta.helm.sh/release-namespace: default
Data
====
create-peers.sh:
----
#!/bin/sh
set -eu
i=0
while [ $i -lt 3 ]
do
if [ $i = 0 ]
then
echo -n "xdbmysql57001-${i}.xdbmysql57001.default:8801"
else
echo -n ",xdbmysql57001-${i}.xdbmysql57001.default:8801"
fi
i=$((i+1))
done
leader-start.sh:
----
#!/usr/bin/env bash
for i in `seq 1 10`;do
if curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -H "Content-Type: application/json-patch+json" \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME \
-d '[{"op": "replace", "path": "/metadata/labels/role", "value": "leader"}]' ;then
echo "label role to leader successs."
break
else
echo "label role to leader failed, retry times ${i}/10, interval 10s".
sleep 10
fi
done
leader-stop.sh:
----
#!/usr/bin/env bash
for i in `seq 1 10`;do
if curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -H "Content-Type: application/json-patch+json" \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/api/v1/namespaces/default/pods/$HOSTNAME \
-d '[{"op": "replace", "path": "/metadata/labels/role", "value": "follower"}]' ;then
echo "label role to follower successs."
break
else
echo "label role to leader failed, retry times ${i}/10, interval 5s".
sleep 5
fi
done
node.cnf:
----
[mysqld]
default_storage_engine=InnoDB
max_connections=131072
innodb-buffer-pool-size=2867M
# 如果要修改密码强度,请在参数前面加上'loose-'前缀
# 半同步插件,如果不使用请注释下面所有配置项,否则会安装出错
plugin-load-add="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose-rpl_semi_sync_master_enabled=ON #表示开启半同步复制
loose-rpl_semi_sync_master_timeout=10000 #单位为毫秒,超过此时间将切换为异步复制
loose-rpl_semi_sync_master_wait_no_slave=ON #表示是否允许master每个事务都要等待slave接收确认。默认为ON,如果slave crash后,当slave追赶上master的日志时,可以自动的切换为半同步方式。
loose-rpl_semi_sync_master_trace_level=32 #表示用于开启半同步复制时的调试级别,默认32
loose-rpl_semi_sync_master_wait_for_slave_count=1 #主库需要等待多少个slave应答,才能返回给客户端,默认为1。
loose-rpl_semi_sync_master_wait_point=AFTER_SYNC #半同步模式下主库在返回结果给会话之前提交事务的方式
loose-rpl_semi_sync_slave_enabled=ON #master和slave需同时启动,以便在切换后能继续使用半同步复制
loose-rpl_semi_sync_slave_trace_level=32 #表示用于开启半同步复制时的调试级别,默认32
server-id.cnf:
----
[mysqld]
server-id=@@SERVER_ID@@
Events: <none>
Last updated