Kubernetes——应用程序配置管理及 ConfigMap 资源

应用程序配置管理及 ConfigMap 资源

  说到配置中心,大家接触过微服务的话,应该不陌生,像国内的分布式配置中心相关开源项目有 Diamond(阿里)、Apollo(携程)、Qconf(奇虎360)和 disconf(百度)等。

  作为分布式系统的 Kubernetes 也提供了统一配置管理方案——ConfigMap。

  Kubernetes 基于 ConfigMap 对象实现了将配置文件从容器镜像中解耦,从而增强了容器应用的可移植性。简单来说,一个 ConfigMap 对象就是一系列配置数据的集合,这些数据可 "注入" 到 Pod 对象中,并为容器应用所用,注入方式有挂载为存储卷和传递为环境变量两种。

  ConfigMap 对象将配置数据以键值对的形式进行存储,这些数据可以在 Pod 对象中使用或者为系统组件提供配置。无论应用程序如何使用 ConfigMap 对象中的数据,用户都完全可以通过在不同的环境中创建名称相同但内容不同的 ConfigMap 对象,从而为不同环境中同一功能的 Pod 资源提供不同的配置信息,实现应用与配置的灵活勾兑。

一、创建 ConfigMap 对象

  Kubernetes 的不少资源既可以使用 kubectl create 命令创建,也可以使用清单创建,例如前面讲到的 namespace。

  ConfigMap 是另一个两种创建方式都比较常用的资源。而且,通过使用 "kubectl create configmap" 命令,用户可以根据目录、文件或直接值创建 ConfigMap对象。命令的语法格式如下所示:

root@mh-k8s-master-247-10 ~]# kubectl create configmap --help
Create a configmap based on a file, directory, or specified literal value.

 A single configmap may package one or more key/value pairs.

 When creating a configmap based on a file, the key will default to the basename of the file, and
the value will default to the file content.  If the basename is an invalid key, you may specify an
alternate key.

 When creating a configmap based on a directory, each file whose basename is a valid key in the
directory will be packaged into the configmap.  Any directory entries except regular files are
ignored (e.g. subdirectories, symlinks, devices, pipes, etc).

Aliases:
configmap, cm

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
  
  # Create a new configmap named my-config from the key=value pairs in the file
  kubectl create configmap my-config --from-file=path/to/bar
  
  # Create a new configmap named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/bar.env

Options:
      --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or
map key is missing in the template. Only applies to golang and jsonpath output formats.
      --append-hash=false: Append a hash of the configmap to its name.
      --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the
object that would be sent, without sending it. If server strategy, submit server-side request
without persisting the resource.
      --from-env-file='': Specify the path to a file to read lines of key=val pairs to create a
configmap (i.e. a Docker .env file).
      --from-file=[]: Key file can be specified using its file path, in which case file basename
will be used as configmap key, or optionally with a key and file path, in which case the given key
will be used.  Specifying a directory will iterate each named file in the directory whose basename
is a valid configmap key.
      --from-literal=[]: Specify a key and literal value to insert in configmap (i.e.
mykey=somevalue)
  -o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
      --save-config=false: If true, the configuration of current object will be saved in its
annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to
perform kubectl apply on this object in the future.
      --template='': Template string or path to template file to use when -o=go-template,
-o=go-template-file. The template format is golang templates
[http://golang.org/pkg/text/template/#pkg-overview].
      --validate=true: If true, use a schema to validate the input before sending it

Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1]
[--dry-run=server|client|none] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@mh-k8s-master-247-10 ~]# 

  其中,<map-name> 即为 ConfigMap 对象的名称,而 <data-source> 是数据源,它可以通过直接值、文件或目录来获取。无论是哪一种数据源供给方式,它都要转换为 ConfigMap 对象中的 Key-Value 数据,其中 Key 由用户在命令行给出或是文件数据源的文件名,它仅能由字母、数字、连接号和点号组成,而 Value 则是直接值或文件数据源的内容。

1、利用直接值创建

  为 "kubectl create configmap" 命令使用 "--from-literal" 选项可在命令行直接给出键值对来创建 ConfigMap 对象,重复使用此选项则可以传递多个键值对。命令格式如下:

kubectl create configmap configmap_name --from-literal=key-name-1=value-1 --from-literal=key-name-2=value-2

help:
   --from-literal=[]: Specify a key and literal value to insert in configmap (i.e.mykey=somevalue)

  "kubectl get configmap" 命令可用于查看创建的 ConfigMap 对象 special-config 的相关信息。举个例子:

[root@mh-k8s-master-247-10 ~]# kubectl get configmap
NAME                 DATA   AGE
istio-ca-root-cert   1      74d
[root@mh-k8s-master-247-10 ~]# kubectl get configmap istio-ca-root-cert -o yaml
apiVersion: v1
data:
  root-cert.pem: |
    -----BEGIN CERTIFICATE-----
              省略
    -----END CERTIFICATE-----
kind: ConfigMap
metadata:
  creationTimestamp: "2022-04-12T05:23:11Z"
  labels:
    istio.io/config: "true"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:root-cert.pem: {}
      f:metadata:
        f:labels:
          .: {}
          f:istio.io/config: {}
    manager: pilot-discovery
    operation: Update
    time: "2022-04-12T05:23:11Z"
  name: istio-ca-root-cert
  namespace: default
  resourceVersion: "6208"
  selfLink: /api/v1/namespaces/default/configmaps/istio-ca-root-cert
  uid: e03bd294-dd7d-417c-a6eb-3a6066cde0dd
[root@mh-k8s-master-247-10 ~]# 

2、基于文件创建

  为 "kubeclt create configmap" 命令使用 "--from-file" 选项即可基于文件内容来创建 ConfigMap 对象,可以重复多次使用 "--from-file" 选项以传递多个文件内容,它的命令格式如下:

Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none] [options]

  例如,下面命令可以把事先准备好的 Nginx 配置文件模板保存于 ConfigMap 对象 nginx-config:

kubectl create configmap nginx-config\
--from-file=./data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=./data/configs/nginx/conf.d/www.bbb.com.conf

  如果需要自行指定键名,则可在 "--from-file" 选项中直接指定自定义的键,命令格式如下:

kubectl create configmap nginx-config\
--from-file=aaa=./data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=bbb=./data/configs/nginx/conf.d/www.bbb.com.conf

3、基于目录创建  

  如果配置文件数量较多且存储于有限的目录中时,kubeclt 还提供了基于目录直接将多个文件分别纳为键值数据的 ConfigMap 资源创建方式。将 "--from-file" 选项后面所跟的路径指向一个目录路径就能将目录下的所有创建于同一 ConfigMap 资源中,命令格式如下:

Usage:
  kubectl create configmap <configmap_nam>[--from-file=<path-to-directory>]

  如下面的命令,将 /data/configs/nginx/conf.d/  目录下的所有文件都保存于 nginx-config-files 对象中:

kubect  create configmap nginx-config-file --from-file=./data/confnigs/nginx/conf.d/

4、使用清单创建

  基于配置文件创建 ConfigMap 资源时,它所使用的字段包括通常的 apiVersion、kind 和 metadata 字段,以及用于存储数据的关键字段 "data"。例如下面的示例代码:

apiVersion: v1
kind: configMap
metadata:
  name: configmap-demo
  namespace: default
data:
  log_level: INFO
  log_file: /var/log/test.log

  如果其值来自于文件内容时,则使用配置文件创建 ConfigMap 资源的便捷性还不如直接通过命令行的方式,因此建议直接使用命令行加载文件或目录的方式进行创建。为了便于配置留存,可以在创建完成后使用 get -o yaml 命令获取到相关信息后再进行编辑留存。

 二、向 Pod 环境变量传递 ConfigMap 对象键值数据

  Pod 资源的环境变量的获得方式之一包括引用 ConfigMap 对象中的数据,这一点通过在 env 字段中为 valueFrom 内嵌 configMapKeyRef 对象即可实现,其使用格式如下:

valueFrom:
  configMapKeyRef:
    key:
	name:
	  optional:

  下面是保存于配置文件 configmap-env.yaml 的资源定义示例,它包含了两个资源,彼此之间使用 "---" 互相分隔。

    1. 第一个资源是 busybox-httpd-config 的 ConfigMap 对象,它包含了两个键值数据;
    2. 第二个资源是 configmap-env-demo 的 Pod 对象,它通过环境变量引用了 busybox-httpd-config 对象中的键值数据,并将其直接传递给了自定义运行的容器应用 httpd:
apiVersion: v1
kind: ConfigMap
metadata:
  name: busybox-httpd-config
  namespace: default
data:
  http_port: "8080"
  verbose_level: "-vv"
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
  namespace: default
spec:
  containers:
  - image: busybox-httpd
    command: ["/bin/httpd"]
	args: ["-f", "-p", "$(HTTPD_PORT)","$(HTTPD_LOG_VERBOSE)"]
	env:
	- name: HTTP_PORT
	  valueFrom:
	    configMapKeyRef:
		  name: busybox-httpd-config
		  key: httpd_port
    - name: HTTPD_LOG_VERBOSE
	  valueFrom:
	    configMapKeyRef
		  name: busybox-httpd-config
		  key: verbose_level
		  optional: true

  注意,在 command 或 args 字段中引用环境变量要使用 "$(VAR_NAME)" 的格式。待上面配置文件中的资源创建完成后,可以通过如下命令验证 pod 资源监听的端口等配置信息是否为 busybox-httpd-config 中定义的内容:

kubectl exec configmap-env-demo ps aux

  ConfigMap 是名称空间级别的资源,它必须与引用它的 Pod 资源在同一空间中。

三、ConfigMap 存储卷

  若 ConfigMap 对象中的键值来源于较长的文件内容,那么使用环境变量将其导入会使得变量值占据过多的内存空间而且不易处理。此类数据通常用于为容器应用提供配置文件,因此将其内容直接作为文件进行引用是较好的选择。其实现方式是,在定义 Pod 资源时,将此类 ConfigMap 对象配置为 ConfigMap 类型的存储卷,而后由容器将其挂载至特定的挂载点后直接进行访问。

1)挂载整个存储卷

  关联为 Pod 资源的存储卷时,ConfigMap 对象中的每个键都对应地表现为一个文件,键名转为文件名,而键值则为相应文件的内容,即便是通过直接值创建的键值数据,也一样表现为文件视图。挂载于容器上之后,由键值数据表现出的文件位于挂载点目录中,容器中的进程可直接读取这些文件的内容。
  配置 Pod 资源时,基于存储卷的方式引用 ConfigMap 对象的方法非常简单,仅需要指明存储卷名称及要应用的 ConfigMap 对象名称即可。

  下面是于配置文件 configmap-volume-pod.yaml 中定义的 Pod 资源,具体如下:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
	volumeMounts:
	- name: ngxconfig
	  mountPath: /etc/nginx/conf.d/
	  readOnly: true
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files

2)挂载存储卷中的部分键值

  有时候,我们可能期望在容器中挂载某 ConfigMap 存储卷后,只 "导出" 部分文件内容(只导出部分 key:value 数据),示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-2
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
	volumeMounts:
	- name: ngxconfig
	  mountPath: /etc/nginx/conf.d/
	  readOnly: true
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files
	  items:
	  - key: myserver.conf
	    path: myserver.conf
		mode: 0644
	  items:
	  - key: youserver.conf
	    path: youserver.conf
		mode: 0644

  pod.spec.volumes.configMap 字段定义如下:

[root@mh-k8s-master-247-10 ~]# kubectl explain pod.spec.volumes.configMap
KIND:     Pod
VERSION:  v1

RESOURCE: configMap <Object>

DESCRIPTION:
     ConfigMap represents a configMap that should populate this volume

     Adapts a ConfigMap into a volume. The contents of the target ConfigMap's
     Data field will be presented in a volume as files using the keys in the
     Data field as the file names, unless the items element is populated with
     specific mappings of keys to paths. ConfigMap volumes support ownership
     management and SELinux relabeling.

FIELDS:
   defaultMode	<integer>
     Optional: mode bits to use on created files by default. Must be a value
     between 0 and 0777. Defaults to 0644. Directories within the path are not
     affected by this setting. This might be in conflict with other options that
     affect the file mode, like fsGroup, and the result can be other mode bits
     set.

   items	<[]Object>
     If unspecified, each key-value pair in the Data field of the referenced
     ConfigMap will be projected into the volume as a file whose name is the key
     and content is the value. If specified, the listed keys will be projected
     into the specified paths, and unlisted keys will not be present. If a key
     is specified which is not present in the ConfigMap, the volume setup will
     error unless it is marked optional. Paths must be relative and may not
     contain the '..' path or start with '..'.

   name	<string>
     Name of the referent. More info:
     https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

   optional	<boolean>
     Specify whether the ConfigMap or its keys must be defined

[root@mh-k8s-master-247-10 ~]# 

  pod.spec.volumes.configMap.items 字段定义如下:

[root@mh-k8s-master-247-10 ~]# kubectl explain pod.spec.volumes.configMap.items
KIND:     Pod
VERSION:  v1

RESOURCE: items <[]Object>

DESCRIPTION:
     If unspecified, each key-value pair in the Data field of the referenced
     ConfigMap will be projected into the volume as a file whose name is the key
     and content is the value. If specified, the listed keys will be projected
     into the specified paths, and unlisted keys will not be present. If a key
     is specified which is not present in the ConfigMap, the volume setup will
     error unless it is marked optional. Paths must be relative and may not
     contain the '..' path or start with '..'.

     Maps a string key to a path within a volume.

FIELDS:
   key	<string> -required-
     The key to project.

   mode	<integer>
     Optional: mode bits to use on this file, must be a value between 0 and
     0777. If not specified, the volume defaultMode will be used. This might be
     in conflict with other options that affect the file mode, like fsGroup, and
     the result can be other mode bits set.

   path	<string> -required-
     The relative path of the file to map the key to. May not be an absolute
     path. May not contain the path element '..'. May not start with the string
     '..'.

[root@mh-k8s-master-247-10 ~]# 

3)独立挂载存储卷中的键值

  前面几种方式中,无论是挂载所有文件还是部分文件,挂载点目录下原有的文件都会被隐藏。对于期望将 ConfigMap 对象提供的配置文件补充于挂载点目录下,并且不影响原本就存在的一些文件,这种方式显然难以如愿。

  例如:/etc/nginx/conf.d 目录中原本就存在一些文件(如 default.conf),用户期望将 nginx-config-files 中的全部或部分文件装载进此目录中而不影响其原有的文件。

  解决办法:使用容器的 volumeMounts 字段中使用的 subPath 字段来解决,它可以支持用户从存储卷挂载单个文件或单个目录而非整个存储卷。

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-3
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
	volumeMounts:
	- name: ngxconfig
	  mountPath: /etc/nginx/conf.d/myserver.conf
	  subPath: myserver.conf
	  readOnly: true
	- name: ngxconfig
	  mountPath: /etc/nginx/conf.d/yourserver.conf
	  subPath: yourserver.conf
	  readOnly: true
  volumes:
  - name: ngxconfig
    configMap:
	  name: nginx-config-files

  pod.spec.containers.volumeMounts 字段定义如下:

[root@mh-k8s-master-247-10 ~]# kubectl explain pod.spec.containers.volumeMounts
KIND:     Pod
VERSION:  v1

RESOURCE: volumeMounts <[]Object>

DESCRIPTION:
     Pod volumes to mount into the container's filesystem. Cannot be updated.

     VolumeMount describes a mounting of a Volume within a container.

FIELDS:
   mountPath	<string> -required-
     Path within the container at which the volume should be mounted. Must not
     contain ':'.

   mountPropagation	<string>
     mountPropagation determines how mounts are propagated from the host to
     container and the other way around. When not set, MountPropagationNone is
     used. This field is beta in 1.10.

   name	<string> -required-
     This must match the Name of a Volume.

   readOnly	<boolean>
     Mounted read-only if true, read-write otherwise (false or unspecified).
     Defaults to false.

   subPath	<string>
     Path within the volume from which the container's volume should be mounted.
     Defaults to "" (volume's root).

   subPathExpr	<string>
     Expanded path within the volume from which the container's volume should be
     mounted. Behaves similarly to SubPath but environment variable references
     $(VAR_NAME) are expanded using the container's environment. Defaults to ""
     (volume's root). SubPathExpr and SubPath are mutually exclusive.

[root@mh-k8s-master-247-10 ~]# 

4)容器应用重载新配置

  建议:重启容器。

posted @ 2022-06-25 20:15  左扬  阅读(315)  评论(0编辑  收藏  举报
levels of contents