1、169.254.169.254
在实例中有一个魔法IP 169.254.169.254,通过访问这个ip,能获得许多与这个实例相关的信息,这些信息被称为metadata,我们在实例上发送:curl http://169.254.169.254/latest/meta-data/。
2、请求流程
1)instance 通过预定义的 169.254.169.254
请求 metadata;
2)请求被转发到 neutron router;
3)router 将请求转发给 neutron-ns-metadata-proxy;
4)再后面就简单了:neutron-ns-metadata-proxy 将请求通过 unix domain socket 发给 neutron-metadata-agent,后者再通过管理网络发给 nova-api-metadata;
参考https://blog.csdn.net/u010258235/article/details/101207119
3、nova代码解析
/nova/api/metadata/handler.py
def __call__(self, req):
if os.path.normpath(req.path_info) == "/":
resp = base.ec2_md_print(base.VERSIONS + ["latest"])
req.response.body = encodeutils.to_utf8(resp)
req.response.content_type = base.MIME_TYPE_TEXT_PLAIN
return req.response
#不同的场景不同的方式获取meta
if CONF.neutron.service_metadata_proxy:
if req.headers.get('X-Metadata-Provider'):
meta_data = self._handle_instance_id_request_from_lb(req)
else:
meta_data = self._handle_instance_id_request(req)
else:
if req.headers.get('X-Instance-ID'):
LOG.warning(
_LW("X-Instance-ID present in request headers. The "
"'service_metadata_proxy' option must be "
"enabled to process this header."))
meta_data = self._handle_remote_ip_request(req)
if meta_data is None:
raise webob.exc.HTTPNotFound()
#格式数据
try:
data = meta_data.lookup(req.path_info)
except base.InvalidMetadataPath:
raise webob.exc.HTTPNotFound()
if callable(data):
return data(req, meta_data)
resp = base.ec2_md_print(data)
req.response.body = encodeutils.to_utf8(resp)
req.response.content_type = meta_data.get_mimetype()
return req.response
/nova/api/metadata/handler.py
def get_metadata_by_instance_id(self, instance_id, address):
cache_key = 'metadata-%s' % instance_id
#缓存中获取metadata
data = self._cache.get(cache_key)
if data:
LOG.debug("Using cached metadata for instance %s", instance_id)
return data
#缓存不存在通过instance_id获取metadata
try:
data = base.get_metadata_by_instance_id(instance_id, address)
except exception.NotFound:
return None
#将metadata放入缓存中
if CONF.api.metadata_cache_expiration > 0:
self._cache.set(cache_key, data)
return data