侧边栏壁纸
  • 累计撰写 51 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

K8s Pod 和 Service 2

zhanjie.me
2020-11-05 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

2.1 ConfigMap 简介

想象一个场景,在 Kubernetes 集群中有的时候我们需要传递一些配置给应用,比如:数据库地址、用户名、密码等,我们可以有哪些办法呢?

  • 在打包镜像时将配置信息直接写入配置文件中:使用这种方式特别死板,并且配置数据不能共享,坏处显而易见
  • 在配置文件中通过 env 环境变量传入:这种方式如果要修改 env,就必须修改 YAML 文件,并重启所有 container,而且配置数据也不能共享
  • 在应用启动时通过数据库获取配置数据:这种方式具有一定可行性,配置信息可以多应用共享,但是自己实现起来比较麻烦

所以,kubernetes 提供了统一的应用配置管理方案 ConfigMap 方便我们将配置信息与应用程序分离。

ConfigMap 概述

ConfigMap 在容器中使用的场景通常有 3 种,分别如下所示:

  • 生成为容器中的环境变量
  • 设置容器启动命令的启动参数(需设置为环境变量)
  • 以 Volume 的形式挂载为容器内部的文件或目录

使用 ConfigMap 的限制条件

  • ConfigMap 必须在 Pod 之前创建
  • ConfigMap 受 Namespace 限制,只有处于相同 Namespace 中的 Pod 才可以引用它
  • kubelet 只支持可以被 API Server 管理的 Pod 使用 ConfigMap,kubelet 在本 Node 上通过 --manifest-url 或 --config 自动创建的静态 Pod 无法引用 ConfigMap
  • 在 Pod 对 ConfigMap 进行挂载 (volume) 操作时,在容器内部只能挂载为“目录”,不能挂载为“文件”。在挂载到容器内部后,在目录下将包含 ConfigMap 定义的每个 item,如果在该目录下原来还有其它文件,则容器内的该目录将被挂载的 ConfigMap 覆盖。如果想要保存原来的其它文件,可以将 ConfigMap 挂载到容器内部的临时目录,再通过启动脚本将配置文件复制 (cp) 或链接 (link) 到应用所在的实际目录下

2.2 创建 ConfigMap 资源对象

创建 ConfigMap 资源对象的方式有两种:第一种是通过 YAML 配置文件的方式进行创建,第二种是通过 kubectl 命令行方式创建,第三种是通过 ConfigMap 生成器 kustomization.yaml 方式进行创建(从 Kubernetes v1.14 版本开始支持 kustomization.yaml)。

ConfigMap 以一个或多个 key:value 的形式将配置信息保存在 Kubernetes etcd 数据库中,键值对的形式既可以表示单个属性/一个变量的值,比如:apploglevel=info,也可以表示整个配置文件/JSON 二进制对象的内容,比如:server.xml=<?xml...>...

ConfigMap 中保存的配置信息既可以在 Pod 中使用,也可以用于系统组件(比如:Controller)存储配置数据,ConfigMap 与我们后面将会介绍的 Secret 用法有些类似,不过 ConfigMap 主要用于存储不含敏感信息的数据。

通过 YAML 配置文件方式创建

这种创建方式和使用其它的 YAML 文件是相同的,使用的命令为 kubectl create -f xxxx.yaml

新建 cm-appvars.yaml 文件,并写入如下内容:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-appvars # ConfigMap 的名称
data: # 配置信息
  apploglevel: info
  appdatadir: /var/data

这里需要注意的是:ConfigMap 不是属性文件的替代品,它只是作为多个配置文件的引用,类似于 Linux 系统中的 /etc 目录,是专门用来存储配置文件的目录。在上面的 YAML 文件中,在 data 下配置的每一项都会成为一个新文件。

使用命令执行创建:

$ kubectl create -f cm-appvars.yaml
configmap/cm-appvars created

查看刚刚创建的 ConfigMap:

$ kubectl get configmap
NAME         DATA   AGE
cm-appvars   2      26s
$ kubectl describe configmap cm-appvars
Name:         cm-appvars
Namespace:    user-test
Labels:       <none>
Annotations:  <none>

Data
====
apploglevel:
----
info
appdatadir:
----
/var/data
Events:  <none>

通过 kubectl 命令行方式创建

命令形式如下:

kubectl create configmap <map-name> <data-source>

其中,<map-name> 是设置的 configmap 的名字,<data-source> 可以是目录、文件、或是 key-value 键值对。

<data-source> 中的可选参数为:--from-file/--from-env-file(从目录或文件创建) 和 --from-literal(直接指定键值对创建)。configmap 也可以缩写为 cm。

可以在命令行中执行 kubectl create configmap -h 查看具体参数和使用方法。

从目录中创建 ConfigMap

这种方式适用于在一个目录下有多个配置文件。

新建 configmap 文件夹,并在 configmap 文件夹下新建两个文件,分别名为:game.propertiesui.properties

执行创建:

# 这里设置 configmap 的名称为 game-config
$ kubectl create configmap game-config --from-file=/root/learning/configmap/
configmap/game-config created

查看configmap:

$ kubectl get configmap game-config -o yaml
apiVersion: v1
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
...
$ kubectl describe configmap game-config
Name:         game-config
Namespace:    user-test
Labels:       <none>
Annotations:  <none>

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

Events:  <none>

从文件中创建 ConfigMap

可以从单独的文件或是多个文件中进行创建。

# 使用单个文件创建
kubectl create configmap game-config-2 --from-file=/root/learning/configmap/game.properties
configmap/game-config-2 created

# 使用多个文件创建
kubectl create configmap game-config-3 --from-file=/root/learning/configmap/game.properties --from-file=/root/learning/configmap/ui.properties
configmap/game-config-3 created

使用参数 --from-env-file 从 env-file 中创建 ConfigMap。env-file 是包含了环境变量的列表。

新建 game-env-file.properties 文件,并写入如下内容:

执行创建:

$ kubectl create configmap game-config-env-file --from-env-file=/root/learning/configmap/game-env-file.properties
configmap/game-config-env-file created
$ kubectl get configmap game-config-env-file -o yaml
apiVersion: v1
data:
  allowed: '"true"'
  enemies: aliens
  lives: "3"
kind: ConfigMap
metadata:
...

另外使用文件创建的话,可以使用自定义的名称替代默认使用的文件名,比如:

# 使用 game.properties 文件创建,但是将其重命名为 game-special-key
$ kubectl create configmap game-config-4 --from-file=game-special-key=/root/learning/configmap/game.properties
configmap/game-config-4 created
# 可以看到这里显示的是 game-special-key,而不再是之前的 game.properties
$ kubectl describe configmap game-config-4
Name:         game-config-4
Namespace:    user-test
Labels:       <none>
Annotations:  <none>

Data
====
game-special-key:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

Events:  <none>

使用 key-value 键值对创建 ConfigMap

使用参数 --from-literal 直接在命令中设置 key-value 键值对。

# 传递多组键值对
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
configmap/special-config created
$ kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
  special.how: very
  special.type: charm
kind: ConfigMap
...

通过生成器创建 ConfigMap

使用生成器创建 ConfigMap,然后发送给 API Server 创建资源对象。生成器是在 kustomization.yaml 文件内部指定。

从文件创建生成器

使用 configmap/game.properties 文件生成一个 ConfigMap:

$ cat <<EOF >/root/learning/kustomization.yaml
configMapGenerator:
- name: game-config-5
  files:
  - configmap/game.properties
EOF

执行创建:

$ kubectl apply -k .
configmap/game-config-5-8b5gm5fhkb created
# 可以看到使用生成器创建的 ConfigMap 在名称末尾有一个 hash 后缀,这样可以确保每次配置文件内容修改以后生成器会生成一个新的 ConfigMap
$ kubectl get configmap|grep game-config-5
game-config-5-8b5gm5fhkb   1      48s
$ kubectl describe configmaps game-config-5-8b5gm5fhkb
Name:         game-config-5-8b5gm5fhkb
Namespace:    user-test
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
...

类似的我们可以将配置文件的名称进行重命名,只需要将 kustomization.yaml 中的 files 如下:

# 使用名称 game-special-key 替代 game.properties
- name: game-config-5
  files:
    - game-special-key=configmap/game.properties

然后执行 kubectl apply -k . 会生成新的 ConfigMap。

从键值对生成 ConfigMap

在终端执行如下命令写入值:

$ cat <<EOF >/root/learning/kustomization.yaml
configMapGenerator:
- name: special-config-2
  literals:
  - special.how=very
  - special.type=charm
EOF

执行创建:

$ kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created

2.3 在 Pod 中使用 ConfigMap

每次使用的时候,我们都需要先定义 ConfigMap,然后在 Pod 中引用定义好的配置信息。

通过环境变量方式使用 ConfigMap。

使用一个 ConfigMap 中的配置信息作为环境变量

使用 key-value 键值对定义一个用作环境变量的 ConfigMap:

$ kubectl create configmap config-1 --from-literal=special.how=very
configmap/config-1 created

定义 Pod YAML 文件时,SPECIAL_LEVEL_KEY 环境变量使用在 ConfigMap 中定义的 special.how 配置信息的值,新建 pods 文件夹,并在该文件夹下新建 pod-single-configmap-env-variable.yaml 文件,向该文件中写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: ["/bin/sh", "-c", "env"] # 容器的启动命令是输出环境变量
      env:
        - name: SPECIAL_LEVEL_KEY # 定义环境变量的名称
          valueFrom: # 环境变量 SPECIAL_LEVEL_KEY 的取值
            configMapKeyRef:
              name: config-1 # 环境变量的值取自于 config-1 ConfigMap
              key: special.how # key 为 special.how
  restartPolicy: Never

执行创建 Pod:

$ kubectl create -f pods/pod-single-configmap-env-variable.yaml
pod/dapi-test-pod created
# 查看状态为 Completed,因为启动容器后只查看了环境变量,并且设置为再也不重启,所以容器打印环境变量之后也变为完成状态,并且不会在重启
$ kubectl get pods
NAME              READY   STATUS      RESTARTS   AGE
dapi-test-pod     0/1     Completed   0          33s

然后查看日志,检查是否有成功设置环境变量:

$ kubectl logs dapi-test-pod|grep SPECIAL_LEVEL_KEY
SPECIAL_LEVEL_KEY=very

使用多个 ConfigMap 中的配置信息作为环境变量

新建 configmaps.yaml 文件,并写入如下内容:

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-2
  namespace: default
data:
  special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-3
  namespace: default
data:
  log_level: INFO

执行创建:

$ $ kubectl create -f configmap/configmaps.yaml
configmap/config-2 created
configmap/config-3 created

在 Pod YAML 文件中使用前面定义的 ConfigMap 中的配置信息,将下面的内容写入 pod-multiple-configmap-env-variable.yaml 文件中:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod-2
spec:
  containers:
    - name: test-container-2
      image: busybox
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: config-2
              key: special.how
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: config-3
              key: log_level
  restartPolicy: Never

执行创建:

$ kubectl create -f pods/pod-multiple-configmap-env-variable.yaml -n default
pod/dapi-test-pod-2 created

执行命令 kubectl logs dapi-test-pod-2 可以看到打印出的环境变量中有 LOG_LEVEL=INFO 以及 SPECIAL_LEVEL_KEY=very。

使用 ConfigMap 中的所有配置信息作为环境变量

新建 configmap-multikeys.yaml 文件,并写入如下内容:

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-4
  namespace: default
data:
  SPECIAL_LEVEL: very
  SPECIAL_TYPE: charm

执行创建:

$ kubectl create -f configmap/configmap-multikeys.yaml
configmap/config-4 created

使用 envFrom 将 ConfigMap 中的所有配置信息定义为容器的环境变量,ConfigMap 中的 key 会成为 Pod 中的环境变量名。新建 pod-configmap-envFrom.yaml 文件并写入如下内容:

$ kubectl create -f pods/pod-configmap-envFrom.yaml -n default
pod/dapi-test-pod-3 created

执行命令 kubectl logs dapi-test-pod-3 可以看到打印出的环境变量中有 SPECIAL_LEVEL=very 以及 SPECIAL_TYPE=charm。

在 Pod 命令中引用环境变量

在 Pod YAML 文件的 command 部分可以使用 $(VAR_NAME) 方式引用环境变量。

新建 pod-configmap-env-var-valueFrom.yaml 文件并写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod-4
spec:
  containers:
    - name: test-container-4
      image: busybox
      command:
        ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: config-4
              key: SPECIAL_LEVEL
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: config-4
              key: SPECIAL_TYPE
  restartPolicy: Never

执行创建:

$ kubectl create -f pods/pod-configmap-env-var-valueFrom.yaml -n default
pod/dapi-test-pod-4 created

执行命令 kubectl logs dapi-test-pod-4 可以看到输出的环境变量 very 和 charm。

$ kubectl logs dapi-test-pod-4 -n default
very charm

2.4 通过卷挂载 (volumeMount) 方式使用 ConfigMap

前面提到过可以使用参数 --from-file 从文件中创建 ConfigMap,这个时候文件名就成为了 ConfigMap 中的 key,文件中的内容就是 key 对应的 value。

使用 ConfigMap 中的配置数据挂载到卷

Pod YAML 文件定义中,在 volumes 指定 ConfigMap 的名字,在 volumeMounts.mountPath 指定具体挂载到容器中的目录。

新建 pod-configmap-volume.yaml 文件,并写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod-5
spec:
  containers:
    - name: test-container-5
      image: busybox
      command: ["/bin/sh", "-c", "ls /etc/config"] #查看是否成功挂载
      volumeMounts:
        - name: config-volume # 引用 volume 的名称
          mountPath: /etc/config # 挂载到容器内的目录路径
  volumes:
    - name: config-volume # 定义 volume 的名称
      configMap:
        name: config-4 # 使用 ConfigMap "config-4"
  restartPolicy: Never

执行创建:

$ kubectl create -f pods/pod-configmap-volume.yaml -n default
pod/dapi-test-pod-5 created

查看日志,获取容器中 /etc/config 目录下的文件列表:

$ kubectl logs dapi-test-pod-5 -n default
SPECIAL_LEVEL
SPECIAL_TYPE

可以很明确的发现,ConfigMap 配置信息的 key 成为了挂载到容器后的文件名。如果容器在 /etc/config 目录下存在文件,挂载后原有文件将会被覆盖。

卷挂载时明确存储路径

使用 path 字段可以明确挂载到容器后的文件名。

新建 pod-configmap-volume-specific-key.yaml 文件,并写入如下内容:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod-6
spec:
  containers:
    - name: test-container-6
      image: busybox
      command: ["/bin/sh", "-c", "cat /etc/config/keys"]
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: config-4
        items:
          - key: SPECIAL_LEVEL
            path: keys # SPECIAL_LEVEL 的 value 以 keys 文件名进行挂载
  restartPolicy: Never

执行创建:

$ kubectl create -f pods/pod-configmap-volume-specific-key.yaml -n default
pod/dapi-test-pod-6 created

查看日志,检查 /etc/config/keys 文件中存储的值是否为 SPECIAL_LEVEL 对应的值:

$ kubectl logs dapi-test-pod-6 -n default
very
0

评论区