应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名、密码。将这些信息直接保存在容器镜像中显然不妥,Kubernetes提供的解决方案是Secret。Secret会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。
Secret会以Volume的形式被mount到Pod,容器可通过文件的方式使用Secret中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。Secret可通过命令行或YAML创建。
创建Secret
(1)通过--from-literal:
[root@master pods]# kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456
secret/mysecret created
(2)通过--from-file:
[root@master pods]# echo -n admin > ./username
[root@master pods]# echo -n 123456 > ./password
[root@master pods]# kubectl create secret generic mysecret --from-file=./username --from-file=./password
error: failed to create secret secrets "mysecret" already exists
(3)通过--from-env-file:
[root@master pods]# cat << EOF > env.txt
> username=admin
> password=123456
> EOF
[root@master pods]# kubectl create secret generic mysecret --from-env-file=env.txt
error: failed to create secret secrets "mysecret" already exists
(4)通过YAML配置文件:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
username: YWRtaW4=
password: MTIzNDU2
或
apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: dev
type: Opaque
stringData:
username: admin
password: 123456
使用data,文件中的敏感数据必须是通过base64编码后的结果;使用strinData,可以写明文
[root@master ~]# echo -n admin | base64
YWRtaW4=
[root@master ~]# echo -n 123456 | base64
MTIzNDU2
查看Secret
如果要查看value,通过kubectl edit secret mysecret
,将其base64解码即可
[root@master ~]# kubectl edit secret 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:
creationTimestamp: "2022-08-01T06:15:53Z"
name: mysecret
namespace: default
resourceVersion: "549320"
uid: 30646142-6f2b-40f6-88fe-03fcf5305f18
type: Opaque
[root@master ~]# echo MTIzNDU2 | base64 --decode
123456[root@master ~]#
在Pod中使用Secret
Pod可以通过Volume或者环境变量的方式使用Secret。
Volume方式
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
[root@master ~]# kubectl apply -f mypod.yml
pod/mypod created
[root@master ~]# kubectl exec -it mypod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /etc/foo/
/etc/foo # ls
password username
/etc/foo # cat username
admin/etc/foo # cat password
123456/etc/foo #
可以看到,Kubernetes会在指定的路径/etc/foo下为每条敏感数据创建一个文件,文件名就是数据条目的Key,这里是/etc/foo/username和/etc/foo/password,Value则以明文存放在文件中。
以Volume方式使用的Secret支持动态更新:Secret更新后,容器中的数据也会更新。
将secret配置文件中密码改为123(base64编码后)
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
username: YWRtaW4=
password: MTIz
[root@master ~]# kubectl apply -f secret.yml
Warning: resource secrets/mysecret is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
secret/mysecret configured
[root@master ~]# kubectl exec -it mypod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /etc/foo/
/etc/foo # ls
password username
/etc/foo # cat password
123/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
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
[root@master ~]# kubectl exec mypod -it sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
123
/ #
通过环境变量SECRET_USERNAME和SECRET_PASSWORD成功读取到Secret的数据。
需要注意的是,环境变量读取Secret很方便,但无法支撑Secret动态更新。
ConfigMap
Secret可以为Pod提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以用ConfigMap。
ConfigMap的创建和使用方式与Secret非常类似,主要的不同是数据以明文的形式存放。
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
logging.conf: |
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: %hostname-%timestamp.log
注意,别漏写了Key logging.conf后面的|符号
创建并查看ConfigMap
[root@master ~]# kubectl apply -f configMap.yml
configmap/myconfigmap created
[root@master ~]# kubectl get configmap myconfigmap
NAME DATA AGE
myconfigmap 1 32s
[root@master ~]# kubectl describe configmap myconfigmap
Name: myconfigmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
logging.conf:
----
class: logging.handlers.RotatingFileHandler
formatter: precise
level: INFO
filename: %hostname-%timestamp.log
BinaryData
====
Events: <none>
在Pod中使用ConfigMap示例
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap
namespace: dev
data:
info:
username:admin
password:123456
apiVersion: v1
kind: Pod
metadata:
name: pod-configmap
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
volumeMounts:
- mountPath: /configmap/config
name: config
volumes:
- name: config
configMap:
name: configmap