Secret和ConfigMap

在日常单机甚至集群状态下,我们需要对一个应用进行配置,只需要修改其配置文件即可。

传统的实践过程中通常有以下几种方式:

启动容器时,通过命令传递参数;

将定义好的配置文件通过镜像文件进行写入;

通过环境变量的方式传递配置数据;

挂载Docker卷传送配置文件;

而在Kubernetes系统之中也存在这样的组件,就是特殊的存储卷类型。其并不是提供pod存储空间,而是给管理员或用户提供从集群外部向Pod内部的应用注入配置信息的方式。这两种特殊类型的存储卷分别是:configMap和secret

Secret:用于向Pod传递敏感信息,比如密码,私钥,证书文件等,这些信息如果在容器中定义容易泄露,Secret资源可以让用户将这些信息存储在急群众,然后通过Pod进行挂载,实现敏感数据和系统解耦的效果;

ConfigMap:主要用于向Pod注入非敏感数据,使用时,用户将数据直接存储在ConfigMap对象当中,然后Pod通过使用ConfigMap卷进行引用,实现容器的配置文件集中定义和管理;

一、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;

1.1 创建Secret的方式:

1.1.1 --from-literal

查看帮助

[root@master ~]# kubectl create secret -h

Create a secret using specified subcommand.

Available Commands:

docker-registry 创建一个给 Docker registry 使用的 secret

generic 从本地 file, directory 或者 literal value 创建一个 secret

tls 创建一个 TLS secret

Usage:

kubectl create secret [flags] [options]

Use "kubectl <command> --help" for more information about a given command.

Use "kubectl options" for a list of global command-line options (applies to all commands).

PS:一个–from-literal语句,只能保存一条信息

[root@master ~]# kubectl create secret generic mysecret1 --from-literal=username=root --from-literal=password=123.com

secret/mysecret1 created

查看Secrets资源对象

[root@master ~]# kubectl get secrets

NAME TYPE DATA AGE

default-token-bql2v kubernetes.io/service-account-token 3 8d

mysecret1 Opaque 2 112s

查看详细信息

[root@master ~]# kubectl describe secrets mysecret1

Name: mysecret1

Namespace: default

Labels: <none>

Annotations: <none>

Type: Opaque

Data

====

password: 7 bytes

username: 4 bytes

PS:查看详细信息的时候,在看到对应的key值,却看不到详细values值,因为在创建资源的时候对这个数据做了一个加密

1.1.2 --from-file

PS:–from-file的方式是每个文件内容对应一个信息条目。

[root@master ~]# echo root > username

[root@master ~]# echo 123.com > password

[root@master ~]# kubectl create secret generic mysecret2 --from-file=username --from-file=password

secret/mysecret2 created

[root@master ~]# kubectl get secrets

NAME TYPE DATA AGE

default-token-bql2v kubernetes.io/service-account-token 3 8d

mysecret1 Opaque 2 10m

mysecret2 Opaque 2 4s

1.1.3 --from-env-file

PS:文件 env.txt 中每行 Key=Value 对应一个信息条目。就是文件中的每一行只能记录一条数据

[root@master ~]# vim env.txt

username=root

password=123.com

[root@master ~]# kubectl create secret generic myseret3 --from-env-file=env.txt

secret/myseret3 created

[root@master ~]# kubectl get secrets | grep myseret3

NAME TYPE DATA AGE

myseret3 Opaque 2 22s

1.1.4 通过yaml清单创建

提前把数据进行加密

[root@master ~]# echo root | base64

cm9vdAo=

[root@master ~]# echo 123.com | base64

MTIzLmNvbQo=

yaml清单

[root@master ~]# vim secret.yaml

kind: Secret

apiVersion: v1

metadata:

name: mysecret4

data:

username: cm9vdAo=

password: MTIzLmNvbQo=

[root@master ~]# kubectl apply -f secret.yaml

secret/mysecret4 created

[root@master ~]# kubectl get secrets | grep mysecret4

NAME TYPE DATA AGE

mysecret4 Opaque 2 17s

解码

PS:在保存数据前,对保存的数据做了加密处理,但是base64这种方法也不是绝对的安全,比如上边用base64这种方法得到的乱码字符串,就可以使用–decode解码

[root@master ~]# echo -n cm9vdAo= | base64 --decode

root

[root@master ~]# echo -n MTIzLmNvbQo= | base64 --decode

123.com

1.2 Secret资源的使用

PS:Pod 可以通过 Volume 或者环境变量的方式使用 Secret

1.2.1 Volume

yaml清单

[root@master ~]# vim volume.yaml

kind: Pod

apiVersion: v1

metadata:

name: pod

spec:

volumes:

- name: test-volume

secret:

secretName: mysecret1

containers:

- name: pod

image: busybox

args:

- /bin/sh

- -c

- sleep 30000

volumeMounts:

- name: test-volume

mountPath: "/etc/volume"

readOnly: true


[root@master ~]# kubectl apply -f volume.yaml

pod/pod created

PS:以volume的挂载方式去使用secret资源,它会随着secret资源对象数据的改变而改变。所以,通常用volume挂载的时候,为了保证secret资源的安全,在挂载的使用都是只读挂载(readOnly)

查看pod内是否有对应数据

[root@master ~]# kubectl get pod

NAME READY STATUS RESTARTS AGE

pod 1/1 Running 0 61s

[root@master ~]# kubectl exec pod cat /etc/volume/username

root

[root@master ~]# kubectl exec pod cat /etc/volume/password

123.com

也可以自己定义存放数据路径

[root@master ~]# kubectl delete -f volume.yaml

pod "pod" deleted

[root@master ~]# vim volume.yaml

......

spec:

volumes:

- name: test-volume

secret:

secretName: mysecret1

items:

- key: username

path: mygroup/my-username

- key: password

path: mygroup/my-password

......

[root@master ~]# kubectl apply -f volume.yaml

pod/pod created

[root@master ~]# kubectl exec -it pod sh

/ # cd /etc/volume/

/etc/volume # ls

mygroup

/etc/volume # ls mygroup/

my-password my-username

或者

[root@master ~]# kubectl exec pod cat /etc/volume/mygroup/my-username

root

[root@master ~]# kubectl exec pod cat /etc/volume/mygroup/my-password

123.com

1.2.2 环境变量

PS:把上方文件复制一份更改名字为bianliang

[root@master ~]# kubectl delete -f volume.yaml

pod "pod" deleted

[root@master ~]# mv volume.yaml bianliang.yaml

[root@master ~]# vim bianliang.yaml

kind: Pod

apiVersion: v1

metadata:

name: pod

spec:

containers:

- name: pod

image: busybox

args:

- /bin/sh

- -c

- sleep 30000

env:

- name: SECRET_USERNAME

valueFrom:

secretKeyRef:

name: mysecret1

key: username

- name: SECRET_PASSWORD

valueFrom:

secretKeyRef:

name: mysecret1

key: password


[root@master ~]# kubectl apply -f bianliang.yaml

pod/pod created

查看数据

[root@master ~]# kubectl get pod

NAME READY STATUS RESTARTS AGE

pod 1/1 Running 0 50s

[root@master ~]# kubectl exec -it pod sh

/ # echo $SECRET_USERNAME

root

/ # echo $SECRET_PASSWORD

123.com

把用命令行创建的资源导出为yaml清单。

[root@master ~]# kubectl get secrets

NAME TYPE DATA AGE

default-token-bql2v kubernetes.io/service-account-token 3 8d

mysecret1 Opaque 2 50m

mysecret2 Opaque 2 40m

mysecret4 Opaque 2 33m

myseret3 Opaque 2 39m

[root@master ~]# kubectl get secrets mysecret2 -o yaml >> mysecret2.yaml

[root@master ~]# cat mysecret2.yaml

apiVersion: v1

data:

password: MTIzLmNvbQo=

username: cm9vdAo=

kind: Secret

metadata:

creationTimestamp: "2020-11-15T06:56:01Z"

name: mysecret2

namespace: default

resourceVersion: "8821"

selfLink: /api/v1/namespaces/default/secrets/mysecret2

uid: 3d7db9bb-5fdc-40db-8cf4-f59624f9ec42

type: Opaque

总结:

资源在创建的过程中,可以直接使用命令的方式创、也可以使用yaml文件的方式,虽然yaml文件的方式创建,相对比较麻烦,但是它会将我们在创建对应资源的时候的把基本状态做一个保存。

用环境变量的方式也可以正确引用secret资源,但是,它并不会像Volume的方式一样,它引用数据不会进行动态的更新。但volume支持动态的数据更新。

二、ConfigMap

configmap是让配置文件从镜像中解耦,让镜像的可移植性和可复制性。许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。这些配置信息需要与docker image解耦,你总不能每修改一个配置就重做一个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项都会成为一个新文件

2.1 创建ConfigMap的方式:

2.1.1 --from-literal

[root@master ~]# kubectl create configmap mycondifmap1 --from-literal=user1=admin --from-literal=user2=root

configmap/mycondifmap1 created

[root@master ~]# kubectl describe configmaps mycondifmap1

Name: mycondifmap1

Namespace: default

Labels: <none>

Annotations: <none>

Data

====

user2:

----

root

user1:

----

admin

Events: <none>

2.1.2 --from-file

[root@master ~]# echo admin > user1

[root@master ~]# echo root > user2

[root@master ~]# kubectl create configmap myconfigmap2 --from-file=user1 --from-file=user2

configmap/myconfigmap2 created

[root@master ~]# kubectl describe configmaps myconfigmap2

Name: myconfigmap2

Namespace: default

Labels: <none>

Annotations: <none>

Data

====

user2:

----

root

user1:

----

admin

Events: <none>

2.1.3 --from-env-file

[root@master ~]# cat user.txt

user1=admin

user2=root

[root@master ~]# kubectl create configmap myconfigmap3 --from-env-file=user.txt

configmap/myconfigmap3 created

[root@master ~]# kubectl describe configmaps myconfigmap3

Name: myconfigmap3

Namespace: default

Labels: <none>

Annotations: <none>

Data

====

user2:

----

root

user1:

----

admin

Events: <none>

2.1.4 通过yaml清单创建

[root@master ~]# vim configmap.yaml

kind: ConfigMap

apiVersion: v1

metadata:

name: myconfigmap4

data:

user1: admin

user2: root

[root@master ~]# kubectl apply -f configmap.yaml

configmap/myconfigmap4 created

[root@master ~]# kubectl describe configmaps myconfigmap4

Name: myconfigmap4

Namespace: default

Labels: <none>

Annotations: kubectl.kubernetes.io/last-applied-configuration:

{"apiVersion":"v1","data":{"user1":"admin","user2":"root"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"myconfigmap4","namespac...

Data

====

user1:

----

admin

user2:

----

root

Events: <none>

2.2 ConfigMap资源的使用

2.1.1 Volume

[root@master ~]# vim volume.yaml


kind: Pod

apiVersion: v1

metadata:

name: pod

spec:

volumes:

- name: test-volume

configMap:

name: mycondifmap1

containers:

- name: pod

image: busybox

args:

- /bin/sh

- -c

- sleep 30000

volumeMounts:

- name: test-volume

mountPath: "/tmp/volume"

readOnly: true

[root@master ~]# kubectl apply -f volume.yaml

pod/pod created

查看数据

pod 1/1 Running 0 37s

[root@master ~]# kubectl exec pod cat /tmp/volume/user1

admin

[root@master ~]# kubectl exec pod cat /tmp/volume/user2

root

假如将myconfigmap1对应的user1的值进行更改,会看到Pod内对应的值也会进行动态的更新

[root@master ~]# kubectl edit configmaps mycondifmap1

......

apiVersion: v1

data:

user1: test

......

configmap/mycondifmap1 edited

[root@master ~]# kubectl exec pod cat /tmp/volume/user1

test

2.2.2 环境变量

[root@master ~]# vim configmap-bianliang.yaml

kind: Pod

apiVersion: v1

metadata:

name: pod

spec:

containers:

- name: pod

image: busybox

args:

- /bin/sh

- -c

- sleep 30000

env:

- name: USER_1

valueFrom:

configMapKeyRef:

name: mycondifmap1

key: user1

- name: USER_2

valueFrom:

configMapKeyRef:

name: mycondifmap1

key: user2


[root@master ~]# kubectl apply -f configmap-bianliang.yaml

pod/pod created

查看对应的数据

[root@master ~]# kubectl get pod

NAME READY STATUS RESTARTS AGE

pod 1/1 Running 0 9m6s

[root@master ~]# kubectl exec -it pod sh

/ # echo $USER_1

test

/ # echo $USER_2

root

更改数据源查看数据会不会有变化

[root@master ~]# kubectl edit configmaps mycondifmap1

......

apiVersion: v1

data:

user1: admin

......

configmap/mycondifmap1 edited

[root@master ~]# kubectl exec -it pod sh

/ # echo $USER_1

test

/ # echo $USER_1

test

/ #

/ # echo $USER_1

test

/ # echo $USER_2

root

总结:

ConfigMap用volume的方式创建完成之后支持动态更新,而变量创建的ConfigMap不支持动态的更新

————————————————

版权声明:本文为博主「有趣的灵魂!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。