|
|
虚拟机启动时候需要注入hostname、password、public-key、network-info之类的信息,以便虚拟机能够被租户管理。对于这些信息的注入openstack提供了两种方式, guestfs-inject以及metadata-server。! I; k- J% l2 G9 k3 _0 |
7 s( \& K% n6 Bguestfs-inject的使用很受限制尤其是并不是所有镜像都能够支持这种方式,I版本也以及取消了这种方式; metadata-server使用上更为灵活,但是他们都依赖镜像内部必须装有cloud-init组件,尽管如此,由于aws力挺metadata-server,所以这已经成为了虚拟机 信息注入方案事实上的标准。
7 ?, ]9 [0 y: U+ Q
' F( Y" Y. M& H8 y) m1 H本文主要探讨metadata-server在openstack中如何实现。
. ?: h* P0 O& i4 t# x2 P% @
* q: Q: m# q$ c+ F1 @8 ^* _1. cloud-init! w5 h2 p' L1 ^0 Q. |* z6 I
: d/ E$ ]+ m# i8 U. ncloud-init是一个在启动的时候定制你的Iaas平台中虚拟机的包,它可以帮助你重新定义你的虚拟机而不需要重新安装,只需要加入对应的配置项即可。在Ec2中有很多镜像都安装了cloud-init来方便用户定制自己的虚拟机。它可以让你在虚拟机启动的时候设置语言环境,设置主机名,甚至生成私钥,添加用户自己的ssh公钥到虚拟机.ssh/authorized_keys, 设置临时挂载点等等。
+ ]. G% b* ^; T, ?7 ~& ^' S! y( w4 b2 B9 D) k3 q2 o% g* {8 ~, i
cloud-init 项目地址: https://launchpad.net/cloud-init
( l4 K7 S, ~9 H* x% h, E$ W7 [( K. v
cloud-init 文档地址: http://cloudinit.readthedocs.org
7 h5 R, r+ a$ p) O5 W+ |0 c9 Z2 U; Y2 c3 z* @
2. metadata元数据服务9 \' n4 S( d* \3 ~
$ y; z2 l0 ]! g- d
metadata字面上是元数据,是一个不容易理解的概念。在除了openstack的其他场合也经常会碰到。openstack里的metadata,是提供一个机制给用户,可以设定每一个instance 的参数。9 [ }, P1 V6 v9 v& g
$ N& s& H! z: g4 c0 r' WAmazon首先提出了metadata的概念,并搭建了metadata的服务,这个服务的公网IP是169.254.169.254,通常虚拟机通过cloud-init发出的请求是:
, J3 e+ j! M( Z( B! M7 A/ k
* d- |% \. X; ~, ~http://169.254.169.254/latest/meta-data
" A5 p3 X A, M: _4 ?9 H) ]
9 u1 x4 `$ S1 n" ]6 M后来很多人给亚马逊定制了一些操作系统的镜像,比如 ubuntu, fedora, centos 等等,而且将里面获取 metadta 的api地址也写死了。所以opentack为了兼容,保留了这个地址 169.254.169.254。然后通过iptables nat映射到真实的api上。5 Z3 i! _, \% P# r: c
( i+ Y, e* Y7 r
metadata在openstack中的BP: https://blueprints.launchpad.net ... nstack-api-metadata
c# p% A& G( `2 p1 s2 W5 [* W |' _3 e6 e2 V* R# u
nova中的metadata-server
; Y* ]- w6 Q P% y3 h k. k: h" `2 |9 q' g
metadata-server的具体实现是在nova-api组件中,nova.conf中与metadata有关的配置如下:
* u) }; i! `% j- F" renabled_apis=ec2,osapi_compute,metadata
, z' u: u: j5 q, K5 _7 x
: W! B. Q& Z( m8 L& H# OpenStack metadata service manager
) R9 u- H. e$ R1 k% J4 vmetadata_manager=nova.api.manager.MetadataManager
' D$ S: e, u4 H) P ]+ S6 g' j6 E: N
# IP address for metadata api to listen# f, m) D, H9 x6 |, o( ?% y
metadata_listen=0.0.0.0( H5 h4 n) x5 W: X5 {" h5 C$ Z
$ @5 [) h& f F/ Q0 l0 V# port for metadata api to listen
$ s3 @: O7 D' Q6 ^: G, i! fmetadata_listen_port=8775
6 n) n4 G0 R: @) q- b7 P
% m) ~7 i1 w2 ?+ K7 z% J+ ~& w v+ o# Number of workers for metadata service
3 V/ V7 G8 ^/ x2 g8 c1 umetadata_workers=
" U% F: H9 B' Y- f
6 J7 p. \1 q) c1 P$ t* b& M3 V# 和neutron-metadata-agent 通信相关: o2 O8 Q) O. ~0 G
service_neutron_metadata_proxy=True; {+ d# N, a2 A/ ]8 j5 [
neutron_metadata_proxy_shared_secret=, [" E. M$ H! c8 P& y
+ W* \, u3 B0 K' T3 [
) [) _# C; }; W' W: u
具体的代码实现在 api/metadata 下:
+ e+ n3 M' I# e
/ X0 x( {. K" D; j- imetadata=metadata {8 u- p: Y1 ?2 {* i
__init__.py9 `* X" T8 ?+ A
base.py7 z* A2 { k% u2 n
handler.py
, W( r. Y C$ ~% x5 u password.py) J. g' u) y3 ]6 Y
vendordata_json.py: J! e3 ?" o" w @+ h
}
6 v: s0 D; H* X; J" A5 w# ]0 W+ e; u* E6 `, n8 A& c0 q* ^
; }% ~7 \ F, s! }& ~: ~ G2 P$ V与neutron的结合使用
. D* q2 n$ [' F" |0 m/ r1 I通常我们使用neutron实现虚拟机的网络方案,neutron的metadata-agent并不会自己实现metadata服务,而是把cloud-init的请求转发给nova-api中的metadata服务,具体服务流程请看下图:0 ?# Q1 n# m0 ~& u& W
. x: k" x& r0 w/ J5 h( m8 J. C
) N0 M6 N# q- ^: g虚拟机通过cloud-init组件请求169.254.169.254这个地址的metadata服务,这时这个请求会有两种方式处理。
& L7 z& X3 I* e7 Q server" title="openstack中的metadata server" action-data="http%3A%2F%2Fs14.sinaimg.cn%2Fmw690%2F0000cGopgy6TdIm27252d%26690" action-type="show-slide" style="border-width: 0px; border-style: initial; list-style: none;">
9 S0 g: N7 j* t3 @7 z" r4 U" L5 ^% F+ a- ]
" w0 q3 S6 q/ N5 _% k, f3 n2 @
当虚拟机所在的子网拥有网关而且连接了l3-router,则通过qrouter的namespace中的iptables处理; 当虚拟机所在的子网没有网关,是个封闭的子网,那么dhcp服务的虚拟网卡会添加一个169.254.169.254的ip;5 A8 O) r1 j! ?8 S$ y2 T7 g
接收的cloud-init请求由ns-metadata-proxy处理,ns-metadata-proxy与metadata-agent通过unix domain socket实现IPC,实现将对ns-metadata-proxy的请求交给metadata-agent处理。
, L( B3 F+ P3 bmetadata-agent接收请求,将请求交给metadata-server的真实实现者nova-api。
/ v% W" m- s6 e2 i( _' D0 I* H# r# l1 B" g( t
|
|