14.实践篇:Secret资源深度剖析
14.实践篇:Secret资源深度剖析
Secret解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。
1.What is Secret?
kubernetes的secret对象可以让你存储和管理敏感信息,如密码、oauth token和ssh keys。把这些信息配置到secret里面会比在pod spec中定义更安全和灵活。
如果有兴趣,你还可以参考阅读secret的设计目的(https://git.k8s.io/community/contributors/design-proposals/auth/secrets.md)。
2.如何创建一个Secret
你同样可以采用命令行和yaml配置文件的方式,来创建一个secret。
2.1.命令行方式
kubectl create secret [TYPE] [NAME] [DATA]
你需要注意secret资源有以下三种[TYPE]类型:
1>docker-registry:创建一个给Docker registry容器镜像仓库使用的secret
2>generic: 从本地file, directory或者literal value创建一个 secret(这是大多数情况使用的)
3>tls: 创建一个TLS secret
[DATA]和我们上一节将configmap一样,也可以细分为--from-literal和--from-file
2.2.yaml配置文件方式
apiVersion: v1 kind: Secret type: Opaque data: username: YWRtaW4= stringData: username: administrator
以上就是secret定义的核心配置,你需要额外注意的是type字段,其值为Opaque,对应我们上面提及的generic类型
Opaque:base64编码格式的Secret,用来存储密码、密钥等;
你可以通过以下命令进行secret配置字段的查看
kubectl explain secret
3.通过生成器创建一个Secret
除了命令行和yaml方式创建之外,从v1.14版本开始,kubectl支持通过使用Kustomize来管理对象,你同样可以使用他的generators来创建一个secret,并且在apiserver上将其运行起来。
1)首先,generators需要配置一个kustomization.yaml文件,对于上面的例子,我们可以这样来申明:
# Create a kustomization.yaml file with SecretGenerator cat <<EOF >./kustomization.yaml secretGenerator: - name: db-user-pass files: - username.txt - password.txt EOF
2)如果你没有相关的txt文件,别忘了生成一份
[root@centos-1 tmp]# kubectl apply -k . secret/db-user-pass-96mffmfh4k created
3)接着,我们使用-k参数来申明
[root@centos-1 tmp]# kubectl apply -k .secret/db-user-pass-96mffmfh4k created
4)此时你可以看到如下信息的secret:
[root@centos-1 tmp]# kubectl get secrets NAME TYPE DATA AGE db-user-pass-96mffmfh4k Opaque 2 47s default-token-4fl6p kubernetes.io/service-account-token 3 39d [root@centos-1 tmp]# kubectl describe secrets/db-user-pass-96mffmfh4k Name: db-user-pass-96mffmfh4k Namespace: default Labels: <none> Annotations: Type: Opaque Data ==== password.txt: 12 bytes username.txt: 5 bytes
5)你也可以通过kustomize来申明一个literals的类型:
cat <<EOF >./kustomization.yaml secretGenerator: - name: db-user-pass literals: - username=admin - password=secret EOF [root@centos-1 tmp]# kubectl apply -k . secret/db-user-pass-4mf9kckdb5 created
注意:secret名是根据文本内容hash计算出来的,这得以保证每次可以得到一个修改后的文本内容
4.编辑一个Secret
你同样可以使用edit命令编辑一个secret,里面的信息修改后保存即可:
kubectl edit secrets mysecret
5.申明对照表
虽然我们上面提到,secret也可以通过--from-literal和--from-file来申明,但是对于三种不同类型[TYPE]的secret,还是有一些区分的,具体参见下面的表格:
TYPE类型 | 申明方式 |
---|---|
docker-registry | --docker-username,--docker-password,--docker-email |
generic | --from-literal和--from-file |
tls | --cert--key |
6.如何使用一个Secret
secret的使用也是会因为使用类型不同而不同的,下面我会有一个详细的explain API的表格,可以帮助你更好地学习:
TYPE类型 | 使用方式 |
---|---|
docker-registry | spec.imagePullSecrets <[]Object> |
docker-registry | ServiceAccount |
generic和tls | spec.containers.env.valueFrom.secretKeyRef |
generic和tls | spec.containers.envFrom.secretRef |
generic和tls | spec.volumes.secret.secretName/items |
注意:通过使用 kubectl explain <使用方式>就可以查到对应的配置字段的要求了。
理论部分已经讲完,接下来我们将以generic类型进行实战讲解
secret资源同样提供了以env和volume的两种方式进行载入,我们来看一下吧
7.实战:以环境变量方式载入Secret
1) 首先,创建所需的文本文件username.txt和password.txt
echo -n 'admin' > ./username.txt echo -n '1f2d1e2e67df' > ./password.txt
2) 创建generic类型的secret,名字为db-user-pass,并从刚才的两个文件中载入
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
3) 观察secret情况,观察相关信息是否被成功载入
[root@centos-1 mainfasts]# kubectl get secrets/db-user-pass -o yaml apiVersion: v1 data: password.txt: MWYyZDFlMmU2N2Rm username.txt: YWRtaW4= kind: Secret metadata: creationTimestamp: "2019-12-05T07:39:02Z" name: db-user-pass namespace: default resourceVersion: "10014" selfLink: /api/v1/namespaces/default/secrets/db-user-pass uid: 6b15c821-5975-405f-9144-0c1fbaa1e341 type: Opaque
注意:secret中的信息是通过base64进行编码的
4) 我们可以尝试使用base64解码配置文件中的对应信息,来验证上面的说法是否正确
[root@centos-1 mainfasts]# echo YWRtaW4=|base64 -d admin [root@centos-1 mainfasts]# echo MWYyZDFlMmU2N2Rm|base64 -d 1f2d1e2e67df
5) 接着,编辑redis-secretenv-demo.yaml,让他读取我们创建的名为db-user-pass的secret,并且将变量名username.txt的值赋值给SECRET_USERNAME的环境变量,以及password.txt赋值给SECRET_PASSWORD。别忘了使用apply -f生效这个配置文件。
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: db-user-pass key: username.txt - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: db-user-pass key: password.txt restartPolicy: Never
6) 随后,进入Pod的交互式接口模式,观察secret变量载入情况。
你可以发现我们传递的变量已经成功读取到了。
[root@centos-1 secret]# kubectl exec -it secret-env-pod -- /bin/sh # printenv KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_SERVICE_PORT=443 HOSTNAME=secret-env-pod REDIS_DOWNLOAD_SHA=61db74eabf6801f057fd24b590232f2f337d422280fd19486eca03be87d3a82b HOME=/root SECRET_PASSWORD=1f2d1e2e67df TERM=xterm KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_PROTO=tcp SECRET_USERNAME=admin REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-5.0.7.tar.gz KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 REDIS_VERSION=5.0.7 GOSU_VERSION=1.11 KUBERNETES_SERVICE_HOST=10.96.0.1 PWD=/data
8.实战:以存储卷方式载入Secret
1) 我们重新编辑redis-secretfiles-volumes,新增一个secret类型的volumes叫做secret-volume,我们把他挂载到pod容器的"/etc/secret-volume"目录,并且期望变量名改为username,而不是username.txt。
apiVersion: v1 kind: Pod metadata: name: secret-dotfiles-pod spec: volumes: - name: secret-volume secret: secretName: db-user-pass items: - key: username.txt #secrets中key的名字 path: username #希望映射在Pod中的名字 - key: password.txt path: password containers: - name: dotfile-test-container image: redis volumeMounts: - name: secret-volume readOnly: true mountPath: "/etc/secret-volume"
2) apply -f之后,我们还是进入pod的交互式接口模式,发现/etc/secret-volume中已经生成对应的配置文件。并且文件名也已经成功替换映射过来了,是username而不是username.txt。
[root@centos-1 secret]# kubectl exec -it secret-dotfiles-pod -- /bin/sh # cd /etc/secret-volume # ls password username # cat password 1f2d1e2e67df # cat username admin#
@版权声明:51CTO独家出品,未经允许不能转载,否则追究法律责任