iT邦幫忙

2022 iThome 鐵人賽

DAY 14
1
DevOps

30天準備CKA考試系列 第 14

Day 14:ConfigMap & Secret

  • 分享至 

  • xImage
  •  

昨天介紹環境變數時,有提到了ConfigMap與Secret,當我們想要將一些資料和程式碼分開時,而這些資料如果是非機密資料,那我們會用ConfigMap,若是機密資料,我們則會用Secret。

兩者的主要使用方式有:

  • 提供環境變數
  • 當成Command的參數
  • 存成文件給Pod使用
  • 在Pod內,用程式透過kube-APIServer來讀取。這部分比較跟程式開發有關,不在考CKA的範圍內。

接下來我們來好好聊聊ConfigMap~

ConfigMap

首先,它在設計上不是為了大數據而設計,ConfigMap所保存的資料不能超過1MiB。

來看看ConfigMap的YAML:

apiVersion: v1
kind: ConfigMap
metadata:
  name: game-demo
data:
  # 類屬性Key,每一個Key都映設到一個簡單的值
  player_initial_lives: "3"
  ui_properties_file_name: "user-interface.properties"

  # 類文件Key
  game.properties: |
    enemy.types=aliens,monsters
    player.maximum-lives=5    
  user-interface.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true

我們可以發現它和之前提到YAML最主要的四大要素不同,它沒有spec,取而代之的是data。

接下來我們再看看Pod要怎麼從YAML讀取ConfigMap:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      env:
        - name: PLAYER_INITIAL_LIVES # 這裡的Key是給Container的
          valueFrom:
            configMapKeyRef:
              name: game-demo           # 這個是ConfigMap的Name
              key: player_initial_lives # 這是ConfigMap內的Key
        - name: UI_PROPERTIES_FILE_NAME
          valueFrom:
            configMapKeyRef:
              name: game-demo
              key: ui_properties_file_name
      volumeMounts:
      - name: config
        mountPath: "/config"
        readOnly: true
  volumes:
    - name: config
      configMap:
        # ConfigMap的Name
        name: game-demo
        # 將ConfigMap的內容存成文件
        items:
        - key: "game.properties"
          path: "game.properties"
        - key: "user-interface.properties"
          path: "user-interface.properties"

從這邊我們可以看到兩種ConfigMap的用法:

  • 第一種就是昨天提到的env。
  • 第二種是把ConfigMap的內容存成文件給Pod使用。

另外從YAML中我們可以看到一些之前沒看過的:

  • volume:就是有點類似這個Pod的外接硬碟。
  • volumeMounts:就是設定要怎麼使用volume,這些部分會在Storage的章節詳談。
  • items:每個volumes的key都會變成一個與key同名的文件。

要是沒有使用items的話,ConfigMap的data內的每個Key都會變成與Key同名的文件,所以items算是指定的作用。

除了上面的用法以外,還可以使用envFrom來取代env:

envFrom:
  - configMapRef:
    name: game-demo

這樣ConfigMap中的Key-Value都會變成Pod的環境變數。

以ConfigMap當作Command的參數

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type

我們可以在command的那行看到有使用$(SPECIAL_LEVEL_KEY)和$(SPECIAL_TYPE_KEY),而這兩者的值會從env中取得。

當ConfigMap被更新時,其他Object會跟著更新嗎?

一般來說是會!

但是若是使用ConfigMap來設定環境變數,則須等到Pod被重建時,才會跟著生效。之前有提過Pod在運行狀態中是無法更新的。

另外,若是將ConfigMap作為subPath也是無法更新。subPath就是將記錄在ConfigMap的Value,當作volumeMounts的路徑。

建立ConfigMap

前面提到的都是用YAML來建立,那如果是用指令呢?

普遍來說會有兩種方式:

  • File:指定一個或多個檔案當作ConfigMap的內容。
  • Literal:直接給值,類似於我們在幫Node加Label的作法。
  • ENV File:設定.env檔,會將裡面的內容變成key-value。
# 使用一個路徑
kubectl create configmap my-config --from-file=path/to/bar

# 指定key1和key2,並分別對應到某檔案
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

# 直接設定內容
kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

# 使用env檔
kubectl create configmap my-config --from-env-file=path/to/bar/file.env

Secret

我認為Secret與ConfigMap最大的不同在於前者的value需要用base64編碼,例如:

apiVersion: v1
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: { ... }
  creationTimestamp: 2020-01-22T18:41:56Z
  name: mysecret
  namespace: default
  resourceVersion: "164619"
  uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque
  • type:Opaque代表支援任意類型的資料,這是預設值。

我們也可以像ConfigMap一樣當成Volumes使用~

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
		env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
            optional: false
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
            optional: false
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      optional: false # 預設fales,代表mysecret一定要存在
			defaultMode: 0400
  • defaultMode:設定這個Secret文件的訪問權限0400,若不指定則會預設0644。
    • 這邊是8進位的值,若不是用YAML,而用JSON,因為JSON不支援8進位,可以改成10進位來使用,0400 ⇒ 256。

另外還有幾點補充:

  • 這邊也可以使用前面提到的items來指定欄位。
  • 也可以用envFrom,方法和ConfigMap類似。
  • 若使用--from-literal來建立Secret,則不須事先使用base64編碼。

這邊我是列出Secret和ConfigMap主要不同的地方,明天來談談集群的更新~

參考資料

Secret

ConfigMap

https://jimmysong.io/kubernetes-handbook/concepts/configmap.html


上一篇
Day 13:Environment Variable
下一篇
Day 15:Cluster Upgrade
系列文
30天準備CKA考試30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言