Metadata即实例的元数据,主要包括了虚拟机的一些资深属性,比如Hostname,网络配置,注入的Keypair,这些主要是虚拟机的metadata;除此之外,应该还有用户自定义的User data,可以是一些定时脚本,命令等
虚拟机的一些Metadata信息其实可以通过client命令nova show得到,OpenStack提供了RESTful接口来获取metadata,不过获取方式基本就是照搬亚马逊的AWS,通过http://169.254.169.254来获取
~$ curl 169.254.169.254 1.0 2007-01-19 2007-03-01 2007-08-29 2007-10-10 2007-12-15 2008-02-01 2008-09-01 2009-04-04
这里的结果是metadata服务目前支持的最新的接口版本号,选择一个最新的查询
~$ curl 169.254.169.254/2009-04-04/meta-data ami-id ami-launch-index ami-manifest-path block-device-mapping/ hostname instance-action instance-id instance-type kernel-id local-hostname local-ipv4 placement/ public-hostname public-ipv4 public-keys/ ramdisk-id reservation-id
虚拟机通过这个RESTful接口获取metadata信息,会分别经过nova和neutron,首先请求会经过网络,通过iptables的NAT规则重定向到neutron-ns-metadata-proxy,在这个请求中添加router-id和network-id,然后转发给neutron-metadata-agent,根据请求的router-id,network-id和IP来获取PORT信息,拿到instance-id和tenant-id加入到请求,最后请求转发给nova-api-metadata,利用instance-id和tenant-id获取虚拟机的metadata,进而返回(改编自IBM文档库)
Nova-api-metadata:启动RESTful服务,处理虚拟机发送的REST API请求,从数据库中读取虚拟机的metadata信息
Neutron-metadata-agent:在网络节点上,负责将接收到的获取metadata请求转发给nova-api-metadata
Neutron-ns-metadata-proxy:在网络节点上,连通不同的namespace,最终虚拟机是向neutron-ns-metadata-proxy来发送请求,这个过程比较复杂,经过了router,dhcp
在路由表中都能找到这样
169.254.169.254 via 10.180.156.1 dev eth0
这里curl请求的包首先到达网关,然后network namespace里有iptables规则,包会被NAT转发到9697端口
lihui@devstack:~$ sudo ip netns exec qrouter-7b2bed3f-0515-43bd-be4f-8a46300f8dc2 iptables -t nat -S | grep 9697 -A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697 lihui@devstack:~$ sudo ip netns exec qrouter-7b2bed3f-0515-43bd-be4f-8a46300f8dc2 iptables -S | grep 9697 -A neutron-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT
查看neutron-ns-metadata-proxy进程,可以看到正监听9697端口
~$ ps aux | grep neutron-ns-metadata-proxy lihui 3030 0.0 0.0 13660 968 pts/0 S+ 02:22 0:00 grep --color=auto neutron-ns-metadata-proxy root 25102 0.0 0.1 91196 25452 ? S Dec02 0:00 /usr/bin/python /usr/local/bin/neutron-ns-metadata-proxy --pid_file=/opt/stack/data/neutron/external/pids/7b2bed3f-0515-43bd-be4f-8a46300f8dc2.pid --metadata_proxy_socket=/opt/stack/data/neutron/metadata_proxy --router_id=7b2bed3f-0515-43bd-be4f-8a46300f8dc2 --state_path=/opt/stack/data/neutron --metadata_port=9697 --debug --verbose
因为包被neutron-ns-metadata-proxy获取,接着就经过neutron-metadata-agent和nova-api-metadata进而返回metadata
从这个过程来看,我只是想获取下metadata信息,却与网络是不可分割的,就造成了一个问题,虚拟机的状态十分依赖网络,假如169.254.169.254这个接口不通,会导致虚拟机的一些信息或者状态异常,操作系统不可用状态,会给人一些误解,此时虚拟机应该没问题,只不过一些metadata无法返回,导致出错,甚至可以直接攻击这个接口,因此这个接口可用性不是特别好,除非对网络配置十分自信