本文的試驗環境為CentOS 7.3,Kubernetes集群為1.11.2,安裝步驟參見kubeadm安裝kubernetes V1.11.1 集群
應用場景:鏡像往往是一個應用的基礎,還有很多需要自定義的參數或配置,例如資源的消耗、日志的位置級別等等,這些配置可能會有很多,因此不能放入鏡像中,Kubernetes中提供了Configmap來實現向容器中提供配置文件或環境變量來實現不同配置,從而實現了鏡像配置與鏡像本身解耦,使容器應用做到不依賴於環境配置。
向容器傳遞參數
Docker | Kubernetes | 描述 |
---|---|---|
ENTRYPOINT | command | 容器中的可執行文件 |
CMD | args | 需要傳遞給可執行文件的參數 |
如果需要向容器傳遞參數,可以在Yaml文件中通過command和args或者環境變量的方式實現。
kind: Pod
spec:
containers:
- image: docker.io/nginx
command: ["/bin/command"]
args: ["arg1", "arg2", "arg3"]
env:
- name: INTERVAL
value: "30"
- name: FIRST_VAR
value: "foo"
- name: SECOND_VAR
value: "$(FIRST_VAR)bar"
可以看到,我們可以利用env標簽向容器中傳遞環境變量,環境變量還可以相互引用。這種方式的問題在於配置文件和部署是綁定的,那么對於同樣的應用,測試環境的參數和生產環境是不一樣的,這樣就要求寫兩個部署文件,管理起來不是很方便。
什么是ConfigMap
上面提到的例子,利用ConfigMap可以解耦部署與配置的關系,對於同一個應用部署文件,可以利用valueFrom
字段引用一個在測試環境和生產環境都有的ConfigMap(當然配置內容不相同,只是名字相同),就可以降低環境管理和部署的復雜度。
ConfigMap有三種用法:
- 生成為容器內的環境變量
- 設置容器啟動命令的參數
- 掛載為容器內部的文件或目錄
ConfigMap的缺點
- ConfigMap必須在Pod之前創建
- ConfigMap屬於某個NameSpace,只有處於相同NameSpace的Pod才可以應用它
- ConfigMap中的配額管理還未實現
- 如果是volume的形式掛載到容器內部,只能掛載到某個目錄下,該目錄下原有的文件會被覆蓋掉
- 靜態Pod不能用ConfigMap
ConfigMap的創建
$ kubectl create configmap <map-name> --from-literal=<parameter-name>=<parameter-value>
$ kubectl create configmap <map-name> --from-literal=<parameter1>=<parameter1-value> --from-literal=<parameter2>=<parameter2-value> --from-literal=<parameter3>=<parameter3-value>
$ kubectl create configmap <map-name> --from-file=<file-path>
$ kubectl apply -f <configmap-file.yaml>
# 還可以從一個文件夾創建configmap
$ kubectl create configmap <map-name> --from-file=/path/to/dir
Yaml 的聲明方式
apiVersion: v1
data:
my-nginx-config.conf: |
server {
listen 80;
server_name www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
sleep-interval: |
25
kind: ConfigMap
ConfigMap的調用
環境變量的方式
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- image: nginx
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: <map-name>
key: sleep-interval
如果引用了一個不存在的ConfigMap,則創建Pod時會報錯,直到能夠正常讀取ConfigMap后,Pod會自動創建。
一次傳遞所有的環境變量
spec:
containers:
- image: nginx
envFrom:
- prefix: CONFIG_
configMapRef:
name: <map-name>
命令行參數的方式
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- image: nginx
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: <map-name>
key: sleep-interval
args: ["$(INTERVAL)"]
以配置文件的方式
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
spec:
containers:
- image: nginx
name: web-server
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
readOnly: true
volumes:
- name: config
configMap:
name: <map-name>
將Configmap掛載為一個文件夾后,原來在鏡像中的文件夾里的內容就看不到,這是什么原理?這是因為原來文件夾下的內容無法進入,所以顯示不出來。為了避免這種掛載方式影響應用的正常運行,可以將configmap掛載為一個配置文件。
spec:
containers:
- image: nginx
volumeMounts:
- name: config
mountPath: /etc/someconfig.conf
subPath: myconfig.conf
Configmap的更新
$ kubectl edit configmap <map-name>
confgimap更新后,如果是以文件夾方式掛載的,會自動將掛載的Volume更新。如果是以文件形式掛載的,則不會自動更新。
但是對多數情況的應用來說,配置文件更新后,最簡單的辦法就是重啟Pod(殺掉再重新拉起)。如果是以文件夾形式掛載的,可以通過在容器內重啟應用的方式實現配置文件更新生效。即便是重啟容器內的應用,也要注意configmap的更新和容器內掛載文件的更新不是同步的,可能會有延時,因此一定要確保容器內的配置也已經更新為最新版本后再重新加載應用。
什么是Secret
Secret與ConfigMap類似,但是用來存儲敏感信息。在Master節點上,secret以非加密的形式存儲(意味着我們要對master嚴加管理)。從Kubernetes1.7之后,etcd以加密的形式保存secret。secret的大小被限制為1MB。當Secret掛載到Pod上時,是以tmpfs的形式掛載,即這些內容都是保存在節點的內存中,而不是寫入磁盤,通過這種方式來確保信息的安全性。
Kubernetes helps keep your Secrets safe by making sure each Secret is only distributed to the nodes that run the pods that need access to the Secret. Also, on the nodes themselves, Secrets are always stored in memory and never written to physical storage, which would require wiping the disks after deleting the Secrets from them.
每個Kubernetes集群都有一個默認的secrets
創建和調用的過程與configmap大同小異,這里就不再贅述了。