k8s中的Secret
k8s中的secret用于保存敏感信息,例如service account、密码、docker拉取镜像的凭证等。pod使用secret方式和configMap类型,环境变量和挂载。
k8s中的Secret
1. 背景
Secret
对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在secret中比放在 Pod 的定义、容器镜像中、相对于ConfigMap
说更加安全和灵活。 Secret
是标准的k8s资源对象,使用方法和ConfigMap
非常类似。同时我们可以对Secret
进行访问控制,防止机密数据被访问
2. 概念
Secret
有三种类型:
- Service Account:Pod中的进程用来访问Kubernetes API的凭证,由Kubernetes自动创建,也可以手动创建。当在资源清单的定义中引用自定义的Service Account,如果没有引用,会使用当前namespace下默认的ServiceAccount,并且会自动挂载到容器的
/run/secrets/kubernetes.io/serviceaccount
路径下。有关ServiceAccount
的详细内容可以查看k8s中的访问控制。 - Opaque:base64编码格式的Secert,用来存储密码、密钥等。该数据是key:value类型的。
- kubernetes.io/dockerconfigjson:用来存储私有
docker registry
的认证信息。
3. 创建Secret
3.1 命令行的方式创建Secret
查看创建命令
[root@k8s-master01 secret]# kubectl create secret --help
Create a secret using specified subcommand.
Available Commands:
docker-registry 创建一个给 Docker registry 使用的 secret
generic 从本地 file, directory 或者 literal value 创建一个 secret 本质上是Opaque类型的Secret
tls 创建一个 TLS secret
可以创建3中类型的Secret
:1. docker拉取镜像的凭证、2. base64加密的密文 、3. ca证书的密文
3.1.1 命令行创建Opaque类型的Secret
查看创建Opaque类型的Secret命令帮助
[root@k8s-master01 secret]# kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--from-env-file=source] [--dry-run] [options]
和使用命令行创建ConfigMap
的命令类似。支持从文件夹、单个文件、key=value类型的文件、键值对等方式创建Secret
。
解释说明:
- 使用
--from-file
的方式,文件中的数据不用使用base64加密。和ConfigMap类似,如果不指定key的名称,默认使用文件名。 - 使用
--from-literal
。使用key1=value1的方式,value1不用base64加密,但是需要使用’'单引号括起来进行反转义。 - 其余和
ConfigMap
基本一致,这里不再赘述。
案例演示:
我们可以将连接mysql数据库的用户名和密码使用Secret
保存起来
# 创建本例中要使用的文件
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
kubectl create secret
命令将这些文件打包到一个 Secret
中并在 API server 中创建了一个对象。
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
输出:
secret/db-user-pass created
查看一下刚才创建的Secret
使用yaml的方式查看kubectl get secret db-user-pass -o yaml
apiVersion: v1
data:
password.txt: MWYyZDFlMmU2N2Rm
username.txt: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2020-09-16T09:13:12Z"
name: db-user-pass
namespace: default
resourceVersion: "35680"
selfLink: /api/v1/namespaces/default/secrets/db-user-pass
uid: 2ecf89d5-bdaf-4b91-ac45-d568061e8e52
type: Opaque
这里我们可以看到data的key是文件名,value是使用base64加密后的密文。
使用base64解密查看。
echo YWRtaW4= | base64 -d
admin
使用命令行创建的generic类型的其实是Opaque类型的。
3.1.2 命令行创建docker registry类型的Secret
命令如下:
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
该Secret
的作用是在kubelet拉取镜像的时候,如果该镜像需要认证,该Secret
可以作为拉取镜像的凭证。在pod.spec.imagePullSecrets
可以引用创建的Secret
3.2 yaml文件的方式创建Secret
例如需要将用户名:admin和密码:1f2d1e2e67df放入到Secret
中
先将其进行base64加密
echo -n 'admin' | base64
=> YWRtaW4=
echo -n '1f2d1e2e67df' | base64
=> MWYyZDFlMmU2N2Rm
编写yaml文件 secret1.yaml
apiVersion: v1
kind: Secret
metadata:
name: secret1
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
创建kubectl apply -f secret1.yaml
4. 使用Secret
4.1 将Secret挂在到Volume下,且键名映射到特定路径
在 Pod 中使用存放在卷中的 Secret:
- 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。
- 将
spec.containers[].volumeMounts[]
加到需要用到该 Secret 的容器中。 指定spec.containers[].volumeMounts[].readOnly = true
和spec.containers[].volumeMounts[].mountPath
为你想要该 Secret 出现的尚未使用的目录。 - 修改你的 Pod 定义,在
spec.volumes[]
下增加一个卷。可以给这个卷随意命名, 它的spec.volumes[].secret.secretName
必须是Secret
对象的名字。 - 修改你的镜像并且/或者命令行,让程序从该目录下寻找文件。
Secret
的 data 映射中的每一个键都对应mountPath
下的一个文件名。 - 如果想要使用
Secret
中的某些key,且想要映射到特定路径下,类似于ConfigMap
使用items
案例演示:
资源清单 pod-secret-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: wangyanglinux/myapp:v1
imagePullPolicy: IfNotPresent
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
创建Secret
。kubectl apply -f pod-secret-volume.yaml
查看Pod里面的容器的文件的数据。kubectl exec pod1 cat /etc/foo/my-group/my-username
=> admin
可以看到Secret里面的数据被加载到/etc/foo/my-group/my-username
文件下。/etc/foo/
是挂载的路径,my-group/my-username
是定义的子路径和文件名。文件的内容已经base64解密过了。
4.2 挂载的 Secret 会被自动更新
当已经存储于卷中被使用的 Secret 被更新时,被映射的键也将终将被更新。 组件 kubelet 在周期性同步时检查被挂载的 Secret 是不是最新的。 但是,它会使用其本地缓存的数值作为 Secret 的当前值。
4.3 以环境变量的形式使用 Secrets
在Pod.spec.containers
下使用env
或者是envFrom
将Secret
中的数据加载到容器的环境变量中。env
和envFrom
和引用ConfigMap
类似。
使用env
方式的资源清单。pod-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-test-env
spec:
containers:
- name: test
image: busybox
imagePullPolicy: IfNotPresent
command:
- env
env:
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
restartPolicy: Never
envFrom:
- secretRef:
name: mysecret
key: password
创建Pod kubectl apply -f pod-env.yaml
。
查看日志数据:kubectl logs pod-test-env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=pod-test-env
PASSWORD=123456
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
HOME=/root
这里就不演示envFrom
了,是类似的方式。
5. Secret和ConfigMap对比
相同点:
- key/value的形式
- 属于某个特定的namespace
- 可以导出到环境变量
- 可以通过目录/文件形式挂载(支持挂载所有key和部分key)
不同点:
- Secret可以被ServerAccount关联(使用)
- Secret可以存储register的鉴权信息,用在ImagePullSecret参数中,用于拉取私有仓库的镜像
- Secret支持Base64加密
- Secret分为
kubernetes.io/Service Account
,kubernetes.io/dockerconfigjson
,Opaque
三种类型,Configmap不区分类型 - Secret文件存储在tmpfs文件系统中,Pod删除后Secret文件也会对应的删除。这里删除的是Secret的副本
更多推荐
所有评论(0)