Kubernetes k8s configmap 容器技術解析
1、什么是 ConfigMap?
ConfigMap 是用來存儲配置文件的 Kubernetes 資源對象,配置對象存儲在 Etcd 中,配置的形式可以是完整的配置文件、key/value 等形式。
2、ConfigMap 能帶來什么好處?
傳統(tǒng)的應用服務,每個服務都有自己的配置文件,各自配置文件存儲在服務所在節(jié)點,對于單體應用,這種存儲沒有任何問題,但是隨著用戶數(shù)量的激增,一個節(jié)點不能滿足線上用戶使用,故服務可能從一個節(jié)點擴展到十個節(jié)點,這就導致,如果有一個配置出現(xiàn)變更,就需要對應修改十次配置文件。
這種人肉處理,顯然不能滿足線上部署要求,故引入了各種類似于 ZooKeeper 中間件實現(xiàn)的配置中心,但配置中心屬于 “侵入式” 設計,需要修改引入第三方類庫,它要求每個業(yè)務都調用特定的配置接口,破壞了系統(tǒng)本身的完整性,而Kubernetes 利用了 Volume 功能,完整設計了一套配置中心,其核心對象就是ConfigMap,使用過程不用修改任何原有設計,即可無縫對 ConfigMap;為什么呢?

如圖(1)所示,
- ConfigMap 相當于放入原生應用的配置文件,可以是一個或者多個;
- 容器啟動之后,到宿主機中拉取 ConfigMap 的內(nèi)容,生成本地文件,通過 volume 形式映射到容器內(nèi)部指定目錄上;
- 容器中應用程序按照原有方式讀取容器特定目錄上的配置文件。
在容器看來,配置文件就像是打包在容器內(nèi)部特定目錄,整個過程對應用沒有任何侵入。
3、ConfigMap 三種創(chuàng)建方式
- 指定字面量進行創(chuàng)建,創(chuàng)建命令如下所示:
kubectl create configmap configmaptest --from-literal=foo=bar --from-literal=one=two
創(chuàng)建完成后通過如下方式查看:
[root@k8s-master k8s]# kubectl get configmap configmaptest -o yaml apiVersion: v1 data: foo: bar one: two kind: ConfigMap metadata: creationTimestamp: "2020-04-14T13:53:42Z" name: configmaptest namespace: default resourceVersion: "613402" selfLink: /api/v1/namespaces/default/configmaps/configmaptest uid: 59b91eb4-7e57-11ea-83c7-509a4c36e19d
- 指定特定文件進行創(chuàng)建
kubectl create configmap config-files --from-file=/home/conf/db.properties
可以通過如下方式進行查看,(內(nèi)容過長,影響閱讀,省略 ConfigMap 元信息。)
[root@k8s-master k8s]# kubectl get configmap test-config -o yaml
apiVersion: v1
data:
db.properties: |
driverClassName=com.mysql.jdbc.Driver
......
- 指定特定文件夾進行創(chuàng)建
kubectl create configmap config-dir --from-file=/home/conf/config-test
通過如下方式進行查看
[root@k8s-master k8s]# kubectl get configmap config-test -o yaml
apiVersion: v1
data:
db.properties: |
# 數(shù)據(jù)源配置
driverClassName=com.mysql.jdbc.Driver
......
logback.xml: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"true\"
......
svc.properties: |
#server
protocol=tcp
.......
system.properties: |
time=100
.......
如上描述三種基本的 ConfigMap創(chuàng)建方式,當然也可以使用合并不同選項進行創(chuàng)建配置文件,具體如下所示:
kubectl create configmap config-mix --from-file=/home/conf/biz/ --from-file=/home/conf/db.xml --from-literal=one=two
看到這么多,你可能會想到,--from-file最后一級如果是文件夾會怎樣呢?如你所想,文件夾其實不會被包含,只會查找最后一級目錄下的文件。
4、ConfigMap 作為環(huán)境變量三種使用方式
單個引用
1、首先創(chuàng)建 ConfigMap
kubectl create configmap configmaptest --from-literal=code=25 --from-literal=foo=bar --from-literal=one=two
2、Deployment yaml中引用 ConfigMap 設置環(huán)境變量,如圖(2)所示

3、通過如下方式進行查看,環(huán)境變量是否生效,可以發(fā)現(xiàn),容器環(huán)境中已經(jīng)存在引用ConfigMap中的環(huán)境變量
[root@k8s-master k8s]# kubectl exec nginx-7c958f6448-z5q56 -it /bin/bash [root@nginx-7c958f6448-z5q56 /]# env|grep CODE CODE-TIME=25
多個引用
1、一次性傳遞所有ConfigMap條目作為環(huán)境變量,如圖(3)所示

可以通過如下方式進行查看環(huán)境變量是否生效,如下所示每個環(huán)境變量都按照預設,添加了配置的前綴,有人可能要說,我的配置文件中原來是什么配置現(xiàn)在還保留什么配置,不需要添加預設前綴,那么請查看如圖(4)通過把前綴設置為空串,即可保持原有配置方式。
[root@k8s-master k8s]# kubectl exec nginx-84ccdff98d-vgzcw -it /bin/bash [root@nginx-84ccdff98d-vgzcw /]# env|grep CODE CODE_foo=bar CODE_code=25 CODE_one=two

args 方式傳遞環(huán)境變量
容器啟動時,傳遞該變量到服務,運行 shell 腳本,可能會用到,具體設置方式如圖(5)所示:

以上解釋了通過在 yaml 設置 env 引用 ConfigMap 中配置作為環(huán)境變量的使用,在使用過程中,我參考了 《Kubernetes In Action》這本書,發(fā)現(xiàn)此書中有一段是這樣描述的,如圖(6)所示:

其大概意思是,配置鍵中不能包含破折號,如果包含則不能設置到環(huán)境變量中,此書這部分是基于 Kubernetes 1.6 進行編撰,而我使用的是 kubernetes 1.14,不清楚是不是因為 Kubernetes 已經(jīng)改進的原因,還是其他原因,我有兩點不解的地方。
破折號(——)大多都是指特別長的符號,在編碼過程中很少有人使用這個,即使使用了,Kubernetes 根本無法保存成功。
又何談環(huán)境變量一說呢?會提示如圖(7),圖(8)所示錯誤:


如果破折號換成英文半角字符 - 中劃線呢?如圖(9)所示,是可以保存成功的。當然也可以用于環(huán)境變量中。

當然通過如上方式設置完成之后,就可以直接在容器內(nèi)部使用環(huán)境變量讀取已經(jīng)設置的配置,但是使用環(huán)境變量的方式有一個致命的缺點是,當外部 ConfigMap 更新配置完成之后,容器內(nèi)部環(huán)境變量并不會隨之改變,這是因為 ENV 是容器啟動時候注入的,啟動之后 Kubernetes 就不會改變 ENV 的值,即配置不能同步更新,只能通過重啟容器方式,配置才能生效。
5、掛載 volume
這種方式則是通過 volume 形式映射到容器內(nèi)部指定目錄上,容器內(nèi)部進程直接讀取該目錄下特定文件,這種方式是我們常用的一種方式,具體使用時如下所示:
......
- containerPort: 80
volumeMounts:
- mountPath: /usr/local/nginx/conf/vhost/
name: http
- mountPath: /usr/local/nginx/html/foo
subPath: foo
name: nginx-html
volumes:
- name: http
configMap:
name: nginx-conf
- name: nginx-html
configMap:
name: configmaptest
items:
- key: foo
path: foo
......
volumeMounts 是容器內(nèi)部指定掛載目錄,volumes 是引用目錄,即宿主機設置 ConfigMap 文件地址。
- 可以直接掛載一個目錄到容器內(nèi)部,當宿主機通過如下方式修改 configmap 那么容器內(nèi)部配置將隨之改變,一次性修改所有文件。但是使用這種方式有一個問題需要注意,如果掛載到容器內(nèi)部的文件夾下存在其它文件,這種掛載方式將直接覆蓋原有文件夾下的文件。
[root@k8s-master ~]# kubectl edit configmap configmaptest
- 如果有特定需求,需要掛載某個特定文件,而不允許覆蓋原有文件,可以掛載到指定文件,通過 subPath 配合指定文件。但是單個文件掛載這種方式不能實現(xiàn)熱更新,即宿主機 ConfigMap 文件發(fā)生變化,容器內(nèi)部不會自動重載。
- 至于 items 使用就比較簡單了,如果一個 ConfigMap 中包含多個配置文件,但是只想暴露出來其中一部分,那么可以通過 items 方式進行指定。當然你也可以對文件設置讀寫權限。
6、Secret 使用
Secret 使用類似于 ConfigMap,支持兩種形式的使用:
- 將 Secret 作為環(huán)境變量暴露給容器進程使用。
- 將 Secret 通過volume 數(shù)據(jù)卷提供給容器進程使用。
看到這里你可能要說了,什么都一樣,為啥還要 Secret,一個 ConfigMap 解決問題不就完事了,其實不然,Secret 顧名思義,是用于存儲加密數(shù)據(jù)的,老版本 Kubernetes 只支持 base64 加密,學過計算機的都知道 base64 那就不是什么加密,只是對字符串進行了 encode 編碼,通過 decode 直接可以解出明文。
但后來新版本的 Kubernetes 已經(jīng)實現(xiàn)了真正意義上的加解密,所以 Secret 存在是有一定意義的,使用方式跟 ConfigMap 類似,但是命令確不一樣。
1、創(chuàng)建 Secret 輸入如下:
kubectl create secret generic nginx-ssl --from-file=ca.key --from-file=ca.cert
2、查看 Secret 輸入如下所示:
[root@k8s-master ~]# kubectl get secret NAME TYPE DATA AGE default-token-7h5z9 kubernetes.io/service-account-token 3 6d13h nginx-ssl Opaque 2 21h [root@k8s-master ~]# kubectl get secret nginx-ssl -o yaml apiVersion: v1 data: ca.crt: QmFnIEF0dHJpYnV0ZXMKICAgIGZy....................... ca.key: QmFnIEF0dHJpYnV0ZXMKICAgIGZy...................... kind: Secret .....................
3、Pod 引用方式:
.....................
- containerPort: 80
volumeMounts:
- mountPath: /home/nginx/nginx/conf/cert/
name: nginx-ssl
volumes:
- name: nginx-ssl
secret:
secretName: nginx-ssl
.....................
7、應用程序怎么做到不重啟情況下讀取最新配置
上面已經(jīng)提及使用環(huán)境變量和單文件掛載形式,無法實現(xiàn)熱更新,但是通過 數(shù)據(jù)卷形式可以實現(xiàn)宿主機和 Pod 內(nèi)部讀取配置的實時更新,但是有一點需要注意的是 ConfigMap 更新,數(shù)據(jù)卷也更新了,如果你的應用進程不進行配置重載,即實時讀取配置數(shù)據(jù),同樣還是使用的老配置。
這個問題可以通過把 Pod 的副本數(shù)減少到 0 進行重建 Pod 解決。這種方式雖然能夠解決服務重新加載問題,但是也會帶來問題。
因為可能會導致同一套服務,配置不一致的問題,因此,如果業(yè)務對實時性要求高,建議改成服務實時加載配置。總結一下,Kubernetes 只是把配置實時同步到數(shù)據(jù)卷配置文件中,至于加載時機,還要看自己的應用程序。
舉個例子,nginx 配置存儲在 Kubernetes ConfigMap 里面,公鑰信息存儲在 Secret 中,nginx 充當服務里面的反向代理,因為端口資源規(guī)劃問題,需要修改 nginx 配置文件中端口,修改完成后,Pod 中的數(shù)據(jù)卷配置信息發(fā)生變化,但 nginx 并不會重載已經(jīng)修改的配置信息。
通過如下命令行修改,修改完成后,發(fā)現(xiàn) Pod 中 nginx 配置生效。
kubectl exec nginx -c nginx -- /usr/local/nginx/sbin/nginx -s reload
總結
ConfigMap 本身是一個很接地氣的設計,它借助于 volume ,原有服務不用修改任何代碼,即可無縫對接。如果你已經(jīng)使用了其它分布式配置管理服務,如:DisConf,Apollo等,你也可以保持原有方式,繼續(xù)使用。
以上就是Kubernetes k8s configmap 容器技術解析的詳細內(nèi)容,更多關于k8s configmap 容器技術的資料請關注腳本之家其它相關文章!
相關文章
一文詳解基于Kubescape進行Kubernetes安全加固
這篇文章主要為大家介紹了基于Kubescape進行Kubernetes安全加固詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
k8s service使用詳解(云原生kubernetes)
這篇文章主要介紹了k8s service使用詳解(云原生kubernetes),一個Service可以看作一組提供相同服務的Pod的對外訪問接口,作用于哪些Pod是通過標簽選擇器來定義的 ,Service是一個概念,主要作用的是節(jié)點上的kube-proxy服務進程,本文結合示例代碼詳解,需要的朋友參考下2023-02-02
ES業(yè)務數(shù)據(jù)遷移遇到的精度問題BUG
這篇文章主要為大家介紹了ES業(yè)務數(shù)據(jù)遷移遇到的BUG精度問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

