一、簡介
ConfigMap對像是一系列配置的集合,k8s會將這一集合注入到對應的Pod對像中,並為容器成功啟動使用。注入的方式一般有兩種,一種是掛載存儲卷,一種是傳遞變量。ConfigMap被引用之前必須存在,屬於名稱空間級別,不能跨名稱空間使用,內容明文顯示。ConfigMap內容修改后,對應的pod必須重啟或者重新加載配置。
Secret類似於ConfigMap,是用Base64加密,密文顯示,一般存放敏感數據。一般有兩種創建方式,一種是使用kubectl create創建,一種是用Secret配置文件。
使用場景
我們經常都需要為我們的應用程序配置一些特殊的數據,比如密鑰、Token 、數據庫連接地址或者其他私密的信息。你的應用可能會使用一些特定的配置文件進行配置,比如settings.py文件,或者我們可以在應用的業務邏輯中讀取環境變量或者某些標志來處理配置信息。 我們要做到這個,有好多種方案,比如: 1.我們可以直接在打包鏡像的時候寫在應用配置文件里面,但是這種方式的壞處顯而易見而且非常明顯。 2.我們可以在配置文件里面通過 env 環境變量傳入,但是這樣的話我們要修改 env 就必須去修改 yaml 文件,而且需要重啟所有的 container 才行。 3.我們可以在應用啟動的時候去數據庫或者某個特定的地方拿,沒問題!但是第一,實現起來麻煩;第二,如果配置的地方變了怎么辦? 當然還有別的方案,但是各種方案都有各自的問題。 而且,還有一個問題就是,如果說我的一個配置,是要多個應用一起使用的,以上除了第三種方案,都沒辦法進行配置的共享,就是說我如果要改配置的話,那得一個一個手動改。假如我們有 100 個應用,就得改 100 份配置,以此類推…… kubernetes 對這個問題提供了一個很好的解決方案,就是用 ConfigMap 和 Secret。
二、ConfigMap創建及使用
1.查看命令幫助
[root@k8s-master-155-221 configmap]# kubectl create configmap --help ...... Aliases: configmap, cm #可以使用cm替代 Examples: # Create a new configmap named my-config based on folder bar kubectl create configmap my-config --from-file=path/to/bar #從目錄創建 文件名稱為鍵 文件內容為值? # Create a new configmap named my-config with specified keys instead of file basenames on disk kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt #從文件創建 key1為鍵 文件內容為值 # Create a new configmap named my-config with key1=config1 and key2=config2 kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2 #直接命令行給定,鍵為key1 值為config1 # Create a new configmap named my-config from the key=value pairs in the file kubectl create configmap my-config --from-file=path/to/bar #從文件創建 文件名為鍵 文件內容為值 # Create a new configmap named my-config from an env file kubectl create configmap my-config --from-env-file=path/to/bar.en #不知道,沒用過
2.ConfigMap主要有以下幾種方式創建
通過literal方式創建ConfigMap
[root@k8s-master-155-221 ~]# mkdir manifests [root@k8s-master-155-221 ~]# cd manifests/ [root@k8s-master-155-221 ~]# kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=myapp.qiangungun.com #命令行給定 nginx_port為鍵 80為值 configmap/nginx-config created [root@k8s-master-155-221 ~]# kubectl describe cm nginx-config Name: nginx-config Namespace: default Labels: <none> Annotations: <none> Data ==== sever_name: #鍵 ---- myapp.qiangungun.com #值 nginx_port: #鍵 ----
80 #值 Events: <none> [root@k8s-master-155-221 ~]# kubectl get cm nginx-config -o yaml apiVersion: v1 data: nginx_port: "8088" #鍵:值 server_name: myapp.qiangungun.com #鍵:值對 kind: ConfigMap metadata: ......
通過file的方式創建
[root@k8s-master-155-221 manifests]# mkdir configmap [root@k8s-master-155-221 manifests]# cd configmap/ [root@k8s-master-155-221 configmap]# vim www.conf server{ server_name myapp.magedu.com; listen 80; root /data/web/html; } [root@k8s-master-155-221 configmap]# kubectl create configmap www --from-file=./www.conf #直接以文件名稱為鍵,文件內容為值,也可以使用--from-file=key=/path/to/file自定義鍵 configmap/www created [root@k8s-master-155-221 configmap]# kubectl get configmaps www NAME DATA AGE www 1 23s [root@k8s-master-155-221 configmap]# kubectl get configmaps www -o yaml #或者使用describe命令查看 apiVersion: v1 data: www.conf: | server{ server_name myapp.magedu.com; listen 80; root /data/web/html; } kind: ConfigMap metadata: creationTimestamp: "2020-01-13T14:21:13Z" name: www namespace: default resourceVersion: "7809631" selfLink: /api/v1/namespaces/default/configmaps/www uid: f3dd1cd4-360f-11ea-87ad-525400512eca
通過YAML文件創建
[root@k8s-master-155-221 configmap]# vim my-configmap.yml apiVersion: v1 kind: ConfigMap metadata: name: customer1 data: key1: value1 key2: value2 [root@k8s-master-155-221 configmap]# kubectl apply -f my-configmap.yml configmap/customer1 created [root@k8s-master-155-221 configmap]# kubectl describe cm customer1 Name: customer1 Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","data":{"key1":"value1","key2":"value2"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"customer1","namespace"... Data ==== key1: ---- value1 key2: ---- value2 Events: <none>
3.使用ConfigMap主要有以下幾種方式:
ENV注入:
[root@k8s-master-155-221 configmap]# vim pod-configmap.yaml apiVersion: v1 kind: Pod metadata: name: pod-cm-1
namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: httpd containerPort: 80 env: - name: NGINX_SERVER_PORT #pod中顯示的變量名稱 valueFrom: configMapKeyRef: key: nginx_port #引用的configmap中的鍵名稱 name: nginx-config #引用的configmap的名稱 optional: true #該選項是否是必須的(true表示必須存在,否則pod無法啟動) - name: NGINX_SERVER_NAME valueFrom: configMapKeyRef: key: server_name name: nginx-config optional: true [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap.yaml pod/pod-cm-1 created [root@k8s-master-155-221 configmap]# kubectl get pods |grep pod-cm-1 pod-cm-1 1/1 Running 0 3m11s [root@k8s-master-155-221 configmap]# kubectl get pods |grep pod-cm-1 pod-cm-1 1/1 Running 0 13s [root@k8s-master-155-221 configmap]# kubectl exec -it pod-cm-1 -- /bin/sh / # env|grep NGINX_SERVER_PORT NGINX_SERVER_PORT=80
/ # env|grep NGINX_SERVER_NAME NGINX_SERVER_NAME=myapp.qiangungun.com
/ # env|grep NGINX_SERVER_PORT #稍等片刻,等下面的修改完成后操作,端口沒有改變,即使用環境變量的方式注入配置只會在pod啟動時有效 NGINX_SERVER_PORT=80
#另起一個回話,修改當前使用的ConfigMap
[root@k8s-master-155-221 ~]# kubectl edit configmap nginx-config # 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: nginx_port: "8080" #修改端口為8080 server_name: myapp.qiangungun.com kind: ConfigMap metadata: ...... [root@k8s-master-155-221 ~]# kubectl describe cm nginx-config Name: nginx-config Namespace: default Labels: <none> Annotations: <none> Data ==== nginx_port: ----
8080 server_name: ---- myapp.qiangungun.com Events: <none>
VOLUME掛載
root@k8s-master-155-221 configmap]# kubectl delete pod pod-cm-1 pod "pod-cm-1" deleted [root@k8s-master-155-221 configmap]# cp pod-configmap.yaml pod-configmap-2.yaml [root@k8s-master-155-221 configmap]# vim pod-configmap-2.yaml apiVersion: v1 kind: Pod metadata: name: pod-cm-2
namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: httpd containerPort: 80 volumeMounts: - name: nginx-conf mountPath: /etc/nginx/config.d/ readOnly: true #是否允許pod去修改 volumes: - name: nginx-conf configMap: name: nginx-config [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap-2.yaml pod/pod-cm-2 created [root@k8s-master-155-221 configmap]# kubectl exec -it pod-cm-2 -- /bin/sh / # ls /etc/nginx/config.d/nginx_port /etc/nginx/config.d/nginx_port / # cat /etc/nginx/config.d/nginx_port #注意,是8080,因為之前已經改過一次了 8080/ # / # cat /etc/nginx/config.d/server_name myapp.qiangungun.com/ # / # cat /etc/nginx/config.d/nginx_port #等下面的修改完成后操作,稍等30秒左右,端口發生改變,及以文件掛載的方式可以同步改變 8088/ #
#另起一個回話,修改當前使用的ConfigMap
[root@k8s-master-155-221 ~]# kubectl edit configmap nginx-config nginx_port: "8088" #修改端口由8080改為8088 / # cd /etc/nginx/config.d/
/etc/nginx/config.d # ls -l #掛載的方式實質是一種映射關系 total 0 lrwxrwxrwx 1 root root 17 Jan 13 15:23 nginx_port -> ..data/nginx_port lrwxrwxrwx 1 root root 18 Jan 13 15:23 server_name -> ..data/server_name
4.實際示例
[root@k8s-master-155-221 configmap]# vim pod-configmap-3.yaml apiVersion: v1 kind: Pod metadata: name: pod-cm-3
namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: httpd containerPort: 80 volumeMounts: - name: nginx-conf mountPath: /etc/nginx/conf.d/ readOnly: true volumes: - name: nginx-conf configMap: name: www [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap-3.yaml pod/pod-cm-3 created [root@k8s-master-155-221 configmap]# kubectl exec -it pod-cm-3 -- /bin/sh / # cd /etc/nginx/conf.d/
/etc/nginx/conf.d # ls www.conf #文件名稱即www configmap中的鍵 /etc/nginx/conf.d # cat www.conf #文件內容為www.conf的值 server{ server_name myapp.magedu.com; listen 80; root /data/web/html; } /etc/nginx/conf.d # nginx -T #查看載入的配置 ...... # configuration file /etc/nginx/conf.d/www.conf: server{ server_name myapp.magedu.com; listen 80; root /data/web/html; } /etc/nginx/conf.d # mkdir -p /data/web/html /etc/nginx/conf.d # echo "<h1>Nginx Server configured by CM</h1>" > /data/web/html/index.html
在集群任意節點上
[root@k8s-master-155-221 configmap]# kubectl get pods -o wide|grep pod-cm-3 pod-cm-3 1/1 Running 0 5m13s 172.17.248.4 172.16.155.224 <none> <none> [root@k8s-master-155-221 configmap]# echo "172.17.248.4 myapp.magedu.com" >> /etc/hosts [root@k8s-master-155-221 configmap]# curl myapp.magedu.com Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> [root@k8s-master-155-221 configmap]# kubectl edit cm www apiVersion: v1 data: www.conf: | server{ server_name myapp.magedu.com; listen 8080; root /data/web/html; } kind: ConfigMap metadata: creationTimestamp: "2020-01-13T14:21:13Z" name: www namespace: default resourceVersion: "7809631" selfLink: /api/v1/namespaces/default/configmaps/www uid: f3dd1cd4-360f-11ea-87ad-525400512eca
pod中查看
/etc/nginx/conf.d # cat www.conf #等上面的修改完成后操作,稍等30秒左右,端口發生改變 server_name myapp.magedu.com; listen 8080; root /data/web/html; } /etc/nginx/conf.d # netstat -tnl #配置雖然改變,但是服務監聽端口不會發生改變,需要通過某種方式重載服務 Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
三、Secret創建及使用
通過上面的部分,我們可以看到 ConfigMap 是用來做一些配置信息的,那么如果我們有一些機密信息比如說密鑰、密碼之類的信息,應該存在哪里呢?看到這個名字大家應該就明白了吧,kubernetes 提供了 Secret 來存儲相關的信息。
Secret命令幫助(secret創建和使用與ConfigMap大同小異,注意區別在於內容被base64加密了)
[root@k8s-master-155-221 manifests]# kubectl create secret --help Create a secret using specified subcommand. Available Commands: #secret主要有以下三種類型 docker-registry 創建一個給 Docker registry 使用的 secret #docker-registry私有倉庫的證書,pod中pod.spec.imagePullSecrets字段使用 generic 從本地 file, directory 或者 literal value #通用的secret tls 創建一個 TLS secret #保存私鑰和證書
1.創建secret
[root@k8s-master-155-221 manifests]# kubectl create secret generic mysql-root-passwd --from-literal=passwd=MyP@ss123 secret/mysql-root-passwd created [root@k8s-master-155-221 manifests]# kubectl describe secrets mysql-root-passwd Name: mysql-root-passwd Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== passwd: 9 bytes #只能看到9個字節 但是看不到內容 [root@k8s-master-155-221 manifests]# kubectl get secrets mysql-root-passwd -o yaml apiVersion: v1 data: passwd: TXlQQHNzMTIz #實際是base64加密 kind: Secret metadata: creationTimestamp: "2020-01-14T01:47:51Z" name: mysql-root-passwd namespace: default resourceVersion: "7896989" selfLink: /api/v1/namespaces/default/secrets/mysql-root-passwd uid: dfb541fa-366f-11ea-87ad-525400512eca type: Opaque [root@k8s-master-155-221 manifests]# echo "TXlQQHNzMTIz"|base64 -d #實際上可以被解碼的 MyP@ss123
2.簡單使用
[root@k8s-master-155-221 configmap]# vim pod-secret-1.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret-1
namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: httpd containerPort: 80 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: key: passwd name: mysql-root-passwd optional: true [root@k8s-master-155-221 configmap]# kubectl apply -f pod-secret-1.yaml pod/pod-secret-1 created [root@k8s-master-155-221 configmap]# kubectl exec -it pod-secret-1 -- /bin/sh / # env|grep MYSQL MYSQL_ROOT_PASSWORD=MyP@ss123 #實際是解密后注入進來的,所以不建議使用環境變量的方式注入密碼
其他方式與configmap雷同,不在贅述
其實目前 Secret 的實現,就是 ConfigMap 把 value 用 base64 encode 了一下.所以,其實不存在任何安全性,只要 decode 一下就能出現原來結果,相當於明文存儲.
參考文檔:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
https://kubernetes.io/docs/concepts/configuration/secret/
