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版权协议,转载请附上原文出处链接及本声明。