Kubernetes的Configmap詳解
ConfigMap是用來儲存配置檔案的kubernetes資源物件,所有的配置內容都儲存在etcd中。
1.建立ConfigMap
建立ConfigMap的方式有4種:
- 通過直接在命令列中指定configmap引數建立,即
--from-literal
- 通過指定檔案建立,即將一個配置檔案建立為一個ConfigMap
--from-file=<檔案>
- 通過指定目錄建立,即將一個目錄下的所有配置檔案建立為一個ConfigMap,
--from-file=<目錄>
通過yaml檔案來建立,另一種是通過kubectl直接在命令列下建立。 - 事先寫好標準的configmap的yaml檔案,然後kubectl create -f 建立
1.1 通過命令列引數--from-literal
建立
示例
建立命令:
kubectl create configmap test-config1 --from-literal=db.host=10.5.10.116 --from-listeral=db.port='3306'
結果如圖中data內容所示:
1.2 指定檔案建立
示例
配置檔案app.properties的內容:
建立命令(可以有多個--from-file
):
kubectl create configmap test-config2 --from-file=./app.properties
結果如圖中data內容所示:
可以看到指定檔案建立時configmap會建立一個key/value對,key是檔名,value是檔案內容。
假如不想configmap中的key為預設的檔名,還可以在建立時指定key名字:
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
1.3 指定目錄建立
示例
configs 目錄下的config-1和config-2內容如下所示:
建立命令:
kubectl create configmap test-config3 --from -file=./configs
結果如圖中data內容所示:
可以看到指定目錄建立時configmap內容中的各個檔案會建立一個key/value對,key是檔名,value是檔案內容。
那假如目錄中還包含子目錄呢?繼續做實驗:
在上一步的configs目錄下建立子目錄subconfigs,並在subconfigs下面建立兩個配置檔案,指定目錄configs建立名為test-config4的configmap:
kubectl create configmap test-config4 --from-file=./configs
結果如下圖所示:
結果說明指定目錄時只會識別其中的檔案,忽略子目錄
1.4 通過事先寫好configmap的標準yaml檔案建立
yaml檔案如圖所示:
結果如圖中data內容所示:
注意其中一個key的value有多行內容時的寫法
2.使用ConfigMap
使用ConfigMap有三種方式:
- 第一種是通過環境變數的方式,直接傳遞給pod
- 使用configmap中指定的key
- 使用configmap中所有的key
- 第二種是通過在pod的命令列下執行的方式(啟動命令中)
- 第三種是作為volume的方式掛載到pod內
2.1 通過環境變數使用
示例:
(1)使用valueFrom
、configMapKeyRef
、name
、key
指定要用的key:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
(2)還可以通過envFrom
、configMapRef
、name
使得configmap中的所有key/value對都自動變成環境變數:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
2.2 在啟動命令中引用
示例:
在命令列下引用時,需要先設定為環境變數,之後可以通過$(VAR_NAME)設定容器啟動命令的啟動引數:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
2.3 作為volume掛載使用
(1)把1.4中test-config4所有key/value掛載進來:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-configmap
spec:
replicas: 1
template:
metadata:
labels:
app: nginx-configmap
spec:
containers:
- name: nginx-configmap
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: config-volume4
mountPath: /tmp/config4
volumes:
- name: config-volume4
configMap:
name: test-config4
進入容器中/tmp/config4檢視:
可以看到,在config4資料夾下以每一個key為檔名value為值建立了多個檔案。
(2)假如不想以key名作為配置檔名可以引入items
欄位,在其中逐個指定要用相對路徑path
替換的key:
volumes:
- name: config-volume4
configMap:
name: test-config4
items:
- key: my.cnf
path: mysql-key
- key: cache_host
path: cache-host
進入容器中看:
備註:
- 刪除configmap後原pod不受影響;然後再刪除pod後,重啟的pod的events會報找不到cofigmap的volume;
- pod起來後再通過kubectl edit configmap …修改configmap,過一會pod內部的配置也會重新整理。
- 在容器內部修改掛進去的配置檔案後,過一會內容會再次被重新整理為原始configmap內容
(3)還可以為以configmap掛載進的volume新增subPath
欄位:
volumeMounts:
- name: config-volume5
mountPath: /tmp/my
subPath: my.cnf
- name: config-volume5
mountPath: /tmp/host
subPath: cache_host
- name: config-volume5
mountPath: /tmp/port
subPath: cache_port
- name: config-volume5
mountPath: /tmp/prefix
subPath: cache_prefix
volumes:
- name: config-volume5
configMap:
name: test-config4
進入容器中看:
注意在容器中的形式與(2)中的不同,(2)中是個連結,鏈到..data/<key-name>
。
備註:
- 刪除configmap後原pod不受影響;然後再刪除pod後,重啟的pod的events會報找不到cofigmap的volume。
- pod起來後再通過kubectl edit configmap …修改configmap,pod內部的配置也會自動重新整理。
- 在容器內部修改掛進去的配置檔案後,內容可以持久儲存,除非殺掉再重啟pod才會刷回原始configmap的內容。
- subPath必須要與configmap中的key同名。
- mountPath如/tmp/prefix:
<1>當/tmp/prefix不存在時(備註:此時/tmp/prefix和/tmp/prefix/無異),會自動建立prefix檔案並把value寫進去;
<2>當/tmp/prefix存在且是個檔案時,裡面內容會被configmap覆蓋;
<3>當/tmp/prefix存在且是資料夾時,無論寫/tmp/prefix還是/tmp/prefix/都會報錯。
3.configmap的熱更新研究
更新 ConfigMap 後:
- 使用該 ConfigMap 掛載的 Env 不會同步更新
- 使用該 ConfigMap 掛載的 Volume 中的資料需要一段時間(實測大概10秒)才能同步更新
ENV 是在容器啟動的時候注入的,啟動之後 kubernetes 就不會再改變環境變數的值,且同一個 namespace 中的 pod 的環境變數是不斷累加的,參考 Kubernetes中的服務發現與docker容器間的環境變數傳遞原始碼探究。為了更新容器中使用 ConfigMap 掛載的配置,可以通過滾動更新 pod 的方式來強制重新掛載 ConfigMap,也可以在更新了 ConfigMap 後,先將副本數設定為 0,然後再擴容。