你的Helm安全吗?

一、背景

Kubernetes是目前最为流行、成为事实标准的容器集群管理平台,为容器化应用提供了部署运行、资源调度、服务发现和动态伸缩等一系列完整功能。在Kubernetes当中,用户通过使用API对象,如Pod、Service、Deployment等,来描述应用的程序规则,而这些资源对象的定义一般需要写入一系列的YAML文件中,然后通过 Kubernetes 命令行工具Kubectl进行部署。由于通常应用程序都涉及到多个Kubernetes API对象,而要描述这些API对象就可能要同时维护多个YAML文件,从而在进行 Kubernetes 软件部署时,通常会面临下述几个问题:

  • 如何管理、编辑和更新这些这些分散的 Kubernetes 应用配置文件
  • 如何把一套相关的配置文件作为一个应用进行管理
  • 如何分发和重用 Kubernetes 的应用配置

Helm (https://helm.sh)的出现就是为了很好地解决上面这些问题,是Kubernetes官方提供的包管理工具,主要是是通过管理被称作Helm Chart的包来描述和管理云服务的。使用 Helm后就不需要再编写复杂的应用部署文件,可以以简单的方式在 Kubernetes 上查找、安装、升级、回滚、卸载应用程序。

在现在常用的Helm V2架构中,有一个称为“Tiller”的服务端组件。Tiller是一个集群内服务器,可与Helm客户端进行交互,并与Kubernetes API服务器连接。但由于Tiller具有root用户访问权限,使得有人可以未经授权访问Kubernetes服务器你,从而构成了很大的风险。

JFrog的专家,也是Helm的联合创始人,Rimas Mocevicius,提供了一种创新的、优雅的方法——Tillerless Helm,来解决这种情况,从而保护用户的Kubernetes集群。

 

二、Helm V2的应用架构

从Helm v2开始,Helm的架构中有一个名为The Tiller Server的服务器部分,该服务器部分是一个与helm客户端交互并与Kubernetes API服务器连接的集群内服务器。服务器负责以下各项工作:

  • 监听来自Helm客户端的传入请求
  • 结合Chart和配置以创建发布版本
  • 将Chart安装到Kubernetes中,然后跟踪后续版本
  • 通过与Kubernetes交互来升级和卸载Chart

简而言之,客户端负责管理Chart,Tiller负责管理发布版本,其架构如下图所示:

 

默认情况下,执行如下命令将Tiller部署安装到Kubernetes集群:

同时还需要为Tiller创建并部署RBAC授权,使其拥有执行任务的权限。Tiller常用的RBAC授权如下所示:

目前这样的架构工作得很好,为用户提供了灵活和方便,但同时也存在一些安全问题。从上面的RBAC文件中可以看出,Tiller被授予了cluster-admin的角色,也就是说,Tiller在用户的Kubernetes集群中具有完全的管理权限,这就具备了有人未经授权而访问和控制集群的风险。

 

三、Helm V2 中的Tillerless方案

其实,在Helm V2中创建Tillerless的架构也并不困难,能够为Helm的应用提供更高的安全保障。JFrog的专家Rimas给出了优化的解决方案,而本节将通过细节的描述来解释该方案如何运行。

首先,可以将Helm客户端和Tiller都部署在工作站上,或者运行在CI/CD流水线中,而不需要将Tiller安装到Kubernetes集群之中。示例的安装方式如下:

 

在这种安装方式下,Helm的运行架构如下图所示:

在这种架构下,Tiller使用和Helm客户端一样的配置(kubeconfig)连接到Kubernetes集群,并按照指定的命名空间(namespace)存储和管理Helm的发行版本信息。用户可以通过这种方式创建许多名称空间,并在Tiller启动时指定应该使用哪个命名空间。用户定义的RBAC规则可以存储在运行指定的名称空间中的密钥/配置映射中,而不再需要为Tiller创建和指定ServiceAccount。而这个架构的另一个好处就是不再限定Kubernetes集群中只能运行一个Tiller实例。

注意,在这种架构下,必须使用如下的命令来初始化Helm客户端,否则Tiller仍然被安装到Kubernetes集群中:

 

四、Helm V2中的Tillerless插件

那么,有没有更加方便的安装方式呢?Rimas为大家提供了一个简单的Helm Tillerless插件,请参见https://github.com/rimusz/helm-tiller

插件的安装非常方便,如下:

该插件提供了四个简单的命令:start,start-ci,stop和run。

 

4.1 在本地使用Tillerless插件

对于在本地开发或访问远程Kubernetes集群时,请使用helm tiller start命令:

 

该命令将在本地启动Tiller,并利用Tiller默认的设置,在kube-system名称空间存储和管理Helm版本。

也可以通过下述命令指定Tiller使用的命名空间:

 

该命令还会打开一个新bash shell,带有预设的环境变量:

 

这样,Helm客户端就知道如何连接Tiller了。

现在,就可以开始部署或更新Helm的发布版本了。

当完成了所有工作之后,只需要运行下述命令,就可以关闭Tiller了。

接下来,用户也可以重复上面的过程,通过指定新的命名空间来部署和更新其他团队的发布版本。

 

4.2 在CI/CD流水线中使用Tillerless插件

那如何在CI/CD流水线当中使用该插件呢?有两种方法:

第一种与上面的过程非常相似,只是没有启动带有预设变量的bash shell。

 

然后,Helm客户端将知道连接到Tiller的位置,而无需在CI流水线中进行任何更改。并且在流水线的结尾执行:

结束全部工作。

第二种也很容易,就是运行helm tiller run,可以使Tiller在指定命令之前或之后启动/停止:

 

举例来看:

附加功能:该插件还能够检查安装的Helm客户端和Tiller的版本,如果不匹配,则下载正确的Tiller版本文件。

 

五、总结

Helm作为Kubenetes的官方包管理工具,为用户提供了方便、快捷的在Kubernetes集群里部署和管理自己应用程序的方式。然而,Helm V2架构中的Tiller组件,在提供了操作便利的同时,也带来了安全上的隐患。

本文为大家介绍了一种在Helm V2中实现Tillerless的Helm部署和应用的解决方案,在保留了Helm V2灵活性和便利性的同时,也大大提升了应用和管理的安全性。

K8S中文社区微信公众号

评论 抢沙发

登录后评论

立即登录