分享

metadata在OpenStack中的使用

rsgg03 发表于 2015-3-4 01:33:05 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 0 64950
本帖最后由 rsgg03 于 2015-3-4 01:37 编辑
问题导读

1.nova就无法区分到底是哪个虚拟机请求metadata是如何解决的?
2.namespace的作用是什么?






版本:Grizzly master分支 2013.6.17
部署:三节点(controller + network + compute)
网络类型:vlan

之前的一篇blog中碰到了虚拟机访问169.254.169.254的问题,在F版中,会在网络节点上做NAT转换,直接访问nova的metadata服务,但这种方法,在使用namespace时就不生效了,因为namespace支持IP地址重叠,这样nova就无法区分到底是哪个虚拟机请求metadata。

该问题在G版得到解决,blueprint在此。采取的方法是在HTTP头部识别是哪个虚拟机。同时,G版在Quantum中加入了两个服务:namespace metadata proxy和metadata agent。一个虚拟机访问169.254.169.254的流程如下图:
1.png

在细讲流程之前,估计很多人并不清楚metadata的作用和由来。不懂的童鞋看这里



1、虚拟机发出请求虚拟机启动时会访问169.254.169.254获取一些内容。这个从我之前出错的日志中就可以看出来:
'http://169.254.169.254/2009-04-04/meta-data/instance-id' failed [0/120s]: http error [404]

在虚拟机内部访问169.254.169.254,看一下都有什么:
  1. ubuntu@ubuntu-test:~$ curl http://169.254.169.254/2009-04-04/meta-data  
  2. ami-id  
  3. ami-launch-index  
  4. ami-manifest-path  
  5. block-device-mapping/  
  6. hostname  
  7. instance-action  
  8. instance-id  
  9. instance-type  
  10. kernel-id  
  11. local-hostname  
  12. local-ipv4  
  13. placement/  
  14. public-hostname  
  15. public-ipv4  
  16. public-keys/  
  17. ramdisk-id  
复制代码

那么这些内容是如何获取到的?因为虚拟机内部没有特殊的路由,所以数据包会直接发送到虚拟机的默认网关,而默认网关是在network node上。虚拟机的网卡信息如下:

  1. ubuntu@ubuntu-test:~$ ip -4 address show dev eth0  
  2. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000  
  3. inet 10.1.1.2/24 brd 10.1.1.255 scope global eth0  
复制代码



虚拟机的路由信息:
  1. ubuntu@ubuntu-test:~$  ip route  
  2. default via 10.1.1.1 dev eth0  metric 100   
  3. 10.1.1.0/24 dev eth0  proto kernel  scope link  src 10.1.1.2  
复制代码




2、namespace-metadata-proxy

因为使用了namespace,在network node上每个namespace里都会有相应的iptables规则和网络设备。
先来看看对应的iptables规则:
  1. -A quantum-l3-agent-PREROUTING -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697  
  2. -A quantum-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT  
复制代码

虚拟机默认网关设备信息的地址信息,可以看到虚拟机网关的IP(10.1.1.1):


  1. root@network232:~# ip netns exec qrouter-b147a74b-39bb-4c7a-aed5-19cac4c2df13 ip addr show qr-f7ec0f5c-2e  
  2. 12: qr-f7ec0f5c-2e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN   
  3.     link/ether fa:16:3e:81:9c:69 brd ff:ff:ff:ff:ff:ff  
  4.     inet 10.1.1.1/24 brd 10.1.1.255 scope global qr-f7ec0f5c-2e  
  5.     inet6 fe80::f816:3eff:fe81:9c69/64 scope link   
  6.        valid_lft forever preferred_lft forever  
复制代码


iptables规则中,会把目的地址169.254.169.254的数据包,重定向到本地端口9697,那么看一下network node上,在该端口的监听进程:
  1. root@network232:~# ip netns exec qrouter-b147a74b-39bb-4c7a-aed5-19cac4c2df13 netstat -nlpt | grep 9697  
  2. tcp        0      0 0.0.0.0:9697            0.0.0.0:*               LISTEN      13249/python  
复制代码


进程号13249,看一下这个进程:
  1. root@network232:~# ps -f --pid 13249 | fold -s -w 85   
  2. UID        PID  PPID  C STIME TTY          TIME CMD  
  3. root     13249     1  0 16:30 ?        00:00:00 python   
  4. /usr/bin/quantum-ns-metadata-proxy   
  5. --pid_file=/var/lib/quantum/external/pids/b147a74b-39bb-4c7a-aed5-19cac4c2df13.pid   
  6. --router_id=b147a74b-39bb-4c7a-aed5-19cac4c2df13 --state_path=/var/lib/quantum   
  7. --metadata_port=9697 --debug --verbose   
  8. --log-file=quantum-ns-metadata-proxyb147a74b-39bb-4c7a-aed5-19cac4c2df13.log   
  9. --log-dir=/var/log/quantum  
复制代码
可能很多人想知道,这个进程从何而来,解释这个问题,可能要贴点代码:

  1. def _spawn_metadata_proxy(self, router_info):  
  2.     def callback(pid_file):  
  3.         proxy_cmd = ['quantum-ns-metadata-proxy',  
  4.                      '--pid_file=%s' % pid_file,  
  5.                      '--router_id=%s' % router_info.router_id,  
  6.                      '--state_path=%s' % self.conf.state_path,  
  7.                      '--metadata_port=%s' % self.conf.metadata_port]  
  8.         proxy_cmd.extend(config.get_log_args(  
  9.             cfg.CONF, 'quantum-ns-metadata-proxy-%s.log' %  
  10.             router_info.router_id))  
  11.         return proxy_cmd  
  12.   
  13.     pm = external_process.ProcessManager(  
  14.         self.conf,  
  15.         router_info.router_id,  
  16.         self.root_helper,  
  17.         router_info.ns_name())  
  18.     pm.enable(callback)  
复制代码


可见,启用namespace场景下,对于每一个router,都会创建这样一个进程。该进程监听9697端口,其主要功能:
1、向请求头部添加X-Forwarded-For和X-Quantum-Router-ID,分别表示虚拟机的fixedIP和router的ID
2、将请求代理至Unix domain socket(/var/lib/quantum/metadata_proxy)



3、Quantum Metadata Agent

network node上的metadata agent监听/var/lib/quantum/metadata_proxy:

  1. root@network232:~# netstat -lxp | grep metadata  
  2. unix  2      [ ACC ]     STREAM     LISTENING     46859    21025/python        /var/lib/quantum/metadata_proxy  
  3. root@network232:~# ps -f --pid 21025 | fold -s   
  4. UID        PID  PPID  C STIME TTY          TIME CMD  
  5. quantum  21025     1  0 16:31 ?        00:00:00 python   
  6. /usr/bin/quantum-metadata-agent --config-file=/etc/quantum/quantum.conf   
  7. --config-file=/etc/quantum/metadata_agent.ini   
  8. --log-file=/var/log/quantum/metadata-agent.log  
复制代码
该进程的功能是,根据请求头部的X-Forwarded-For和X-Quantum-Router-ID参数,向Quantum service查询虚拟机ID,然后向Nova Metadata服务发送请求(默认端口8775),消息头:X-Forwarded-For,X-Instance-ID、X-Instance-ID-Signature分别表示虚拟机的fixedIP,虚拟机ID和虚拟机ID的签名。


4、Nova Metadata ServiceNova的metadata service是随着nova-api启动的,会同时启动三个服务:ec2, osapi_compute, metadata。虚拟机访问169.254.169.254的返回内容,其实就是metadata服务向nova-conductor查询后,返回给network node的metadata agent,再由metadata agent返回给metadata proxy,然后返回给虚拟机的。

  1. root@controller231:~# netstat -nlpt | grep 8775  
  2. tcp        0      0 0.0.0.0:8775            0.0.0.0:*               LISTEN      1714/python      
  3. root@controller231:~# ps -f --pid 1714  
  4. UID        PID  PPID  C STIME TTY          TIME CMD  
  5. nova      1714     1  0 16:40 ?        00:00:01 /usr/bin/python /usr/bin/nova-api --config-file=/etc/nova/nova.conf  
复制代码




上面讲了一个虚拟机如何通过router的namespace-metadata-proxy访问169.254.169.254获取一些自定义信息。其实在Quantum中,还有dhcp的namespace-metadata-proxy可以提供访问。在使用前,需要在dhcp agent的配置文件中增加一个配置:

  1. # The DHCP server can assist with providing metadata support on isolated  
  2. # networks. Setting this value to True will cause the DHCP server to append  
  3. # specific host routes to the DHCP request.  The metadata service will only  
  4. # be activated when the subnet gateway_ip is None.  The guest instance must  
  5. # be configured to request host routes via DHCP (Option 121).  
  6. enable_isolated_metadata = True  
复制代码


然后,创建subnet,注意不要指定gateway:
  1. root@controller231:/usr/lib/python2.7/dist-packages# quantum subnet-create testnet01 172.17.17.0/24 --no-gateway --name=sub_no_gateway  
  2. Created a new subnet:  
  3. +------------------+--------------------------------------------------+  
  4. | Field            | Value                                            |  
  5. +------------------+--------------------------------------------------+  
  6. | allocation_pools | {"start": "172.17.17.1", "end": "172.17.17.254"} |  
  7. | cidr             | 172.17.17.0/24                                   |  
  8. | dns_nameservers  |                                                  |  
  9. | enable_dhcp      | True                                             |  
  10. | gateway_ip       |                                                  |  
  11. | host_routes      |                                                  |  
  12. | id               | 34168195-f101-4be4-8ca8-c9d07b58d41a             |  
  13. | ip_version       | 4                                                |  
  14. | name             | sub_no_gateway                                   |  
  15. | network_id       | 3d42a0d4-a980-4613-ae76-a2cddecff054             |  
  16. | tenant_id        | 6fbe9263116a4b68818cf1edce16bc4f                 |  
  17. +------------------+--------------------------------------------------+  
复制代码


此时,DHCP agent就会在所在的节点上,在dhcp namespace内,添加一个地址169.254.169.254,并启动metadata namespace proxy监听TCP的80端口。
  1. root@network232:~# ip netns | grep qdhcp  
  2. qdhcp-9daeac7c-a98f-430f-8e38-67f9c044e299  
  3. qdhcp-3d42a0d4-a980-4613-ae76-a2cddecff054  
  4. root@network232:~# ip netns exec qdhcp-3d42a0d4-a980-4613-ae76-a2cddecff054 ip -4 a  
  5. 11: tap332ce137-ec: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN   
  6.     inet 10.1.1.3/24 brd 10.1.1.255 scope global tap332ce137-ec  
  7.     inet 10.0.0.2/24 brd 10.0.0.255 scope global tap332ce137-ec  
  8. 14: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN   
  9.     inet 127.0.0.1/8 scope host lo  
  10. 21: tap21b5c483-84: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN   
  11.     inet 10.1.1.3/24 brd 10.1.1.255 scope global tap21b5c483-84  
  12.     inet 169.254.169.254/16 brd 169.254.255.255 scope global tap21b5c483-84  
  13.     inet 10.0.10.2/24 brd 10.0.10.255 scope global tap21b5c483-84  
  14.     inet 10.0.2.2/24 brd 10.0.2.255 scope global tap21b5c483-84  
  15.     inet 172.17.17.1/24 brd 172.17.17.255 scope global tap21b5c483-84  
  16. root@network232:~# ip netns exec qdhcp-3d42a0d4-a980-4613-ae76-a2cddecff054 route -n  
  17. Kernel IP routing table  
  18. Destination     Gateway         Genmask         Flags Metric Ref    Use Iface  
  19. 10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 tap332ce137-ec  
  20. 10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 tap21b5c483-84  
  21. 10.0.10.0       0.0.0.0         255.255.255.0   U     0      0        0 tap21b5c483-84  
  22. 10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap332ce137-ec  
  23. 10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 tap21b5c483-84  
  24. 169.254.0.0     0.0.0.0         255.255.0.0     U     0      0        0 tap21b5c483-84  
  25. 172.17.17.0     0.0.0.0         255.255.255.0   U     0      0        0 tap21b5c483-84  
  26. root@network232:~# ip netns exec qdhcp-3d42a0d4-a980-4613-ae76-a2cddecff054 netstat -4 -anpt  
  27. Active Internet connections (servers and established)  
  28. Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name  
  29. tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      7035/python      
  30. tcp        0      0 10.1.1.3:53             0.0.0.0:*               LISTEN      14592/dnsmasq     
  31. tcp        0      0 169.254.169.254:53      0.0.0.0:*               LISTEN      14592/dnsmasq     
  32. tcp        0      0 10.0.10.2:53            0.0.0.0:*               LISTEN      14592/dnsmasq     
  33. tcp        0      0 10.0.2.2:53             0.0.0.0:*               LISTEN      14592/dnsmasq     
  34. tcp        0      0 172.17.17.1:53          0.0.0.0:*               LISTEN      14592/dnsmasq     
  35. root@network232:~# ps -f --pid 7035 | fold -s -w 82  
  36. UID        PID  PPID  C STIME TTY          TIME CMD  
  37. root      7035     1  0 Jun17 ?        00:00:00 python   
  38. /usr/bin/quantum-ns-metadata-proxy   
  39. --pid_file=/var/lib/quantum/external/pids/3d42a0d4-a980-4613-ae76-a2cddecff054.pid  
  40. --network_id=3d42a0d4-a980-4613-ae76-a2cddecff054 --state_path=/var/lib/quantum   
  41. --metadata_port=80 --debug --verbose   
  42. --log-file=quantum-ns-metadata-proxy3d42a0d4-a980-4613-ae76-a2cddecff054.log   
  43. --log-dir=/var/log/quantum  
  44. root@network232:~# ps -f --pid 14592 | fold -s -w 82  
  45. UID        PID  PPID  C STIME TTY          TIME CMD  
  46. nobody   14592     1  0 15:34 ?        00:00:00 dnsmasq --no-hosts --no-resolv   
  47. --strict-order --bind-interfaces --interface=tap21b5c483-84 --except-interface=lo   
  48. --pid-file=/var/lib/quantum/dhcp/3d42a0d4-a980-4613-ae76-a2cddecff054/pid   
  49. --dhcp-hostsfile=/var/lib/quantum/dhcp/3d42a0d4-a980-4613-ae76-a2cddecff054/host   
  50. --dhcp-optsfile=/var/lib/quantum/dhcp/3d42a0d4-a980-4613-ae76-a2cddecff054/opts   
  51. --dhcp-script=/usr/bin/quantum-dhcp-agent-dnsmasq-lease-update --leasefile-ro   
  52. --dhcp-range=set:tag0,10.0.2.0,static,120s   
  53. --dhcp-range=set:tag1,172.17.17.0,static,120s   
  54. --dhcp-range=set:tag2,10.0.10.0,static,120s   
  55. --dhcp-range=set:tag3,10.1.1.0,static,120s --conf-file= --domain=openstacklocal     
  56. root@network232:~# cat /var/lib/quantum/dhcp/3d42a0d4-a980-4613-ae76-a2cddecff054/opts   
  57. tag:tag0,option:router,10.0.2.1  
  58. tag:tag1,option:classless-static-route,169.254.169.254/32,172.17.17.1  
  59. tag:tag1,option:router  
  60. tag:tag2,option:dns-server,8.8.8.7,8.8.8.8  
  61. tag:tag2,option:router,10.0.10.1  
  62. tag:tag3,option:dns-server,8.8.8.7,8.8.8.8  
  63. tag:tag3,option:router,10.1.1.1  
复制代码
当DHCP客户端请求DHCP option 121时,就会收到静态路由的配置信息,在虚拟机上其实就会执行:
  1. ip route add 169.254.169.254/32 via 172.17.17.1  
复制代码


(需要注意的是,cirros镜像不会发送dhcp option 121请求)

当虚拟机内有该条静态路由后,到169.254.169.254:80的请求,就会发送到network node上dhcp namespace里的metadata nameserver proxy,proxy就会为消息添加X-Quantum-Network-ID和X-Forwarded-For头部,分别表示network-id和instance-id,然后通过Unix domain socket发送给quantum-metadata-agent,然后的流程就可以参考前一篇blog了。


















欢迎大家如about云官方群371358502,更新咨询,更新资源,随时关注

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条