Back
Featured image of post k8s 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博客