目录
3.1 通过环境变量引入:使用 configMapKeyRef
3.3 把 configmap 做成 volume 挂载到 pod
一、ConfigMap 概述
1.1 什么是 ConfigMap?
Configmap 是 k8s中 的资源对象,用于保存非机密性的配置的,数据可以用 key/value 键值对的形式保存,也可通过文件的形式保存。
1.2 ConfigMap 能解决哪些问题?
我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache 等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s 中引入了 ConfigMap 资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。
- ConfigMap 是 k8s 中的资源,相当于配置文件,可以有一个或者多个 ConfigMap;
- ConfigMap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
- 容器中应用程序按照原有方式读取容器特定目录上的配置文件;
- 在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
1.3 ConfigMap 应用场景
使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,ConfigMap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用性,因为一个 ConfigMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。ConfigMap 注入方式有两种,一种将 ConfigMap 做为存储卷,一种是将 ConfigMap 通过 env 中 configMapKeyRef 注入到容器中。
使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用 ConfigMap 可以友好的进行配置共享。
1.4 局限性
ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
ConfigMap 概念官方参考文档:ConfigMap | Kubernetes
二、ConfigMap 创建方法
你可以使用 kubectl create configmap
或者在 kustomization.yaml
中的 ConfigMap 生成器来创建 ConfigMap。注意,kubectl
从 1.14 版本开始支持 kustomization.yaml
。
使用 kubectl create configmap 创建 ConfigMap:
你可以使用 kubectl create configmap
命令基于目录、 文件或者字面值来创建 ConfigMap:
kubectl create configmap <映射名称> <数据源>
其中,<映射名称>
是为 ConfigMap 指定的名称,<数据源>
是要从中提取数据的目录、 文件或者字面值。ConfigMap 对象的名称必须是合法的 DNS 子域名.
在你基于文件来创建 ConfigMap 时,<数据源>
中的键名默认取自文件的基本名, 而对应的值则默认为文件的内容。
你可以使用 kubectl describe 或者 kubectl get 获取有关 ConfigMap 的信息。
2.1 根据字面值创建 ConfigMap
你可以将 kubectl create configmap
与 --from-literal
参数一起使用, 通过命令行定义文字值:
# 查看帮助命令
[root@k8s-master01 ~]# kubectl create configmap --help
······
Usage:
kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]
[options]
# 创建 configmap
[root@k8s-master01 ~]# kubectl create configmap tomcat-config --from-literal=tomcat_port=8080 --from-literal=server_name=myapp.tomcat.com
[root@k8s-master01 ~]# kubectl get cm
NAME DATA AGE
kube-root-ca.crt 1 59d
tomcat-config 2 39s
# 显示 ConfigMap 的详细信息:命令行中提供的每对键值在 ConfigMap 的 data 部分中均表示为单独的条目。
[root@k8s-master01 ~]# kubectl describe configmaps tomcat-config
Name: tomcat-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
server_name:
----
myapp.tomcat.com
tomcat_port:
----
8080
BinaryData
====
Events: <none>
2.2 基于文件创建 ConfigMap
你可以使用 kubectl create configmap
基于单个文件或多个文件创建 ConfigMap。
[root@k8s-master01 ~]# mkdir configmap
[root@k8s-master01 ~]# cd configmap/
[root@k8s-master01 configmap]# vim nginx.yaml
server {
listen 80;
server_name www.nginx.com;
root /home/nginx/www/
}
# 定义一个 key 是 www,值是 nginx.yaml 中的内容
[root@k8s-master01 configmap]# kubectl create configmap www-nginx --from-file=www=./nginx.yaml
configmap/www-nginx created
[root@k8s-master01 configmap]# kubectl describe configmaps www-nginx
Name: www-nginx
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
www:
----
server {
listen 80;
server_name www.nginx.com;
root /home/nginx/www/
}
BinaryData
====
Events: <none>
[root@k8s-master01 configmap]# kubectl get configmaps www-nginx
NAME DATA AGE
www-nginx 1 34s
2.3 基于目录创建 ConfigMap
你可以使用 kubectl create configmap
基于同一目录中的多个文件创建 ConfigMap。 当你基于目录来创建 ConfigMap 时,kubectl 识别目录下基本名可以作为合法键名的文件, 并将这些文件打包到新的 ConfigMap 中。普通文件之外的所有目录项都会被忽略 (例如:子目录、符号链接、设备、管道等等)。
例如:
# 创建本地目录
[root@k8s-master01 ~]# mkdir -pv configure-pod-container/configmap/
# 创建示例文件到 `configure-pod-container/configmap/` 目录
[root@k8s-master01 ~]# cd configure-pod-container/configmap/
[root@k8s-master01 configmap]# echo "server-id=1" > my-server.conf
[root@k8s-master01 configmap]# echo "server-id=2" > my-slave.conf
# 创建 configmap
[root@k8s-master01 configmap]# kubectl create configmap mysql-config --from-file=/root/configure-pod-container/configmap/
以上命令将 configure-pod-container/configmap
目录下的所有文件,也就是 my-server.conf
和 my-slave.conf
打包到 mysql-config ConfigMap 中。你可以使用下面的命令显示 ConfigMap 的详细信息:
[root@k8s-master01 configmap]# kubectl describe configmaps mysql-config
Name: mysql-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
my-server.conf:
----
server-id=1
my-slave.conf:
----
server-id=2
BinaryData
====
Events: <none>
configure-pod-container/configmap/
目录中的 server.conf
和 my-slave.conf
文件出现在 ConfigMap 的 data
部分。
创建 ConfigMap 官方参考文档: 配置 Pod 使用 ConfigMap | Kubernetes
2.4 编写 configmap 资源清单 YAML 文件
# 查看帮助命令
[root@k8s-master01 ~]# kubectl explain configmap
# 创建 configmap 资源文件
[root@k8s-master01 configmap]# vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
labels:
app: mysql
data:
master.cnf: | # master.cnf 是文件名称,“ | ” 符号代表文件内容有多行
[mysqld]
log-bin
log_bin_trust_function_creators=1
lower_case_table_names=1
slave.cnf: |
[mysqld]
super-read-only
log_bin_trust_function_creators=1
# 创建资源
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml
configmap/mysql created
# 查看是否成功创建
[root@k8s-master01 configmap]# kubectl get configmaps mysql
NAME DATA AGE
mysql 2 14s
编写 configmap 资源清单官方参考文档:ConfigMap | Kubernetes
三、使用 ConfigMap
你可以使用四种方式来使用 ConfigMap 配置 Pod 中的容器:
- 在容器命令和参数内
- 容器的环境变量(常用)
- 在只读卷里面添加一个文件,让应用来读取(常用)
- 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap
这些不同的方法适用于不同的数据使用方式。 对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。
第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改, 你的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间里的 ConfigMap。
3.1 通过环境变量引入:使用 configMapKeyRef
# 创建一个存储 mysql 配置的 configmap
[root@k8s-master01 configmap]# vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
labels:
app: mysql
data:
log: "1"
lower: "1"
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml
# 创建 pod,引用 configmap 中的内容
[root@k8s-master01 configmap]# vim mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
spec:
containers:
- name: mysql
image: busybox
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "sleep 3600" ]
env:
- name: log_bin # 定义环境变量 log_bin
valueFrom:
configMapKeyRef: # ConfigMap 包含你要赋给 log_bin 的值
name: mysql # 指定 configmap 的名字
key: log # 指定 configmap 中的 key,即把 log=1 的值赋给 log_bin 变量
- name: lower # 定义环境变量 lower
valueFrom:
configMapKeyRef:
name: mysql
key: lower
restartPolicy: Never
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod.yaml
pod/mysql-pod created
[root@k8s-master01 configmap]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 20s
# 进入容器内部,Pod 的输出包含环境变量 log_bin=1,lower=1。
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod -- sh
/ # printenv
log_bin=1
lower=1
使用单个 ConfigMap 中的数据定义容器环境变量:配置 Pod 使用 ConfigMap | Kubernetes
3.2 通过环境变量引入:使用 envfrom
使用 envFrom
将所有 ConfigMap 的数据定义为容器环境变量,ConfigMap 中的键成为 Pod 中的环境变量名称。
[root@k8s-master01 configmap]# vim mysql-pod-envfrom.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod-envfrom
spec:
containers:
- name: mysql
image: busybox
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "sleep 3600" ]
envFrom:
- configMapRef:
name: mysql #指定configmap的名字
restartPolicy: Never
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-envfrom.yaml
pod/mysql-pod-envfrom created
[root@k8s-master01 configmap]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 15m
mysql-pod-envfrom 1/1 Running 0 4s
# 进入容器内部查看环境变量
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-envfrom -- sh
/ # printenv
lower=1
log=1
将 ConfigMap 中的所有键值对配置为容器环境变量:配置 Pod 使用 ConfigMap | Kubernetes
3.3 把 configmap 做成 volume 挂载到 pod
在 Pod 规约的 volumes
部分下添加 ConfigMap 名称。 这会将 ConfigMap 数据添加到 volumeMounts.mountPath
所指定的目录 (在本例中为 /tmp/config
)。
# 创建 configmap
[root@k8s-master01 configmap]# vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
labels:
app: mysql
data:
log: "1"
lower: "1"
my.cnf: |
[mysqld]
hello sky
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml
# 创建 pod,使用存储在 ConfigMap 中的数据填充卷
[root@k8s-master01 configmap]# vim mysql-pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod-volume
spec:
containers:
- name: mysql
image: busybox
command: [ "/bin/sh","-c","ls /tmp/config" ]
volumeMounts:
- name: mysql-config # 与 volumes.name 一致
mountPath: /tmp/config # 容器内挂载的目录
volumes:
- name: mysql-config # 卷的名称
configMap:
name: mysql # configmap 的名称
restartPolicy: Never
[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-volume.yaml
pod/mysql-pod-volume created
[root@k8s-master01 configmap]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-pod 1/1 Running 0 55m
mysql-pod-envfrom 1/1 Running 0 40m
mysql-pod-volume 1/1 Running 0 5s
# 进入容器内部查看挂载卷下的数据,把 configmap 的内容变为文件存储了
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -- sh
/ # cd /tmp/config/
/tmp/config # ls
log lower my.cnf
/tmp/config # cat log
1/tmp/config # cat lower
/tmp/config # cat my.cnf
[mysqld]
hello sky
在这里,ConfigMap 中键 log
的内容将挂载在 config-volume
卷中 /tmp/config/log
文件中。
使用存储在 ConfigMap 中的数据填充卷:配置 Pod 使用 ConfigMap | Kubernetes
四、ConfigMap 热更新
当某个已被挂载的 ConfigMap 被更新,所投射的内容最终也会被更新。 对于 Pod 已经启动之后所引用的、可选的 ConfigMap 才出现的情形, 这一动态更新现象也是适用的。
kubelet 在每次周期性同步时都会检查已挂载的 ConfigMap 是否是最新的。 但是,它使用其本地的基于 TTL 的缓存来获取 ConfigMap 的当前值。 因此,从更新 ConfigMap 到将新键映射到 Pod 的总延迟可能等于 kubelet 同步周期 (默认 1 分钟) + ConfigMap 在 kubelet 中缓存的 TTL(默认 1 分钟)。
# 修改 configmap
[root@k8s-master01 ~]# kubectl edit configmaps mysql
apiVersion: v1
data:
log: "2" # 把 1 改为 2
lower: "1"
······
# 进入挂载卷创建的 pod 容器内部查看 log 内容是否有变化
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-volume -- sh
/ # cd /tmp/config/
/tmp/config # ls
log lower my.cnf
/tmp/config # cat log
2/tmp/config #
# 发现 log 值变成了 2,更新生效了
# 进入 env 创建的 pod 查看环境变量是否有变化
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-envfrom -- sh
/ # printenv
lower=1
log=1
# 没有变化
注意:更新 ConfigMap 后,使用该 ConfigMap 挂载的 Env 不会同步更新;使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新。
挂载的 ConfigMap 将被自动更新:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/#mounted-configmaps-are-updated-automatically
上一篇文章:【云原生 | Kubernetes 实战】15、K8s 控制器 Daemonset 入门到企业实战应用
下一篇文章:【云原生 | Kubernetes 实战】17、K8s 配置管理中心 Secret 实现加密数据配置管理_Stars.Sky的博客-CSDN博客
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/74539.html