应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥。将这些信息直接保存在容器镜像中显然不妥,Kubernetes 提供的解决方案是 Secret。
Secret 会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。Secret 会以 Volume 的形式被 mount 到 Pod,容器可通过文件的方式使用 Secret 中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。
创建Secret
有四种方法创建Secret
通过--from-literal
不建议使用,因为会在命令行中留下history
用户名为ammin,密码为123.com
[root@node1 ~]# kubectl create secret generic mysqlsecret --from-literal=username=admin --from-literal=password=123.com
通过--from-file
虽然是通过文件但依然有风险
[root@node1 ~]# echo -n amdin > ./username
[root@node1 ~]# echo -n 123.com > ./password
[root@node1 ~]# kubectl create secret generic mysqlsecret --from-file=./username \
--from-file=./password
通过--from-env-file
和上一种方法类似
[root@node1 ~]# vim env
username=admin
password=123.com
[root@node1 ~]# kubectl create secret generic mysqlsecret --from-env-file=env
通过K8s的Yaml配置文件
推荐使用
提前在某台主机或者虚拟主机生成一个加密的用户名和密码
$ echo -n admin | base64
YWRtaW4=
$ echo -n 123.com | base64
MTIzLmNvbQ==
编写文件
[root@node1 ~]# vim mysecret.yml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
username: YWRtaW4=
password: MTIzLmNvbQ==
创建secret
[root@node1 ~]# kubectl apply -f mysecret.yml
secret/mysecret created
查看secret
[root@node1 ~]# kubectl get secrets
NAME TYPE DATA AGE
default-token-zqqh6 kubernetes.io/service-account-token 3 45h
mysecret Opaque 2 60s
通过详情可以看到创建的两条加密项
[root@node1 ~]# kubectl describe secrets mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations:
Type: Opaque
Data
====
username: 5 bytes # 用户名admin,5个字节
password: 7 bytes # 密码123.com,7个字节
如果想看在yaml文件中设置的值的话
[root@node1 ~]# kubectl edit secrets mysecret
...
data:
password: MTIzLmNvbQ==
username: YWRtaW4=
...
解码加密项
前提是需要知道使用什么加密的
[root@node2 ~]# echo -n YWRtaW4= | base64 --decode
admin
[root@node2 ~]# echo -n MTIzLmNvbQ== | base64 --decode
123.com
Volume使用Secret
编写一个Pod文件
[root@node1 ~]# vim mypod.yml
apiVersion: v1
kind: Pod
metadata:
name: testsecret
spec:
containers:
- name: test
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 3000000
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: True
volumes:
- name: foo
secret:
secretName: mysecret # 上面运行过的secret的name
因为之前的secret在写入data项的时候是以
key: value
的形式写入,key为文件名,value为文件内容
运行Pod
[root@node1 ~]# kubectl apply -f mypod.yml
pod/testsecret created
进入容器查看挂载目录
[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # ls /etc/foo
password username
/ # cat /etc/foo/username
admin
/ # cat /etc/foo/password
123.com
自定义Secret的key
[root@node1 ~]# vim mypod.yml
apiVersion: v1
kind: Pod
metadata:
name: testsecret
spec:
containers:
- name: test
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 3000000
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: True
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
# 将mysecret中的key(username)改为/etc/foo/mygroup/my-username
path: mygroup/my-username
- key: password
path: mygroup/my-password
将Pod删除,重新运行Pod
[root@node1 ~]# kubectl apply -f mypod.yml
pod/testsecret created
进入容器查看
[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # ls /etc/foo
mygroup
/ # ls /etc/foo/mygroup/
my-password my-username
动态更新volume方式的Secret
以 Volume 方式使用的 Secret 支持动态更新:Secret 更新后,容器中的数据也会更新。
尝试修改一个密码
$ echo -n 123456 | base64
MTIzNDU2
修改yml文件
[root@node1 ~]# vi mysecret.yml
password: MTIzNDU2
重新运行一遍secret
[root@node1 ~]# kubectl apply -f mysecret.yml
secret/mysecret configured
需要等待1-2分钟后
进入容器查看密码
[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # cat /etc/foo/mygroup/my-password
123456
使用变量的Secret
先将之前的pod删除
[root@node1 ~]# kubectl delete -f mypod.yml
pod "testsecret" deleted
修改yml文件
[root@node1 ~]# vim mypod.yml
apiVersion: v1
kind: Pod
metadata:
name: testsecret
spec:
containers:
- name: test
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 3000000
# volume内容全部替换为以下内容
env:
- name: SECRET_USERNAME # 变量名
valueFrom: # 变量值来自于secret中的mysecret的username的值
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD # 变量名
valueFrom: # 变量值来自于secret中的mysecret的password的值
secretKeyRef:
name: mysecret
key: password
运行Pod
[root@node1 ~]# kubectl apply -f mypod.yml
pod/testsecret created
进入容器验证变量
[root@node1 ~]# kubectl exec -it testsecret -- sh
/ # echo $SECRET_USERNAME
admin
/ # echo $SECRET_PASSWORD
123456
需要注意的是,环境变量读取 Secret 很方便,但无法支撑 Secret 动态更新。
Secret 可以为 Pod 提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以用 ConfigMap。请看下篇文档