以下将介绍向容器提供配置信息的几种方法
通过命令行参数进行配置
在制作Docker镜像时,Dockerfile中的ENTRYPOINT和CMD指令可用于指定容器启动时要运行的程序及相关参数。CMD指令以列表的形式指定要运行的程序和相关参数,但是如果同时存在ENTRYPOINT指令,则CMD指令中列表的所有元素都将被作为由ENTRYPOINT指定程序的命令行参数。另外在基于某镜像使用Docker命令创建容器时,可以在命令行向ENTRYPOINT中的程序传递额外的自定义参数,甚至还可以修改要运行的应用程序本身,例如以下命令使用docker run创建并启动容器的格式为: docker run [OPTINS] IMAGE [COMMAND] [ARG]
COMMAND
为自定义运行的程序,ARG
为传递给程序的参数,假如定义相关镜像文件时使用了ENTRYPOINT
指令,则COMMAND
和ARG
都会被当作命令行参数传递给ENTRYPOINT
指令中指定的程序,除非运行docker run命令时额外使用--entrypoint
选项来覆盖镜像文件中的ENTRYPOINT
指定的程序。
在Kubernetes系统上创建Pod资源时,也能够向容器化应用传递命令行参数,甚至指定运行其它应用程序,相关的字段分别为pods.spec.containers.command
和pods.spec.containers.args
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| [root@localhost configmap]# kubectl create -f nginx.yaml [root@localhost configmap]# cat nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f" ]
|
Kubernetes配置文件中的command对应于Dockerfile中的ENTRYPOINT,而配置文件的args则对应于Dockerfile中的CMD。在Kubernetes中只给出command字段时,他会覆盖Dockerfile中的ENTRYPOINT和CMD,只给出args字段时,它仅覆盖CMD,而同时给出command和args时,它会对应覆盖ENTRYPOINT和CMD。
将配置文件载入镜像文件
在通过Dockerfile制作镜像时,可以使用COPY或者ADD指定将定义好的配置文件直接复制到镜像文件系统上的相应位置,或者使用RUN指令调用sed或echo一类的命令修改配置文件从而达到为容器化应用提供自定义配置文件之目的。使用Docker Hub上的某镜像文件额外添加配置文件即能符合需要,则克隆其Dockerfile文件修改至符合需求之后再将之推送至GitHub,并由Docker Hub自动构建出镜像文件即可
通过存储卷向容器注入配置信息
Docker存储卷(volumes)能够将宿主机之上的任何文件或目录映射到容器文件系统之上,因此,可以事先将配置文件放置于宿主机之上的某个路径中,而后在启动容器时进行加载。这种方式灵活易用,但也依赖于用户需要事先将配置数据提供在宿主机上的特定路径下,而且在多主机模型中,若容器存在被调度至任一主机运行的可能性时,用户还需要将配置共享到任一宿主机来确保容器能够正常地获取到它们。
通过环境变量向容器注入配置信息
通过环境变量为容器提供配置信息是Docker Hub上最常见的使用方式,例如,使用MySQL官方提供的镜像文件启动MySQL容器时使用的MYSQL_ROOT_PASSWORD
环境变量,它用于为MYSQL服务器的root用户设置登陆密码。
在基于此类镜像启动容器时,用户为 docker run 命令通过 -e 选项向环境变量传值即能实现应用配置,命令的使用格式为 docker run -e SETTING1=foo -e SETTING2=bar ... <image name>
。启动时,容器的ENTRYPOINT
启动脚本会抓取到这些环境变量,并在启动容器应用之前,通过sed或echo等一类的命令将变量值替换到配置文件中。
在Kubernetes中使用镜像启动容器时,可以在Pod资源或Pod模版资源为容器配置使用env参数来定义所使用的环境变量列表,即便容器中的应用本身没定义环境变量,也一样可以向容器传递环境变量,只不过它不被使用罢了。环境变量配置容器化应用时,需要在容器配置段中嵌套使用env字段,它的值是一个由环境变量构建的列表。环境变量由name和value(或valueFrom)字段构成。
name<string>
:环境变量的名称,必须字段。
value<string>
:环境变量的值,通过 ${VAR_NAME} 引用,默认值为空。
valueFrom<Object>
:环境变量值的引用源,例如,当前Pod资源的名称、名称空间、标签等,不能与非空值的value字段同时使用,即环境变量的值要么源于value字段,要么源于valueFrom字段,二者不可同时提供数据。valueFrom字段可引用的值有多种来源,包括当前Pod资源的属性值,容器相关的系统资源配置、ConfigMap对象中的Key以及Secret对象中的Key,它们应分别使用不同的嵌套字段进行定义。
fieldRef<Object>
:当前Pod资源的指定字段,目前支持使用的字段包括 metadata.name、metadata.namespace、metadata.labels、metadata.annotations、spec.nodeName、spec.serviceAccountName、status.hostIP和status.podIP。
configMapKeyRef<Object>
:ConfigMap对象中的特定Key。
secretKeyRef<Object>
:Secret对象中的特定Key。
resourceFieldRef<Object>
:当前容器的特定系统资源的最小值(配额)或最大值(限额),目前支持的引用包括limits.cpu、limts.ephemeral-storage、requests、cpu、requests.memory、requests.ephemeral-storage。
valueFrom属性下面可以有
1)fieldRef【fieldRef下面有
fieldPath】
2)configMapKeyRef
3)secretKeyRef【fieldRef下面有name和key``】
4)resourceFieldRef【resourceFieldRef下面有
resource】
下面是定义在配置文件 nginx.yaml 中的Pod资源,其通过环境变量引用当前Pod资源及其所在节点的相关属性值配置容器,fieldRef字段的值是一个对象,它一般由apiVersion(创建当前Pod资源的API版本)或fieldPath嵌套字段所定义:
1)valueFrom:fieldRef【fieldRef下面有
fieldPath】案列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| [root@localhost configmap]# kubectl create -f nginx.yaml [root@localhost configmap]# cat nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f" ] env: - name: HELLO_WORLD value: just a demo
#fieldRef->fieldPath - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: MY_NODE_IP valueFrom: fieldRef: fieldPath: status.hostIP - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace
#resourceFieldRef->resource - name: MY_REQUESTS_CPU valueFrom: resourceFieldRef: resource: requests.cpu - name: MY_REQUESTS_MEM valueFrom: resourceFieldRef: resource: requests.memory - name: MY_LIMITS_CPU valueFrom: resourceFieldRef: resource: limits.cpu - name: MY_LIMITS_MEM valueFrom: resourceFieldRef: resource: limits.memory
#secretKeyRef->name|key - name: USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
resources: requests: cpu: "250m" memory: "64Mi" limits: cpu: "4000m" memory: "8Gi" #restartPolicy: OnFailure
|
然后打印它的环境变量列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [root@localhost configmap]# kubectl exec -it busybox-7d84ccb8cf-dztmv -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-7d84ccb8cf-dztmv MY_NODE_IP=172.16.10.21 MY_POD_NAMESPACE=default HELLO_WORLD=just a demo MY_NODE_NAME=172.16.10.21 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 KUBERNETES_SERVICE_HOST=10.43.0.1 TERM=xterm HOME=/root
|
3)valueFrom:secretKeyRef【fieldRef下面有name和key``】案列
3.1)创建Secret对象
注意:data中的value内容必须是base64编码格式,可以使用echo -n wubo|base64
完成。
1 2 3 4 5 6 7 8 9 10 11 12
| [root@localhost config]# echo -n wubo | base64 d3Vibw== [root@localhost config]# echo -n 123456aA | base64 MTIzNDU2YUE= [root@localhost config]# cat secrets.yaml apiVersion: v1 kind: Secret metadata: name: mysecret data: username: d3Vibw== password: MTIzNDU2YUE=
|
3.2)创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [root@localhost config]# kubectl create -f secrets.yaml [root@localhost config]# kubectl get secrets mysecret -o yaml apiVersion: v1 data: password: MTIzNDU2YUE= username: d3Vibw== kind: Secret metadata: creationTimestamp: "2022-12-29T06:06:17Z" name: mysecret namespace: default resourceVersion: "14208729" selfLink: /api/v1/namespaces/default/secrets/mysecret uid: 55a84b3e-e597-4f95-aaac-5bf8543fbfc7 type: Opaque
|
3.3)在pod中或deployment中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| [root@localhost config]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox image: harbor.jettech.com/rancher/busybox:latest command: [ "httpd" ] args: [ "-f" ] env: - name: USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
|
然后打印它的环境变量列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [root@localhost config]# kubectl exec -it busybox-d677b8c47-6frp4 -- env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-d677b8c47-6frp4 TERM=xterm USERNAME=wubo PASSWORD=123456aA MY_LIMITS_MEM=8589934592 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 KUBERNETES_SERVICE_HOST=10.43.0.1 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 HOME=/root
|
4)valueFrom: resourceFieldRef【resourceFieldRef下面有
resource】案列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| [root@localhost configmap]# kubectl create -f nginx.yaml [root@localhost configmap]# cat nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f" ] env: #resourceFieldRef->resource - name: MY_REQUESTS_CPU valueFrom: resourceFieldRef: resource: requests.cpu - name: MY_REQUESTS_MEM valueFrom: resourceFieldRef: resource: requests.memory - name: MY_LIMITS_CPU valueFrom: resourceFieldRef: resource: limits.cpu - name: MY_LIMITS_MEM valueFrom: resourceFieldRef: resource: limits.memory
resources: requests: cpu: "250m" memory: "64Mi" limits: cpu: "4000m" memory: "8Gi" #restartPolicy: OnFailure
|
然后打印它的环境变量列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [root@localhost config]# kubectl exec -it busybox-759998fd64-k295s -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-759998fd64-k295s TERM=xterm MY_REQUESTS_CPU=1 MY_REQUESTS_MEM=67108864 MY_LIMITS_CPU=4 MY_LIMITS_MEM=8589934592 KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 KUBERNETES_SERVICE_HOST=10.43.0.1 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 HOME=/root
|
2)valueFrom configMapKeyRef案列如下:
容器的启动脚本或应用程序调用或处理这些环境变量、即可实现容器化应用的配置。相较于命令行参数的方式来说,使用环境变量的配置方式更清晰、易懂,尤其是对于首次使用相关容器的用户来说,这种方式能够快速了解容器的配置方式,不过这两种配置方式有一个共同缺陷:无法在容器应用运行过程中更新环境变量从而达到更新应用目的。这通常意味着用户不得不为production、development和qa等不同的环境分别配置Pod资源。好在,用户还有ConfigMap资源可用
ConfigMap诞生的原因
分布式环境中,基于负载、容错性等需求的考虑,几乎所有的服务都需要在不同的机器节点上部署不止一个实例。随着程序功能的日益复杂,程序的配置日益增多,而且配置文件的修改频率通常远远大于代码本身,这种情况下,有时仅仅是一个配置内容的修改,就不得不重新将代码提交到SVN/Git、打包、分发上线的流程。部署规则较大的场景中,分发上线工作即繁杂又沉重。
究其根本,所有的这些麻烦都是由于配置和代码在管理和发布的过程中不加区分所致。配置本身源于代码,是为了提高代码的灵活性而提取出来的一些经常变化的或需要定制的内容,而正是配置的这种天生变化特性为部署过程中带来了不小的麻烦,也最终催生了分布式系统配置管理系统,将配置内容从代码中完全分离出来,及时可靠高效地提供配置访问和更新服务。
国内分布式配置中心相关的开源项目有 Diamond(阿里)、Apollo(携程)、Qconf(奇虎360)和disconf(百度)等。
ConfigMap作为分布式系统的Kubernetes也提供了统一配置管理方案——ConfigMap。Kubernetes基于ConfigMap对象实现了将配置文件从容器镜像中解耦,从而增强了容器应用的可移植性。简单来说,一个ConfigMap对象就是一系列配置数据的集合,这些数据可“注入”到Pod对象中,并为容器应用所使用,注入方式有挂载为存储卷和传递为环境变量两种
ConfigMap对象创建 是namespace级别的
ConfigMap创建的方式与其它资源一样有两种:
- kubectl create configmap 命令直接创建
- 通过资源配置清单创建
ConfigMap以上两种对于ConfigMap都算是比较常用的创建方式,通过kubectl create configmap命令,用户可以根据目录、文件或者直接创建ConfigMap对象,命令的语法格式如下: kubectl create configmap <map-name> <data-source>
<map-name>
为ConfigMap对象的名称,<data-source>
是数据源,数据源可以直接给定K/V类型的数据,也可以指定文件以及目录来获取,无论是哪一种数据源,它都要转换为ConfigMap对象中的Key-Value数据,其中Key由用户在命令行给出或是文件数据源的文件名,它仅能由字母、数字、连接号和点号组成,而Value则是直接值或文件数据源的内容。
1.通过键值创建ConfigMap
利用kubectl create configmap
命令使用--from-literal
选项可在命令行直接给出键值对来创建ConfigMap对象,重复使用此选项则可以传递多个键值对,命令格式如下: kubectl create configmap cm1 --from-literal=name=wubo
例如下面用命令创建special-config configmap时传递来两个键值对: 键值对第一个key为mysql_ip值为172.16.10.5键值对第二个key为mysql_port值为3306
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [root@localhost configmap]# kubectl create configmap mysql-config --from-literal=mysql_ip=172.16.10.5 --from-literal=mysql_port=3306 -n default
[root@localhost configmap]# kubectl get configmap mysql-config NAME DATA AGE mysql-config 2 53s
使用kubectl describe或-o yaml可以看到configmap中的原始数据 [root@localhost configmap]# kubectl get configmap mysql-config -o yaml apiVersion: v1 data: mysql_ip: 172.16.10.5 mysql_port: "3306" kind: ConfigMap metadata: creationTimestamp: "2022-01-26T03:54:51Z" name: mysql-config namespace: default resourceVersion: "601548" uid: 866f5011-7f14-43ba-88d1-53682a12ac6e
[root@localhost configmap]# kubectl describe configmap mysql-config Name: mysql-config Namespace: default Labels: <none> Annotations: <none>
Data ==== mysql_ip: ---- 172.16.10.5 mysql_port: ---- 3306
BinaryData ====
Events: <none>
|
此类方式提供的数据量有限,一般是在仅通过有限的几个数据项即可为Pod资源提供足够的配置信息时使用。
1)定义configmap对象
1
| [root@localhost config]# kubectl create configmap mysql-config --from-literal=mysql_ip=172.16.10.1 --from-literal=mysql_name=root --from-literal=mysql_password=123456aA -n default
|
2)deployment中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| [root@localhost config]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox image: harbor.jettech.com/rancher/busybox:latest command: [ "httpd" ] args: [ "-f" ] env: - name: MYSQL_IP valueFrom: configMapKeyRef: name: mysql-config key: mysql_ip - name: MYSQL_NAME valueFrom: configMapKeyRef: name: mysql-config key: mysql_name - name: MYSQL_PASSWORD valueFrom: configMapKeyRef: name: mysql-config key: mysql_password
|
3)打印变量
1 2 3 4 5 6 7 8
| [root@localhost config]# kubectl exec -it busybox-655554f856-b6f8h -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-655554f856-b6f8h TERM=xterm MYSQL_IP=172.16.10.1 MYSQL_NAME=root MYSQL_PASSWORD=123456aA HOME=/root
|
利用kubectl create configmap
命令使用--from-file
选项可基于文件内容来创建ConfigMap对象,它的命令格式如下: kubectl create configmap <configmap_name> --from-file=<[key=]source
1.准备配置文件 我们先准备好要载入容器的配置文件,等下通过kubectl create configmap config_name –from-file 来指定我们的配置文件即可创建configmap,以下准备了一个elasticsearch.yaml的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| [root@localhost configmap]# cat config/elasticsearch.yaml cluster.name: elasticsearch node.name: elastic path.data: /usr/local/elastic7.4/data path.logs: /usr/local/elastic7.4/logs bootstrap.memory_lock: true network.host: 0.0.0.0 network.tcp.no_delay: true network.tcp.keep_alive: true network.tcp.reuse_address: true network.tcp.send_buffer_size: 256mb network.tcp.receive_buffer_size: 256mb transport.tcp.port: 9300 transport.tcp.compress: true http.max_content_length: 200mb http.cors.enabled: true http.cors.allow-origin: "*" http.port: 9200 cluster.initial_master_nodes: ["127.0.0.1:9300"] xpack.security.enabled: true xpack.license.self_generated.type: basic xpack.security.transport.ssl.enabled: true xpack.monitoring.collection.enabled: true
|
2.通过文件创建configMap 如果指定文件创建configmap的时候没有指定key,那么kubernetes则以文件名称为key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [root@localhost configmap]# kubectl create configmap elastic-configmap --from-file=config/elasticsearch.yaml
[root@localhost configmap]# kubectl describe configmap elastic-configmap Name: elastic-configmap Namespace: default Labels: <none> Annotations: <none>
Data ==== elasticsearch.yaml: #我们没有指定key,默认以文件名称为key ---- cluster.name: elasticsearch node.name: elastic path.data: /usr/local/elastic7.4/data path.logs: /usr/local/elastic7.4/logs bootstrap.memory_lock: true network.host: 0.0.0.0 network.tcp.no_delay: true network.tcp.keep_alive: true network.tcp.reuse_address: true network.tcp.send_buffer_size: 256mb network.tcp.receive_buffer_size: 256mb transport.tcp.port: 9300 transport.tcp.compress: true http.max_content_length: 200mb http.cors.enabled: true http.cors.allow-origin: "*" http.port: 9200 cluster.initial_master_nodes: ["127.0.0.1:9300"] xpack.security.enabled: true xpack.license.self_generated.type: basic xpack.security.transport.ssl.enabled: true xpack.monitoring.collection.enabled: true
BinaryData ====
Events: <none>
|
如果需要指定键名称,如下在文件前面写入key名称即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| [root@localhost configmap]# kubectl create configmap elastic-configmap --from-file=jettech-elastic-key=config/elasticsearch.yaml configmap/elastic-configmap created [root@localhost configmap]# kubectl describe configmap elastic-configmap Name: elastic-configmap Namespace: default Labels: <none> Annotations: <none>
Data ==== jettech-elastic-key: #指定的key ---- cluster.name: elasticsearch node.name: elastic path.data: /usr/local/elastic7.4/data path.logs: /usr/local/elastic7.4/logs bootstrap.memory_lock: true network.host: 0.0.0.0 network.tcp.no_delay: true network.tcp.keep_alive: true network.tcp.reuse_address: true network.tcp.send_buffer_size: 256mb network.tcp.receive_buffer_size: 256mb transport.tcp.port: 9300 transport.tcp.compress: true http.max_content_length: 200mb http.cors.enabled: true http.cors.allow-origin: "*" http.port: 9200 cluster.initial_master_nodes: ["127.0.0.1:9300"] xpack.security.enabled: true xpack.license.self_generated.type: basic xpack.security.transport.ssl.enabled: true xpack.monitoring.collection.enabled: true
BinaryData ====
Events: <none>
|
通过目录创建ConfigMap
如果配置文件数量较多时,kubectl还提供了基于目录直接将多个文件分别收纳为键值数据的ConfigMap资源创建方式,将--from-file
选项后所跟的路径指向一个目录路径就能把目录下的所有文件一同创建同一个 ConfigMap 资源中,命令格式如下: kubectl create configmap <configmap_name> --from-file=<path-to-directory>
如下命令所示,将/data/configs/nginx/conf.d目录下的所有文件都保存于nginx-config-files对象中
1 2 3 4 5 6 7 8
| [root@localhost configmap]# ls config/ elasticsearch.yaml my.cnf nginx.conf
[root@localhost configmap]# kubectl create configmap elastic-configmap --from-file=config/ configmap/elastic-configmap created
[root@localhost configmap]# kubectl describe configmap elastic-configmap
|
查看创建的configmap对象
注意:kubectl describe 和 kubectl get -o yaml 命令都可以显示由文件创建的键值,不过两者使用的键和值之间的分隔符不同
通过资源配置清单创建
基于配置文件创建ConfigMap时,它所使用的字段通常包括apiVersion
、kind
和metadata字段,以及用于存储数据的关键字段data
。 下面就使用配置清单创建一个ConfigMap
1 2 3 4 5 6 7 8 9 10 11 12 13
| [root@localhost configmap]# cat cm1.yaml apiVersion: v1 kind: ConfigMap metadata: name: configmap-demo namespace: default data: log_level: INFO es_file: config/elasticsearch.yaml
[root@localhost configmap]# kubectl create -f cm1.yaml
[root@localhost configmap]# kubectl describe configmap configmap-demo
|
如果配置信息来自文件内容时,则使用配置清单创建ConfigMap资源的便捷性还不如直接通过命令行的方式,因此建议直接使用命令行加载文件或目录的方式进行创建,为了便于配置留存,可以在创建完成后使用 get -o yaml命令获取到相关信息后在进行编辑留存。
pod使用:两种方式,注入方式有挂载为存储卷和传递为环境变量两种
1)ConfigMap载入Pod方式之环境变量
在Pod中,获取环境变量值的方式之一就包括ConfigMap对象中的数据,这一点通过在env字段中为valueFrom内嵌configMapKeyRef对象即可实现,格式如下:
1 2 3 4 5
| valueFrom: configMapKeyRef: key: name: optional:
|
字段name值为要引用的ConfigMap对象的名称 字段key可用于指定要引用ConfigMap对象中某键的键名 字段optional用于为当前Pod资源指明此引用是否为可选
此类环境变量的使用方式与直接定义的环境变量并无区别,它们可被用于容器的启动脚本或直接传递给容器应用等。
传递ConfigMap中的单个Key
下面示例中包含了两个资源,彼此之间使用 “–” 相分隔,第一个资源是名为 configmap-demo 的 ConfigMap 对象,它包含了两个键值数据;第二个资源是名为 busybox 的 Pod对象,它通过环境变量引用了configmap-demo对象中的键值数据,并将其直接传给了自定义运行的容器应用httpd:
1 2 3 4 5 6 7 8 9 10
| [root@localhost configmap]# cat cm1.yaml apiVersion: v1 kind: ConfigMap metadata: name: configmap-demo namespace: default data: log_level: INFO httpd_port: "8080" es_file: config/elasticsearch.yaml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f","-p","$(HTTPD_PORT)","$(ES_FILE)" ] env: - name: HELLO_WORLD value: just a demo - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: MY_NODE_IP valueFrom: fieldRef: fieldPath: status.hostIP - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: HTTPD_PORT #定义第一个变量名称 valueFrom: #引用变量 configMapKeyRef: #引用来自configMap的变量 name: configmap-demo #指定ConfigMap的名称 key: httpd_port #指定ConfigMap中要引用的key名称 - name: LOG_LEVEL valueFrom: configMapKeyRef: name: configmap-demo key: log_level - name: ES_FILE valueFrom: configMapKeyRef: name: configmap-demo key: es_file
|
注意,在command和args字段中引用环境变量要使用$(VAR_NAME)
的格式,待上面配置文件中的资源创建完成后,可以通过如下命令验证Pod资源监听的端口等配置信息是否为 configmap-demo中定义的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| [root@localhost configmap]# kubectl exec -it busybox-86d74c5877-dqnw2 -- ps aux PID USER TIME COMMAND 1 root 0:00 httpd -f -p 8080 config/elasticsearch.yaml 20 root 0:00 ps aux
[root@localhost configmap]# kubectl exec -it busybox-86d74c5877-dqnw2 -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-86d74c5877-dqnw2 MY_POD_NAMESPACE=default HTTPD_PORT=8080 LOG_LEVEL=INFO ES_FILE=config/elasticsearch.yaml HELLO_WORLD=just a demo MY_NODE_NAME=172.16.10.21 MY_NODE_IP=172.16.10.21 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 KUBERNETES_SERVICE_HOST=10.43.0.1 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 TERM=xterm HOME=/root
[root@localhost configmap]# kubectl exec -it busybox-86d74c5877-dqnw2 -- env | grep HTTPD HTTPD_PORT=8080
|
注意:创建引用了ConfigMap资源的Pod对象时,被引用的资源必须事先存在,否则将无法启动相应的容器,直到被依赖的资源创建完成为止。不过,那些未引用不存在的ConfigMap资源的容器将不受此影响。另外,ConfigMap是名称空间级别的资源,它必须与引用它的Pod资源在同一个名称空间中。
传递ConfigMap中的所有Key
如果我们要引入的变量有很多呢?此时,为容器依次配置相应的环境变量是一件很烦躁的事情,而且容易出错,对此,Pod资源支持在容器中使用envFrom
字段直接将ConfigMap资源中的所有键值一次性地完整导入。格式如下:
1 2 3 4 5 6 7 8 9
| spec: containers: - name: busybox image: docker.io/library/busybox:1.28.4 envFrom: - prefix: HTCPG_ configMapRef: name: configmap_name optional: true
|
envFrom字段是对象列表,可用于同时从多个ConfigMap对象导入键值数据。 为了避免从多个ConfigMap引入键值数据时产生键key重名(名称冲突),可以在每个引用中将被导入的键使用 prefix 字段指定一个特性的前缀,如 HTCPG_
一类的字符串,于是,ConfigMap对象中的httpd_port
将成为Pod资源中名为HTCPG_httpd_port
的变量。
如果键名中使用了连接线 “-“,那么在转换为变量时,连接线将自动被替换为下划线 “_“。
如下:
1 2 3 4 5 6 7 8 9 10
| [root@localhost configmap]# cat cm1.yaml apiVersion: v1 kind: ConfigMap metadata: name: configmap-demo namespace: default data: log_level: INFO httpd_port: "8080" es_file: config/elasticsearch.yaml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f","-p","$(HTCPG_httpd_port)","$(HTCPG_es_file)" ] envFrom: - prefix: HTCPG_ configMapRef: name: configmap-demo optional: false #- prefix: HTCPG1_ # configMapRef: # name: configmap-demo1 # optional: false
|
待Pod资源创建完成后,可通过查看其环境变量验证其导入的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| [root@localhost configmap]# kubectl exec -it busybox-6c685648cc-ltkdb -- ps aux PID USER TIME COMMAND 1 root 0:00 httpd -f -p 8080 config/elasticsearch.yaml 50 root 0:00 ps aux [root@localhost configmap]# kubectl exec -it busybox-6c685648cc-ltkdb -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=busybox-6c685648cc-ltkdb HTCPG_es_file=config/elasticsearch.yaml HTCPG_httpd_port=8080 HTCPG_log_level=INFO KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 KUBERNETES_SERVICE_HOST=10.43.0.1 TERM=xterm HOME=/root
|
注意:从ConfigMap对象导入资源时,prefix为可选字段,不定义时,所有变量名同ConfigMap中的键名。如果不存在键名冲突的可能性,例如从单个ConfigMap对象导入变量或在ConfigMap对象中定义键名时依然添加了特定的前缀,那么省略前缀的定义即不会导致键名冲突,又能保持变量的简洁。
2)ConfigMap载入Pod方式之存储卷
若ConfigMap对象中的键值来源于较长的文件内容,那么使用环境变量将其导入会使得变量值占据过多的内存空间而不易清理。此类数据通常用于为容器应用提供配置文件,因此将其内存直接作为文件进行引用方为较好的选择,其实现方式是,在定义Pod资源时,将此类ConfigMap对象配置为ConfigMap类型的存储卷,而后由容器将其挂载至特定的挂载点后直接进行访问。
2.1 挂载整个存储卷
关联为Pod资源的存储卷时,ConfigMap对象中的每个键都对应地对应为一个文件,键名转为文件名,而值则为相应文件的内容,即便是通过直接创建的键值数据,也一样表现为文件视图。挂载于容器上之后,由键值数据表现出的文件位于挂载点目录中,容器中的进程可直接读取这些文件的内容。
配置Pod资源时,基于存储卷的方式引用ConfigMap对象的方法非常简单,仅需要指明卷名称及要应用的ConfigMap对象名称即可。
2.1.1).创建配置文件 我们下面创建三个Nginx配置文件,然后将这三个配置文件挂载到Nginx的配置目录中
1 2
| [root@localhost configmap]# ls config/ elasticsearch.yaml my.cnf nginx.conf
|
2.1.2).创建ConfigMap对象
基于目录创建config-files对象
1 2 3
| [root@localhost configmap]# kubectl create configmap config-files --from-file=config/
[root@localhost configmap]# kubectl describe cm config-files -n default
|
2.1.3).创建Pod资源清单来引用ConfigMap对象并将其挂载至相应指定的目录中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] #args: [ "-f","-p","$(HTCPG_httpd_port)","$(HTCPG_es_file)" ] args: [ "-f" ] volumeMounts: #卷挂载配置 - name: config #卷名称 mountPath: /tmp #挂载到容器中的路径目录 readOnly: true #是否只读 volumes: #卷配置 - name: config #定义一个卷名称 configMap: #configMap配置 name: config-files #指定configMap名称
|
2.1.4) 查看Pod挂载状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [root@localhost configmap]# kubectl describe pod/busybox-679b55c4fb-x6wdc | grep -A 2 Mounts Mounts: /tmp from config (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-cztvq (ro)
[root@localhost configmap]# kubectl exec -it pod/busybox-679b55c4fb-x6wdc -- ls /tmp/ -al total 0 drwxrwxrwx 3 root root 117 Jan 26 07:20 . drwxr-xr-x 1 root root 51 Jan 26 07:20 .. drwxr-xr-x 2 root root 64 Jan 26 07:20 ..2022_01_26_07_20_49.547544433 lrwxrwxrwx 1 root root 31 Jan 26 07:20 ..data -> ..2022_01_26_07_20_49.547544433 lrwxrwxrwx 1 root root 25 Jan 26 07:20 elasticsearch.yaml -> ..data/elasticsearch.yaml lrwxrwxrwx 1 root root 13 Jan 26 07:20 my.cnf -> ..data/my.cnf lrwxrwxrwx 1 root root 17 Jan 26 07:20 nginx.conf -> ..data/nginx.conf
|
2.2 挂载存储卷中的部分键值
有时候,用户很可能不期望在容器中挂载某ConfigMap存储卷中的所有文件,这在通过一个ConfigMap对象为单个Pod资源中的多个容器分别提供配置时尤其常见。例如前面示例中,用户可能只期望在容器中挂载ConfigMap存储卷后只“导出”其中出my.cnf和elasticsearch.yaml文件.此时将其 volumes 配置段改为如下所示的内容即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] #args: [ "-f","-p","$(HTCPG_httpd_port)","$(HTCPG_es_file)" ] args: [ "-f" ] volumeMounts: #卷挂载配置 - name: config #卷名称 mountPath: /tmp #挂载到容器中的路径目录 readOnly: true #是否只读 volumes: #卷配置 - name: config #定义一个卷名称 configMap: #configMap配置 name: config-files #指定configMap名称 items: #config-files ConfigMap中的键 - key: my.cnf #指定要挂载键 默认文件名就是key,原文件名(key的名称) path: my.cnf #挂载的路径,修改之后的文件名(key的名称) mode: 0644 #挂载后的文件权限 - key: elasticsearch.yaml path: elasticsearch.yaml mode: 0644
|
1)假如不想以key名作为配置文件名可以引入items
字段,在其中逐个指定要用相对路径path
替换的key
2)items还有一个作用,就是只有items下的key对应的文件会被挂载到容器中。
ConfigMap存储卷的items字段的值是一个对象列表,可嵌套使用的字段有三个,具体如下:
- key:要引用的键名称,必选字段。
- path:对应的键于挂载点目录中生成的文件相对路径,可以不同于键名称,必选字段。
- mode:文件的权限模型,可用范围为0到0777。
验证:
1 2 3 4 5 6
| [root@localhost configmap]# kubectl exec -it pod/busybox-67c86587bf-5hjfm -- ls /tmp/ elasticsearch.yaml my.cnf [root@localhost configmap]# kubectl describe pod/busybox-67c86587bf-5hjfm | grep -A 2 Mounts Mounts: /tmp from config (ro) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4tsq4 (ro)
|
2.3 独立挂载存储卷中的键值
上面的两种方式中,无论是装载所有文件还是部分文件,挂载点目录下原有的文件都会被隐藏或者称为覆盖,在我们没有挂载的时候,/etc/nginx/conf.d目录下有default.conf文件,当我们挂载之后default.conf就被隐藏或者说覆盖掉了,但有时候我们希望挂载进的文件不覆盖相应目录下的其它文件,这个时候就可以通过volumeMounts
属性中的subPath
字段来解决,它可以支持用户从存储卷挂载单个文件或者单个目录而非整个存储卷。
subPath的使用方法一共有两种:
1. 同一个pod中多容器挂载同一个卷时提供隔离
2. 将configMap和secret作为文件挂载到容器中而不覆盖挂载目录下的文件
主要解释第一点,按照k8s官网的解释,subPath在是挂载卷中的存储目录,不指定默认存储在卷的根目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] #args: [ "-f","-p","$(HTCPG_httpd_port)","$(HTCPG_es_file)" ] args: [ "-f" ] volumeMounts: #卷挂载配置 - name: mysql-config #卷名称 mountPath: /etc/my.cnf #挂载到容器中的路径目录 不指定subPath 那么/etc/my.cnf当做目录 subPath: my.cnf #subPath此时指的就是configMap中的key,也就是文件名 readOnly: true #是否只读 - name: es-config #卷名称 mountPath: /etc/elasticsearch.yaml #挂载到容器中的路径目录 subPath: elasticsearch.yaml readOnly: true #是否只读 volumes: #卷配置 - name: mysql-config #定义一个卷名称 configMap: #configMap配置 name: mysql-config-files #指定configMap名称 - name: es-config #定义一个卷名称 configMap: #configMap配置
|
1
| \# 如果没有subPath,则//etc/my.cnf和/etc/elasticsearch.yaml将被当成一个目录而不是文件,根据Linux挂载的概念,该目录下的所有文件会被覆盖。
|
subPath此时指的就是configMap中的key,也就是文件名
测试一下:
首先创建一个包含两个container的pod,对应的yaml文件如下,两个container挂载目录下的文件都会存储在卷的根目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox-mysql image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f" ] volumeMounts: #- name: mysql-config - name: es-config mountPath: /etc/wubo #subPath: my.cnf #readOnly: false - name: busybox-es image: docker.io/library/busybox:1.28.4 command: [ "/bin/sh" ] args: [ "-c","sleep 30000" ] volumeMounts: - name: es-config mountPath: /etc/wubo #subPath: elasticsearch.yaml #readOnly: false volumes: - name: es-config hostPath: path: /opt/wubo type: Directory
|
接下来做一个简单的验证,首先进到busybox-mysql中在/etc/wubo/a.txt下创建一个a.txt的文件,退出之后进入busybox-es的/etc/wubo/a.txt目录,因为未指定subPath,文件会直接存储在卷的根目录下,所以在busybox-es下可以看见busybox-mysqlr刚刚新建的a.txt文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| root@localhost configmap]# kubectl exec -it pod/busybox-6fbbc45c5c-qfxpw -c busybox-mysql -- sh /etc # cd etc/wubo/ /etc/wubo # mkdir wuqi /etc/wubo # cd wuqi/ /etc/wubo/wuqi # touch a /etc/wubo/wuqi # echo aaa > a /etc/wubo/wuqi # cat a aaa
[root@localhost configmap]# kubectl exec -it pod/busybox-6fbbc45c5c-qfxpw -c busybox-es -- sh /etc # cd etc/wubo/wuqi /etc/wubo # cd wuqi/ /etc/wubo/wuqi # cat a aaa
|
接下来试着加入subPath,对应的yaml文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox-mysql image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] args: [ "-f" ] volumeMounts: #- name: mysql-config - name: es-config mountPath: /etc/wubo subPath: mysql #readOnly: false - name: busybox-es image: docker.io/library/busybox:1.28.4 command: [ "/bin/sh" ] args: [ "-c","sleep 30000" ] volumeMounts: - name: es-config mountPath: /etc/wubo subPath: es #readOnly: false volumes: - name: es-config hostPath: path: /opt/wubo type: Directory
|
同样进入两个容器的挂载目录下创建新文件,可以看到subPath起到了隔离的作用,在另一个容易看不到目录和文件了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [root@localhost configmap]# kubectl exec -it pod/busybox-f6966c85-b4fvl -c busybox-mysql -- sh / # cd etc/wubo /etc/wubo # mkdir wuqi /etc/wubo # cd wuqi/ /etc/wubo/wuqi # echo aaa > a /etc/wubo/wuqi # cat a aaa [root@localhost configmap]# kubectl exec -it pod/busybox-f6966c85-b4fvl -c busybox-es -- sh / # cd etc/ /etc # ls group hostname hosts localtime network passwd resolv.conf shadow wubo /etc # cd wubo/ /etc/wubo # ls /etc/wubo # pwd /etc/wubo
|
例如下面示例/etc 目录中挂载一个elasticsearch.yaml和my.cnf 文件,并且不覆盖原来目录etc下的原有的 文件。
删除之前看下容器里面的文件内容
1 2 3
| [root@localhost configmap]# kubectl exec -it pod/busybox-67c86587bf-5hjfm -- ls /etc group hosts network resolv.conf hostname localtime passwd shadow
|
是没有 elasticsearch.yaml和my.cnf两个文件的
2.3.1) 删除原来创建的ConfigMap和Pod
1 2
| [root@localhost configmap]# kubectl delete cm config-files [root@localhost configmap]# kubectl delete -f busybox.yaml
|
2.3.2)创建两个ConfigMap,分别用于测试文件elasticsearch.yaml和my.cnf
1 2 3 4
| [root@localhost configmap]# kubectl create configmap mysql-config-files --from-file=./config/mysql/my.cnf configmap/mysql-config-files created [root@localhost configmap]# kubectl create configmap es-config-files --from-file=./config/es/elasticsearch.yaml configmap/es-config-files created
|
2.3.3)创建Pod资源配置清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| [root@localhost configmap]# cat busybox.yaml apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default labels: {name: busybox} spec: replicas: 1 selector: matchLabels: {name: busybox} template: metadata: name: busybox labels: {name: busybox} spec: containers: - name: busybox #image: harbor.jettech.com/jettechtools/busybox:1.21.4 #image: 172.16.10.5:5000/library/busybox:1.21.4 image: docker.io/library/busybox:1.28.4 command: [ "httpd" ] #args: [ "-f","-p","$(HTCPG_httpd_port)","$(HTCPG_es_file)" ] args: [ "-f" ] volumeMounts: #卷挂载配置 - name: mysql-config #卷名称 mountPath: /etc/my.cnf #挂载到容器中的路径目录 subPath: my.cnf readOnly: true #是否只读 - name: es-config #卷名称 mountPath: /etc/elasticsearch.yaml #挂载到容器中的路径目录 subPath: elasticsearch.yaml readOnly: true #是否只读 volumes: #卷配置 - name: mysql-config #定义一个卷名称 configMap: #configMap配置 name: mysql-config-files #指定configMap名称 - name: es-config #定义一个卷名称 configMap: #configMap配置 name: es-config-files #指定configMap
|
2.3.4)查看Pod对象挂载状态
1 2 3 4 5 6 7 8 9 10
| [root@localhost configmap]# kubectl exec -it pod/busybox-7548665cfc-26kc6 -- ls /etc/ elasticsearch.yaml localtime resolv.conf group my.cnf shadow hostname network hosts passwd [root@localhost configmap]# kubectl describe pod/busybox-7548665cfc-26kc6 | grep -A 3 Mounts Mounts: /etc/elasticsearch.yaml from es-config (ro,path="elasticsearch.yaml") /etc/my.cnf from mysql-config (ro,path="my.cnf") /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7sfvm (ro)
|
使用ConfigMap资源的注意事项
在Pod资源中调用ConfigMap对象时需要注意以下几个问题。
- 以存储卷访问引用的ConfigMap必须在Pod启动前存在,除非在Pod中将他们全部标记为
optional
,否则会导致Pod无法正常启动的错误,同样即使存在ConfigMap,在引用ConfigMap中的键不存在时,也会导致一样的错误。
- 当以环境变量注入的ConfigMap中的键不存在时会被忽略,Pod可以正常启动,但错误引用的信息会以
InvalidVariableNames
事件记录于日志中。
- ConfigMap是namespace级的资源,因此引用它的Pod必须处于同一名称空间中。
- kubelet不支持引用Kubernetes API Server上不存在的ConfigMap,这包括那些通过kubelet的
--manifest-url
或--config
选项,以及 kubelet REST API 创建的Pod。
redis完整案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
| [root@jettoloader redis]# cat jettoloader-redis-develop-poc.yaml apiVersion: v1 kind: Namespace metadata: name: jettoloader-poc --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jettoloader-redis-poc-pvc namespace: jettoloader-poc spec: accessModes: #访问模式 #- ReadWriteOnce #- ReadWriteOncePod - ReadWriteMany #- ReadOnlyMany resources: #申请资源,1Gi存储空间 requests: storage: 1Gi storageClassName: jettech-nfs-storage #selector: # matchLabels: # name: "wubo-pv1" # matchExpressions: # - {key: environment, operator: In, values: [dev]} --- apiVersion: v1 kind: ConfigMap metadata: name: jettoloader-redis-poc-conf namespace: jettoloader-poc data: redis.conf: | bind 0.0.0.0 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised no #pidfile /var/run/redis_6379.pid pidfile /data/redis_6379.pid loglevel notice logfile /var/log/redis/redis.log #logfile /data/redis.log databases 16 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb #dir /var/lib/redis dir /data slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 requirepass "123456aA" appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes --- apiVersion: v1 kind: Service metadata: labels: {name: jettoloader-redis-poc-server} name: jettoloader-redis-poc-server namespace: jettoloader-poc spec: ports: - {name: t16379, nodePort: 16379, port: 6379, protocol: TCP, targetPort: t6379} selector: {name: jettoloader-redis-poc-pod} type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: labels: {name: jettoloader-redis-poc-deploy} name: jettoloader-redis-poc-deploy namespace: jettoloader-poc spec: replicas: 1 selector: matchLabels: {name: jettoloader-redis-poc-pod} template: metadata: labels: {name: jettoloader-redis-poc-pod} name: jettoloader-redis-poc-pod spec: #affinity: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: # - matchExpressions: # - key: envtype # operator: In # values: # - poc #initContainers: containers: - name: jettoloader-redis-poc-container image: 172.16.10.21:5000/jettechtools/redis:3.2 #lifecycle: # postStart: # exec: # command: ["/bin/sh","-c","mkdir -p /var/log/redis && ln -sf /data/redis.log /var/log/redis/redis.log"] #preStop: #env: # - {name: APPLY_PORT, value: '8097'} securityContext: privileged: true ports: - {containerPort: 6379, name: t6379, protocol: TCP } #volumeMounts: #- name: redis-conf # mountPath: /etc/redis/ #- name: redis-data # mountPath: /data volumeMounts: - name: jettoloader-redis-poc-conf mountPath: /etc/redis/redis.conf subPath: redis.conf #cm中的key readOnly: true - name: jettoloader-redis-poc-data mountPath: /data command: - "redis-server" args: - "/etc/redis/redis.conf" - "--appendonly yes" imagePullPolicy: Always #[Always | Never | IfNotPresent] securityContext: privileged: true #hostNetwork: true restartPolicy: Always #Never volumes: - name: jettoloader-redis-poc-conf configMap: name: jettoloader-redis-poc-conf items: - key: redis.conf path: redis.conf - name: jettoloader-redis-poc-data persistentVolumeClaim: claimName: jettoloader-redis-poc-pvc #volumes: #- name: redis-conf # nfs: # server: 172.16.10.4 # path: /var/ftp/jettech/jettoloader/tools/poc/redis/conf #- name: redis-data # nfs: # server: 172.16.10.4 # path: /var/ftp/jettech/jettoloader/tools/poc/redis/data
|