K8S入门系列:K8S 之 configMap 存储

8.1 kubernetes – configMap(用于保存配置文件的存储方案)

configMap 功能在 kubernetes 1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中去读取配置信息。configMap API 给我们提供了向容器中注入配置信息的机制,configMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 json 二进制对象。

其实在我们生产环境中有一种机制,这种机制比较像我们的 configMap,它叫配置文件的注释中心。如下图所示:

这东西怎么理解呢?我们想一下我现在有一千台的 nginx ,这些 nginx 的配置文件需要有一天进行更改。那我们的操作可能是通过一些自动化脚本,或者是通过 ansibel 进行集群化的修改,把这 1000 台 nginx 的配置文件进行改掉。但其实在很多情况下我们会发现,他还分了好几组不同环境下的 nginx ,并且每一组的配置文件他都不一样。那在这种环境中我们会发现管理起来就已经非常费劲了,所以在这种结构下我们会引入一种配置文件注册中心的这么一个概念。

在这种情况下它是怎么样一种构建方式呢,首先所有的服务想去正常访问的话,nginx 会向配置文件的注册中心里去索要它的配置信息,这时候配置文件注册中心回去匹配它的对应信息,比如主机名或者是 ip 地址的范围进行分配他的配置文件;那当然不同的一些集群或索要到一些不同的配置文件,包括以后我们要去修改这些的配置文件我们只需要到配置文件注册中心中进行更新,那这样就会触发每一个进程自己的修改以及运行,这样的话我们更改起来包括我们的保存和维护起来更简单更方便。这就是我们配置文件注册中心的一个概念,在 K8S 里它的 configMap也是这样去想的。

8.1.1 configMap 原理

首先我们可以创建一个 configMap ,比如这保存的是一个 nignx.conf 配置文件(这个也就是所谓的保存的资源)。这个资源呢在后期我们创建 pod 的时候告诉它,在创建 pod 的时候要去引用这么一个 configMap 的配置信息,那这样的话我们的 nginx.conf 配置文件就会注入到该 pod 中,并且不管多少个 pod 过来以后它都能去申请同一个 nginx.conf 的这么一个资源请求。并且后期我对 nginx.conf 文件进行修改以后这里的 pod 里面的内容也会发生变化。当然我们的服务暂时还不支持直接创建文件,我们需要进行 pod 的重启或重载,让他实现热更新才可以。这和我们的 configMap 没有关系主要是和 nginx 的这么一个问题。

  • configmap 原理总结:

    • 将配置信息和镜像解耦

    • 将配置信息放到 configmap 对象中,然后在 pod 的对象中导入 configmap 对象,实现导入配置的操作

    • 声明一个 ConfigMap 的对象,作为 Volume 挂载到 pod 中

8.1.2 configMap 的创建

首先对于我们的 configMap 创建有好几种方式:

  1. 使用目录创建

  2. 使用文件创建

  3. 使用字面值创建

8.1.2.1 使用目录创建 configMap

第一种使用目录创建,我们先来看一下它的创建方式:

在某个目录下有两个文件,我们在创建的时候

--from-file 指定在目录下的所有文件都会被创建在 configMap 里面创建一个键值对、键的名字就是文件名,值就是文件里的内容。也就是他存储的结构依旧是一个 Key:value 键值

1、先创建一个 configmap 文件。用于存放我们的 configmap 的创建文件

[15:38:47 root@master-1 ~]#mkdir configmap
[15:38:55 root@master-1 ~]#cd configmap/

#在创建一个 dir 文件使用的是目录来创建我们的 configmap
[15:38:59 root@master-1 configmap]#mkdir dir
[15:39:03 root@master-1 configmap]#cd dir/

2、编写第一个测试文件。这个只是为了演示 configMap 存储的使用方案而已

[15:39:07 root@master-1 dir]#vim game.properties

enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allwoed=true
secret.code.lives=30

3、编写第二个测试文件,这个只是为了演示 configMap 存储的使用方案而已

[15:45:19 root@master-1 dir]#vim ui.properties

color.good=purple
color.good=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

4、然后我们就可以直接通过kubectl create创建了

[15:48:09 root@master-1 dir]#kubectl create configmap game-config --from-file=../dir/

kubectl create configmap:   #创建 configmap 存储类型
game-config:                #创建出来的文件名字叫做 game-config
--from-file=../dir/:        #文件路径是我的 /root/configmap/dir 

5、通过kubectl get configmaps查看我们的 configmap 存储类型信息,就会发现有两个数据

[15:51:00 root@master-1 dir]#kubectl get configmaps 
NAME          DATA   AGE
game-config   2      102s

#直接使用 kubectl get cm 也可以
[15:51:17 root@master-1 dir]#kubectl get cm
NAME          DATA   AGE
game-config   2      2m55s

6、通过kubectl get cm game-config -o yaml

[15:53:32 root@master-1 dir]#kubectl get cm game-config -o yaml

kubectl get cm:         #获取 configmap 的资源信息
game-config -o yaml:    #指定查看 game-config 资源的信息

7、当然也可以通过 kubectl describe 查看该 configmap 存储类型的信息,也是采用的键值对存储方式

[15:53:42 root@master-1 dir]#kubectl describe cm game-config

kubectl describe:       #查看详细信息描述
cm game-config:         #类型是 configmap 中的 game-config 资源

这就是通过我们的目录保存的一种方案,接着我们看第二种使用文件创建。

8.1.2.2 使用文件创建 configMap

从单一文件去创建,只要指定为一个文件就可以从单个文件中创建 configmap。其实我们通过命令会发现它的创建方式和我们的目录创建没有区别。其实这里唯一的区别就是一个指定的是目录一个指定的是文件的本体。

--from-file这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的

1、通过kubectl create configmap创建

[15:58:10 root@master-1 dir]#kubectl create configmap game-config2 --from-file=game.properties 

kubectl create configmap:       #创建 configmap 存储类型
game-config2:                   # configmap 类型名为 game-config2
--from-file=game.properties:    # 使用的文件路径是当前路径下的 game.properties 文件

2、通过kubectl get cm查看当前的 configmap 类型,就会发现多了一个 mage-config 2 ,并且数据只有一个

[16:19:51 root@master-1 dir]#kubectl get cm
NAME           DATA   AGE
game-config    2      31m
game-config2   1      94s

3、通过kubectl describe 命令查看 configmap 类型信息,并且指定查看 game-config2 这个资源

[16:21:25 root@master-1 dir]#kubectl describe configmaps game-config2 

kubectl describe configmaps:    #查看 configmap 类型信息
game-config2:                   #指定查看 game-config2 资源

8.1.2.3 使用字面值创建 configmap

使用文字值创建,利用--from-literal(来自文字)参数传递配置信息,该参数可以多次使用,格式如下

1、通过指定键名键值来创建

[16:22:42 root@master-1 dir]#kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

kubectl create configmap:               #创建 configmap 存储类型
special-config:                         #指定了 configmap 的名称为 special-config
--from-literal=special.how=very:        #指定了键名是 special.how 键值是 very
--from-literal=special.type=charm:      #又指定了键名为 special.type 键值是 charm

2、通过kubectl describe查看 cm(cm 也就是 configmap 的缩写)信息描述

[16:28:12 root@master-1 dir]#kubectl describe cm special-config 

kubectl describe cm:        #查看 configmap 描述信息
special-config:             #指定查看 special-config 

既然有三种创建方案,那么创建完成以后呢就带着大家去把这些配置在 pod 中使用看一下效果。

8.1.3 pod 中使用 configMap

8.1.3.1 使用 configMap 来代替我们的环境变量

8.1.3.1.1 创建 special 的 configMap

这里举了一个例子,例子就是先创建了一个 configmap

configMap yaml 文件详解:

apiVersion: v1              # api 版本是 V1 版
kind: ConfigMap             # kind 类型为 configmap
metadata:                   # configmap 元数据信息
  name: special-config      # 该 configmap 名为 special-config
  namespace: default        # 使用的是默认名称空间 default
data:                       # 数据信息
  special.how: very         # 数据信息键值对为 special.how=very
  special.type: charm       # 数据信息键值对为 special.type=charm

1、 编写我们的第一个special-config configmap

[16:48:30 root@master-1 dir]#vim sc.yaml 

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

2、通过kubectl apply声明式创建

[16:49:12 root@master-1 dir]#kubectl create -f sc.yaml 

3、通过kubectl get cm查看当前的 configMap 资源信息就发现多了一个 special-config 的资源

8.1.3.1.2 创建 env 的 configMap

创建为了 special configmap 之后我们就开始创建 env 的 configmap

1、回到 configmap 文件中创建一个 env 的目录

[16:49:49 root@master-1 dir]#cd /root/configmap/
[16:52:35 root@master-1 configmap]#mkdir env
[16:52:44 root@master-1 configmap]#cd env/

2、编写一个 env 的 yaml 文件。我是以资源清单的方案来创建 configmap

[16:52:46 root@master-1 env]#vim env.yaml

apiVersion: v1              # api 主板是 v1
kind: ConfigMap             # kind 类型为 configmap
metadata:                   # 该 configmap 的元数据信息
  name: env-config          # 该 configmap 名为 env-config
  namespace: default        # 使用的是默认名称空间,
data:                       # 该 configmap 使用数据
  log_level: INFO           # log_level 为它的键名,键值为 INFO

3、通过 kubectl apply 声明式创建该 configmap

[16:56:46 root@master-1 env]#kubectl create -f env.yaml 

4、通过kubectl get cm查看当前 configmap 的资源信息,发现 env-config 已经创建

[16:57:16 root@master-1 env]#kubectl get cm

现在就会发现已经有了我们的 env-config 和 special-config ,我们就会那这两个 config 资源注入到我们的一个 pod 的这么一个环境变量中。

8.1.3.1.3 创建 pod 将 env-config 和 special-config 注入到环境变量中

pod yaml 文件详解:

apiVersion: v1                              # api 使用的是 v1 版
kind: Pod                                   # kind 类型为 pod
metadata:                                   # 该 pod 的元数据信息
  name: dapi-test-pod                       # 该 pod 名为 dapi-test-pod
spec:                                       # 该 pod 描述信息
  containers:                               # 该 pod 使用的容器信息
    - name: test-container                  # 容器名称为 test-container
      image: nginx                          # 使用的镜像是 nginx
      command: [ "/bin/sh","-c","env" ]     # 在容器中运行了一条命令也就是打印出来了环境变量
      env:                                  # env 环境变量信息
        - name: SPECIAL_LEVEL_KEY           # 给这个 env 起了一个名称叫做 SPECIAL_LEVEL_KEY
          valueFrom:                        # 值得来源
            configMapKeyRef:                # 从哪一个 configmap 中导入
              name: special-config          # 从 special-config 中导入
              key: special.how              # 导入得是 special.how 这个键,因为我们在 special-config 中有两个键值对,我们把这个 special.how 得值赋予给 SPECIAL_LEVEL_KEY 也就是意味着现在SPECIAL_LEVEL_KEY 值也就是我们的 special.how 对应得值 very 
        - name: SPECIAL_TYPE_KEY            # 这个 SPECIAL_TYPE_KEY 导入的是 special.type 的值也就是 charm 
          valueFrom:                        # 值得来源
            configMapKeyRef:                # 从哪一个 configmap 中导入
              name: special-config          # 从 special-config 中导入
              key: special.type             # 导入得是 special.type 这个键
      envFrom:                              # env 来源信息
        - configMapRef:                     # env 是从 configmap 这个存储类型中来的
            name: env-config                
            # 并且使用的是这个 configmap 存储中的 env-config,这样的话这个 env-config 就被导入了
  restartPolicy: Never                  # 重启策略为 never 永不重启

我将这个 yaml 文件导入之后我们会有三个不同的环境变量,第一个是我们得 env-config 它得键名就是我们的 log_level 键值就是 INFO 。第二个环境变量就是 SPECIAL_LEVEL_KEY 值是对应的 special-config中的special.how 键名的值也就是 very。第三个环境变量就是 SPECIAL_TYPE_KEY 值对应的是 special-config中的special.type 键名的值也就是 charm。

1、编写yaml文件

[17:25:08 root@master-1 env]#vim cm-env-pod.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: nginx
      command: [ "/bin/sh","-c","env" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

2、通过kubectl create声明式创建 pod

[17:37:05 root@master-1 env]#kubectl create -f cm-env-pod.yaml 

3、通过kubectl get pod 状态信息

[17:37:16 root@master-1 env]#kubectl get pod
NAME            READY   STATUS      RESTARTS   AGE
dapi-test-pod   0/1     Completed   0          55s

意味该 pod 一启动以后打印了环境变量就没了。

4、通过Kubectl logs 查看 dapi-test-pod 这个 pod 的日志信息

[17:38:01 root@master-1 env]#kubectl logs dapi-test-pod 
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://172.30.0.1:443
HOSTNAME=dapi-test-pod
HOME=/root
PKG_RELEASE=1~buster
SPECIAL_TYPE_KEY=charm
KUBERNETES_PORT_443_TCP_ADDR=172.30.0.1
NGINX_VERSION=1.19.2
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
NJS_VERSION=0.4.3
KUBERNETES_PORT_443_TCP_PROTO=tcp
SPECIAL_LEVEL_KEY=very
log_level=INFO
KUBERNETES_PORT_443_TCP=tcp://172.30.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=172.30.0.1
PWD=/

这就是通过 configMap 把我们的一个环境变量注入到我们的 pod 内部

8.1.3.2 在 pod 中使用 configMap 设置命令行参数

8.1.3.2.1 创建 special 的 configmap

使用 configmap 设置命令行得参数,这里得 yaml 文件详解

yaml 文件详解:

apiVersion: v1                  # api使用的是 v1 版本
kind: ConfigMap                 # kind 类型为 configmap
metadata:                       # 这个 configmap 得元数据信息
  name: special-config          # 这个 configmap 叫做 special-config
  namespace: default            # 使用的名称空间是默认名称空间
data:                           # 数据信息
  special.how: very             # 数据信息键值对为 special.how=very
  special.type: charm           # 数据信息键值对为 special.type=charm

但是这个 configmap 已经在上面一个实验中创建了,所以不用再才创建

8.1.3.2.2 创建 pod 进行演示

yaml 文件详解:

apiVersion: v1                      # api 使用版本 v1
kind: Pod                           # kind 类型为 pod
metadata:                           # 该 pod 的元数据信息
  name: dapi-test-pod66             # 该 pod 名为 dapi-test-pod66
spec:                               # 该 pod 详细描述
  containers:                       # 容器信息
    - name: test-container          # 容器名称为 test-container
      image: nginx                  # 使用的是 nginx 镜像
      command: [ "/bin/sh","-c","echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
      # 在 sh 中使用 echo 命令,将我们的环境变量作为输出的命令,其实会发现这里我们导入的配置变量方式和上一个实验一摸一样的
      env:                          # env 变量信息
        - name: SPECIAL_LEVEL_KEY   # 变量名为 SPECIAL_LEVEL_KEY
          valueFrom:                # 变量值来源信息
            configMapKeyRef:        # 从哪一个 configmap 中来的变量
              name: special-config  # 使用的是 special-config 这个 configmap 存储中的变量
              key: special.how      # 并且键名为 special.how
        - name: SPECIAL_TYPE_KEY    # 变量名为 SPECIAL_TYPE_KEY
          valueFrom:                # 变量值来源信息
            configMapKeyRef:        # 从哪一个 configmap 中来的变量
              name: special-config  # 使用的是 special-config 这个 configmap 存储中的变量
              key: special.type     # 并且键名为 special.type
  restartPolicy: Never              # 重启策略为永不重启

如果想让每一个 pod 启用命令可以被调整我们可以通过环境变量的方式进行注入,导入变量再上一个实验演示中已经看过了,就是通过 env 这个关键字进行导入。

1、编写 yaml 文件。

[08:51:18 root@master-1 env]#vim cm-cmd-pod.yaml

apiVersion: v1
kind: Pod
metadata: 
  name: dapi-test-pod66
spec: 
  containers:
    - name: test-container
      image: nginx
      command: [ "/bin/sh","-c","echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
  restartPolicy: Never

2、通过kubectl apply声明式创建 pod

[09:06:21 root@master-1 env]#kubectl apply -f cm-cmd-pod.yaml 

3、通过kubectl get pod查看 pod 信息 并且状态为完成

[09:06:46 root@master-1 env]#kubectl get pod

4、接着通过kubectl logs查看该 pod 的日志,已经将这两个变量值输出出来,因为我们在该 pod 的 yaml 文件中让他 echo 出了这两个变量的命令

[09:06:57 root@master-1 env]#kubectl logs dapi-test-pod66 

8.1.3.3 通过数据卷插件使用 ConfigMap

通过我们数据卷插件的方式来使用 configMap

8.1.3.3.1 创建 special 的 configmap

使用 configmap 设置命令行得参数,这里得 yaml 文件详解

yaml 文件详解:

apiVersion: v1                  # api使用的是 v1 版本
kind: ConfigMap                 # kind 类型为 configmap
metadata:                       # 这个 configmap 得元数据信息
  name: special-config          # 这个 configmap 叫做 special-config
  namespace: default            # 使用的名称空间是默认名称空间
data:                           # 数据信息
  special.how: very         # 数据信息键值对为 special.how=very
  special.type: charm       # 数据信息键值对为 special.type=charm

但是这个 configmap 已经在上面一个实验中创建了,所以不用再才创建

在数据卷里面使用这个 configMap,有不同的选项。最基本的都是将文件填入数据卷中,在这个文件中,键就是文件名,键值就是文件内容

8.1.3.3.2 创建 pod 进行演示

yaml 文件详解:

apiVersion: v1                      # api 接口为 v1
kind: Pod                           # kind 类型为 pod
metadata:                           # pod 元数据信息
  name: dapi-test-pod11             # pod 名称为 dapi-test-pod11
spec:                               # 该 pod 详细信息描述
  containers:                       # 该 pod 使用的容器
    - name: test-container          # 容器名为 test-container
      image: nginx                  # 使用的镜像是 nginx
      command: [ "/bin/sh","-c","cat /etc/config/special.how" ]
      # 在该容器中运行得命令是 cat /etc/config/special.how 这个文件
      volumeMounts:                 # 然后再这个容器下进行 volume 的挂载
      - name: config-volume         # 挂载的是下面 config-volume 这个 volume 必须和下面匹配
        mountPath: /etc/config      # 挂载到 /etc/config 这个目录下
  volumes:                          # 数据卷信息
    - name: config-volume           # 这个数据卷得名称为 config-volume 并且必须和上面匹配
      configMap:                    # configMap 来源信息
        name: special-config        # 这 configmap 是由 special-config 这个 configMap 中得到
  restartPolicy: Never              # 重启策略为永不重启

1、编写yaml 文件

[09:09:58 root@master-1 env]#vim cm-vloumes-pod.yaml

apiVersion: v1
kind: Pod
metadata: 
  name: dapi-test-pod11
spec:
  containers:
    - name: test-container
      image: nginx
      command: [ "/bin/sh","-c","cat /etc/config/special.how" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

2、通过kubectl apply声明式创建 pod

[10:48:16 root@master-1 env]#kubectl apply -f cm-vloumes-pod.yaml 

3、通过kubectl get pod 进行查看状态已经执行成功

[10:48:58 root@master-1 env]#kubectl get pod
dapi-test-pod11   0/1     Completed   0          20s

4、通过kubectl logs 查看该 pod 日志,会看到容器中/etc/config/special.how 这个文件的信息也就是它的变量赋值。

[10:49:01 root@master-1 env]#kubectl logs dapi-test-pod11 
very

5、我们修改该 pod 的 yaml 文件等会好进入这个 pod 中查看它的文件挂载信息。

[10:53:42 root@master-1 env]#vim cm-vloumes-pod.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod11
spec:
  containers:
    - name: test-container
      image: nginx
      command: [ "/bin/sh","-c","sleep 600" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

6、删除所有 pod 然后再将cm-vloumes-pod.yaml文件构建为 pod

[10:54:34 root@master-1 env]#kubectl delete pod --all

7、通过kubectl apply重新构建该 pod

[10:54:52 root@master-1 env]#kubectl apply -f cm-vloumes-pod.yaml 

8、通过kubectl get pod查看就会发现这个 pod 正在运行中

[10:55:34 root@master-1 env]#kubectl get pod
NAME              READY   STATUS    RESTARTS   AGE
dapi-test-pod11   1/1     Running   0          39s

9、然后我能进入到这个 pod 中,

#进入到该 pod 中
[10:57:05 root@master-1 env]#kubectl exec -it dapi-test-pod11 -- /bin/bash
 
#进入到该 pod 的 /etc/config/ 目录下
root@dapi-test-pod11:/# cd /etc/config/

#通过 ls 查看就会多了两个文件
root@dapi-test-pod11:/etc/config# ls
special.how  special.type

#查看 special.how 文件内容为我们的赋值 very
root@dapi-test-pod11:/etc/config# cat special.how 
very

#查看 special.type 文件内容为我们的赋值 charm
root@dapi-test-pod11:/etc/config# cat special.type 
charm

这个的含义就是会将我们的 special-config 这个 configmap 的 pod 信息挂载到这个 pod 的 /etc/config 这个目录,也就是会把我们 configMap 中的键名如果以我们 volume 的方案他就会挂载为文件名,键值就会成为文件内容,这也是我们怎么去利用 configmap 达到注册中心的这么一个原理。

8.1.4 ConfigMap 的热更新

我们可以看一下真正的 configMap 热更新,这里给大家做了一个演示,演示的第一个就是创建了一个 configmap

8.1.4.1 创建 configMap

yaml 文件详解:

apiVersion: v1          # api 使用版本为 v1
kind: ConfigMap         # kind 类型为 configmap
metadata:               # 该 configmap 元数据信息
  name: log-config      # 该 configmap 名称为 log-config
  namespace: default    # 使用的名称空间是默认名称空间
data:                   # 数据信息
  log_level: INFO       # 键名为 log_level,键值为 INFO 

---                     # 使用 --- 分隔创建一个新的 deployment 资源,在这个 deployment 中调用,调用的方式是通过 volumes 的方式进行挂载
apiVersion: apps/v1             # api 使用版本为 apps/v1
kind: Deployment                # kind 类型是 deployment
metadata:                       # 这个 deployment 的元数据信息
  name: my-nginx                # 这个 deployment 名为 my-nginx
spec:                           # 这个 deployment 详细描述
  replicas: 1                   # pod 副本数目为 1
  selector:                     # 选择器匹配
    matchLabels:                # 匹配标签
      run: my-nginx             # 匹配的是 run=nginx 的这个标签
  template:                     # pod 模板标签
    metadata:                   # pod 元数据详细
      labels:                   # 匹配标签信息
        run: my-nginx           # 匹配规则为 run=my-nginx
    spec:                       # 详细信息描述
      containers:               # 容器信息
      - name: my-nginx          # 容器名为 my-nginx
        image: nginx            # 使用的镜像是 nginx
        ports:                  # 端口暴露规则
        - containerPort: 80     # 容器端口为 80
        volumeMounts:           # 数据卷挂载信息
        - name: config-volume   # 匹配的是名为 config-volume 的这个数据卷
          mountPath: /etc/config # 挂载路径为 /etc/config
      volumes:                  # 数据卷信息
        - name: config-volume   # 该数据卷名为 config-volume
          configMap:            # 调用的 configMap 信息
            name: log-config    # 调用的是一个名为 log-config 的这个 configmap,也就是上面这个configmap 相互呼应相互匹配

1、编写一个yaml 文件

[11:37:15 root@master-1 env]#vim cm.yaml 

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: log-config

2、通过kubectl apply声明式创建

[11:36:37 root@master-1 ~]#kubectl apply -f svc-deployment.yaml 

3、通过 kubectl get pod 查看。并且已经在运行状态。

[11:43:23 root@master-1 env]#kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
my-nginx-74c9c94899-x9lnq      1/1     Running   0          2m48s

4、进入到该 pod 中查看这个文件到底存不存在。

#进入到这个 pod 中
[11:54:00 root@master-1 env]#kubectl exec -it my-nginx-74c9c94899-x9lnq -- /bin/bash

#在这个 pod 中在进入到  /etc/config/ 文件下
root@my-nginx-74c9c94899-x9lnq:/# cd /etc/config/

#通过查看就发现有一个 log_level 的文件
root@my-nginx-74c9c94899-x9lnq:/etc/config# ls
log_level

#通过查看该文件里面的内容正好就是我们在 yaml 文件中定义的变量赋值
root@my-nginx-74c9c94899-x9lnq:/etc/config# cat log_level 
INFO

那我们现在进行热更新看一下,通过直接修改这个 configmap。

8.1.4.2 修改 configMap

1、通过kubectl edie后面加上我们要修改的资源类型

[13:58:49 root@master-1 env]#kubectl edit configmaps log-config 

kubectl edit:           # 使用 kubectl edit 进行修改
configmaps:             # 需要修改的资源类型是我们的 configmap
log-config:             # 修改在 configmap 下的 log-config 这个 configmap

2、将 log_level 对呀的值修改为 debug 级别,修改下面红框中的内容改为 DEBUG

3、在通过cat命令查看就会发现/etc/config/log_level 中已经修改为了 DEBUG 级别了,这样也就意味着我们刚才修改的是 configMap ,而我们 pod 中的文件内容已经发生变化了,如果这个是我们的 nginx 的话就已经到达热更新的这么一个目的了

8.1.4.3 configMap 更新注意事项

注意:

config Map 更新后他并不会让我们的 pod 重载这个文件,也就是比如这个是我们 nginx 的 configmap 文件,然后有一个是我们的 nginx 主进程,这个 nginx 的主进程在启动的时候会加载我们的 nginx 配置文件,并且加载完成以后就不会再看这个文件了,哪怕这个文件发生变化以后也不会进行重读。

那如果我能让这个 pod 去重启,那就相当于它去重新都这个 nginx 的配置文件达到这么一个更新的状态。如果这个服务能够实时的监控这个文件发生变化进行更改的话就不用需要这么一个重启 pod 的过程了,但是我们大部分服务还是不会这样的。

更新 configmap 目前并不会触发相关 pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新,修改它的时间,这个时间的更改会触发我们的热更新,这是一种比较简单的触发方案。

kubectl pathc deployment my-nginx --patch '{"spec":{"template":{"metadata":{"annotations":{"version/config":"20190411"}}}}}'

这个例子里我们再.spec.template.metadata.annotations中添加version/config,每次通过修改version/config来触发滚动更新

!!!更新 configmap 后:

  • 使用该 configmap 挂载的 ENV 不会同步更新

  • 使用该 configmap 挂载的 volume 中的数据需要一段时间(实测大概10秒)才能同步更新

8.1.5 configmap 实现 nginx 域名访问

这里的是一个简单的 nginx 的 server 配置,在 nginx 中都是多域名的,其实像这种情况我们可以通过在打镜像的时候就将配置打到镜像中,但是我这里采用的是 configmap

1.编写 configmap

[19:51:44 root@master configm]#vim nginx_configmap.yaml 

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  default: |                                        # 命名为 default 的配置信息
    server {
      listen       80;
      server_name  www.testnginx.com;
      index        index.html;

      location / {
        root /data/nginx/html;                      # nginx 中 / 页面路径
        if (!-e $request_filename) {
            rewrite ^/(.*) /index.html last;
                                   }
                  }
    }

2.编写一个 depolyment 将该 configmap 进行挂载

通过卷的 items 属性能够指定哪些条目会被暴露作为configMap卷中的文件

因为在同一个 configmap 中可能有多个配置项,所以我们通过 items 可以找到指定的配置项

[18:54:49 root@master configm]#vim nginx_dep.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-configmap
  template:
    metadata:
      labels:
        app: ng-configmap
    spec:
      containers:
      - name: nginx-configmap
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-static-dir
          mountPath: /data/nginx/html
        - name: nginx-config
          mountPath: /etc/nginx/conf.d          
      volumes:
      - name: nginx-static-dir
        hostPath:                       # 这里是本地挂载我们的 html 静态文件
          path: /data/nginx/test1
      - name: nginx-config              # 挂载到容器的名字这里我定义为 nginx-config
        configMap:                      # 存储类型为 configmap
          name: nginx-config            # 对应刚才上面所创建的 configmap 名称
          items:                        # 指定挂载 configmap 的 default 配置
            - key: default
              path: testnginx.conf      # 挂载点,将 default 挂载至容器的 testnginx.conf 中

3.编写 svc

[19:26:00 root@master configm]#vim nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: ng-configmap
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30019
    protocol: TCP
  type: NodePort
  selector:
    app: ng-configmap           # 标签选择器匹配刚才在 nginx-de.yaml 中定义的 app: ng-configmap

4.创建 configmap、deployment、svc

[19:52:24 root@master configm]#kubectl apply -f nginx_configmap.yaml 
[19:52:31 root@master configm]#kubectl apply -f nginx_svc.yaml
[19:52:38 root@master configm]#kubectl apply -f nginx_dep.yaml 

5.查看 pod 已经启动,并且被调度到了 node-1 节点上

[22:24:01 root@master configm]#kubectl get pod -o wide
NAME                         READY   STATUS    RESTARTS   AGE    IP              NODE     NOMINATED NODE   READINESS GATES
nginx-dep-6c8955c659-wzn89   1/1     Running   0          152m   10.200.84.133   node-1              

6.进入容器查看 configmap 已经挂载成功

[19:54:01 root@master configm]#kubectl exec -it nginx-dep-6c8955c659-wzn89 /bin/bash
root@nginx-dep-6c8955c659-wzn89:/# cat /etc/nginx/conf.d/testnginx.conf 
server {
  listen       80;
  server_name  www.testnginx.com;
  index        index.html;

  location / {
    root /data/nginx/html;
    if (!-e $request_filename) {
        rewrite ^/(.*) /index.html last;
                               }
              }
}

7.到 node-1 节点的 /data/nginx/test1 目录下创建 index.html 文件

# /data/nginx/test1 会随着 pod 的挂载自定创建
[22:26:03 root@node-1 ~]#echo "node1 nginx configmap" >  /data/nginx/test1/index.html

8.浏览器访问验证

但是现在并不能通过域名访问,所以我们需要配置 HA 来实现代理

8.1.5.1 配置 HAproxy 实现域名访问

由于 K8S 并不能通过 7 层访问,所以我们还需要通过安装 HAproxy 来实现代理

1.安装 ha

[22:36:31 root@master configm]#apt install haproxy

# 设置开机启动
[22:38:16 root@master configm]#systemctl enable --now haproxy.service

2.配置 ha

[22:48:34 root@master configm]#vim /etc/haproxy/haproxy.cfg 
# 只需在 haproxy 配置文件中添加下面代码
listen k8s-nginx-configmap          # 监听ipv6、ipv4和unix sock文件
  bind 10.0.0.100:80                # 指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中
  mode tcp                          # 监听模式
  server nginx 10.0.0.100:30019 check inter 3s fall 3 rise 5    # 监听服务为 nginx 地址 10.0.0.100:30019 和心跳检测配置

3.重启 ha 服务

[22:51:45 root@master configm]#systemctl restart haproxy.service

4.在其他节点添加主机头实现访问

[22:54:38 root@node-1 ~]#vim /etc/hosts
10.0.0.100 www.testnginx.com

5.访问测试可以看到现在已经实现访问

[22:54:37 root@node-1 ~]#curl www.testnginx.com
node1 nginx configmap

评论

  1. ldy
    3年前
    2021-12-09 16:46:56

    最后nginx实验,deploymen的spec写成了spce,哈哈哈

    • 博主
      ldy
      3年前
      2021-12-10 11:05:35

      敲快了我现在就改

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇