kubernetes的secret和configmap

用kubernetes管理机密信息

          应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥,将这些信息直接保存在容器镜像中显然不妥,kubernetes提供了解决方案是secret

          secret资源对象:解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。

           secret可通过命令行或YAML创建。比如希望secret包含如下信息:

            1.用户名 admin 

             2.密码 123456

创建secret

通过 --from-kiteral:

[root@master de]# kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456
[root@master de]# kubectl describe secrets mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  5 bytes

每个 --from-literal 对应一个信息条目。

Generic:通用的、一般的。加密方式。

通过--from-file:

[root@master de]# echo -n admin > ./username
[root@master de]# echo -n 123456 > ./password
[root@master de]# kubectl create secret  generic mysecret --from-file=./username --from-file=./passwo
secret/mysecret created

每个文件内容对应一个信息条目

   这种方式不推荐使用,需要将存储的数据写入到文件中,注意每个文件只能存储一个数据。

[root@master de]# kubectl get secrets mysecret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      2m27s
[root@master de]# kubectl describe secrets mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  5 bytes

通过--from-env-file:

[root@master de]# cat env.txt 
username=admin
password=123456
[root@master de]# kubectl create secret generic mysecret --from-env-file=env.txt
secret/mysecret created

 这种方式可以在同一个文件内写入多个数据

[root@master de]# kubectl get secrets mysecret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      2m33s

通过yaml配置文件:

 

[root@master de]# echo -n admin | base64
YWRtaW4=
[root@master de]# echo -n 123456 | base64
MTIzNDU2
[root@master de]# 
[root@master de]# vim env.yml
[root@master de]# kubectl get secrets mysecret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      6m21s
[root@master de]# kubectl delete secrets mysecret
secret "mysecret" deleted
[root@master de]# kubectl apply -f env.
env.txt  env.yml  
[root@master de]# kubectl apply -f env.yml 
secret/mysecret created
[root@master de]# kubectl get secrets mysecret
NAME       TYPE     DATA   AGE
mysecret   Opaque   2      32s
[root@master de]# kubectl describe secrets mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  
Type:         Opaque

Data
====
password:  6 bytes
username:  5 bytes

查看value

[root@master de]# kubectl edit secrets mysecret

# 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:
  password: MTIzNDU2
  username: YWRtaW4=
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"MTIzNDU2","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"}}
  creationTimestamp: "2020-07-26T06:44:04Z"
  name: mysecret
  namespace: default
  resourceVersion: "160163"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 73ffac16-1c59-4488-ab58-3c05ef1b092f
type: Opaque

通过base64将value反编码

123456[root@master de]# echo -n YWRtaW4= | base64 --decode
admin[root@master de]# 

volume方式使用secret

1.pod可以通过volume或者环境变量的方式使用secret

  pod配置文件如下:

[root@master de]# cat pod.yml 
apiVersion: v1
kind: Pod
metadata:
   name: mypod
spec:
  containers:
  - image: busybox
    name: mypod
    volumeMounts:
    - mountPath: /etc/foo
      name: foo
      readOnly: true
    args:
    - /bin/sh
    - -c
    - sleep  30000
 
  volumes:
  - name: foo
    secret:
      secretName: mysecret

查看

[root@master de]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
mypod   1/1     Running   0          3s

[root@master de]# kubectl exec -it mypod sh
/ # ls /etc/foo/
password username
/ # exit
[root@master de]# kubectl exec -it mypod sh
/ # cat /etc/foo/
..2020_07_26_07_07_36.664212846/ password
..data/ username
/ # cat /etc/foo/username
admin/ #

可以看到,kubernetes会在指定的路径/etc/foo/username和 /etc/foo/password, value则以明文存放在文件中。

我们也可以自定义存放数据的文件名:

[root@master de]# cat pod.yml 
apiVersion: v1
kind: Pod
metadata:
   name: mypod
spec:
  containers:
  - image: busybox
    name: mypod
    volumeMounts:
    - mountPath: /etc/foo
      name: foo
      readOnly: true
    args:
    - /bin/sh
    - -c
    - sleep  30000
 
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
       - key: username
         path: my-group/my-username
       - key: password
         path: my-group/my-password
[root@master de]# kubectl apply -f pod.yml 
pod/mypod created
[root@master de]# kubectl exec -it mypod sh
/ # cat etc/foo/my-group/my-password 
/ # cat etc/foo/my-group/my-username  
admin/ # exit

  这时数据将分别存放在 /etc/foo/my-group/my-username 和 /etc/foo/my-group/my-password中。

以volume方式使用的secret 支持动态更新: secret更细后,容器中的数据也就更新。

[root@master de]# echo -n caoyi888 | base64
Y2FveWk4ODg=
[root@master de]# cat env.yml 
apiVersion: v1
data:
   password: Y2FveWk4ODg=
   username: YWRtaW4=
kind: Secret
metadata:
   name: mysecret1
[root@master de]# kubectl apply -f env.yml 
secret/mysecret1 configured
[root@master de]# kubectl exec -it mypod sh
/ # cat /etc/foo/my-group/my-username 
/ # cat /etc/foo/my-group/my-password 
caoyi888/ # exit

没有动pod,就可以动态更新密码

环境变量方式使用secret

通过volume使用secret ,容器必须从文件读取数据,会稍微麻烦,kubernetes还支持通过环境变量使用secret 

[root@master de]# cat pod.yml 

apiVersion: v1
kind: Pod
metadata:
   name: mypod
spec:
  containers:
  - image: busybox
    name: mypod
    args:
    - /bin/sh
    - -c
    - sleep  30000
    env:
       - name: SECRET_USERNAME
         valueFrom:
          secretKeyRef:
             name: mysecret
             key: username
       - name: SECRET_PASSWORD
         valueFrom:
           secretKeyRef:
             name: mysecret
             key: password
[root@master de]# kubectl exec -it mypod sh 
/ # echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
123456

通过环境变量secret_username和secret_password成功读取到secret的数据。

  需要注意的是,环境变量读取secret很方便,但无法支撑secret动态更新。

用configMap管理配置

secret可以为pod提供密码、token,私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,用configMap。

    configMap的创建和使用方法好与secregt非常类似,主要的不同是数据以明文形式存放。

通过--from-literal:

[root@master de]# kubectl create configmap myconfigimap --from-literal=config1=xxx --from-literal=config2=yy
configmap/myconfigimap created


[root@master de]# kubectl describe configmaps myconfigimap
Name:         myconfigimap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
config2:
----
yy
config1:
----
xxx
Events:  <none>

每个--from-literal对应一个信息条目。

通过--from-file:

[root@master de]# echo -n aaa > ./config1
[root@master de]# echo -n bbb > ./config2
[root@master de]# kubectl create configmap myconfigmap1 --from-file=./config1 --from-file=./config2
configmap/myconfigmap1 created
[root@master de]# kubectl get configmap myconfigmap1
NAME           DATA   AGE
myconfigmap1   2      74s
[root@master de]# kubectl describe configmaps myconfigmap1
Name:         myconfigmap1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
config1:
----
aaa
config2:
----
bbb
Events:  <none>

每个文件内容对应一个信息条目。

通过 --from-env-file

[root@master de]# cat env.txt 
config1=aaa
config2=bbb


[root@master de]# kubectl create configmap myconfigmap --from-env-file=env.txt
configmap/myconfigmap created
[root@master de]# kubectl get configmaps
NAME           DATA   AGE
myconfigimap   2      7m42s
myconfigmap    2      26s
myconfigmap1   2      4m42s
[root@master de]# kubectl describe configmaps myconfigmap
Name:         myconfigmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
config1:
----
aaa
config2:
----
bbb
Events:  <none>

文件env.txt中每行key=value对应每一个信息条目

通过YAML配置文件:

[root@master de]# cat caoyi.yml 
apiVersion: v1
data:
  config1: aaa
  config2: bbb
kind: ConfigMap
metadata:
   name: myconfigmap2


[root@master de]# kubectl apply -f caoyi.yml 
configmap/myconfigmap2 created
[root@master de]# kubectl get configmaps
NAME           DATA   AGE
myconfigimap   2      11m
myconfigmap    2      4m15s
myconfigmap1   2      8m31s
myconfigmap2   2      12s
[root@master de]# kubectl describe configmaps myconfigmap2
Name:         myconfigmap2
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","data":{"config1":"aaa","config2":"bbb"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"myconfigmap2","namespa...

Data
====
config1:
----
aaa
config2:
----
bbb
Events:  <none>

案例:

通过volume方式

 

[root@master de]# cat pod.yml 
apiVersion: v1
kind: Pod
metadata:
   name: mypod
spec:
  containers:
  - image: busybox
    name: mypod
    volumeMounts:
    - mountPath: /etc/foo
      name: foo
      readOnly: true
    args:
    - /bin/sh
    - -c
    - sleep 30000
 
  volumes:
  - name: foo
    configMap:
        name: myconfigmap2
[root@master de]# kubectl exec -it mypod sh
/ # cat /etc/foo/
..2020_07_26_08_12_42.774514494/  config1
..data/                           config2
/ # cat /etc/foo/config1 
/ # cat /etc/foo/config2
bbb/ # exit

环境变量方式:

[root@master de]# cat pod.yml 
apiVersion: v1
kind: Pod
metadata:
   name: mypod
spec:
  containers:
  - image: busybox
    name: mypod
    args:
    - /bin/sh
    - -c
    - sleep 30000
    env:
     - name: BALALA_1
       valueFrom:
        configMapKeyRef:
         name: myconfigmap2
         key: config1
     - name: BALALA_2
       valueFrom:
        configMapKeyRef:
         name: myconfigmap2
         key: config2
[root@master de]# kubectl exec -it mypod sh
/ # echo $BALALA

/ # echo $BALALA_1
aaa
/ # echo $BALALA_2
bbb

大多数情况下,配置信息都已文件形式提供,所以在创建configMap时通常采用 --from-file或ymal方式,读取configMap 时通常采用volume方式

 

比如给pod传递如何记录日志的配置信息:

[root@master de]# cat loggin.conf 
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: %hostname-%timestamp.log


[root@master de]# kubectl create configmap myconfigmap3 --from-file=loggin.conf  --dry-run  -o yaml
apiVersion: v1
data:
  loggin.conf: |
    class: logging.handlers.RotatingFileHandler
    formatter: precise
    level: INFO
    filename: %hostname-%timestamp.log
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: myconfigmap3

[root@master de]# cat caoyi1.yml 
apiVersion: v1
data:
  loggin.conf: |
    class: logging.handlers.RotatingFileHandler
    formatter: precise
    level: INFO
    filename: %hostname-%timestamp.log
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: myconfigmap3


[root@master de]# kubectl apply -f caoyi1.yml 
configmap/myconfigmap3 created
[root@master de]# kubectl get configmaps
NAME           DATA   AGE
myconfigimap   2      35m
myconfigmap    2      27m
myconfigmap1   2      32m
myconfigmap2   2      23m
myconfigmap3   1      11s
[root@master de]# kubectl describe configmaps myconfigmap3
Name:         myconfigmap3
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","data":{"loggin.conf":"class: logging.handlers.RotatingFileHandler\nformatter: precise\nlevel: INFO\nfilename: %hostnam...

Data
====
loggin.conf:
----
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: %hostname-%timestamp.log

Events:  <none>
[root@master de]# cat loggin.conf 
class: logging.handlers.RotatingFileHandler

在pod中使用此configMap,配置文件为:

[root@master de]# kubectl exec -it mypod sh
/ # ls /etc/config/de/loggin.conf 
/etc/config/de/loggin.conf
/ # cat /etc/config/de/loggin.conf 
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: %hostname-%timestamp.log
/ # exit

配置信息已经保存到/etc/myapp/loggin.conf文件中。secret一样,volume形式的configMAP也支持动态更新。