1. 程式人生 > 其它 >【Kubernetes系列九】Kubernetes ConfigMap和Secret

【Kubernetes系列九】Kubernetes ConfigMap和Secret

1. ConfigMap介紹

ConfigMap是讓配置檔案從映象中解耦,讓映象的可移植性和可複製性。許多應用程式會從配置檔案、命令列引數或環境變數中讀取配置資訊。這些配置資訊需要與docker image解耦,你總不能每修改一個配置就重做一個image吧?ConfigMap API給我們提供了向容器中注入配置資訊的機制,ConfigMap可以被用來儲存單個屬性,也可以用來儲存整個配置檔案或者JSON二進位制大物件。ConfigMap儲存的值為鍵值方式,value長度沒有限制。
注意:configmap是名稱空間級別的資源,它必須與引用它的pod資源在同一空間中

2. 建立ConfigMap

ConfigMap支援命令建立和使用清單建立。有以下四種方式建立。

(1) 命令直接建立
為“kubectl create configmap”命令使用"--from-literal"選項可在命令列直接給出鍵值來建立ConfigMap物件,重複使用此選項可以傳遞多個鍵值對。格式如下:

~]# kubectl create configmap NAME --from-literal=key1=value1 --from-literal=key2=value2

示列:

~]# kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=www.ilinux.cn
~]# kubectl get cm    #檢視cm資源
NAME           DATA   AGE
nginx-config   2      4s
~]# kubectl describe cm/nginx-config    #檢視cm資源nginx-config的詳細資訊
或者~]# kubectl get configmaps nginx-config -o yaml

(2) 基於檔案建立
“kubectl create configmap”命令使用“--from-file”選項即可基於檔案內容來建立ConfigMap物件,同樣可以重複多次使用。格式如下:

~]# kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

示列:

~]# mkdir configmap && cd configmap
~]# vim www.conf
server {
    server_name www.ilinux.cn;
    listen 80;
    root /data/web/html/;
}

~]# kubectl create configmap nginx-www --from-file=www.conf=./www.conf    #使用上面建立的檔案來建立cm資源物件
~]# kubectl get cm
~]# kubectl get cm nginx-www -o yaml
apiVersion: v1
data:
  www.conf: |
    server {
        server_name www.ilinux.cn;
        listen 80;
        root /data/web/html/;
    }
kind: ConfigMa
......

(3) 基於目錄建立
如果配置檔案數量較多且儲存於有限的目錄之中,kubectl還提供了基於目錄直接將多個檔案分別收納為鍵值資料的ConfigMap資源建立方式。將“--from-file”選項後面所跟的路徑指向一個目錄路徑就能將目錄下的所有檔案一同創建於同一ConfigMap資源中,命令格式如下:

~]# kubectl create configmap <configmap_name> --from-file=<path-to-directory>

這裡假設/data/configs/nginx/conf.d/這個目錄下有許多的nginx的配置檔案,下面這條命令則將這個目錄下的所有配置檔案在建立ConfigMap資源時,會分別儲存為對應的鍵值資料。

~]# kubectl create configmap nginx-config-files --from-file=/data/configs/nginx/conf.d/

(4) 使用資源清單建立
基於清單檔案建立ConfigMap資源時,它所使用的欄位包括通常的apiVersion、kind和metadata欄位,以及用於儲存資料的關鍵欄位“data”。格式如下:

~]# kubectl explain cm
KIND:     ConfigMap
VERSION:  v1
FIELDS:
apiVersion    <string>
kind    <string>
metadata    <Object>
binaryData    <map[string]string>
data    <map[string]string>

示列:

~]# vim configmap-demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-demo
  namespace: default
data:
  log_level: INFO
  log_file: /var/log/test.log

~]# kubectl apply -f configmap-demo.yaml 
~]# kubectl get cm
~]# kubectl get cm/configmap-demo -o yaml
apiVersion: v1
data:
  log_file: /var/log/test.log
  log_level: INFO
kind: ConfigMap
metadata:
......

3. 使用ConfigMap

(1) 環境變數方式注入到pod

~]# vim pod-configmap-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-1
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    env:
    - name: NGINX_SERVER_PORT
      valueFrom:    #下面這一段表示變數NGINX_SERVER_PORT的值來自於configmap資源nginx-config的key(nginx_port)的值
        configMapKeyRef:
          name: nginx-config    #configmap資源名稱
          key: nginx_port      #configmap資源裡面的key名
    - name: NGINX_SERVER_NAME
      valueFrom:
        configMapKeyRef:
          name: nginx-config
          key: server_name
~]# kubectl apply -f pod-configmap-1.yaml
~]# kubectl get pods
~]# kubectl exec -it pod-cm-1 -- printenv |grep NGINX    #連線pod資源pod-cm-1並執行命令printenv列印環境變數。過濾是否有上面定義的兩個環境變數
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=www.ilinux.cn


#測試,修改埠,可以發現使用環境變數的注入pod中的埠不會根據配置的變更而改變
[root@k8s-master configmap]# kubectl edit cm/nginx-config   #編輯cm資源nginx-config將nginx_port值改為8080
......
apiVersion: v1
data:
  nginx_port: "8080"
......
[root@k8s-master configmap]# kubectl exec -it pod-cm-1 -- printenv |grep NGINX
NGINX_SERVER_PORT=80
NGINX_SERVER_NAME=www.ilinux.cn

上述存在鍵值資料不多,如果鍵值資料過多,可以直接使用envFrom欄位匯入configmap,上述示列可以修改如下

~]# vim pod-configmap-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-1
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    envFrom:
    - prefix: HTCFG_     #防止匯入多個configmap,出現鍵值重複,設定字首
      configMapKeyRef:
        name: nginx-config
        optional: false

(2) 儲存卷方式掛載ConfigMap

~]# vim pod-configmap-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-2
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: nginxconf
      mountPath: /etc/nginx/config.d/
      readOnly: true
  volumes:    #建立一個儲存卷
  - name: nginxconf    #儲存卷名稱
    configMap:    #使用configMap型別
      name: nginx-config    #指定configmap資源名稱
]# kubectl apply -f pod-configmap-2.yaml
]# kubectl get pods
]# kubectl exec -it pod-cm-2 -- /bin/sh    #連線pod資源pod-cm-2,並進入到掛載目錄檢視。
/ # ls /etc/nginx/config.d/
nginx_port   server_name
/ # cd /etc/nginx/config.d/
/etc/nginx/config.d # cat nginx_port 
8080
/etc/nginx/config.d # cat server_name 
www.ilinux.cn 

#測試,修改埠,可以發現使用volume的方式掛載configmap到容器中,支援動態更新。
[root@k8s-master configmap]# kubectl edit cm/nginx-config    #編輯cm資源nginx-config將nginx_port值改為8088
apiVersion: v1
data:
  nginx_port: "8088"
[root@k8s-master configmap]# kubectl exec -it pod-cm-2 -- /bin/sh
/etc/nginx/config.d # cat nginx_port 
8088

當然,除了上述掛載整個儲存卷,還可以掛載儲存卷中的部分鍵值,獨立掛載儲存卷中的鍵值,配置如下
掛載儲存卷中的部分鍵值

~]# vim pod-configmap-3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-3
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: nginxconf
      mountPath: /etc/nginx/config.d/
      readOnly: true
  volumes:    #建立一個儲存卷
    - name: nginxconf    #儲存卷名稱
    configMap:    #使用configMap型別
        name: nginx-config    #指定configmap資源名稱
        items:
        - key: myserver.conf
        path: myserver.conf
        mode: 644

獨立掛載儲存卷中的鍵值

~]# vim pod-configmap-4.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm-4
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: nginxconf
      mountPath: /etc/nginx/config.d/myserver.conf
      subpath: myserver.conf
      readOnly: true
  volumes:    #建立一個儲存卷
  - name: nginxconf    #儲存卷名稱
    configMap:    #使用configMap型別
        name: nginx-config    #指定configmap資源名稱

4. Secret資源介紹

Secret物件儲存資料的方式及使用方式類似於ConfigMap物件,以鍵值方式儲存資料,在Pod資源中通過環境變數或儲存捲進行資料訪問,解決了密碼、token、金鑰等敏感資料的配置問題,而不需要將這些敏感資料暴露到映象或者pod spec中。另外,Secret物件的資料儲存和列印格式為Base64編碼的字串,因此使用者在建立Secret物件時也要提供此種編碼格式的資料。在容器中以環境變數或儲存卷的方式訪問時,它們會被自動解碼為明文格式。需要注意的是,如果是在Master節點上,Secret物件以非加密的格式儲存在etcd中,所以需要對etcd的管理和許可權進行嚴格控制。

Secret的四種類型

Opaque: 自定義資料內容;base64編碼,用來儲存密碼、祕鑰、資訊、證書等資料,型別識別符號為generic。

kubernetes.io/service-account-token: Service Account的認證資訊,可在建立Service Account`時由Kubernetes自動建立。

kubernetes.io/dockerconfigjson: 用來儲存Docker映象倉庫的認證資訊,型別識別符號為docker-regiestry。

kubernetes.io/tls: 用於為SSL通訊模式儲存證書和私鑰檔案,命令式建立時型別標識為tls。

5.建立Secret

(1) 命令式建立
為“kubectl create secret generic”命令使用“--from-literal”選項可在命令列直接給出鍵值來建立ConfigMap物件,重複使用此選項可以傳遞多個鍵值對。格式如下:

~]# kubectl create secret generic NAME --from-literal=key1=value1 --from-literal=key2=value2

示列:

~]# kubectl create secret generic mysql-auth --from-literal=username=root --from-literal=password=passw0rd    #建立secret資源mysql-auth,並指定兩個鍵值
~]# kubectl get secret     #檢視secret資源
NAME                  TYPE                                  DATA   AGE
default-token-tnwkb   kubernetes.io/service-account-token   3      110d
mysql-auth            Opaque                                2      17s
~]# kubectl describe secret/mysql-auth 
Name:         mysql-auth
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  8 bytes
username:  4 bytes

(2) 基於檔案建立
為“kubectl create secret generic”命令使用“--from-file”選項即可基於檔案內容來建立ConfigMap物件,同樣可以重複多次使用。格式如下:

~]# kubectl create secret generic my-secret --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

示列:

~]# mkdir secret && cd secret
~]# echo -n admin > ./username
~]# echo -n 123456 > ./password
~]# kubectl create secret generic mysecret --from-file=username=./username --from-file=password=./password
secret/mysecret created
~]# kubectl get secret 
NAME                  TYPE                                  DATA   AGE
default-token-blm9l   kubernetes.io/service-account-token   3      3d
mysecret              Opaque                                2      6s
mysql-auth            Opaque                                2      5m23s
~]# kubectl get secret/mysecret -o yaml
apiVersion: v1
data:
  password: MTIzNDU2    #這裡可以看到secret儲存的值都是base64編碼格式
  username: YWRtaW4=
kind: Secret
metadata
......

(3) 使用資源清單建立
Secret資源是標準的Kubernetes API物件,除了標準的apiVersion、kind和metadata欄位,它可用的其他欄位如下:

data    <map[string]string>    #"key:value"格式的資料,通常是敏感資訊,資料格式需要以Base64格式編碼的字串,因此需要事先完成編碼
stringData    <map[string]string>    #以明文格式(非Base64編碼)定義的“key:value"資料;無須事先對資料進行Base64編碼,而是在建立為Secret物件時自動進行編碼並保存於data欄位中。
type    <string>    #僅是為了便於程式設計方式處理Secret資料而提供的型別標識。

示列:

~]# vim secret-demo.yaml
apiVersion: v1
kind: Secret
metadata:
  name: secret-demo
  namespace: default
stringData:
  username: redis
  password: redisP@ss
type: Opaque
~]# kubectl apply -f secret-demo.yaml 
~]# kubectl get secret
~]# kubectl get secret/secret-demo -o yaml
apiVersion: v1
data:
  password: cmVkaXNQQHNz
  username: cmVkaXM=
kind: Secret
metadata:
......

6.使用secret

類似於Pod消費ConfigMap物件的方式,Secret物件可以注入為環境變數,也可以儲存為儲存卷形式掛載使用。因為Secret預設儲存的是非明文格式,通過注入為環境變數實為不明智。

儲存卷方式示例:
(1) 建立私鑰和自簽證書

~]# openssl genrsa -out nginx.key 2048
~]# openssl req -new -x509 -key nginx.key -out nginx.crt -subj /C=CN/ST=ShenZhen/L=ShenZhen/O=DevOps/CN=www.ilinux.cn

(2) 建立secret

]# kubectl create secret tls nginx-ssl --key=./nginx.key --cert=./nginx.crt 
]# kubectl get secret nginx-ssl

(3) 建立pod使用secret

~]# vim pod-secret-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-demo
  namespace: default
spec:
  containers:
  - name: web-server
    image: nginx:1.12
    volumeMounts:
    - name: nginxcert
      mountPath: /etc/nginx/ssl/
      readOnly: true
  volumes:
  - name: nginxcert
    secret:
      secretName: nginx-ssl

~]# kubectl apply -f pod-secret-demo.yaml 
~]# kubectl exec -it secret-volume-demo -- /bin/sh
# ls /etc/nginx/ssl
tls.crt  tls.key