在kubernetes中,secret对象类型主要目的是 保存一些私密数据,比如密码,OAuth tokens,ssh keys等信息。将这些信息放在secret对象中 比 直接放在pod或docker image中更安全,也更方便使用。
secrets描述
创建secrets对象的方式有两种,一种是用户手动创建,另一种是集群自动创建。
一个已经创建好的secrets对象有两种方式被pod对象使用,其一,在container中的volume对象里以file的形式被使用,其二,在pull images时被kubelet使用。
为了使用secret对象,pod必须‘引用’这个secret,同样可以手动或者自动来执行‘引用’操作。
自动建立ServiceAccount && 使用secret API
kubernetes会自动创建包含证书信息的secret,并且使用它来访问api,kubernetes也将自动修改pod来使用这个secret。
自动创建的secret 以及 所使用的api证书 可以根据需要disable 或者 覆盖。如果仅仅需要 安全访问apiserver,那么上述的流程是推荐的方式。
手动创建secret
以下是一个简单secret对象的例子:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMQ0K
数据中的字段为map类型。其中keys必须符合dns_subdomain规则,values可以为任意类型,使用base64编码。上述例子中,username和password的数据值在base64编码前的值为value-1 和 value-2。
一旦secret被创建,可以:
- 通过ServiceAccount使用它自动创建pod;
- 修改pod来使用secret;
手动为pod绑定secret
以下是一个例子,绑定secret到一个pod的volume:
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "mypod",
"namespace": "myns"
},
"spec": {
"containers": [{
"name": "mypod",
"image": "redis",
"volumeMounts": [{
"name": "foo",
"mountPath": "/etc/foo",
"readOnly": true
}]
}],
"volumes": [{
"name": "foo",
"secret": {
"secretName": "mysecret"
}
}]
}
}
注意,必须有spec.volumes才能使用secret。
如果一个pod中有多个container,每个container需要他们单独对应的volumeMounts ,但是一个secret只能对应一个spec.volumes。
只要需要,可以将许多文件打包进一个secret,或者使用多个secret。
手动指定imagePullSecret
详细信息见:images documentation
Details
限制
在使用之前,secret volume 资源被验证,以确保指定的对象引用真是指向一个secret对象。因此,在pod使用它之前必须保证需要的secret被成功创建。
secret api对象从属于namespace,一个secret对象只能被同namespace的pod所使用。
单个secret限制在1Mb之内,防止过大的secret耗尽apiserver & kubelet的内存。然而,创建许多类似的secret同样也会无用的消耗掉apiserver&kubelet的内存。
kubelet目前只支持pod使用来自于apiserver的secret。pods包括了被 kubectl创建的pod 或者 被replication controller间接创建的。
Consuming Secret Values
在一个绑定了secret的container中,会以secret keys为名的文件,其内容为secret value的base64 decode后的内容。下面是上述例子的输出:
$ ls /etc/foo/
username
password
$ cat /etc/foo/username
value-1
$ cat /etc/foo/password
value-2
container中的程序可以读取其中的文件来获取其内容。
Secret 与 Pod Lifetime 关系
当通过api创建一个pod后,不会去检查所引用的secret是否存在。一旦这个pod被使用,kubelet将会尝试去获取引用的secret的值。如果这个secret不存在,或者kubelet暂时链接不上apiserver,kubelet将会定期重试,并发送一个event来解释pod没有启动的原因。如果获取到了对应的secret,kubelet将会创建对应的volume并绑定到container。
一旦kubelet创建了一个pod,则container使用的相关secret volume不会在改变,即使对应的secret对象被修改。如果为了改变使用的secret,则必须删除旧的pod,并重新创建一个新的pod。
User Case
Use-Case: Pod with ssh keys
pod通过secret来使用ssh-key,首先得先创建对应的secret:
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "ssh-key-secret"
},
"data": {
"id-rsa": "dmFsdWUtMg0KDQo=",
"id-rsa.pub": "dmFsdWUtMQ0K"
}
}
Note:其中secret的data数据经过base64编码,不包含换行符。
现在我们能创建使用这个secret的pod:
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "secret-test-pod",
"labels": {
"name": "secret-test"
}
},
"spec": {
"volumes": [
{
"name": "secret-volume",
"secret": {
"secretName": "ssh-key-secret"
}
}
],
"containers": [
{
"name": "ssh-test-container",
"image": "mySshImage",
"volumeMounts": [
{
"name": "secret-volume",
"readOnly": true,
"mountPath": "/etc/secret-volume"
}
]
}
]
}
}
当这个pod中的container运行后,将会有如下两个文件及对应的内容:
/etc/secret-volume/id-rsa.pub
/etc/secret-volume/id-rsa
现在container可以用这个secret数据来建立ssh连接。
Use-Case: Pods with prod / test credentials
下面的例子将会展示 一个pod使用包含prod环境证书的secret对象,另一个pod使用包含test环境证书的secret对象:
secret对象:
{
"apiVersion": "v1",
"kind": "List",
"items":
[{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "prod-db-secret"
},
"data": {
"password": "dmFsdWUtMg0KDQo=",
"username": "dmFsdWUtMQ0K"
}
},
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "test-db-secret"
},
"data": {
"password": "dmFsdWUtMg0KDQo=",
"username": "dmFsdWUtMQ0K"
}
}]
}
建立pods:
{
"apiVersion": "v1",
"kind": "List",
"items":
[{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "prod-db-client-pod",
"labels": {
"name": "prod-db-client"
}
},
"spec": {
"volumes": [
{
"name": "secret-volume",
"secret": {
"secretName": "prod-db-secret"
}
}
],
"containers": [
{
"name": "db-client-container",
"image": "myClientImage",
"volumeMounts": [
{
"name": "secret-volume",
"readOnly": true,
"mountPath": "/etc/secret-volume"
}
]
}
]
}
},
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "test-db-client-pod",
"labels": {
"name": "test-db-client"
}
},
"spec": {
"volumes": [
{
"name": "secret-volume",
"secret": {
"secretName": "test-db-secret"
}
}
],
"containers": [
{
"name": "db-client-container",
"image": "myClientImage",
"volumeMounts": [
{
"name": "secret-volume",
"readOnly": true,
"mountPath": "/etc/secret-volume"
}
]
}
]
}
}]
}
建立的两个pod都拥有两个文件:
/etc/secret-volume/username
/etc/secret-volume/password
可以使用service accounts来简化上述的流程,一个是prod-user对应prod-db-secret,另一个是test-user对应test-db-secret,如:
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "prod-db-client-pod",
"labels": {
"name": "prod-db-client"
}
},
"spec": {
"serviceAccount": "prod-db-client",
"containers": [
{
"name": "db-client-container",
"image": "myClientImage",
}
]
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。