1. 程式人生 > >Kubernetes的Configmap詳解

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)使用valueFromconfigMapKeyRefnamekey指定要用的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)還可以通過envFromconfigMapRefname使得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

進入容器中看:
這裡寫圖片描述

備註:

  1. 刪除configmap後原pod不受影響;然後再刪除pod後,重啟的pod的events會報找不到cofigmap的volume;
  2. pod起來後再通過kubectl edit configmap …修改configmap,過一會pod內部的配置也會重新整理。
  3. 在容器內部修改掛進去的配置檔案後,過一會內容會再次被重新整理為原始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>
備註:

  1. 刪除configmap後原pod不受影響;然後再刪除pod後,重啟的pod的events會報找不到cofigmap的volume。
  2. pod起來後再通過kubectl edit configmap …修改configmap,pod內部的配置也會自動重新整理。
  3. 在容器內部修改掛進去的配置檔案後,內容可以持久儲存,除非殺掉再重啟pod才會刷回原始configmap的內容。
  4. subPath必須要與configmap中的key同名。
  5. 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,然後再擴容。

參考