昨天介紹環境變數時,有提到了ConfigMap與Secret,當我們想要將一些資料和程式碼分開時,而這些資料如果是非機密資料,那我們會用ConfigMap,若是機密資料,我們則會用Secret。
兩者的主要使用方式有:
接下來我們來好好聊聊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的用法:
另外從YAML中我們可以看到一些之前沒看過的:
要是沒有使用items的話,ConfigMap的data內的每個Key都會變成與Key同名的文件,所以items算是指定的作用。
除了上面的用法以外,還可以使用envFrom來取代env:
envFrom:
- configMapRef:
name: game-demo
這樣ConfigMap中的Key-Value都會變成Pod的環境變數。
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來設定環境變數,則須等到Pod被重建時,才會跟著生效。之前有提過Pod在運行狀態中是無法更新的。
另外,若是將ConfigMap作為subPath也是無法更新。subPath就是將記錄在ConfigMap的Value,當作volumeMounts的路徑。
前面提到的都是用YAML來建立,那如果是用指令呢?
普遍來說會有兩種方式:
# 使用一個路徑
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與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
我們也可以像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
另外還有幾點補充:
這邊我是列出Secret和ConfigMap主要不同的地方,明天來談談集群的更新~
https://jimmysong.io/kubernetes-handbook/concepts/configmap.html