一、什麼是ConfigMap
ConfigMap翻譯過來即為“配置字典”,在實際的生產環境中,應用程式配置經常需要且又較為複雜,引數、config檔案、變數等如果直接打包到映象中,將會降低映象的可移植性,因此期望有一種方式可以將配置從應用程式中解耦出來,ConfigMap正是在此背景下誕生的,它用於儲存配置資料的鍵值(key-value)對,可以用來儲存單個屬性,也可以用來儲存配置檔案。ConfigMap 跟 secret 很類似,但它可以更方便地處理不包含敏感資訊的字串。
二、適用場景?
適用於儲存不包含敏感資訊的變數、屬性或檔案。
比如在一個叢集中,可將應用程式所需的引數、變數、配置檔案存放到ConfigMap中,在開發、測試和生產環境將同1個ConfigMap(前提是同1個namespace)掛載到Pod中,這樣既可以實現配置和容器映象的分離,也可方便的實現統一管理,比如可以利用其熱更新的機制,修改完成後會同步到掛載了此ConfigMap的所有Pod中。
三、ConfigMap的建立
1、檔案目錄建立
支援以目錄的方式建立ConfigMap,其中檔名將作為key,檔案內容作為value,有幾個檔案將會存在幾個鍵值對,如下圖,先建立1個目錄,此目錄下存在兩個檔案
[root@k8s-master confdirtest]# ls conftest1.txt conftest.txt
[root@k8s-master consecret]# kubectl create configmap con-dir-test --from-file=confdirtest/ configmap/con-dir-test created
其格式為kubectl creat configmap "configmap的名字" --from-file="目錄"/,這種適用於將某個目錄下的所有檔案作為key,檔案內容作為value進行建立。
[root@k8s-master consecret]# kubectl get cm | grep con-dir-test con-dir-test 2 20s [root@k8s-master consecret]# kubectl describe cm con-dir-test Name: con-dir-test Namespace: default Labels: <none> Annotations: <none> Data ==== conftest.txt: ---- name=this is test #檔案conftest.txt的內容 conftest1.txt: ---- name=this is test1 #檔案conftest1.txt的內容 Events: <none>
2、檔案方式建立
--from-file的方式除了用於目錄的方式之外,同樣還適用於指定檔案的方式進行建立,其中檔名稱將作為key名稱,檔案內容作為value,如下所示,先建立一個配置檔案testconf.cfg
[root@k8s-master consecret]# cat testconf.cfg listenport=8080 name=testconf serverip=10.0.0.1
接下里將其生成1個configmap檔案,如下所示,其格式為:kubectl create configmap "configmap名稱" --from-file=“檔名”
[root@k8s-master consecret]# kubectl create configmap conf-file-test --from-file=testconf.cfg configmap/conf-file-test created [root@k8s-master consecret]# kubectl describe cm conf-file-test Name: conf-file-test Namespace: default Labels: <none> Annotations: <none> Data ==== testconf.cfg: ---- listenport=8080 name=testconf serverip=10.0.0.1 Events: <none>
此方式適用於將某個或多個配置檔案生成同一個configmap檔案的場景
3、直接建立key-value
可直接指定需要data的key-value鍵值對進行建立,如下所示,使用"--from-literal"選項可在命令列直接建立configmap物件,若是建立多個,可重複多次進行建立,但是注意其key的名稱不可重複,這種方式適用於直接指定key-value的方式進行建立。
[root@k8s-master consecret]# kubectl create configmap con-key-value --from-literal=key1=name1 configmap/con-key-value created [root@k8s-master consecret]# kubectl describe cm con-key-value Name: con-key-value Namespace: default Labels: <none> Annotations: <none> Data ==== key1: ---- name1 Events: <none> [root@k8s-master consecret]# kubectl create configmap con-key-value-test --from-literal=class.1=202 --from-literal=class.2=502 configmap/con-key-value-test created [root@k8s-master consecret]# kubectl describe cm con-key-value-test Name: con-key-value-test Namespace: default Labels: <none> Annotations: <none> Data ==== class.1: ---- 202 class.2: ---- 502 Events: <none>
4、匯入環境變數建立
可將環境變數以--from-env-file的方式進行建立,其格式為:kubectl crete configmap "configmap的名稱" --from-env=file=環境變數檔案.env
[root@k8s-master consecret]# echo -e "testenv1=1\testenv2=2" | tee configtest.env testenv1=1 estenv2=2 [root@k8s-master consecret]# kubectl create configmap conf-env-test --from-env-file=configtest.env configmap/conf-env-test created [root@k8s-master consecret]# kubectl describe cm conf-env-test Name: conf-env-test Namespace: default Labels: <none> Annotations: <none> Data ==== testenv1: ---- 1 estenv2=2 Events: <none>
四、ConfigMap的使用
1、熱更新(目錄形式掛載)
首先先成功建立一個ConfigMap
[root@k8s-master consecret]# cat conf-delete-test.yaml apiVersion: v1 kind: ConfigMap metadata: name: zltest-conf-delete namespace: default data: zltest.show: delete-test
[root@k8s-master consecret]# kubectl delete deployment dep-deleye-conf-test deployment.apps "dep-deleye-conf-test" deleted [root@k8s-master consecret]# kubectl create -f conf-delete-test.yaml configmap/zltest-conf-delete created [root@k8s-master consecret]# kubectl get cm | grep zltest-conf-delete zltest-conf-delete 1 44s
將其以卷目錄形式掛載到Pod容器中,建立一個deployment
[root@k8s-master zhanglei]# cat dep-delete-con.yaml apiVersion: apps/v1 kind: Deployment metadata: name: dep-deleye-conf-test namespace: default labels: app: nginx-delete-conf-test spec: replicas: 2 selector: matchLabels: app: nginx-deployment-delete template: metadata: labels: app: nginx-deployment-delete spec: containers: - name: nginx image: nginx:latest ports: - name: testconf containerPort: 80 volumeMounts: - name: nginxconf mountPath: /data/deletetest volumes: - name: nginxconf configMap: name: zltest-conf-delete
[root@k8s-master zhanglei]# kubectl create -f dep-delete-con.yaml deployment.apps/dep-deleye-conf-test created [root@k8s-master zhanglei]# kubectl get deployment |grep dep-deleye-conf-test dep-deleye-conf-test 2/2 2 2 56s
執行以上的步驟後,名為zltest-conf-delete的ConfigMap已被成功掛載到Pod的容器中,如果在執行的過程中,修改下ConfigMap的檔案,會出現怎樣的情況呢?先edit下ConfigMap,增加一個鍵值對
[root@k8s-master zhanglei]# kubectl describe cm zltest-conf-delete Name: zltest-conf-delete Namespace: default Labels: <none> Annotations: <none> Data ==== zltest.show: ---- delete-test Events: <none>
[root@k8s-master consecret]# kubectl edit cm zltest-conf-delete # Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 data: zltest.show: delete-test addkey: addvalue # 新增的鍵值對 kind: ConfigMap metadata: creationTimestamp: "2020-07-23T11:29:11Z" managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:data: .: {} f:zltest.show: {} manager: kubectl operation: Update time: "2020-07-23T11:29:11Z" name: zltest-conf-delete namespace: default
[root@k8s-master consecret]# kubectl edit cm zltest-conf-delete
configmap/zltest-conf-delete edited
驗證下新增的鍵值對是否會同步熱更新到Pod的容器中,通過exec的方式登入到容器中進行檢視,新新增的鍵值對以同步更新到Pod的容器中,
不需要以容器進行額外的操作,這是卷目錄的形式掛載的熱更新,但是若是通過環境變數env或者通過檔案的形式掛載到容器中,是不會支援熱更新的,這裡需要注意下。
[root@k8s-master consecret]# kubectl exec -it dep-deleye-conf-test-869747b77f-67w9h -- bash root@dep-deleye-conf-test-869747b77f-67w9h:/# cd data root@dep-deleye-conf-test-869747b77f-67w9h:/data# ls deletetest root@dep-deleye-conf-test-869747b77f-67w9h:/data# cd deletetest/ root@dep-deleye-conf-test-869747b77f-67w9h:/data/deletetest# ls addkey zltest.show
如果刪除已將掛載到Pod中的容器的ConfigMap會出現怎樣的情況呢,先刪除ConfigMap,然後再次登入到容器中進行驗證
[root@k8s-master consecret]# kubectl delete cm zltest-conf-delete configmap "zltest-conf-delete" deleted [root@k8s-master consecret]# kubectl exec -it dep-deleye-conf-test-869747b77f-67w9h -- bash root@dep-deleye-conf-test-869747b77f-67w9h:/data/deletetest# ls addkey zltest.show
若未對Pod進行刪除的操作,刪除ConfigMap成功,但是掛載到容器的目錄依然會存在,並不會一起被刪除,此時若刪除Pod,副本控制器會重新拉
起1個Pod,會建立成功嗎?接下來驗證下
[root@k8s-master consecret]# kubectl get pod | grep dep-deleye-conf-test dep-deleye-conf-test-869747b77f-kgzqt 1/1 Running 0 134m dep-deleye-conf-test-869747b77f-mf6vc 0/1 ContainerCreating 0 2m13s
重新拉起Pod一直會是ContainerCreating狀態,詳細檢視下原因
[root@k8s-master consecret]# kubectl describe pod dep-deleye-conf-test-869747b77f-mf6vc Name: dep-deleye-conf-test-869747b77f-mf6vc Namespace: default Priority: 0 Node: k8s-master/192.168.126.129 Start Time: Thu, 23 Jul 2020 21:47:00 +0800 Labels: app=nginx-deployment-delete pod-template-hash=869747b77f Annotations: <none> Status: Pending IP: IPs: <none> Controlled By: ReplicaSet/dep-deleye-conf-test-869747b77f Containers: nginx: Container ID: Image: nginx:latest Image ID: Port: 80/TCP Host Port: 0/TCP State: Waiting Reason: ContainerCreating Ready: False Restart Count: 0 Environment: <none> Mounts: /data/deletetest from nginxconf (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-74s86 (ro) Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled True Volumes: nginxconf: Type: ConfigMap (a volume populated by a ConfigMap) Name: zltest-conf-delete Optional: false default-token-74s86: Type: Secret (a volume populated by a Secret) SecretName: default-token-74s86 Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled <unknown> default-scheduler Successfully assigned default/dep-deleye-conf-test-869747b77f-mf6vc to k8s-master Warning FailedMount 11s (x8 over 75s) kubelet, k8s-master MountVolume.SetUp failed for volume "nginxconf" : configmap "zltest-conf-delete" not found
可以看到是FailedMount,volume異常了,K8S中刪除的時候是不會判斷這個依賴關係的,因此在生產的實際使用中,這點還是需要注意。
2、通過環境變數引入
除了通過volume的方式掛載到容器中使用之外,還可將configmap作為環境變數的方式引入到容器中,這裡以con-key-value-test作為例子
[root@k8s-master consecret]# kubectl get cm |grep con-key-value-test con-key-value-test 2 34m
[root@k8s-master zhanglei]# cat dep-conf-test.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-conf-env-test namespace: default labels: app: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx-deployment template: metadata: labels: app: nginx-deployment spec: containers: - name: nginx image: nginx:latest # command: [ "/bin/bash","-c","env" ] ports: - containerPort: 80 env: - name: test-env1-conf # 環境變數名稱1 valueFrom: configMapKeyRef: name: con-key-value-test key: class.1 # 指定key名稱即可 - name: test-env2-conf # 環境變數名稱2 valueFrom: configMapKeyRef: name: con-key-value-test # 引入configmap key: class.2
[root@k8s-master zhanglei]# kubectl create -f dep-conf-test.yaml deployment.apps/nginx-conf-env-test created [root@k8s-master zhanglei]# kubectl get pod |grep env-test nginx-conf-env-test-56f5c9b88-xt86x 1/1 Running 0 34s
可以看到Pod處於running的狀態,登入到容器驗證下以存在環境變數,如下所示,驗證成功,值得注意的是,這種方式相當於新生成的環境變數指向configmap中的key所對應的value
root@nginx-conf-env-test-56f5c9b88-xt86x:/# ls bin docker-entrypoint.d home media proc sbin tmp boot docker-entrypoint.sh lib mnt root srv usr dev etc lib64 opt run sys var root@nginx-conf-env-test-56f5c9b88-xt86x:/# env test-env2-conf=502 # 環境變數=原class.1的value test-env1-conf=202
五、總結
configmap是K8s中重要的配置管理方式,本文介紹了configmap的概念、使用場景、多種建立的方式、最後介紹瞭如何進行使用,希望能給大家的學習帶來一點幫助。
作者簡介:雲端計算容器\Docker\K8s\Serverless方向產品經理,學點技術,為更好地設計產品。