深度解析 OpenStack metadata 服务架构

启迪云-高级开发工程师 郭全

前言

下图是OpenStack虚拟机在启动过程中发出的一个请求,我们在里面可以看到cloud-init和169.254.169.254。那么它们分别是做什么用的呢,接下来我们将会做一个详细的介绍。

深度解析 OpenStack metadata 服务架构

众所周知,在创建虚拟机的时候,用户往往需要对虚拟机进行一些配置,比如:开启一些服务、安装某些包、添加SSH 秘钥、配置 hostname,修改密码等等。这里有两个问题,一个是谁负责初始化虚拟机配置,另一个是虚拟机如何获取到这些配置信息的。

首先这些信息的初始化是通过cloud-Init的方式配置到虚拟机中。cloud-Init是一个用来自动配置虚拟机的初始设置的工具,它可以在使用模板部署虚拟机时使用,从而达到避免网络冲突的目的。在使用这个工具前,cloud-init 软件包必须在虚拟机上被安装。安装后,cloud-Init服务会在系统启动时搜索如何配置系统的信息。您可以使用只运行一次窗口来提供只需要配置一次的设置信息;或在新建虚拟机、编辑虚拟机和编辑模板窗口中输入虚拟机每次启动都需要的配置信息。

cloud-init负责初始化虚拟机配置,那么虚拟机如何获取到用户传递的配置信息呢?OpenStack提供了两种方式获取这些配置信息,一种是config drive,一种是metadata RESTful服务。由于篇幅关系,本文主要阐述metadata RESTful服务。

OpenStack nova-api-metadata服务提供了RESTful 接口,虚拟机可以通过访问API获取metadata 信息。要完成从虚拟机至网络节点的请求发送和响应,保证链路的连通,只有nova-api-metadata服务是不够的,OpenStack提供neutron-metadata-agent 和 neutron-ns-metadata-proxy服务保证虚拟机的请求可以发送到nova-api-metadata服务。

◘ 下图展示了虚拟机可以获取到的metadata信息

深度解析 OpenStack metadata 服务架构_第1张图片

神奇的169.254.169.254

这个地址来源于AWS,亚马逊在设计公有云的时候为了让instance 能够访问 metadata,就将 169.254.169.254 这个特殊的IP 作为metadata 服务器的地址。然后大家在给亚马逊定制各种操作系统镜像的时候获取metadata的api地址就写的是169.254.169.254。为了这些镜像也能在OpenStack上运行,为了兼容它。OpenStack就保留了这个地址。

nova-api-metadata服务

nova-api-metadata启动了RESTful 服务,负责处理虚拟机发送来的REST API 请求。从请求的HTTP 头部中取出相应的信息,获得虚拟机的ID,继而从数据库中读取虚拟机的metadata 信息,最后将结果返回。

neutron-metadata-agent服务

neutron-metadata-agent 运行在网络节点,负责将接收到的获取metadata 的请求转发给nova-api-metadata。neutron-metadata-agent 会获取虚拟机和租户的ID,添加到请求的HTTP 头部中。nova-api-metadata 会根据这些信息获取metadata。

neutron-ns-metadata-proxy服务

neutron-ns-metadata-proxy 也运行在网络节点。为了解决网络节点的网段和租户的虚拟网段重复的问题,OpenStack 引入了网络命名空间。neutron 中的路由和DHCP 服务器都在各自独立的命名空间中。由于虚拟机获取metadata 的请求都是以路由和DHCP 服务器作为网络出口,所以需要通过neutron-ns-metadata-proxy 联通不同的网络命名空间,将请求在网络命名空间之间转发。

neutron-ns-metadata-proxy利用在unix domain socket 之上的HTTP技术,实现了不同网络命名空间之间的HTTP 请求转发。并在请求头中添加’X-Neutron-Router-ID’和’X-Neutron-Network-ID’信息,以便neutron-metadata-agent 来辨别发送请求的虚拟机,获取虚拟机的ID。通过下图可以看出每个网络或者router均会有一个服务进程,网络对应的端口号为80,router对应的端口号为9697。

深度解析 OpenStack metadata 服务架构_第2张图片


虚拟机获取metadata流程


深度解析 OpenStack metadata 服务架构_第3张图片

如上图所示,虚拟机获取metadata 的大致流程为:首先请求被发送至neutron-ns-metadata-proxy,此时会在请求中添加router-id 和network-id,然后请求通过unix domian socket 被转发给neutron-metadata-agent,根据请求中的router-id、network-id 和IP,获取port 信息,从而拿到instance-id 和tenant-id 加入请求中,最后请求被转发给nova-api-metadata,其利用instance-id 和tenant-id 获取虚拟机的metadata,返回相应。

上面我们分析了各个服务之间转发请求的流程,那么现在只存在一个问题,整个获取metadata 的路线就通畅了:虚拟机如何将请求发送至neutron-ns-metadata-proxy? neutron通过两种方式来解决这个问题:通过router 发送请求和通过DHCP 发送请求。

◘ 通过router发送请求

如果虚拟机所在subnet 连接在了router 上,那么发向169.254.169.254 的报文会被发至router。如下图所示,neutron 通过在router 所在网络命名空间添加iptables 规则,将该报文转发至9697 端口,而neutron-ns-metadata-proxy 监听着该端口,所以报文被neutron-ns-metadata-proxy 获取。


深度解析 OpenStack metadata 服务架构


◘通过DHCP发送请求

如果虚拟机所在subnet 没有连接在任何router 上,那么请求则无法通过router 转发。此时 neutron 通过DHCP 服务器来转发metadata 请求。从 下图可以看到DHCP 服务器的IP 配置信息,发现DHCP 服务器配置了两个IP,其中一个就是169.254.169.254。并且DHCP服务器对应的neutron-ns-metadata-proxy监听着80端口,从而发向169.254.169.254 的报文会被发至neutron-ns-metadata-proxy。


深度解析 OpenStack metadata 服务架构_第4张图片



总结

OpenStack metadata服务为用户自定义配置虚拟机提供了有效的解决方案,在虚拟机创建阶段可以方便的将一些参数配置到虚拟机中。如果是在虚拟机的运行阶段,用户期待的一些参数又该如何传递到虚拟机呢,我们将会在后续的文章中讲解。

你可能感兴趣的:(深度解析 OpenStack metadata 服务架构)