一 基本概念
User 代表可以通过keystone进行访问的人或程序 通过认证信息进行验证
Tenant 是各个服务中的一些可以访问的资源集合 例如,在Nova中一个tenant可以是一些机器,在Swift和Glance中一个tenant可以是一些镜像存储,在Quantum中一个tenant可以是一些网络资源。Users默认的总是绑定到某些tenant上。
Role 即角色,Roles代表一组用户可以访问的资源权限,例如Nova中的虚拟机、Glance中的镜像。Users可以被添加到任意一个全局的 或 租户内的角色中。在全局的role中,用户的role权限作用于所有的租户,即可以对所有的租户执行role规定的权限;在租户内的role中,用户仅能在当前租户内执行role规定的权限。
Service 即服务,如Nova、Glance、Swift。根据前三个概念(User,Tenant和Role)一个服务可以确认当前用户是否具有访问其资源的权限。但是当一个user尝试着访问其租户内的service时,他必须知道这个service是否存在以及如何访问这个service,这里通常使用一些不同的名称表示不同的服务。在上文中谈到的Role,实际上也是可以绑定到某个service的。例如,当swift需要一个管理员权限的访问进行对象创建时,对于相同的role我们并不一定也需要对nova进行管理员权限的访问。为了实现这个目标,我们应该创建两个独立的管理员role,一个绑定到swift,另一个绑定到nova,从而实现对swift进行管理员权限访问不会影响到Nova或其他服务。
Endpoint 翻译为“端点”,我们可以理解它是一个服务暴露出来的访问点,如果需要访问一个服务,则必须知道他的endpoint。因此,在keystone中包含一个endpoint模板(endpoint template,在安装keystone的时候我们可以在conf文件夹下看到这个文件),这个模板提供了所有存在的服务endpoints信息。一个endpoint template包含一个URLs列表,列表中的每个URL都对应一个服务实例的访问地址,并且具有public、private和admin这三种权限。public url可以被全局访问(如http://compute.example.com),private url只能被局域网访问(如http://compute.example.local),admin url被从常规的访问中分离。
二 访问流程
用户Alice通过自己的户名和密码向keystone申请token,keystone认证用户名和密码后,返回token1
Alice通过token1发送keystone查询他所拥有的租户,keystone验证token1成功后,返回Alice的所有Tenant
Alice选择一个租户,通过用户名和密码申请token,keystone认证用户名、密码、tenant后,返回token2。(其实1、2步仅仅是为了查询tenant,如果已经知道tenant,可以忽略1、2步)
Alice通过token2发送创建server的请求,keystone验证token2(包括该token是否有效,是否有权限创建虚拟机等)成功后,然后再把请求下发到nova,最终创建虚拟机。
集群运行较长时间之后 访问其API会变得奇慢无比 keystone数据库存储了大量的token导致性能太差 解决的办法是经常清理token
为了避免上述问题,社区提出了 Fernet token ,它采用 cryptography 对称加密库(symmetric cryptography,加密密钥和解密密钥相同) 加密 token,具体由 AES-CBC 加密和散列函数 SHA256 签名。 Fernet 是专为 API token 设计的一种轻量级安全消息格式,不需要存储于数据库,减少了磁盘的 IO,带来了一定的 性能提升 。为了提高安全性,需要采用 Key Rotation 更换密钥。
Token 类型的选择涉及多个因素,包括 Keystone server 的负载、region 数量、安全因素、维护成本以及 token 本身的成熟度。region 的数量影响 PKI/PKIZ token 的大小,从安全的角度上看,UUID 无需维护密钥,PKI 需要妥善保管 Keystone server 上的私钥,Fernet 需要周期性的更换密钥,因此从安全、维护成本和成熟度上看,UUID > PKI/PKIZ > Fernet 如果:
Keystone server 负载低,region 少于 3 个,采用 UUID token。
Keystone server 负载高,region 少于 3 个,采用 PKI/PKIZ token。
Keystone server 负载低,region 大与或等于 3 个,采用 UUID token。
Keystone server 负载高,region 大于或等于 3 个,K 版本及以上可考虑采用 Fernet token。
性能优化
openstack采用了token认证的机制,各api的调用都会涉及到token的验证问题,使得keystone成为一个性能的瓶颈。
token的验证环节包括:验证请求中包含的token是否有效、过期,该token对应的用户组和用户id,对应的授权服务访问地址等。
性能瓶颈的解决-1:memcache缓存
性能瓶颈的解决-2:keystone并行化
当前的keystone实现中并没有采用并行化的机制,keystone-all运行时分别发起两个进程、绑定到两个socket上,分别处理5000和35357端口上的请求。
大概的修改如下:
引入了多线程下共享的socket
根据配置选项works的大小,发起多个进程处理api的请求
代码修改之后,还需对keystone的配置做适当更新:
keystone默认的token存储后端为基于内存的k-v,范围在一个进程的空间内。并行化之后,多个进程需共享访问token的存储后端,这里采用memcache。修改keystone.conf,并安装memcache服务。