一、概述

1.概念

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap将你的环境配置信息和容器镜像解耦,便于应用配置的修改。

2.作用

每个服务都有自己的配置文件,在k8s里面一个服务通常会有多个副本,如果没有cofigmap,当需要修改配置的时候就需要逐个修改pod,如果有了configmap,那么只需要修改configmap,再重启pod加载配置即可。

3.使用方式

  1. 在容器命令和参数内
  2. 容器的环境变量
  3. 在只读卷里面添加一个文件,让应用来读取
  4. 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

二、配置详解

kind: ConfigMap					## 资源类型
apiVersion: v1					## 接口版本
metadata:
  name: cm-nginx				## configmap名称
  namespace: mx-test			## 命名空间
data:							## 配置数据
  nginx: |						## nginx为key,|管道符下面是整段配置,方便生成配置文件,再挂载
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
  test: helloworld			## k:v形式,方便环境变量调用及启动参数调用

三、演练

1.创建一个cm

[root@localhost base-image]# vim configmap-nginx.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: cm-nginx
  namespace: mx-test
data:
  nginx: |
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
  test: helloworld
[root@localhost base-image]# kubectl apply -f configmap-nginx.yaml
configmap/cm-nginx created

查看详情

[root@iZbp19rn9u8eqyzc5hgemcZ base-image]# kubectl get cm -n mx-test
NAME               DATA   AGE
cm-nginx           2      20s				
kube-root-ca.crt   1      17h

NOTE:DATA下面是2,代表里面有2个k:v配置

2.创建一个没有configmap的pod

[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  namespace: mx-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
  namespace: mx-test
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app created
service/nginx-app-svc created

进入pod,查看配置

[root@localhost base-image]# kubectl get pod -n mx-test
NAME                         READY   STATUS    RESTARTS   AGE
nginx-app-7848d4b86f-pj5wp   1/1     Running   0          63s
nginx-app-7848d4b86f-vqk5z   1/1     Running   0          63s
[root@localhost base-image]# kubectl exec -it nginx-app-7848d4b86f-pj5wp  -n mx-test -- /bin/bash
root@nginx-app-7848d4b86f-pj5wp:/# cat /etc/nginx/conf.d/default.conf   // 默认的nginx配置,有很多注释内容
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

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

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

3.以卷的形式挂载

[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  namespace: mx-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:							## 卷挂载信息
        - name: nginx-conf						## 卷名称
          mountPath: /etc/nginx/conf.d/			## 挂载到容器的目录
      volumes:									## 卷详细信息
      - name: nginx-conf						## 卷名称
        configMap:								## 卷类型:configmap
          name: cm-nginx						## configmap名称
          items:								## configmap的某个项
          - key: nginx							## configmap的某一个key
            path: default.conf					## 用configmap配置生成的文件名称
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
  namespace: mx-test
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app configured
service/nginx-app-svc unchanged

查看configmap挂载情况

[root@localhost ~]# kubectl get pod -n mx-test
NAME                         READY   STATUS    RESTARTS   AGE
nginx-app-77fffffb59-bsll5   1/1     Running   0          14s
nginx-app-77fffffb59-gkgdb   1/1     Running   0          18s
[root@localhost ~]# kubectl exec -it nginx-app-77fffffb59-bsll5 -n mx-test -- /bin/bash
root@nginx-app-77fffffb59-bsll5:/# cat /etc/nginx/conf.d/default.conf	## 新挂载的配置由于文件名称一样,所以直接覆盖了默认配置文件
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

4.访问测试

[root@localhost base-image]# kubectl get pod -n mx-test -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP              NODE                      NOMINATED NODE   READINESS GATES
nginx-app-77fffffb59-bsll5   1/1     Running   0          7m48s   100.64.49.226   izbp19rn9u8eqyzc5hgemdz   <none>           <none>
nginx-app-77fffffb59-gkgdb   1/1     Running   0          7m52s   100.64.49.225   izbp19rn9u8eqyzc5hgemdz   <none>           <none>
[root@localhost base-image]# curl 100.64.49.226
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

5.环境变量引用

pod yaml文件添加env环境变量

[root@localhost base-image]# vim app-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-app
  namespace: mx-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        env:									## 环境变量
        - name: TEST							## 变量名称
          valueFrom:							## 变量值来自哪里?
            configMapKeyRef:					## 来自configmap
              name: cm-nginx					## 那个configmap?
              key: test							## 那个key?
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/conf.d/
      volumes:
      - name: nginx-conf
        configMap:
          name: cm-nginx
          items:
          - key: nginx
            path: default.conf
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-app-svc
  namespace: mx-test
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  selector:
    app: nginx
[root@localhost base-image]# kubectl apply -f app-nginx.yaml
deployment.apps/nginx-app configured
service/nginx-app-svc unchanged

查看环境变量

[root@localhost ~]# kubectl get pod -n mx-test
NAME                         READY   STATUS    RESTARTS   AGE
nginx-app-67b764c499-8pvwg   1/1     Running   0          28s
nginx-app-67b764c499-jvq68   1/1     Running   0          24s
[root@localhost ~]# kubectl exec -it nginx-app-67b764c499-8pvwg -n mx-test -- /bin/bash
root@nginx-app-67b764c499-8pvwg:/# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=nginx-app-67b764c499-8pvwg
NGINX_APP_SVC_PORT_80_TCP_PROTO=tcp
NGINX_APP_SVC_PORT_80_TCP_PORT=80
PWD=/
NGINX_APP_SVC_PORT_80_TCP=tcp://10.96.88.30:80
PKG_RELEASE=1~bookworm
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NGINX_APP_SVC_PORT_80_TCP_ADDR=10.96.88.30
NJS_VERSION=0.7.12
TERM=xterm
NGINX_APP_SVC_PORT=tcp://10.96.88.30:80
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_APP_SVC_SERVICE_HOST=10.96.88.30
NGINX_APP_SVC_SERVICE_PORT=80
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.25.1
TEST=helloworld													## TEST=helloworld 
_=/usr/bin/env
root@nginx-app-67b764c499-8pvwg:/# env | grep -i test			## TEST=helloworld 
TEST=helloworld

6.容器命令引用

创建一个pod

[root@localhost base-image]# vim pod-busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test
  namespace: mx-test
spec:
  containers:
    - name: test-container
      image: busybox								## busybox 镜像
      command: [ "/bin/echo", "$(TEST)" ]			## 启动命令输出一个TEST变量
      env:
        - name: TEST
          valueFrom:
            configMapKeyRef:
              name: cm-nginx
              key: test
  restartPolicy: Never
[root@localhost base-image]# kubectl apply -f pod-busybox.yaml
pod/test created

查看pod log是否有输出变量的值

[root@localhost base-image]# kubectl get pod -n mx-test
NAME                         READY   STATUS      RESTARTS   AGE
nginx-app-67b764c499-8pvwg   1/1     Running     0          10m
nginx-app-67b764c499-jvq68   1/1     Running     0          10m
test                         0/1     Completed   0          8s
[root@iZbp19rn9u8eqyzc5hgemcZ base-image]# kubectl logs -f  test -n mx-test --tail 20
helloworld

7.使用kubernetes API读取Configmap

先获取token,测试使用default sa的secret中的token

[root@localhost pki]# kubectl get sa default  -n kube-system
NAME      SECRETS   AGE
default   1         78d
[root@localhost pki]# kubectl get sa default  -n kube-system -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2023-05-25T02:21:18Z"
  name: default
  namespace: kube-system
  resourceVersion: "347"
  uid: d22f9c2a-7195-4f66-8f10-837724bda60a
secrets:
- name: default-token-ztl2m
[root@localhost pki]# kubectl describe secret default-token-ztl2m -n kube-system
Name:         default-token-ztl2m
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: d22f9c2a-7195-4f66-8f10-837724bda60a

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1070 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg

赋值给TOKEN

[root@localhost pki]# TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg'
[root@localhost pki]# echo $TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6IkoyZkhTSmF2SThXdDlhRUFUc3NJZnFXcFpKbnhzMUJpelRHeU9PdkFlUncifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXp0bDJtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMjJmOWMyYS03MTk1LTRmNjYtOGYxMC04Mzc3MjRiZGE2MGEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.yYnIffR_GePEMucYQ0-XCzsSL3R5GtLbcnLtcYOMKqSJAhMj3G3TSZ99lyvPuRJzDLsKkwKjlrwGkM3a9HSEzBYFxy5e6JMIr_FB2udxEPsFTmOuN9ApWAFset1Pg8CVj39yB4Gvk_5_CoUmmcFULvfCs3ZHh9pdgd-6eb2_UkpTPVrE-uRTmDyIfc4MRHPvGN8tp-npiCbCXHETDDKWVaSvL_AzgOVk45XDyF9t5ILft7VPyL6F2xa9xH1VwIWhDBmUi4ARlKBv4jbXWfq7w8SeBgaTWLV-F_yQ1wQTOK2kXqE_xXUlJYIxsxotRYSuwPLLjL34y_hsxhzAE-1Jgg

使用curl命令,GET方法访问apiserver

[root@localhost pki]# curl -XGET -k -H "Authorization: Bearer $TOKEN" https://apiserver.cluster.local:6443/api/v1/namespaces/mx-test/configmaps/cm-nginx
{
  "kind": "ConfigMap",
  "apiVersion": "v1",
  "metadata": {
    "name": "cm-nginx",
    "namespace": "mx-test",
    "uid": "16d12f26-f886-4bed-af38-1054981860af",
    "resourceVersion": "265265705",
    "creationTimestamp": "2023-08-11T01:48:03Z",
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"nginx\":\"server {\\n    listen       80;\\n    server_name  localhost;\\n    location / {\\n        root   /usr/share/nginx/html;\\n        index  index.html index.htm;\\n    }\\n    error_page   500 502 503 504  /50x.html;\\n    location = /50x.html {\\n        root   /usr/share/nginx/html;\\n    }\\n}\\n\",\"test\":\"helloworld\"},\"kind\":\"ConfigMap\",\"metadata\":{\"annotations\":{},\"name\":\"cm-nginx\",\"namespace\":\"mx-test\"}}\n"
    },
    "managedFields": [
      {
        "manager": "kubectl-client-side-apply",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2023-08-11T01:48:03Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {"f:data":{".":{},"f:nginx":{},"f:test":{}},"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}}}
      }
    ]
  },
  "data": {
    "nginx": "server {\n    listen       80;\n    server_name  localhost;\n    location / {\n        root   /usr/share/nginx/html;\n        index  index.html index.htm;\n    }\n    error_page   500 502 503 504  /50x.html;\n    location = /50x.html {\n        root   /usr/share/nginx/html;\n    }\n}\n",
    "test": "helloworld"
  }
}

通过jq工具格式化,拿出名称为cm-nginx中的nginx配置

[root@localhost pki]# curl -XGET -k -H "Authorization: Bearer $TOKEN" https://apiserver.cluster.local:6443/api/v1/namespaces/mx-test/configmaps/cm-nginx | jq -r .data.nginx
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1555  100  1555    0     0   126k      0 --:--:-- --:--:-- --:--:--  126k
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Kubernetes API文档参考:http://kubernetes.kansea.com/docs/api-reference/v1/operations/

补充

configmap 多层嵌套例子

apiVersion: v1
kind: ConfigMap
metadata:
  name: nested-configmap
data:
  config.json: |
    {
      "level1": {
        "level2": {
          "key1": "value1",
          "key2": "value2"
        }
      }
    }
  nested.properties: |
    level1.level2.key3=value3
    level1.level2.key4=value4

上段配置可以看出,多层嵌套有两种格式,其中:
config.json是用json对象格式
nested.properties是用键值对格式
官网链接:https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#create-a-configmap-from-generator

在实际应用场景中,如果嵌套层数比较多且配置比较多的话,推荐使用键值对格式,键值对格式key:value一目了然

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐