K8S 十一月 22, 2020

K8s ConfigMap

文章字数 8.2k 阅读约需 7 mins. 阅读次数

在 k8s 集群中部署第一个应用 中,完成了一个基本的 NGINX 服务的部署,但在真实环境中使用 NGINX 时,一般都需要定制其配置文件,使满足实际代理需求。K8s 提供了一个 ConfigMap 的概念,允许将配置文件与镜像文件分离,以使容器化的应用程序具有可移植性。

什么是 ConfigMap

可以按字面方式,将 ConfigMap,理解为一个 Config 的 Map:

  • Map 的 Key 为配置标识,可以是文件名等
  • Map 的 Value 为配置内容,可以是字符串、文本内容等

一个 ConfigMap 中可以包含多个 Key / Value 对。

怎么创建 ConfigMap

可以使用 kubectl create configmap 命令基于 目录、文件 或字符串来创建 ConfigMap,也可以直接编写 yaml 文件进行定义:

# nginx-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx_conf: |
    user  nginx;
    worker_processes  2;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  65;

        #gzip  on;

        include /etc/nginx/conf.d/*.conf;
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: confd-config
data:
  file_server.conf: |
    server {
        listen       2020;
        server_name  file_server;
        location / {
            autoindex on;
            root /usr/share/nginx;
            charset utf-8;
        }
    }
  another.conf: |
    server {
        listen       8000;
        server_name  another;
        location / {
            root /usr/share/nginx/html;
        }
    }

之后可使用 kubectl apply -f nginx-config.yml 完成 ConfigMap 的创建。

怎么使用 ConfigMap

ConfigMap 有多种定义形式,也有多种使用形式,详细情况可以查阅 官方文档。本文仍以 NGINX 配置文件为例,说明一下 ConfigMap 中定义的配置文件的使用方式。

上面的 nginx-config.yml 定义了两个 ConfigMap,目标是放到 NGINX 容器中的如下两个位置:

  • nginx-config => /etc/nginx/nginx.conf
  • confd-config => /etc/nginx/conf.d

可以将 ConfigMap 添加到 Volume 中,再进行挂载以使用,如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.9
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: nginx-config-vol
          mountPath: /etc/nginx/nginx.conf # 也可挂载到文件
          subPath: nginx.conf # 挂载到文件时,需设置子路径
        - name: confd-vol # 与 volumes 中的 name 对应
          mountPath: /etc/nginx/conf.d # 配置文件要挂载的路径
      volumes:
      - name: nginx-config-vol # 对应 ConfigMap 的 name
        configMap:
          name: nginx-config
          items:
          - key: nginx_conf
            path: nginx.conf
      - name: confd-vol
        configMap:
          name: confd-config
          # 此时会将此 ConfigMap 中的所有配置以文件形式挂载
          # 如果只需挂载一个文件(如 file_server.conf),可以按如下方式指定:
          # items:
          # - key: file_server.conf
          #   path: file_server.conf

有两个地方需要说明一下:

使用 mountPath 挂载路径时

比如上例中的 mountPath: /etc/nginx/conf.d,此时可指定挂载 ConfigMap 中的某个配置到该路径下的具体文件,也可将整个 ConfigMap 中的所有配置以多个文件的形式挂载到指定路径下。

不论哪种方式,都会将容器中原路径下所有先前的文件清除,需注意。

使用 mountPath 挂载文件时

若想将配置文件挂载至容器中某个具体文件处,不影响该文件所在路径的其他文件,可按上例中的 nginx.conf 文件方式:

mountPath: /etc/nginx/nginx.conf # 也可挂载到文件
subPath: nginx.conf # 挂载到文件时,需设置子路径

mountPath 直接指定到具体文件,并通过 subPath 表明文件名。

挂载的 ConfigMap 自动更新

更新已经在数据卷中使用的 ConfigMap 时,已映射的配置内容最终也会被自动更新。kubelet 在每次定期同步时都会检查已挂载的 ConfigMap 是否是最新的。但是,它使用其本地的基于 TTL 的缓存来获取 ConfigMap 的当前值。因此,从更新 ConfigMap 到将新值映射到 Pod 的总延迟,可能与 kubelet 同步周期 + ConfigMap 在 kuelet 中缓存的 TTL 一样长。

另外,使用 ConfigMap 作为 subPath 的数据卷将不会收到 ConfigMap 更新。

以上面配置为例,当更新 ConfigMap 中 NGINX 配置文件内容并 apply 到集群之后,可以稍等一会,然后进入到容器中观察配置文件,nginx.conf 文件的内容不会随 ConfigMap 文件更新同步,但 /etc/nginx/conf.d 路径下内容,会按更新周期,自动同步 confd-config 中的所有变更,包括配置文件内容,以及配置文件个数。

完整的 K8s 配置

本文中完整的 K8s 配置如下:

# nginx-test.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx_conf: |
    user  nginx;
    worker_processes  2;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  65;

        #gzip  on;

        include /etc/nginx/conf.d/*.conf;
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: confd-config
data:
  file_server.conf: |
    server {
        listen       2020;
        server_name  file_server;
        location / {
            autoindex on;
            root /usr/share/nginx;
            charset utf-8;
        }
    }
  another.conf: |
    server {
        listen       8000;
        server_name  another;
        location / {
            root /usr/share/nginx/html;
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.9
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: nginx-config-vol
          mountPath: /etc/nginx/nginx.conf # 也可挂载到文件
          subPath: nginx.conf # 挂载到文件时,需设置子路径
        - name: confd-vol # 与 volumes 中的 name 对应
          mountPath: /etc/nginx/conf.d # 配置文件要挂载的路径
      volumes:
      - name: nginx-config-vol # 对应 ConfigMap 的 name
        configMap:
          name: nginx-config
          items:
          - key: nginx_conf
            path: nginx.conf
      - name: confd-vol
        configMap:
          name: confd-config
          # 此时会将此 ConfigMap 中的所有配置以文件形式挂载
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  type: NodePort
  ports:
  - name: file
    port: 2020
    nodePort: 30081
  - name: fb
    port: 8000
    nodePort: 30082
  selector:
    app: nginx

kubectl apply -f nginx-test.yml 完成部署之后,可通过集群的 30081 端口访问容器内 2020 端口的服务,并可以修改 ConfigMap 中内容,进入到容器中观察 NGINX 对应配置文件的变化。

0%