Back
Featured image of post k8s configmap 详解, 从理解 k8s volumes 挂载方式, 带你解决挂载 configmap 的种种疑难杂症, 以及 k8s 中如何创建 configmap

k8s configmap 详解, 从理解 k8s volumes 挂载方式, 带你解决挂载 configmap 的种种疑难杂症, 以及 k8s 中如何创建 configmap

ConfigMap 顾名思义,是用于保存配置数据的键值对,可以用来保存单个属性,也可以保存配置文件。Secret 可以为 Pod 提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以使用 ConfigMap。

引言

ConfigMap 顾名思义,是用于保存配置数据的键值对,可以用来保存单个属性,也可以保存配置文件。Secret 可以为 Pod 提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以使用 ConfigMap。

ConfigMap 的创建和使用方式与 Secret 非常类似,主要的不同是以明文的形式存放

创建方式:

序号 创建方式 参数
1 命令行 key-value 格式创建 (字面量方式创建) –from-literal
2 根据文件创建 (env 方式创建) –from-env-file
3 从目录创建 –from-file
4 根据 yaml 创建 kubectl create -f

1. 命令行 key-value 格式创建 (字面量方式创建)

$ kubectl create configmap literal-configmap --from-literal=key1=value1 --from-literal=key2=value2 --from-literal=key3=value3

$ kubectl get configmap literal-configmap -oyaml
apiVersion: v1
data:
  key1: value1
  key2: value2
  key3: value3
kind: ConfigMap
metadata:
  creationTimestamp: "2024-01-09T04:25:43Z"
  name: literal-configmap
  namespace: default
  resourceVersion: "594871"
  uid: b7f8824c-01dd-4438-994d-fc8c9d50649c

2. 根据文件创建 (env 方式创建)

文件格式为: key=value, 与 .ini格式一致

$ cat testenv
envkey1=envvalue1
envkey2=envvalue2

$ kubectl create configmap envfile-configmap --from-env-file testenv

$ kubectl get configmaps envfile-configmap -oyaml
apiVersion: v1
data:
  envkey1: envvalue1
  envkey2: envvalue2
kind: ConfigMap
metadata:
  creationTimestamp: "2024-01-09T04:31:45Z"
  name: envfile-configmap
  namespace: default
  resourceVersion: "595672"
  uid: 8841549f-73da-4040-8c76-39517d1bd2d7

3. 从目录创建

从目录创建 configmap 只会读取文件夹第一级内容, 不会递归搜索

# 创建两个 pod yaml
$ mkdir pods
$ kubectl run nginxpod --image=nginx --dry-run=client -oyaml > pods/nginxpod.yaml
$ kubectl run envoypod --image=envoy --dry-run=client -oyaml > pods/envoypod.yaml

# 把 pods 整个目录下内容作为 configmap 的 data
# key: 文件名
# value: 文件内容
$ kubectl create configmap testfile --from-file pods/

$ kubectl get configmaps testfile -oyaml
apiVersion: v1
data:
  envoypod.yaml: |
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: envoypod
      name: envoypod
    spec:
      containers:
      - image: envoy
        name: envoypod
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}    
  nginxpod.yaml: |
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: nginxpod
      name: nginxpod
    spec:
      containers:
      - image: nginx
        name: nginxpod
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}    
kind: ConfigMap
metadata:
  creationTimestamp: "2024-01-09T05:14:01Z"
  name: testfile
  namespace: default
  resourceVersion: "601262"
  uid: 89254512-f822-4414-927f-1bdb4fd1dcef

4. 根据 yaml 创建

创建 configmap yaml:

apiVersion: v1
data:
  yamlkey1: yamlvalue1
  yamlkey1: yamlvalue1
kind: ConfigMap
metadata:
  name: yaml-configmap
  namespace: default
$ kubectl create -f yaml-configmap.yaml

configmap 的使用

  1. 作为环境变量注入
  2. 以 volume 方式挂载

注意!!

  • ConfigMap必须在Pod使用它之前创建
  • 使用envFrom时,将会自动忽略无效的键
  • Pod只能使用同一个命名空间的ConfigMap

1. 作为环境变量注入

创建 pod:

apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - image: busybox
    name: busybox
    command: ["/bin/sh","-c","echo $KEY1 && env"]
    env:
    - name: KEY1
      valueFrom:
        configMapKeyRef:
          key: key1
          name: literal-configmap  # configmap 名称
          optional: true  # 将环境变量标记为可选
    - name: KEY2
      valueFrom:
        configMapKeyRef:
          key: key2
          name: literal-configmap
  restartPolicy: Never

查看 pod1

$ kubectl get po
NAME                         READY   STATUS      RESTARTS       AGE
pod1                         0/1     Completed   0              7s
......

# 查看 pod1 的标准输出
$ kubectl logs pod1
value1
KEY1=value1
KEY2=value2
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod1
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/

2. 以 volume 方式挂载

一个 key 对应一个文件

挂载完整的 configmap

**注意: **直接挂载 configmap 会覆盖 mountPath 文件夹, 需要确保 mountPath 为空目录, 否则 pod 无法创建

查看 configmap 值

# 输出 go map 类型
# kubectl get cm testfile -o go-template='{{.data}}'
Name:         testfile
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
envoypod.yaml:
----
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: envoypod
  name: envoypod
spec:
  containers:
  - image: envoy
    name: envoypod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

nginxpod.yaml:
----
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginxpod
  name: nginxpod
spec:
  containers:
  - image: nginx
    name: nginxpod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}


BinaryData
====

Events:  <none>
  • 两个 key

创建 pod

apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  volumes:
  - name: cm
    configMap:
      name: testfile
  containers:
  - image: busybox
    name: busybox
    command: ["sleep", "24h"]
    volumeMounts:
    - mountPath: /etc/config
      name: cm
$ kubectl create -f pod2.yaml

$ kubectl exec pod2 -- ls /etc/config
envoypod.yaml
nginxpod.yaml
$ kubectl exec pod2 -- cat /etc/config/nginxpod.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginxpod
  name: nginxpod
spec:
  containers:
  - image: nginx
    name: nginxpod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

挂载 configmap 中特定 key

**注意: ** configmap 挂载都是覆盖行为

  • 对于多个 key: 确保挂载 mountPath 为空目录
  • 对于单一 key: 确保 mountPath 为空文件

创建 pod

apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  volumes:
  - name: cm
    configMap:
      name: testfile
      items:
      - key: nginxpod.yaml
        path: keys/nginx.yaml  # 该字段指定相对路径地址
      - key: envoypod.yaml
        path: envoy.yaml
  containers:
  - image: busybox
    name: busybox
    command: ["sleep", "24h"]
    volumeMounts:
    - mountPath: /etc/yaml
      name: cm
$ kubectl exec pod3 -- ls -l /etc/yaml/
lrwxrwxrwx    1 root     root            17 Jan  9 06:34 envoy.yaml -> ..data/envoy.yaml
lrwxrwxrwx    1 root     root            11 Jan  9 06:34 keys -> ..data/keys
$ kubectl exec pod3 -- ls -l /etc/yaml/keys/
-rw-r--r--    1 root     root           241 Jan  9 06:34 nginx.yaml

练习

  1. 真实世界的案例:使用 ConfigMap 来配置 Redis

参考:

  1. https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/#add-configmap-data-to-a-volume
  2. https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/#use-configmap-defined-environment-variables-in-pod-commands
  3. k8s – ConfigMap - 简书 (jianshu.com)
  4. k8s之ConfigMap详细理解及使用-CSDN博客