cloud init 原理分析

应用场景

控制节点上

1. 创建 key-pair,将控制节点的 publish key 添加到其中

# openstack keypair create --public-key ~/.ssh/id_rsa.pub con

 

2. 创建虚拟机,指定 key-pair(启动过程中会通过 cloud-init 将相关信息配置在虚拟机中)

-- 创建成功后,可以从控制节点免密登录

# openstack server create --flavor mid --image ubuntu --nic net-id=ae93bdde-9746-4bd2-b876-a424c35e7dd6 --key-name con vm-key

# nova list

 # ssh ubuntu@192.168.67.180

 

 

过程分析

(本文主要分析 cloud init 获取 metadata 的过程)

前提:

-- nova-api 是 metadata 的提供者,虚拟机通过访问 nova-api 可以获取 metadata 信息

-- neutron-metadata-agent 可以与 nova-api 通信

-- 虚拟机所在网络的 dhcp agent 管理 ns-metadata-proxy 进程

过程:

1. 虚拟机 vm-key 通过169.254.169.254 请求获取 metadata

2. 请求被转发到虚拟机所在网络的 dhcp 的网络空间中,其中所运行 ns-metadata-proxy 服务进程获取请求

3. ns-metadata-proxy 将请求发送给 neutron-metadata-agent,由 neutron-metadata-agent 通过管理网 REST API 与 nova-api 通信获取 metadata

 

下面一步步实践体会一下

首先,查看虚拟机 vm-key 所在网络的 dhcp 网络空间(控制节点上)

- vm-key 所在网络 ID 为 ae93bdde-9746-4bd2-b876-a424c35e7dd6

- 169.254.169.254 是 metadata 服务的 IP 地址

- ns-metadata-proxy 服务进程监听该网络空间的 80 端口

# ip netns exec qdhcp-ae93bdde-9746-4bd2-b876-a424c35e7dd6 ip a

# ps -ef|grep meta

# ip netns exec qdhcp-ae93bdde-9746-4bd2-b876-a424c35e7dd6 netstat -ntple | grep 2935

 

 

1. 虚拟机 vm-key 通过169.254.169.254 请求获取 metadata

1)计算节点上,查看虚拟机 vm-key 的启动日志

-- 192.168.67.180 是 vm-key 的 IP 地址

-- 192.168.67.130 是 dhcp 的 IP 地址

# cat /var/lib/nova/instances/a1bbe620-d8b9-4340-96a2-21120f039028/console.log

2)虚拟机内部(执行 curl 169.254.169.254,看看会发生什么

查看路由,通过192.168.67.130 访问 169.254.169.254

# ip r

# curl 169.254.169.254

 

 

2. 请求被转发到虚拟机所在网络的 dhcp 的网络空间中,其中所运行 ns-metadata-proxy 服务进程获取请求

-- vm-key(192.168.67.180) 与 dhcp 网络空间的 80 端口(169.254.169.254: 80 也就是 ns-metadata-proxy 监听的端口)连接通信

控制节点上,抓包

# ip netns exec qdhcp-ae93bdde-9746-4bd2-b876-a424c35e7dd6 tcpdump -nnv -i ns-2e9f25b8-0c host 192.168.67.180

 

 

3. ns-metadata-proxy 将请求发送给 neutron-metadata-agent,由 neutron-metadata-agent 通过管理网 REST API 与 nova-api 通信获取 metadata

控制节点上

1)查看日志

# vim /var/log/neutron/metadata-agent.log

2020-05-13 06:59:26.234 17286 DEBUG eventlet.wsgi.server [-] (17286) accepted '' server /usr/lib/python2.7/site-packages/eventlet/wsgi.py:985
2020-05-13 06:59:26.235 17286 DEBUG neutron.agent.metadata.agent [-] Request: GET / HTTP/1.0^M
Accept: */*^M
Connection: close^M
Content-Type: text/plain^M
Host: 169.254.169.254^M
User-Agent: curl/7.58.0^M
X-Forwarded-For: 192.168.67.180^M
X-Neutron-Network-Id: ae93bdde-9746-4bd2-b876-a424c35e7dd6 __call__ /usr/lib/python2.7/site-packages/neutron/agent/metadata/agent.py:86
2020-05-13 06:59:26.347 17286 DEBUG neutron.agent.metadata.agent [-] Gotten ports for remote_address 192.168.67.180, network_id ae93bdde-9746-4bd2-b876-a424c35e7dd6, router_id None are: [{u'allowed_address_pairs': [], u'extra_dhcp_opts': [], u'updated_at': u'2020-05-13T09:21:14Z', u'device_owner': u'compute:nova', u'revision_number': 9, u'port_security_enabled': True, u'binding:profile': {}, u'fixed_ips': [{u'subnet_id': u'c2badbea-57d9-4dad-81d0-15faf15d99db', u'ip_address': u'192.168.67.180'}], u'id': u'17de0356-8656-46f4-b69d-d17124911fb3', u'security_groups': [u'fe4f420a-3b29-48e3-b8b1-acb616c832a1'], u'binding:vif_details': {u'connectivity': u'l2', u'port_filter': True}, u'binding:vif_type': u'bridge', u'mac_address': u'fa:16:3e:ea:2e:a2', u'project_id': u'b84ffc54cb7e47d785a2d7b5bd0aeaf9', u'status': u'ACTIVE', u'binding:host_id': u'com1', u'description': u'', u'tags': [], u'device_id': u'a1bbe620-d8b9-4340-96a2-21120f039028', u'name': u'', u'admin_state_up': True, u'network_id': u'ae93bdde-9746-4bd2-b876-a424c35e7dd6', u'tenant_id': u'b84ffc54cb7e47d785a2d7b5bd0aeaf9', u'created_at': u'2020-05-13T08:45:43Z', u'binding:vnic_type': u'normal'}] _get_instance_and_tenant_id /usr/lib/python2.7/site-packages/neutron/agent/metadata/agent.py:168
2020-05-13 06:59:26.357 17286 DEBUG neutron.agent.metadata.agent [-] <Response [200]> _proxy_request /usr/lib/python2.7/site-packages/neutron/agent/metadata/agent.py:213
2020-05-13 06:59:26.357 17286 INFO eventlet.wsgi.server [-] 192.168.67.180,<local> "GET / HTTP/1.1" status: 200  len: 234 time: 0.1224608

 # vim /var/log/nova/nova-api.log

2020-05-13 06:59:26.352 17837 DEBUG nova.metadata.wsgi.server [req-26066104-97e6-48cb-9b85-eb9fbe27a894 - - - - -] (17837) accepted ('192.168.73.137', 43404) server /usr/lib/python2.7/site-packages/eventlet/wsgi.py:985
2020-05-13 06:59:26.355 17837 INFO nova.metadata.wsgi.server [-] 192.168.67.180,192.168.73.137 "GET / HTTP/1.1" status: 200 len: 239 time: 0.0007169

 2)代码分析(neutron-metadata-agent 向 nova-api 发送 REST API 请求)

neutron/agent/metadata/agent.py 中插入断点后,执行命令进行调试,查看关键的参数值

(# su -s /bin/sh -c "/usr/bin/python2 /usr/bin/neutron-metadata-agent --config-file /usr/share/neutron/neutron-dist.conf --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metadata_agent.ini --config-dir /etc/neutron/conf.d/common --config-dir /etc/neutron/conf.d/neutron-metadata-agent --log-file /var/log/neutron/metadata-agent.log" neutron)

def _proxy_request(self, instance_id, tenant_id, req):
......

# method = GET
# url = http://con:8775/
# headers: {'X-Forwarded-For': '192.168.67.180',
'X-Instance-ID-Signature': '539ad54f0101c374a033a1688cf7d0a7b2895dcf4d00e0fa68b6e144e8c97650',
'X-Tenant-ID': u'b84ffc54cb7e47d785a2d7b5bd0aeaf9',
'X-Instance-ID': u'a1bbe620-d8b9-4340-96a2-21120f039028'}
# cert: None
# data: ''
# verify: True resp = requests.request(method=req.method, url=url, headers=headers, data=req.body, cert=client_cert, verify=verify_cert) if resp.status_code == 200: req.response.content_type = resp.headers['content-type'] req.response.body = resp.content LOG.debug(str(resp)) return req.response

......

 3)在控制节点上手动执行 curl 命令获取 vm-key 的metadata

(先执行 openstack token issue 命令获取 token)

# curl -i -X GET http://con:8775/ -H "X-Auth-Token:gAAAAAB..." -H "X-Instance-ID: a1bbe620-d8b9-4340-96a2-21120f039028"

# curl -i -X GET http://con:8775/1.0/ -H "X-Au/meth-Token:gAAAAAB..." -H "X-Instance-ID: a1bbe620-d8b9-4340-96a2-21120f039028" -H "X-Instance-ID-Signature: 539ad54f0101c374a033a1688cf7d0a7b2895dcf4d00e0fa68b6e144e8c97650" -H "X-Tenant-ID: b84ffc54cb7e47d785a2d7b5bd0aeaf9" 

# curl -i -X GET http://con:8775/1.0/meta-data -H "X-Au/meth-Token:gAAAAAB..." -H "X-Instance-ID: a1bbe620-d8b9-4340-96a2-21120f039028" -H "X-Instance-ID-Signature: 539ad54f0101c374a033a1688cf7d0a7b2895dcf4d00e0fa68b6e144e8c97650" -H "X-Tenant-ID: b84ffc54cb7e47d785a2d7b5bd0aeaf9"

 

 

 小结:虚拟机可以通过 169.254.169.254 获取 user data 设置用户名密码、获取 hostname、获取 ssh keys 等,由 cloud init 根据这些数据来定制个性化的虚拟机

 

posted @ 2020-05-19 07:17  丫uan丫ue  阅读(686)  评论(0编辑  收藏  举报