OpenStack 中自动回收实例和镜像的最佳实践介绍
发布日期:2016-3-13 15:3:18
OpenStack 中自动回收实例和镜像的最佳实践介绍 OpenStack 是云计算领域中最广为人知的开源项目,它作为最流行的开源云项目它在全球被广泛应用,管理着大量的 IT 资源。然而,由于缺乏良好的回收机制,如果一些闲置的实例和镜像没有被及时地回收,那么将会导致 OpenStack 云中的低利用率并影响系统性能。为解决这一问题从而降低 IT 成本,自动回收实例与镜像的解决方案很有必要。 技术背景介绍: 本文所介绍的解决方案应用于 OpenStack 云管理平台,使用 Python 编程语言实现必要的功能,利用邮件服务器和 Web 服务器完成用户自服务,作为自动回收机制的补充。 自动回收的价值 提高 IT 资源的利用率 通过自动回收 OpenStack 中的实例和镜像,避免存在和积累闲置的实例和镜像,使得 IT 资源(CPU、内存、存储、网络等)保持有效的使用状态,最大程度地提高 IT 资源利用率,保护用户的 IT 投资。 提高 Cloud 上的系统性能 对于一个特定的 Cloud 平台,它的最大负载性能是有限的,而闲置的实例和镜像仍会占用部分这有限的性能,这在一定程度上会影响同一平台上其它系统的性能。以存储 I/O 性能为例,越是少量的系统的进行并发读写,对其中单个系统而言所拥有的性能越是良好。 节省 IT 成本 启用自动回收可以避免用户在 IT 投资上的无谓的浪费,无须盲目地增加投资而一样可以达到负载的需求。 如何实现自动回收 自动回收的条件和前提 使用 OpenStack 云管理平台可以利用一个现有的邮件服务器OpenStack 用户需要有电子邮件地址信息OpenStack 数据库中记录有对实例和镜像的最后修改时间,对此值的修改不应影响其它任何功能。自动回收机制的设计 自动回收通过 web service 实现检测实例和镜像的状态,完成与相关用户的交互,最终达到回收的作用,工作原理如图1所示。 下图是 自动回收工作原理图 本解决方案中通过 Jenkins 每天触发并完成一次回收工作,实际应用中可根据需要采用不同的触发方式和频率。 在 OpenStack 的数据库中记录资源信息及所有者信息,因此可以准确地与资源对应的所有者通过电子邮件进行交互。 通过比较资源的最后修改日期和当前日期,可以识别出将过期或已过期(周期可配置,详见清单1)的资源:对于已过期的资源,将执行自动清除并通知所有者;对于将过期的资源,将提醒所有者进行延期或主动清除操作。操作方式仅需点击一次邮件中的链接。若直至最后一次通知,所有者仍未进行任何操作响应,意味着该资源将正式过期并被自动清除。 自动回收的具体实现 首先,对于自动回收服务是可以根据不同的环境和需求进行配置的,如清单1所示。当自动回收服务(见下文中 Python 实现的 web service)启动时,将读取该配置使得回收工作能正常进行。 清单 1. 定义自动回收配置 [SERVICE] port=set me [WHITELIST] users=set me or keep empty instances=set me or keep empty images=set me or keep empty [LIFETIME] keep_days=set me remind_days=set me [DATABASE] host=set me nova_user=set me nova_pwd=set me keystone_user=set me keystone_pwd=set me [CLOUD] OS_USERNAME=set me OS_PASSWORD=set me OS_TENANT_NAME=set me OS_AUTH_URL=set me [EMAIL] smtp_server=set me smtp_user=set me smtp_pwd=set me [SERVICE]: 自动回收 web service 的相关配置 Port: web service 的服务端口[WHITELIST]: 白名单配置,用于避免某些资源被自动回收 Users: 指定用户清单,他们的资源将被视为永不过期Instances: 指定实例清单,视为永不过期Images: 指定镜像清单,视为永不过期[LIFETIME]: 资源的生命周期配置 Keep_days: 资源可保持的时长,以天为单位Remind_days: 通知时间范围,以天为单位,指在资源生命周期最后一段时间内开始对所有者进行通知提醒[DATABASE]: OpenStack 数据库的连接配置 Host: 数据库服务器地址Nova_user: nova 数据库的用户名Nova_pwd: nova 数据库的用户密码Keystone_user: keystone 数据库的用户名Keystone_pwd: keystone 数据库的用户密码[CLOUD]: OpenStack 云的管理帐号信息 Os_auth_url: OpenStack 的授权验证服务地址Os_tenant_name: OpenStack 中需要进行管理的 tenant 名称Os_username: OpenStack 中用于管理以上 tenant 的用户名Os_password: OpenStack 中上述用户的密码其次,通过运行简单的 Python 程序(见清单 2),即可启动一个 web server,也可以将该 web service 运行为 linux 系统服务(见清单 3)。 清单 2. 启动轻量 web 服务器 if __name__ == '__main__': serveraddr = ('0.0.0.0', int(SERVICE_PORT)) srvr = HTTPServer(serveraddr, RequestHandler) srvr.serve_forever() 清单 3. 创建 linux 系统服务 function start() { echo "Starting OS_Recycle ..." daemon "python ${PY_FILE} ${CONFIG_FILE} >> ${LOG_FILE} 2>&1 &" sleep 2 status } 在以上 web service 中,为所需要的功能实现 REST API,本解决方案中为优化用户体验,对资源的延期及回收操作同样采用 GET 响应。见清单 4。 清单 4. 定义 REST API 实现功能 def do_GET(self): self._writeheaders() self.apiGET() def apiGET(self): path=self.path.split('/') if len(path) == 2 and path[1] == 'instances': self.wfile.write(json.dumps(self.getInstances())) ... def getInstances(self): #connect to nova database and keystone database to get data ... instJson=json.loads('[]') for inst in instances: for user in users: if user[0] == inst[1]: instJson.append(json.loads('{"created_at":"%s", "user_id":"%s", "hostname":"%s", "ip_address":"%s", "uuid":"%s", "user_name":"%s"}' % (inst[0], inst[1], inst[2], inst[4], inst[3], user[1]) )) break return instJson 程序中对于资源及过期信息的查询操作,匀直接通过连接数据库查询实现,DB2 SQL 命令示例: novaSql = "SELECT char(a.created_at),a.user_id,a.hostname,a.uuid,cast(b.NETWORK_INFO as varchar(1000)) from instances a left join INSTANCE_INFO_CACHES b on a.uuid=b.INSTANCE_UUID \ where a.project_id = '%s' and a.deleted_at is null" % CLOUD_OS_TENANT_ID 对于资源的延期操作,即更新资源的最后修改时间为当前时间,意味着重置生命周期,DB2 SQL 命令示例: novaSql = "update instances set created_at=current timestamp where uuid='%s'" % uuid 而对于资源的清除操作,则需要通过调用 OpenStack 相关的 REST API 实现,见清单 5。 清单 5. 调用 OpenStack REST API 实现删除操作 def deleteInstance(self,uuid): req_url = '%s/tokens' % CLOUD_OS_AUTH_URL resp, resp_body = httplib2.Http().request(req_url, 'POST', headers={'Accept':'application/json', 'Content-Type':'application/json'}, body='{"auth": {"tenantName": "%s", "passwordCredentials": {"username": "%s", "password": "%s"}}}' % (CLOUD_OS_TENANT_NAME, CLOUD_OS_USERNAME, CLOUD_OS_PASSWORD) ) if resp['status'] != '200': return False resp_json = json.loads(resp_body) token_id = resp_json['access']['token']['id'] for service in resp_json['access']['serviceCatalog']: if service['name'] == 'nova': nova_admin_url = service['endpoints'][0]['adminURL'] break if not nova_admin_url: return False resp, resp_body = httplib2.Http().request('%s/servers/%s' % (nova_admin_url, uuid), 'DELETE', headers={'Accept':'application/json', 'X-Auth-Project-Id':'%s' % CLOUD_OS_TENANT_NAME, 'X-Auth-Token':'%s' % token_id } ) if resp['status'] != '204': return False return True 在资源将要过期或已被自动回收时,需要对所有者进行邮件通知,在邮件中提供必要的 link 供所有者进行操作。示例见清单 6。注意本程序中使用的是 SMTP,并且要求应用程序能够正常连接到指定的邮件服务器,而该邮件服务器亦能正常发送邮件到达资源所有者。 清单 6. 邮件通知资源所有者 import smtplib from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText ... SMTP_SERVER='set me' SMTP_USER='set me' SMTP_PWD='set me' msg = MIMEMultipart() msg["From"] = SMTP_USER msg["To"] = 'set me' msg["Subject"] = "set me" msg.attach(MIMEText("set me")) mailServer = smtplib.SMTP(SMTP_SERVER, timeout=20) mailServer.ehlo() mailServer.starttls() mailServer.login(SMTP_USER, SMTP_PWD) mailServer.sendmail(SMTP_USER, msg["To"], msg.as_string()) mailServer.quit() 至此,OpenStack 平台上自动回收实例及镜像的功能即可实现。 应用的增强与扩展 上述应用的实现可满足大部分场景的需求,同时也存在可增强的几方面: 使用额外的数据库,用以跟 OpenStack 数据库同步资源信息,并记录生命周期,避免直接修改 OpenStack 的数据。实现专用的邮件服务器,用于本应用与资源所有者的邮件交互,避免网络受限与安全风险。包装成为 OpenStack 的可选功能,使得用户可以方便地启用该功能,而无需过多的手工配置。基于上述实现及可增强的部分,自动回收可扩展到更多的应用场景: 可用于回收 OpenStack 中的其它类型的资源和数据,例如用户,flavor,网络等,而不仅限于实例与镜像以相同的思路在平它系统平台中实现自动回收资源:即给资源配置生命周期,并跟踪资源的状态,在与所有者有自动交互的基础上实现自动回收。
|