Kubernetes之(十三)ConfigMap和Secret


Kubernetes之(十三)ConfigMap和Secret

簡介
ConfigMap和Secret是kubernetes系統上兩種特殊類型的存儲卷,ConfigMao對象用於為容器中的應用提供配置數據以定制程序行為,不過年敏感的配置信息,例如密鑰,證書等通常由Secret對象來進行配置,它們將相應的配置信息保存於對象中,而后在Pod資源上以存儲卷的形式將其掛載並獲取相關配置,以實現配置與鏡像文件的解耦。

傳統的實踐過程中們需要對一個應用進行配置,只需要修改其配置文件通常有以下幾種方式:

  • 啟動容器時,通過命令傳遞參數 command args自定義參數
  • 把配置文件寫入鏡像內
  • 通過環境變量的方式傳遞配置數據
    • cloud native的程序,一般通過環境變量加載配置
    • 通過enteypoint腳本預處理變量為配置文件中的配置信息
  • 掛載Docker卷傳送配置文件

而在Kubernetes系統之中也存在這樣的組件,就是特殊的存儲卷類型。其並不是提供pod存儲空間,而是給管理員或用戶提供從集群外部向Pod內部的應用注入配置信息的方式。這兩種特殊類型的存儲卷:configMap和secret

ConfigMap:主要用於向Pod注入非敏感數據,使用時,用戶將數據直接存儲在ConfigMap對象當中,然后Pod通過使用ConfigMap卷進行引用,實現容器的配置文件集中定義和管理。
Secret:用於向Pod傳遞敏感信息,比如密碼,私鑰,證書文件等,這些信息如果在容器中定義容易泄露,Secret資源可以讓用戶將這些信息存儲在急群眾,然后通過Pod進行掛載,實現敏感數據和系統解耦的效果。

ConfigMap

configmap是讓配置文件從鏡像中解耦,讓鏡像的可移植性和可復制性。許多應用程序會從配置文件、命令行參數或環境變量中讀取配置信息。這些配置信息需要與docker image解耦,ConfigMap API給我們提供了向容器中注入配置信息的機制,ConfigMap可以被用來保存單個屬性,也可以用來保存整個配置文件或者JSON二進制對象。

ConfigMap API資源用來保存key-value pair配置數據,這個數據可以在pods里使用,或者被用來為像controller一樣的系統組件存儲配置數據。雖然ConfigMap跟Secrets類似,但是ConfigMap更方便的處理不含敏感信息的字符串。 注意:ConfigMaps不是屬性配置文件的替代品。ConfigMaps只是作為多個properties文件的引用。可以把它理解為Linux系統中的/etc目錄,專門用來存儲配置文件的目錄。下面舉個例子,使用ConfigMap配置來創建Kuberntes Volumes,ConfigMap中的每個data項都會成為一個新文件。

[root@master ~]# kubectl explain cm.
KIND:     ConfigMap
VERSION:  v1

FIELDS:
   apiVersion   <string>

   data <map[string]string>

   kind <string>

   metadata     <Object>

ConfigMap創建方式

1、 通過 --from-literal:

[root@master configmap]# kubectl create configmap nginx-config --from-literal=nginx_port=8080 --from-literal=server_name=myapp.white.com
configmap/nginx-config created
[root@master configmap]# kubectl get cm
NAME           DATA   AGE
nginx-config   2      4s

[root@master configmap]# kubectl describe cm nginx-config 
Name:         nginx-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx_port:
----
8080
server_name:
----
myapp.white.com
Events:  <none>

2、通過 --from-file:

[root@master configmap]# vim www.conf
server {
        server_name myapp.white.com;
        listen 80;
        root /data/web/html/;
}


[root@master configmap]# kubectl create configmap nginx-www --from-file=./www.conf 
configmap/nginx-www created
[root@master configmap]# kubectl get cm
NAME           DATA   AGE
nginx-config   2      3m5s
nginx-www      1      3s
[root@master configmap]# kubectl get cm nginx-www -o yaml
apiVersion: v1
data:
  www.conf: "server {\n\tserver_name myapp.white.com;\n\tlisten 80;\n\troot /data/web/html/;\n}\n"
kind: ConfigMap
metadata:
  creationTimestamp: "2019-04-03T02:25:57Z"
  name: nginx-www
  namespace: default
  resourceVersion: "207536"
  selfLink: /api/v1/namespaces/default/configmaps/nginx-www
  uid: d0171cb8-55b7-11e9-80a7-000c295ec349

將cm注入到pod內

[root@master 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: http
      containerPort: 80
    env:
    - name: NGINX_SERVER_PORT
      valueFrom:
        configMapKeyRef:
          name: nginx-config
          key: nginx_port
    - name: NGINX_SERVER_NAME
      valueFrom:
        configMapKeyRef:
          name: nginx-config
          key: server_name

[root@master configmap]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
myapp-backend-pod-6b56d98b6b-2dh5h   1/1     Running   0          25h
myapp-backend-pod-6b56d98b6b-hwzws   1/1     Running   0          25h
myapp-backend-pod-6b56d98b6b-ztwn2   1/1     Running   0          25h
pod-cm-1                             1/1     Running   0          19s
pod-hostpath-vol                     1/1     Running   0          20h
pod-pvc-vol                          1/1     Running   0          17h
tomcat-deploy-5f554cd88d-7gzc7       1/1     Running   0          24h
tomcat-deploy-5f554cd88d-c42t6       1/1     Running   0          24h
tomcat-deploy-5f554cd88d-qhc4j       1/1     Running   0          24h

進入容器查看:

[root@master configmap]# kubectl exec -it pod-cm-1  -- /bin/sh
/ # printenv
MYAPP_SVC_PORT_80_TCP_ADDR=10.98.57.156
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
MYAPP_SERVICE_PORT_HTTP=80
TOMCAT_PORT_8080_TCP=tcp://10.107.88.118:8080
TOMCAT_PORT_8009_TCP=tcp://10.107.88.118:8009
MYAPP_SVC_PORT_80_TCP_PORT=80
HOSTNAME=pod-cm-1
SHLVL=1
MYAPP_SVC_PORT_80_TCP_PROTO=tcp
HOME=/root
MYAPP_SERVICE_HOST=10.100.41.152
NGINX_SERVER_PORT=8080   #已經被調用
NGINX_SERVER_NAME=myapp.white.com   #已經被調用
MYAPP_SVC_PORT_80_TCP=tcp://10.98.57.156:80
MYAPP_PORT=tcp://10.100.41.152:80
MYAPP_SERVICE_PORT=80
TERM=xterm
NGINX_VERSION=1.12.2
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYAPP_PORT_80_TCP_ADDR=10.100.41.152
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TOMCAT_SERVICE_PORT_HTTP=8080
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYAPP_PORT_80_TCP_PORT=80
MYAPP_PORT_80_TCP_PROTO=tcp
MYAPP_SVC_SERVICE_HOST=10.98.57.156
TOMCAT_PORT_8080_TCP_ADDR=10.107.88.118
TOMCAT_SERVICE_HOST=10.107.88.118
TOMCAT_PORT_8009_TCP_ADDR=10.107.88.118
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
TOMCAT_PORT_8080_TCP_PORT=8080
PWD=/
KUBERNETES_SERVICE_HOST=10.96.0.1
MYAPP_PORT_80_TCP=tcp://10.100.41.152:80
TOMCAT_PORT_8080_TCP_PROTO=tcp
TOMCAT_PORT_8009_TCP_PORT=8009
MYAPP_SVC_SERVICE_PORT=80
MYAPP_SVC_PORT=tcp://10.98.57.156:80
TOMCAT_PORT_8009_TCP_PROTO=tcp
TOMCAT_PORT=tcp://10.107.88.118:8080
TOMCAT_SERVICE_PORT=8080
TOMCAT_SERVICE_PORT_AJP=8009

如果此時使用kubectl edit cm來修改configmap 此時在容器內查看環境變量不會被修改,因為該env是在pod創建的時候獲取的,不會被修改

存儲卷方式掛載configmap:

[root@master 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: http
      containerPort: 80
    volumeMounts:
    - name: nginxconf
      mountPath: /etc/nginx/config.d/
      readOnly: true
  volumes:
  - name: nginxconf
    configMap:
      name: nginx-config


[root@master configmap]# kubectl apply -f pod-configmap-2.yaml 
pod/pod-cm-2 created

查看並進入Pod

[root@master configmap]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
myapp-backend-pod-6b56d98b6b-2dh5h   1/1     Running   0          29h
myapp-backend-pod-6b56d98b6b-hwzws   1/1     Running   0          29h
myapp-backend-pod-6b56d98b6b-ztwn2   1/1     Running   0          29h
pod-cm-2                             1/1     Running   0          53s
pod-hostpath-vol                     1/1     Running   0          23h
pod-pvc-vol                          1/1     Running   0          20h
tomcat-deploy-5f554cd88d-7gzc7       1/1     Running   0          27h
tomcat-deploy-5f554cd88d-c42t6       1/1     Running   0          27h
tomcat-deploy-5f554cd88d-qhc4j       1/1     Running   0          27h

[root@master configmap]# kubectl exec -it pod-cm-2 -- /bin/sh
/ # cd /etc/nginx/config.d/
/etc/nginx/config.d # ls
nginx_port   server_name
/etc/nginx/config.d # cat nginx_port
8080
/etc/nginx/config.d # cat server_name
myapp.white.com/etc/nginx/config.d 

此時使用kubectl edit修改端口,進入容器進行查看

[root@master ~]# kubectl edit cm 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: "11111"
  server_name: myapp.white.com
kind: ConfigMap
metadata:
  creationTimestamp: "2019-04-03T02:22:55Z"
  name: nginx-config
  namespace: default
  resourceVersion: "207257"
  selfLink: /api/v1/namespaces/default/configmaps/nginx-config
  uid: 63e91046-55b7-11e9-80a7-000c295ec349

進入容器查看(需要等待一小會,有一定延遲時間)

/etc/nginx/config.d # cat nginx_port 
11111
/etc/nginx/config.d #

使用nginx-www配置nginx

nginx-www是使用文件創建的cm,文件名是鍵名,內容是值。

[root@master 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: http
      containerPort: 80
    volumeMounts:
    - name: nginxconf
      mountPath: /etc/nginx/conf.d/
      readOnly: true
  volumes:
  - name: nginxconf
    configMap:
      name: nginx-www

創建並查看

[root@master configmap]# kubectl apply -f pod-configmap-3.yaml
pod/pod-cm-3 created
[root@master configmap]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
myapp-backend-pod-6b56d98b6b-2dh5h   1/1     Running   0          29h
myapp-backend-pod-6b56d98b6b-hwzws   1/1     Running   0          29h
myapp-backend-pod-6b56d98b6b-ztwn2   1/1     Running   0          29h
pod-cm-3                             1/1     Running   0          5s
pod-hostpath-vol                     1/1     Running   0          23h
pod-pvc-vol                          1/1     Running   0          20h
tomcat-deploy-5f554cd88d-7gzc7       1/1     Running   0          28h
tomcat-deploy-5f554cd88d-c42t6       1/1     Running   0          28h
tomcat-deploy-5f554cd88d-qhc4j       1/1     Running   0          28h

進入容器查看

[root@master configmap]# kubectl exec -it pod-cm-3 -- /bin/sh 
/ # cd /etc/nginx/conf.d/
/etc/nginx/conf.d # ls
www.conf
/etc/nginx/conf.d # cat www.conf 
server {
        server_name myapp.white.com;
        listen 80;
        root /data/web/html/;
}

查看nginx加載的內容
/etc/nginx/conf.d # nginx -T
... ...
# configuration file /etc/nginx/conf.d/www.conf:
server {
        server_name myapp.white.com;
        listen 80;
        root /data/web/html/;
}

此時使用kubectl edit修改cm內的內容,容器內部會被修改,但是nginx 需要重載才能生效,如果需要這樣配置,需要手動或配置腳本進行nginx -s reload。

Secret

Secret對象存儲數據的方式是以鍵值方式存儲數據,在Pod資源進行調用Secret的方式是通過環境變量或者存儲卷的方式進行訪問數據,解決了密碼、token、密鑰等敏感數據的配置問題,而不需要把這些敏感數據暴露到鏡像或者Pod Spec中。另外,Secret對象的數據存儲和打印格式為Base64編碼的字符串,因此用戶在創建Secret對象時,也需要提供該類型的編碼格式的數據。在容器中以環境變量或存儲卷的方式訪問時,會自動解碼為明文格式。需要注意的是,如果是在Master節點上,Secret對象以非加密的格式存儲在etcd中,所以需要對etcd的管理和權限進行嚴格控制。
Secret有4種類型:

  • Service Account :用來訪問Kubernetes API,由Kubernetes自動創建,並且會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中;
  • Opaque :base64編碼格式的Secret,用來存儲密碼、密鑰、信息、證書等,類型標識符為generic;
  • kubernetes.io/dockerconfigjson :用來存儲私有docker registry的認證信息,類型標識為docker-registry。
  • kubernetes.io/tls:用於為SSL通信模式存儲證書和私鑰文件,命令式創建類型標識為tls。

創建 Secret

使用--from-literal

[root@master configmap]# kubectl create secret generic mysql-root-password --from-literal=password=MyP@ss123
secret/mysql-root-password created
[root@master configmap]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
default-token-dqd2f     kubernetes.io/service-account-token   3      6d22h
mysql-root-password     Opaque                                1      4s
tomcat-ingress-secret   kubernetes.io/tls                     2      28h

查看

[root@master configmap]# kubectl describe secret mysql-root-password
Name:         mysql-root-password
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  9 bytes

查看可知只有9個字節,沒有顯示內容。可以轉換成YAML格式文件查看Base64加密后的password

[root@master configmap]# kubectl describe secret mysql-root-password
Name:         mysql-root-password
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  9 bytes
[root@master configmap]# kubectl get secret mysql-root-password -o yaml
apiVersion: v1
data:
  password: TXlQQHNzMTIz
kind: Secret
metadata:
  creationTimestamp: "2019-04-03T06:46:00Z"
  name: mysql-root-password
  namespace: default
  resourceVersion: "226351"
  selfLink: /api/v1/namespaces/default/secrets/mysql-root-password
  uid: 247548a3-55dc-11e9-80a7-000c295ec349
type: Opaque

解碼

[root@master configmap]# echo TXlQQHNzMTIz|base64 -d
MyP@ss123

使用--from-file

[root@master configmap]# echo -n admin > ./username
[root@master configmap]#  echo -n 123456 > ./password
[root@master configmap]# kubectl create secret generic mysecret --from-file=./username --from-file=./password 
secret/mysecret created
[root@master configmap]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
default-token-dqd2f     kubernetes.io/service-account-token   3      6d22h
mysecret                Opaque                                2      4s
mysql-root-password     Opaque                                1      6m6s
tomcat-ingress-secret   kubernetes.io/tls                     2      28h

通過 --from-env-file

文件 env.txt 中每行 Key=Value 對應一個信息條目。

[root@master 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: http
      containerPort: 80
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-root-password
          key: password


[root@master configmap]# kubectl apply -f pod-secret-1.yaml 
pod/pod-secret-1 created

進入Pod查看

[root@master configmap]# kubectl exec -it pod-secret-1 -- /bin/sh
/ # printenv|grep MYSQL_ROOT_PASSWORD
MYSQL_ROOT_PASSWORD=MyP@ss123

在Pod內已經是轉換后的密碼,任何人都可以看到,不夠安全。

使用掛在存儲卷方式

[root@master configmap]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
default-token-dqd2f     kubernetes.io/service-account-token   3      6d22h
mysecret                Opaque                                2      11m
mysql-root-password     Opaque                                1      17m
tomcat-ingress-secret   kubernetes.io/tls                     2      28h

[root@master configmap]# vim pod-secret-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-vol
spec:
  containers:
  - name: pod-secret-vol
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10;touch /tmp/healthy;sleep 36000
    volumeMounts:
    - name: test
      mountPath: "/etc/test"
      readOnly: true
  volumes:
  - name: test
    secret:
      secretName: mysecret

[root@master configmap]# kubectl apply -f pod-secret-demo.yaml 
pod/pod-secret-vol created

[root@master configmap]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
myapp-backend-pod-6b56d98b6b-2dh5h   1/1     Running   0          30h
myapp-backend-pod-6b56d98b6b-hwzws   1/1     Running   0          30h
myapp-backend-pod-6b56d98b6b-ztwn2   1/1     Running   0          30h
pod-hostpath-vol                     1/1     Running   0          24h
pod-pvc-vol                          1/1     Running   0          21h
pod-secret-1                         1/1     Running   0          9m
pod-secret-vol                       1/1     Running   0          7s
tomcat-deploy-5f554cd88d-7gzc7       1/1     Running   0          29h
tomcat-deploy-5f554cd88d-c42t6       1/1     Running   0          29h
tomcat-deploy-5f554cd88d-qhc4j       1/1     Running   0          29h

進入Pod查看

[root@master configmap]# kubectl exec -it pod-secret-vol -- /bin/sh
/ # cd /etc/test/
/etc/test # ls
password  username
/etc/test # cat username
admin
/etc/test # cat password
123456

可以看到,Kubernetes 會在指定的路徑 /etc/test 下為每條敏感數據創建一個文件,文件名就是數據條目的 Key,這里是 /etc/test/username 和 /etc/test/password,Value 則以明文存放在文件中。
也可以自定義存放數據的文件名,比如將配置文件改為:

[root@master configmap]# vim  pod-secret-damo-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-vol-1
spec:
  containers:
  - name: pod-secret-vol-1
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10;touch /tmp/healthy;sleep 36000
    volumeMounts:
    - name: test
      mountPath: "/etc/test"
      readOnly: true
  volumes:
  - name: test
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-secret/my-username
      - key: password
        path: my-secret/my-password


這時數據將分別存放在 /etc/test/my-secret/my-username 和 /etc/test/my-secret/my-password 中。

[root@master configmap]# kubectl exec -it pod-secret-vol-1 -- /bin/sh
/ # cd /etc/test/
/etc/test # ls
my-secret
/etc/test # cd my-secret/
/etc/test/..2019_04_03_07_12_02.941048565/my-secret # ls
my-password  my-username
/etc/test/..2019_04_03_07_12_02.941048565/my-secret # cat  my-username
admin
/etc/test/..2019_04_03_07_12_02.941048565/my-secret # cat my-password
123456

以 Volume 方式使用的 Secret 支持動態更新:Secret 更新后,容器中的數據也會更新。
將 password 更新為 abcdef,base64 編碼為 YWJjZGVm

[root@master configmap]#  vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  username: YWRtaW4=   #echo -n  admin|base64
  password: YWJjZGVm   #echo -n   abcdef|base64


[root@master configmap]# kubectl exec -it pod-secret-vol-1 -- /bin/sh
/etc # cd test/my-secret/
/etc/test/..2019_04_03_07_18_09.073816450/my-secret # ls
my-password  my-username
/etc/test/..2019_04_03_07_18_09.073816450/my-secret # cat my-password 
abcdef

通過 Volume 使用 Secret,容器必須從文件讀取數據,會稍顯麻煩,Kubernetes 還支持通過環境變量使用 Secret。

[root@master configmap]# vim pod-secret-env-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-secret-env
spec:
  containers:
  - name: pod-secret-env
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10;touch /tmp/healthy;sleep 36000
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password


[root@master configmap]# kubectl apply -f pod-secret-env-demo.yaml
pod/pod-secret-env created

[root@master configmap]# kubectl exec -it pod-secret-env sh
/ #  echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
abcdef

總結:
通過環境變量 SECRET_USERNAME 和 SECRET_PASSWORD 成功讀取到 Secret 的數據。
需要注意的是,環境變量讀取 Secret 很方便,但不支持Secret 動態更新。

參考資料

https://www.cnblogs.com/linuxk
馬永亮. Kubernetes進階實戰 (雲計算與虛擬化技術叢書)
Kubernetes-handbook-jimmysong-20181218


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM