linux运维、架构之路-K8s Secret & Configmap
一、介绍
应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名、密码或者秘钥等。这些信息保存在镜像中不太好。Secret会以密文方式存储数据,避免直接在配置文件中保存敏感信息,Secret会以Volume的形式被mount到Pod,容器通过文件的方式使用Secret中的敏感数据;此外,容器也可以通过环境变量的方式使用这些数据。
二、Secret
1、创建Secret
①通过 --from-litera
kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456
[root@k8s-node1 ~]# kubectl get secret NAME TYPE DATA AGE default-token-ff5wq kubernetes.io/service-account-token 3 13d mysecret Opaque 2 6s
②通过 --from-file
kubectl create secret generic mysecret --from-file=./username --from-file=./password
③通过 --from-env-file
[root@k8s-node1 ~]# cat <<EOF >env.txt > username=admin > password=123456 > EOF [root@k8s-node1 ~]# cat env.txt username=admin password=123456 [root@k8s-node1 ~]# kubectl create secret generic mysecret --from-env-file=env.txt
④通过YAML配置文件
#文件中的敏感数据通过base64编码后# [root@k8s-node1 ~]# echo -n admin|base64 YWRtaW4= [root@k8s-node1 ~]# echo -n 123456|base64 MTIzNDU2
[root@k8s-node1 ~]# cat mysecret.yaml apiVersion: v1 kind: Secret metadata: name: mysecret data: username: YWRtaW4= password: MTIzNDU2
⑤创建查看
[root@k8s-node1 ~]# kubectl apply -f mysecret.yaml secret "mysecret" created [root@k8s-node1 ~]# kubectl get secret mysecret NAME TYPE DATA AGE mysecret Opaque 2 1m
[root@k8s-node1 ~]# kubectl describe secret mysecret Name: mysecret Namespace: default Labels: <none> Annotations: Type: Opaque Data ==== password: 6 bytes username: 5 bytes
⑥通过base64将Value反编码
[root@k8s-node1 ~]# echo -n YWRtaW4=|base64 --decode admin[root@k8s-node1 ~]# echo -n MTIzNDU2|base64 --decode 123456[root@k8s-node1 ~]#
三、在Pod中使用Secret
Pod可以通过Volume或者环境变量的方式使用Secret。
1、Volume方式
①创建Pod并在容器中读取Secret
[root@k8s-node1 ~]# cat mypod.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" #将foo mount到容器路径/etc/foo,权限为readOnly readOnly: true volumes: - name: foo #定义volume foo,来源为secret mysecret secret: secretName: mysecret
创建并进到容器中查看
[root@k8s-node1 ~]# kubectl apply -f mypod.yaml pod "mypod" created [root@k8s-node1 ~]# kubectl exec -it mypod /bin/sh / # ls /etc/foo password username / # cat /etc/foo/username admin/ # cat /etc/foo/password 123456/ #
结果:k8s会在指定的路径/etc/foo下为每条敏感数据创建一个文件,以明文存放在文件中,存放数据的文件名可以自定义
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret items: - key: username path: my-group/my-username - key: password path: my-group/my-password
以上自定义数据分别存放在/etc/foo/my-group/my-username和/etc/foo/my-group/my-password中,以Volume方式使用的secret支持动态更新,Secret更新后,容器中的数据也会更新。
②动态更新Secret测试
#将password更新为abcdef [root@k8s-node1 ~]# echo -n abcdef|base64 YWJjZGVm
[root@k8s-node1 ~]# cat mysecret.yaml apiVersion: v1 kind: Secret metadata: name: mysecret data: username: YWRtaW4= password: YWJjZGVm
创建几秒钟后查看
[root@k8s-node1 ~]# kubectl apply -f mysecret.yaml secret "mysecret" configured [root@k8s-node1 ~]# kubectl exec -it mypod /bin/sh / # cat /etc/foo/password abcdef/ #
2、环境变量方式
通过Volume使用Secret,容器必须从文件读取数据,k8s还支持通过环境变量使用Secret。
①Pod配置文件
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
②创建Pod并读取Secret
[root@k8s-node1 ~]# kubectl apply -f mypod-env.yaml pod "mypod" created [root@k8s-node1 ~]# kubectl exec -it mypod /bin/sh / # echo $SECRET_USERNAME admin / # echo $SECRET_PASSWORD abcdef
四、ConfigMap
Secret可以为Pod提供密码、Token、私钥等敏感数据,对于一些非敏感数据,如配置信息,则可以用ConfigMap,使用方式与Secret非常类似,主要不同的是数据以明文形式存在。
1、创建ConfigMap
①通过 --from-litera
[root@k8s-node1 ~]# kubectl create configmap myconfigmap --from-literal=config1=xxx --from-literal=config2=yyy configmap "myconfigmap" created [root@k8s-node1 ~]# kubectl get configmap NAME DATA AGE myconfigmap 2 9s
②通过 --from-file
echo -n xxx >./config1 echo -n yyy >./config2 kubectl create configmap myconfigmap --from-file=./config1 --from-file=./config2
③通过 --from-env-file
cat <<EOF >env.txt config1=xxx config2=yyy EOF kubectl create configmap myconfigmap --from-env-file=env.txt
④通过YAML配置文件-Volume方式
[root@k8s-node1 ~]# cat myconfigmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
config1: xxx
config2: yyy
[root@k8s-node1 ~]# cat pod_volume.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: myconfigmap
⑤通过YAML配置文件-环境变量方式
[root@k8s-node1 ~]# cat pod_env.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 env: - name: CONFIG_1 valueFrom: secretKeyRef: name: myconfigmap key: config1 - name: CONFIG_2 valueFrom: secretKeyRef: name: myconfigmap key: config2
结论:大多数情况下,配置信息都以文件形式提供,所以创建configMap时通常采用--from-file或YAML方式,读取ConfigMap时通常采用Volume方式。
2、在Pod中使用ConfigMap
①创建YAML配置文件
[root@k8s-node1 ~]# cat myconfigmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: myconfigmap data: logging.conf: | class: logging.handlers.RotatingFileHandler formatter: precise level: INFO filename: %hostname-%timestamp.log
②查看ConfigMap
[root@k8s-node1 ~]# kubectl apply -f myconfigmap.yaml configmap "myconfigmap" created [root@k8s-node1 ~]# kubectl get configmap myconfigmap NAME DATA AGE myconfigmap 1 7s [root@k8s-node1 ~]# kubectl describe configmap myconfigmap Name: myconfigmap Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","data":{"logging.conf":"class: logging.handlers.RotatingFileHandler\nformatter: precise\nlevel: INFO\nfilename: %hostname-%timestamp... Data ==== logging.conf: ---- class: logging.handlers.RotatingFileHandler formatter: precise level: INFO filename: %hostname-%timestamp.log Events: <none>
③Pod中使用ConfigMap
[root@k8s-node1 ~]# cat pod_configmap.yaml apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: busybox args: - /bin/sh - -c - sleep 10; touch /tmp/healthy;sleep 30000 volumeMounts: - name: foo mountPath: "/etc" #将volume mount到容器 volumes: - name: foo configMap: name: myconfigmap items: - key: logging.conf path: myapp/logging.conf #在volume中指定存放配置信息的文件相对路径为myapp/logging.cnf
④创建Pod并读取配置信息
[root@k8s-node1 ~]# kubectl apply -f pod_configmap.yaml pod "mypod" created [root@k8s-node1 ~]# kubectl exec -it mypod /bin/sh / # cat /etc/myapp/logging.conf class: logging.handlers.RotatingFileHandler formatter: precise level: INFO filename: %hostname-%timestamp.log / #
结论:配置信息已保存到/etc/myapp/logging.conf文件中,与Secret一样,Volume形式的ConfigMap也支持动态更新。
成功最有效的方法就是向有经验的人学习!