玩轉Configmap設定應用的各種姿勢

2022-09-12 12:01:19

在 k8s 中使用設定主要可以有以下幾種方式來實現:

  1. 向容器傳遞命令列引數

  2. 為每個容器指定自定義的環境變數

  3. 通過特殊型別的卷將組態檔掛載到容器中

 

在 k8s 中覆蓋命令列引數

和 docker 內一樣,可以定義容器啟動中的執行程式和引數,並且映象的 ENTRYPOINT 和 CMD 會被 k8s 中的 command 和 args 覆蓋。

Docker K8s 描述
ENTRYPOINT command 容器中執行可執行檔案
CMD args 傳給可執行檔案的引數

在pod定義中可以這樣子宣告 command 和 args

kind: Pod
spec:
    containers:
    - image: some/image
      command: ["/bin/command"]
      args: ["args1", "args2", "args3"]

 

在容器中指定環境變數

在 k8s 中宣告環境變數,在容器中可以通過環境變數來進行設定,但是需要注意的是,在每個容器中,k8s 會自動暴露相同名稱空間下每個 service 對應的環境變數。雖然環境變數是被設定在 pod 的容器定義中,但是並非是 pod 級別的,比如說運維需要在容器中宣告一些運維中特殊宣告的環境變數。比如叢集中的dns域名解析,當前宿主ip,當前pod的ip等等。

kind: Pod
spec:
    containers:
    - image: xxx/image
      env:
      - name: INTERVAL
        value: "30"
      name: env-config-name
...

在環境變數中參照另一個環境變數

env:
- name: OTHER_VAR
  value: "foo"
- name: THIS_VAR
  value: "$(OTHER_VAR)_change"  

 

利用 config 設定

上面的兩種設定方式更適合運維和 k8s 工程師在設定叢集的時候進行寫死的設定,對於服務開發來說,這兩種設定方式不太合適。

使用指令 kubectl 建立 ConfigMap

$ kubectl create configmap set-config --from-literal=keyname=config-key-value --from-literal=one=two

$ kubectl describe configmap set-config
Name:         set-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
keyname:
----
config-key-value
one:
----
two
Events:  <none>

configmap可以混合使用不同的自選選項:完整資料夾、單獨檔案、自定義鍵名條目下的檔案以及字面量等等。

$ kubectl create configmap my-config
    --from-file=foo.json                     ## 單獨檔案
    --from-file=var=foobar.conf          ## 自定義鍵名條目下的檔案
    --from-file=config-opts/               ##  完整的資料夾
    --from-literral=some=thing          ## 字面量

在實際應用中,我們一般這樣子使用 configmap,利用 configmap 設定不同環境下的組態檔,然後利用 volume 來掛載到 pod 容器資料夾內。

例如,先宣告兩個configmap,一個代表正式環境,一個代表測試環境

$ vim config-learn-test.xml
<conf>
  <env>test</env>
  <service>
    <servicename></servicname>
    <host></host>
    <port></port>
  </service>
<conf>

$ vim config-learn-prod.xml
<conf>
  <env>prod</env>
  <service>
    <servicename></servicname>
    <host></host>
    <port></port>
  </service>
<conf>

生成 configmap

$ kubectl create configmap config-learn-prod --from-file=config-learn.xml=/path/configmap-learn/config-learn-prod.xml
$ kubectl create configmap config-learn-test --from-file=config-learn.xml=/path/configmap-learn/config-learn-test.xml

注意這裡兩個都使用的設定名稱為 config-learn.xml,這樣方便統一設定名

建立 pod,並且宣告需要的設定,如果環境是測試則選擇 config-learn-test,如果環境為正式則選擇 config-learn-prod

$ vim ./configmap-learn.yaml
apiVersion: v1
kind: Pod
metadata:
 name: configmap-learn
spec:
 containers:
 - image: luksa/kubia
   name: kubia
   ports:
   - containerPort: 8080
     protocol: TCP
   volumeMounts:
   - name: configname
     mountPath: /data/service/conf
     readOnly: true
 volumes:
 - name: configname
   configMap:
    name: config-learn-test

在生成的 pod 中去檢驗對應目錄下的組態檔如下:

$ kubectl exec configmap-learn cat /data/service/conf/config-learn.xml
<conf>
  <env>test</env>
  <service>
    <servicename></servicname>
    <host></host>
    <port></port>
  </service>
<conf>

可以看到確實是採取的測試環境設定,而且如果此目錄下有相同名字的組態檔,此檔案會被覆蓋。

編輯修改configmap

$ kubectl edit configmap config-learn-prod

# 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: config-learn.xml: | <conf> <env>prod</env> <service> <servicename></servicname> <host></host> <port></port> </service> <conf> kind: ConfigMap metadata: creationTimestamp: "2022-09-11T10:59:28Z" managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:data: .: {} f:config-learn.xml: {} manager: kubectl operation: Update time: "2022-09-11T10:59:28Z" name: config-learn-prod namespace: default resourceVersion: "23045374" selfLink: /api/v1/namespaces/default/configmaps/config-learn-prod uid: 79663144-2b5e-4e29-8c94-0469d5906e19

儲存檔案後關閉編輯器,configmap 會在不久後更新對應的檔案,檔案更新過程需要一些時間,最後會看到組態檔的變化。但是一般容器程序並不會監控檔案的變化在載入之後,所以一般都是重啟容器並載入設定的。