Secret安全存储
我们上节课学习了Kubernetes 一个非常重要的对象ConfigMap ,一般情况下ConfigMap 如果涉及到一些安全相关数据,则用于存储一些不安全的配置信息ConfigMap 因为ConfigMap 它被称为存储,我们说这个时候我们就需要用到另外一个资源对象了:Secret , ,把这些信息放在里面Secret 中比放在Pod 定义中或docker 镜像更安全灵活。
Secret 有三种类型:
- Opaque: base64 编码格式的 Secret,用于存储密码、密钥等,但数据也可以通过base64 –decode对原始数据进行解码,所有加密性都很弱。
- kubernetes.io/dockerconfigjson:用于存储私有docker registry的认证信息。
- kubernetes.io/service-account-token:用于被serviceaccount引用,serviceaccout 创建时Kubernetes默认会创建相应的secret。Pod如果使用了serviceaccount,对应的secret自动挂载Pod目 录/run/secrets/kubernetes.io/serviceaccount 中。
Opaque 一种类型的数据 map 类型,要求value是base64 例如,创建用户名称的编码格式 admin,密码为 admin321 的 Secret 对象,首先,用户名和密码 base64 编码,
[root@k8s-master ~]# echo -n "fbw" | base64 ZmJ3 [root@k8s-master ~]# echo -n "fbw321" | base64 ZmJ3MzIx
编写上述编码后的数据YAML文件:
[root@k8s-master ~]# vim secret-demo.yaml apiVersion: v1 kind: Secret #类型 metadata: name: mysecret #secret名称 type: Opaque #secret类型 data: #数据 username: ZmJ3 #数据键值对,值是base64编码 password: ZmJ3MzIx #数据键值对,值是base64编码
创建并检查相应的secret
[root@k8s-master ~]# kubectl create -f secret-demo.yaml secret/mysecret created [root@k8s-master ~]# kubectl get secrets NAME TYPE DATA AGE default-token-whcrj kubernetes.io/service-account-token 3 10d mysecret Opaque 2 18s #您可以查看相应的名称mysecret的secret,secret类型Opaque
其中default-token-cty7pdefault-token-n9w2d 默认为创建集群而创建 secret,被serviceacount/default 引用。
使用describe命令查看细节
[root@k8s-master ~]# kubectl describe secrets mysecret Name: mysecret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 6 bytes #只能查看相应的字节数,不能查看原始数据 username: 3 bytes
可见使用describe命令查看Data如果你想看到它,它没有直接显示。Data里面的详细信息,同样我们可以输出成YAML查看文件:
[root@k8s-master ~]# kubectl get secret mysecret -o yaml apiVersion: v1 data: password: ZmJ3MzIx #可查看使用情况base64加密数据 username: ZmJ3
kind: Secret
metadata:
creationTimestamp: "2021-03-05T02:47:11Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {
}
f:password: {
}
f:username: {
}
f:type: {
}
manager: kubectl
operation: Update
time: "2021-03-05T02:47:11Z"
name: mysecret
namespace: default
resourceVersion: "62423"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: b9edff60-b5be-4016-8868-c2f0fc2ad77b
type: Opaque
查看到的内容可以进行base64解密:
[root@k8s-master ~]# echo ZmJ3MzIx | base64 -dsh
fbw321
#此时已经进行解密成功,显示出对应的密码
创建好Secret对象后,有两种方式来使用它:
- 以环境变量的形式
- 以Volume的形式挂载(存储都可以使用卷挂载)
环境变量方式演示
首先来测试下环境变量的方式,使用一个简单的busybox镜像来测试下:
[root@k8s-master ~]# vim secret1-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret1-pod
spec:
containers:
- name: secret1
image: busybox
command: [ "/bin/sh", "-c", "env" ] #打印环境变量
env: #定义环境变量
- name: USERNAME #定义环境变量的键
valueFrom: #以挂载的方式获取
secretKeyRef: #从secret中获取
name: mysecret #从secret名称为mysecret的文件中获取
key: username #mysecret的文件中获取环境变量的值
#整体意思:定义一个名称为USERNAME环境变量,值以挂载的方式获取,挂载secret中名称为mysecret中的username值
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
#同上只是键值对不同其他一样
上面环境变量中定义的secretKeyRef 关键字,和之前讲的configMapKeyRef是不是比较类似,一个是从 Secret 对象中获取,一个是从ConfigMap 对象中获取,创建上面的Pod :创建
[root@k8s-master ~]# kubectl create -f secret1-pod.yaml
pod/secret1-pod created
查看pod的日志中是否有对应的变量信息
[root@k8s-master ~]# kubectl logs secret1-pod |grep fbw
USERNAME=fbw
PASSWORD=fbw321
#可以查看到对应的环境变量
容器执行完命令就会退出,并且一直重启,可以通过查看状态查看
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
secret1-pod 0/1 CrashLoopBackOff 7 12m
验证Volume 挂载,创建一个Pod 文件:
[root@k8s-master ~]# vim secret2-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret2-pod
spec:
containers:
- name: secret2
image: busybox
command: ["/bin/sh", "-c", "ls -l /etc/secrets"]
volumeMounts: #挂载卷
- name: secrets #挂载卷名称
mountPath: /etc/secrets #挂载到容器中的路径
volumes: #创建卷
- name: secrets #创建的卷名称
secret: #把创建的secret创建成一个卷
secretName: mysecret #选择secret中的mysecret
#整体意思:将secrets中的名称为mysecret的创建为一个卷,并以卷的方式挂载到容器中的/etc/secrets这个路径
创建Pod :
[root@k8s-master ~]# kubectl create -f secret2-pod.yaml
pod/secret2-pod created
查看日志
[root@k8s-master ~]# kubectl logs secret2-pod
total 0
lrwxrwxrwx 1 root root 15 Mar 5 03:29 password -> ..data/password
lrwxrwxrwx 1 root root 15 Mar 5 03:29 username -> ..data/username
#此时已经以卷的方式挂载到容器内部
可以看到secret 把两个key挂载成了两个对应的文件。当然如果想要挂载到指定的文件上面,是不是也可以使用上一节课的方法**:在secretName 下面添加items指定 key 和 path挂载到指定路径**,这个大家可以参考上节课ConfigMap 中的方法去测试下。
除了上面的Opaque 这种类型外,还可以来创建用户docker registry认证的Secret (用于认证信息下载私有仓库的镜像),直接使用kubectl create命令创建即可,如下
[root@k8s-master ~]# kubectl create secret docker-registry myregistry --docker-server=DOCKER_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistry created
#参数解释:
# kubectl create secret:创建secret的关键命令
# docker-registry:创建的secret类型
# myregistry :创建的secret名称
# --docker-server=DOCKER_SERVER:表示仓库服务器地址
# --docker-username=DOCKER_USER:指定用户名
# --docker-password=DOCKER_PASSWORD:指定密码
# --docker-email=DOCKER_EMAIL:指定邮箱
例如:下载私有仓库中的镜像,(如果使用自动下载私有仓库中的镜像,不填写认证信息的话,下载镜像会报错,可以用此方法自动提交认证信息并下载私有仓库的镜像)
[root@server1 secret]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: nginx
image: 192.168.10.101:5000/test:v1 #此处指定私有镜像仓库的镜像
imagePullSecrets: #镜像下载密钥
- name: myregistry #使用的Secret名称
我们需要拉取私有仓库镜像192.168.1.100:5000/test:v1 ,我们就需要针对该私有仓库来创建一个如上的Secret ,然后在Pod 的 YAML 文件中指定imagePullSecrets 。
可以通过查看以输出yaml的方式详细信息,可以查看到data的详细信息
[root@k8s-master ~]# kubectl get secrets myregistry -o yaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0=
kind: Secret
metadata:
creationTimestamp: "2021-03-05T03:49:24Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:.dockerconfigjson: {}
f:type: {}
manager: kubectl
operation: Update
time: "2021-03-05T03:49:24Z"
name: myregistry
namespace: default
resourceVersion: "71645"
selfLink: /api/v1/namespaces/default/secrets/myregistry
uid: c42e0eea-8c2c-48bb-990b-63eb50619971
type: kubernetes.io/dockerconfigjson
上方查看到的信息可以进行base64进行解密
[root@k8s-master ~]# echo eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiVSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0= | base64 -d
#数出的结果是json格式的
{"auths":{"DOCKER_SERVER":{"username":"DOCKER_USER","password":"DOCKER_PASSWORD","email":"DOCKER_EMAIL","auth":"RE9DS0VSX1VTRVI6RE9DS0VSX1BBU1NXT1JE"}}}
注意看上面的TYPE类型, myregistry 是不是对应的kubernetes.io/dockerconfigjson ,可以使用describe命令来查看详细信息
[root@k8s-master ~]# kubectl describe secret myregistry
Name: myregistry
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Datas
====
.dockerconfigjson: 152 bytes #只能查看到字节数
另外一种Secret 类型就是kubernetes.io/service-account-token,用于被serviceaccount引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的secret会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount 目录中。这里我们使用一个nginx 镜像来验证一下。
[root@k8s-master ~]# kubectl run secret-pod3 --image nginx:1.7.9
pod/secret-pod3 created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
secret-pod3 1/1 Running 0 30s
[root@k8s-master ~]# kubectl exec secret-pod3 -- ls /run/secrets/kubernetes.io/serviceaccount
#进入容器内查看是否有证书文件
ca.crt
namespace
token
[root@k8s-master ~]# kubectl exec secret-pod3 -- cat /run/secrets/kubernetes.io/serviceaccount/token #查看token文件
eyJhbGciOiJSUzI1NiIsImtpZCI6Im1KbUotQV8zdlllUWVuX0JrNFppdDJGOTFXc21RNVhrOTJyYXZEbjJGZ2MifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4td2hjcmoiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImYwMjgyOWMyLTE3MzUtNDhlZC05NmM3LTA0Nzc5YzVhMWU1ZSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.DbHavECeu8XuOFCQjqhnr3RnE2gxuiHZsmQw3MIGbqiJROeyvlmFkqSJ0ad5Y_0dYgm73BhyQmCH43XkIeBLnHmQYUeUqkeidL3XVG2AWZupb-cAV4fwskSXVPrfwmkehXmmS7yB5abOG9VCtGxTD5K8lnVc6iLemhFYqcrQQgU8n7zQl5658tRA7_7hjHN8T_HVI1FPe4DFSsUb4tGJ7xOypL7QM0UolzZozg9OTPHsgzTVR0PwU9seL3yoqfLk28mPZ84_FxmBkGjoZ49BVrcYJrd9VrNwzE-Z7aZEGlZNf9vFV6_JX6bq-ZxcvRe8q5X2F3dXACzFPTsDIsF49Q
[root@k8s-master ~]# kubectl exec secret-pod3 -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
#查看所在命名空间
default
- key/value的形式
- 属于某个特定的namespace
- 可以导出到环境变量
- 可以通过目录/文件形式挂载
- 通过 volume 挂载的配置信息均可热更新
- Secret 可以被 ServerAccount 关联
- Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret参数中,用于拉取私有仓库的镜像
- Secret 支持 Base64 加密