为了使保存在Kubernetes中的敏感数据能够被加密存储,我们需要介绍Kubernetes平台上一种叫EncryptionConfiguration的对象,在这个对象中,我们可以配置具体需要加密存储的对象信息,比如可以是Secret对象,也可以是任何Kubernetes支持的对象类型。除了这个EncryptionConfiguration对象之外,我们还需要指定秘钥提供者信息,比如笔者在上篇文章介绍的KMS秘钥管理系统,用来提供加密的算法,以及秘钥等信息。
笔者在前边的文章中多次详细的介绍过当我们执行kubectl apply命令背后发生的系统行为,具体来说,kubectl会将用户输入的YAML文件解析后,调用API Server上对应的API将数据发给Master Node,然后Master node进一步对数据进行验证,处理之后,最终会持久化到etcd数据库中,这里大家要注意的是,如果我们要对数据进行加密,这个加密的过程发生在kube-apiserver这个组件上。
如果我们开启加密功能,那么每次我们通过kubectl apply将YAML文件发送到Master Node之后,kube-apiserver组件将加密的任务委托给加密组件,然后将返回的密文保存到etcd数据库中持久化。当敏感信息需要被读取使用的时候,密文会被加密组件的解密模块自动解密,并返回给使用者。
因此用户的角度,这种在kube-apiserver发生的事情对开发和运维人员是透明的,因此开发人员的整个部署和系统管理不受影响。如下图所示:

通过上图可以看出,我们创建的Secret对象中包含的敏感数据在被保存到etcd之前会被加密,然后保存到etcd中的数据就是密文了。读者需要特别注意的点是,这个加密的过程其实发生在kube-apiserver这个组件上,虽然上图展示了单独的一层。
有了前边内容的铺垫,接下来我们先创建一个EncrytionConfiguration对象,来让Kubernetes对所有的Secret对象加密,加密使用aescbc算法以及手动配置了秘钥,如下图所示:

读者可以使用openssl rand -base64 32来生成秘钥,并替换上图中的secret的值。由于加密的过程发生在kube-apiserver上,因此我们必须把这个encryptionconfiguration文件保存到master node上。
在我们的minikube集群上,由于只有一个节点node,minikube既扮演了工作节点,也扮演了master节点,因此我们直接用熟悉的minikube ssh登陆到这台机器上。登陆成功后通过sudo -i切换到root权限。接着在minikube这台虚拟机的目录/var/lib/minikube/certs/下创建文件encryptionconfig.yaml,并把如下的内容贴进去:

在管理节点上创建好ec文件之后,接下来我们还需要最后一步,配置kube-apiserver进程来读取EncryptionConfiguration配置文件。由于我们的集群正在运行中,我们必须停止集群,然后启动的时候,使用命令行参数-extra-config来指定我们刚才创建的encryptionconfigration文件,minikube stop本地集群,然后运行如下命令。
minikube start --extra-config=apiserver.encryption-providerconfig=/var/lib/minikube/certs/encryptionconfig.yaml,待集群顺利启动后,我们可以来验证加密功能是否生效。如下图所示:

接下来我们从命令行创建一个新的Secret,运行命令:kubectl create secret generic db-secret-encrypted --from-literal=username=qiwangyue --from-literal=password=alicedanghter,secret对象被成功创建后,接下来我们来看看这个叫db-secret-encrypted的Secret对象的数据在etcd中长啥样。
具体如何直接访问etcd的步骤笔者就不重复了,当我们执行./etcdctl get /registry/secrets/default/db-secret-encrypted命令后,返回的数据如下所示:
➜ etcd-v3.4.14-darwin-amd64 ./etcdctl get /registry/secrets/default/db-secret-encrypted
cm < 9 * - ڂȮ~6I=@e.
8Y
tp b
Vw6̒lvEyq.^Znxh$d 놸1yQqLJј}ߧIw%;
如上所示,这样数据在etcd中就以密文的形式被保存了,如果恶意攻击者获取了ETCD的访问权限,从etcd中拿到的数据也无法获知具体的密码等信息,我们的数据就更加安全了。
看到这里,不知道读者是否发现了问题,这样难道真的安全吗?坦白讲,使用encryptionconfigration充其量只能让恶意攻击者获取敏感信息的难度加大,我们并没有彻底保证数据的安全,因为存放在管理节点上的ec文件/var/lib/minikube/certs/encryptionconfig.yaml,如果恶意攻击者获取了管理节点的访问权限,是可以拿到这个key,并基于从etcd获取的数据来解密获取明文,因此笔者才说使用ec充其量只是增加了恶意攻击者获取敏感信息的难度而已。
那我们应该怎么做呢?相信读者已经猜出来了,这就是我们下一篇文章要介绍的,把秘钥和加密后的数据分开到两台服务器上保存,敬请期待笔者的下篇文章!