天天看點

Openstack--虛拟機擷取metadata

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
           

繼續閱讀