
kubernete编排技术七:secret
作者 | 朱晋君
来源 | 君哥聊技术(ID:gh_1f109b82d301)
在前面文章中,我们讲RBAC的时候提到了secret,kubernetes中的secret对象用来保存一些敏感信息,比如密码、token、ssh key等。相比于这些敏感信息存放在pod声明或者容器镜像,secret对象保存的方式更加灵活和安全。
创建secret
创建secret方式有多种,下面介绍5种创建方式,无论哪种方式,都需要在定义yaml文件的时候,把kind定义为secret。
1.双引号引用常量字符创
使用这种方式我们创建这个对象:
创建成功后我们查看一下这个对象的详情:
2.不加双引号需要使用base64转码后的值
3.把引号引用的字符串放在配置文件里面,部署的时候动态地替换,如下,可以在创建这个对象之前替换username和password
4.使用generator来创建,这时我们需要在目录下提前生成这2个文件,如下:
使用这种方式创建这个对象:
这时我们查看这个对象的describe,结果如下:
5.使用literals(字面量)来创建,这个创建命令跟4一样
使用secret
secret可以作为数据卷挂载在pod中的容器上,也可以作为环境变量暴露给pod中的容器。
1.作为pod中的文件
创建这个pod后,我们进入查看,如下:
可以看到这个secret对象以文件的方式挂载在了容器里。
注意:上面的defaultMode: 0400是配置secret生成的文件的访问权限,如果不配置默认是0644,创建pod后,看如下输出:
2.把不同的key放到不同的路径
下面我们编写yaml文件my-secret-pod2.yaml 如下:
我们创建这个pod:
创建成功后我们查看key存放的路径:
3.使用secret作为环境变量
看下面在这个yaml文件my-secret-pod3.yaml
创建这个pod:
进入pod查看环境变量,如下所示:
可以看到,username和password这2个参数已经正确配置到容器中的环境变量。
secret更新
当已经挂载使用的secret被更新时,projected key也最终会被更新。kubelete会周期性地检查secret是否被更新。但是kubelete获取secret的值是从缓存中获取的,secret更新的时候,更新缓存有2种机制,默认使用基于ttl的watch机制,还有一种方式就是把请求直接重定向到api server。因此secret更新的时候,总会有一个延迟时间,这个延迟时间等于kubelete检查更新的周期时间加上刷新缓存的时间。同时要注意:使用子路径挂载secret方式的容器是无法更新secret的。
所以kubernete v1.18版本引入了不可更新的Secrets和ConfigMaps,这样Secrets和ConfigMaps就是不能更新的,如果要更新,只能删除重建。对于有成千上万secret的集群来说,这有2个好处:
- 防止因为更新secret而导致的意外程序中断;
- 关闭kubelete对secret的watch机制,可以减轻kube-apiserver的负载,让集群性能更好。
如下面这个secret的声明,只要定义immutable是true就可以让secret变成不可更新。
使用secret注意事项
1.pod使用secret时必须先成功创建secret,然后才能创建pod,否则pod创建失败。
2.只有secret和pod使用同一个namespace,pod才能使用这个secret。
3.单个secret内存必须小于1M,因此不建议创建很大的secret,因为这会消耗api server和kubelete的内存。不过创建非常多的小的secret也会消耗很大的内存。
4.kubelete只支持用kubectl创建的pod,或者通知控制器复制的pod使用secret,其他方式创建的pod不能使用secret。
5.作为容器中环境变量的使用,如果secretKeyRef字段依赖的key在secret中不存在,pod将创建失败。
6.作为容器中环境变量的使用,如果环境变量名使用envFrom字段来声明(如下代码),这时如果环境变量名不合法,就会被跳过,但是pod可以正常启动。启动后可以通过下面命令来查看被跳过的环境变量:
总结
在secret中保存一些敏感信息确实比较灵活和安全,但也有一些限制,最好把secret设置为不可修改的。
secret的使用主要还是在访问控制中,比如上篇文章讲的RBAC,在多数场景下,我们使用ServiceAccount作为用户,系统会为我们创建默认的secret。
