在Kubernetes平台上,Secret这个对象并不安全,如前边文章所述,并且Kubernetes提供的CLI工具也没有提供原生的工具来对敏感数据进行加密存储,但是由于Kubernetes的开放性,围绕这个问题已经有很多生产ready的成熟工具出现。对于开发和运维人员来说,我们的主要职责就是管理Kubernetes平台上的对象和资源,因此选择什么样的工具和具体要解决的问题有直接的关系,理解有哪些工具可用,以及这些工具在什么情况下可以帮助我们就显得至关重要。接下来我们来详细介绍一下可用的工具。
首先我们顺带提一下Ansible Vault(因为笔者不打算详细介绍)这个工具,可以用来对需要保存在Kubernetes中的敏感数据进行加密,但是这个工具的问题就是我们要编写自动化脚本,并且解密是在客户端,因此敏感信息(无论是明文还是base64编码的数据)有被泄漏的风险。作为企业级用户,我们需要更好的方式,特别是敏感信息的解密在Kubernetes内部完成,不要”出塔“,让开发人员以及运维人员像管理普通Kubernetes资源一样管理加密后的敏感信息。
笔者在前边多篇文章中强调过Kubernetes的本质:从平台的角度设计了一条定义任务之间关系的框架,并为扩展提供了强大的支持。正是由于Kubernetes的这种设计思想,对于敏感数据这个领域,有很多扩展逐步出现并成熟。我们今天介绍第一个工具是Sealed Secret项目,对敏感数据的加密通过运行在Master node上的controller来完成。
Contoller在Kubernetes的Master节点上是个特殊的存在,Controller的核心工作大白话来说很简单:一个用来监控对象资源状态是否和目标状态一致的死循环。每个controller组件只管理一个类型的对象,当目标对象的状态发生变化(CUD操作),那么controller会收到通知,并努力将对象的实际状态和更新后的状态拉齐。
我们已经介绍过ReplicaSet对象,这其实也是Kubenretes平台上最有名的Controller。为啥说有名呢?咱作为开发人员,使用Kubernetes的目的肯定是部署应用程序,运维应用程序等,而我们部署应用程序一般都是通过Deployment这种方式来部署,当Kubernetes创建Deployment对象的时候,会自动创建一个RepicaSet对象,ReplicaSet对象的Controller会负责保证我们在YAML文件中声明数量的应用程序数量正在健康运行。
Kubernets平台大受欢迎的一个很重要的原因就是开放,从这个平台往上往下有很多扩展点,因此被各大科技公司和创业者趋之若鹜。Kubernetes默认提供的对象类型其实并不多,比如我们熟悉的PODS和SECRETS等。随着平台的发展,新的对象资源被不断的加入进来,但是用户的场景千变万化,光靠Kubernetes社区肯定无法满足这种复杂多变的业务诉求。聪明的你可能会想到,不是开源嘛,自己改源代码不就行了,诚然工程化能力强的企业可以这么,但是考虑到上千万行的代码,这绝对不是99%企业能落地的方案。
为了应对这种场景,Kubernetes提供了CRD(Custom Resource Definitions,用户自定义资源)类型的资源,开发人员可以把自己的业务逻辑和接口注册到CRD上,实现自己业务逻辑的同时,也可以leverage Kubernetes提供的各种优势,非常重要的是,这种扩展方式不影响Kuberetes默认的对象类型,稳定性有了保障。
我们来举个例子来说明一下CRD的时候用场景,假设我们需要重新发明异步任务这个轮子,我们自定了CronTabs类型的CRD,这个对象要解决的问题是基于配置的时间来运行异步任务。我们可以自己编写脚本通过API Server来执行预期的业务逻辑,但Kubernetes提供了更好的办法。还记得我们前边提到的Controller对象吗?我们可以自己编写Controller来监控和调谐CronTabs这对象的运行状态,不断的把对象的实际状态和目标状态拉齐,并且Kubernetes提供了SDK,极大的简化了我们开发controller的复杂度。
这种通过开发一个应用程序来监控另外一个应用程序的模式在Kubernetes中有个更好听的名字:Operator模式,已经被社区以及业界广泛接受,我们上边提到的Sealed Secrets工具就是Operator。开发Operator和对应的controllers起初对开发人员来说异常具有挑战性,因为开发人员必须对Kubernetes内部的运行机制有深入和全面的理解,才能写出健壮的应用。幸运的是Kubernetes社区意识到了这个问题,很多因此而诞生的工具包:kubebuiler等极大的简化了Operator开发的难度。如下图所示:
如上图所示,Operator负责管理用户自定义的资源,并响应用户对自定义资源的CUD操作。回到Sealed Secrets工具,因为这个工具在Kubernetes中是个Operator,读者可能会有个疑问,Sealed Secrets到底有哪些功能组件?和所有的Operator类似,本质上Sealed Secrets包含的组件如下所示:
- 理所当然的Operator/Controller组件
- 客户端工具kubeseal(类似于kubectl)来简化用户操作敏感资源
- 用户自定义资源(CRD)SealedSecret
另外当我们在集群中安装了Sealed Secrets工具之后,Controller会自动创建一个新的4096-bit RSA公钥和私钥pair,并且这对秘钥被保存在controller安装的命名空间中。
对于开发和运维人员来说,kubeseal工具会将Kubernetes的标准Secret转换成SealedSecret资源,具体的转换步骤如下:
1,首先保存在Secret中的敏感数据(键值对中的值)被自动产生的32位session秘钥加密
2,session key本身会使用controller生成的秘钥中的公钥进行加密,并使用RSA-OAEP生成证书
3,产生的结果被保存到SealedSecret对象中
增加了SealedSecrets之后,Kubernetes的Secret对象和SealedSecrets对象的关系如下图所示:
接下来我们来看看如何在自己的机器上安装Sealed Secrets工具,首先通过命令kubectl apply -f https://github.com/bitnami-labs/sealedsecrets/releases/download/v0.13.1/controller.yaml 将controller对象添加到集群中,默认情况下,controller会被安装到kube-system命名空间。我们可以通过命令kubectl get pods -n kube-system -l=name=sealed-secrets-controller来查看对象的状态,如下是在笔者机器上输出:
➜ Kubernetes安全 kubectl get pods -n kube-system -l=name=sealed-secrets-controller
NAME READY STATUS RESTARTS AGE
sealed-secrets-controller-5b54cbfb5f-7qhp5 1/1 Running 0 94m
接下来在自己的环境中安装kubeseal客户端工具,由于笔者的Kubernetes环境在自己的macOS上,因此直接使用brew install kubeseal进行安装,其他类型的操作系统可以参考官方文档:github.com/bitnami-labs/sealed-secrets。
安装完成之后,可以通过kubeseal工具来查看controller创建的时候产生的公钥:kubeseal --fetch-cert,成功输出证书信息就表示已经顺利安装了Sealed Secret工具。
工具和环境就位后,接下来我们来把hello-secret这个文件中的信息通过工具来进行加密,具体的命令是:kubeseal --format yaml
读者如果仔细对比两个文件,会发现Sealed Secret会增加namespace和name字段,这两个字段的作用其实就是用来关联Secret和Sealed Secret这两个对象。接下来废话不多说,我们看看这个资源是否能被部署到Kubernetes集群中,在自己的机器上执行kubectl apply命令:kubectl apply -f hello-secret_sealedsecrets.yml。资源创建好之后,通过kubectl get secrets命令来查看新创建的资源,在笔者的机器上输出如下:
➜ ~ kubectl get secret
NAME TYPE DATA AGE
default-token-4l6j9 kubernetes.io/service-account-token 3 293d
demo-secret Opaque 1 39h
hello-secret Opaque 1 9m31s
从上边的输入可以看到,我们的Sealed Secret就创建成功了,并且如果你把对象创建的事件信息打印出来,会看到如下的输出:
➜ ~ kubectl get events -n deafult
LAST SEEN TYPE REASON OBJECT MESSAGE
3m38s Normal Unsealed sealedsecret/hello-secret SealedSecret unsealed
successfully Opaque 1 9m31s
Sealed Secret对象和Secret对象之间的关系是共生,因此当我们删除SealedSecret对象之后,自动生成的Secret对象也会被删除,这背后的原理是Secret属于SealedSecret对象,Kubernetes的垃圾收集机制会在删除SealedSecret对象的时候,将附属的Secret对象也一并删除。
好了,今天这篇文章就这么多了,下篇文章我们来介绍Kubernetes平台上的包管理工具Helm,敬请期待!