找回密码
 注册
查看: 5018|回复: 3

OpenStack Heat 如何来实现和支持编排

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2017-11-6 18:28:08 | 显示全部楼层 |阅读模式
OpenStack 简介
[size=1.0625]OpenStack 是一个云计算操作平台,可以大规模地协调云,管理计算资源、存储资源、网络资源等基础架构。OpenStack 是由 Rackspace Cloud 和 NASA 在 2010 年发起的。 自成立以来,OpenStack 已经获得业界广泛认可,目前,它的支持者包括许多业内最大的组织。它目前的白金会员包括 IBM、Rackspace、Red Hat 和 SUSE 等。
OpenStack Heat 介绍
[size=1.0625]Heat 是一个基于模板来编排复合云应用的服务。 它目前支持亚马逊的 CloudFormation 模板格式,也支持 Heat 自有的 Hot 模板格式。模板的使用简化了复杂基础设施,服务和应用的定义和部署。模板支持丰富的资源类型,不仅覆盖了常用的基础架构,包括计算、网络、存储、镜像,还覆盖了像 Ceilometer 的警报、Sahara 的集群、Trove 的实例等高级资源。
图 1. Heat 和其它模块的关系Heat Architecture
[size=1.0625]Heat 服务包含以下重要的组件:
  • Heat-api 组件实现 OpenStack 天然支持的 REST API。该组件通过把 API 请求经由 AMQP 传送给 Heat engine 来处理 API 请求。
  • Heat-api-cfn 组件提供兼容 AWS CloudFormation 的 API,同时也会把 API 请求通过 AMQP 转发给 heat engine。
  • Heat-engine 组件提供 Heat 最主要的协作功能。" G' b* b) s1 W! T* f% D
[size=1.0625]用户在 Horizon 中或者命令行中提交包含模板和参数输入的请求,Horizon 或者命令行工具会把请求转化为 REST 格式的 API 调用,然后调用 Heat-api 或者是 Heat-api-cfn。Heat-api 和 Heat-api-cfn 会验证模板的正确性,然后通过 AMQP 异步传递给 Heat Engine 来处理请求。
图 2. Heat 架构
[size=1.0625]当 Heat Engine 拿到请求后,会把请求解析为各种类型的资源,每种资源都对应 OpenStack 其它的服务客户端,然后通过发送 REST 的请求给其它服务。通过如此的解析和协作,最终完成请求的处理。
[size=1.0625]Heat Engine 在这里的作用分为三层: 第一层处理 Heat 层面的请求,就是根据模板和输入参数来创建 Stack,这里的 Stack 是由各种资源组合而成。 第二层解析 Stack 里各种资源的依赖关系,Stack 和嵌套 Stack 的关系。第三层就是根据解析出来的关系,依次调用各种服务客户段来创建各种资源。
图 3. Heat Engine 结构编排
[size=1.0625]编排,顾名思义,就是按照一定的目的依次排列。在 IT 的世界里头,一个完整的编排一般包括设置服务器上机器、安装 CPU、内存、硬盘、通电、插入网络接口、安装操作系统、配置操作系统、安装中间件、配置中间件、安装应用程序、配置应用发布程序。对于复杂的需要部署在多台服务器上的应用,需要重复这个过程,而且需要协调各个应用模块的配置,比如配置前面的应用服务器连上后面的数据库服务器。下图显示了一个典型应用需要编排的项目。
图 4. 编排
[size=1.0625]在云计算的世界里,机器这层就变为了虚拟的 VM 或者是容器。管理 VM 所需要的各个资源要素和操作系统本身就成了 IaaS 这层编排的重点。操作系统本身安装完后的配置也是 IaaS 编排所覆盖的范围。除此之外,提供能够接入 PaaS 和 SaaS 编排的框架也是 IaaS 编排的范围。
Heat 编排
[size=1.0625]OpenStack 从最开始就提供了命令行和 Horizon 来供用户管理资源。然而靠敲一行行的命令和在浏览器中的点击相当费时费力。即使把命令行保存为脚本,在输入输出,相互依赖之间要写额外的脚本来进行维护,而且不易于扩展。用户或者直接通过 REST API 编写程序,这里会引入额外的复杂性,同样不易于维护和扩展。 这都不利于用户使用 Openstack 来进行大批量的管理,更不利于使用 OpenStack 来编排各种资源以支撑 IT 应用。
[size=1.0625]Heat 在这种情况下应运而生。Heat 采用了业界流行使用的模板方式来设计或者定义编排。用户只需要打开文本编辑器,编写一段基于 Key-Value 的模板,就能够方便地得到想要的编排。为了方便用户的使用,Heat 提供了大量的模板例子,大多数时候用户只需要选择想要的编排,通过拷贝-粘贴的方式来完成模板的编写。
[size=1.0625]Heat 从四个方面来支持编排。首先是 OpenStack 自己提供的基础架构资源,包括计算,网络和存储等资源。通过编排这些资源,用户就可以得到最基本的 VM。值得提及的是,在编排 VM 的过程中,用户可以提供一些简单的脚本,以便对 VM 做一些简单的配置。然后用户可以通过 Heat 提供的 Software Configuration 和 Software Deployment 等对 VM 进行复杂的配置,比如安装软件、配置软件。接着如果用户有一些高级的功能需求,比如需要一组能够根据负荷自动伸缩的 VM 组,或者需要一组负载均衡的 VM,Heat 提供了 AutoScaling 和 Load Balance 等进行支持。如果要用户自己单独编程来完成这些功能,所花费的时间和编写的代码都是不菲的。现在通过 Heat,只需要一段长度的 Template,就可以实现这些复杂的应用。Heat 对诸如 AutoScaling 和 Load Blance 等复杂应用的支持已经非常成熟,有各种各样的模板供参考。最后如果用户的应用足够复杂,或者说用户的应用已经有了一些基于流行配置管理工具的部署,比如说已经基于 Chef 有了 Cookbook,那么可以通过集成 Chef 来复用这些 Cookbook,这样就能够节省大量的开发时间或者是迁移时间。本文稍后会分别对这四个方面做一些介绍。
图 5. Heat 编排Heat 模板
[size=1.0625]Heat 目前支持两种格式的模板,一种是基于 JSON 格式的 CFN 模板;另外一种是基于 YAML 格式的 HOT 模板。CFN 模板主要是为了保持对 AWS 的兼容性。HOT 模板是 Heat 自有的,资源类型更加丰富,更能体现出 Heat 特点的模板。
[size=1.0625]一个典型的 HOT 模板由下列元素构成:
  • 模板版本:必填字段,指定所对应的模板版本,Heat 会根据版本进行检验。
  • 参数列表:选填,指输入参数列表。
  • 资源列表:必填,指生成的 Stack 所包含的各种资源。可以定义资源间的依赖关系,比如说生成 Port,然后再用 port 来生成 VM。
  • 输出列表:选填,指生成的 Stack 暴露出来的信息,可以用来给用户使用,也可以用来作为输入提供给其它的 Stack。: C. a7 _+ u5 y! S4 D
[size=1.0625]对于 CFN 模板和 HOT 模板的不同,包括所支持的资源类型的不同,不在本文的讨论范围内。本文会主要用 HOT 模板。HOT 模板的全称是 Heat Orchestration Template,是 Heat 发展的重心。
Heat 对基础架构的编排
[size=1.0625]对于不同的资源,Heat 都提供了对应的资源类型。比如对于 VM,Heat 提供了 OS::Nova::Server。OS::Nova::Server 有一些参数,比如 key、image、flavor 等,这些参数可以直接指定,可以由客户在创建 Stack 时提供,也可以由上下文其它的参数获得。
清单 1. 创建一个 VM/ `8 N* D1 J- j% Q* X3 I
resources:1 e! p, j3 i& x& D3 q
server:8 a5 y# m8 M/ x0 M; T* s, V
type: OS::Nova::Server
2 B4 c4 z1 N- o7 G! c8 p' @$ ?properties:
" ]! u3 e: ^1 tkey_name: { get_param: key_name }& [" N. F2 V" o! j/ L
image: { get_param: image }
2 w9 Y5 ^) f0 nflavor: { get_param: flavor }
/ }- E3 U" Z& J0 C$ ~user_data: |( H$ _. X" d4 C" A& R5 Q# q1 ~
#!/bin/bash
0 O: S0 H6 V3 |1 q' ~. {* m9 Fecho “10.10.10.10 testvm” >> /etc/hosts
' N, W, y# |# ?& }- V; e$ t4 T7 h1 X5 e) |/ ~' E" _6 K
! d. y# c# V' s5 c; S6 W
[size=1.0625]在上面创建 VM 的例子中,我们选择从输入参数获得 OS::Nova::Server 所需的值。其中利用 user_data 做了一些简单的配置。
Heat 对软件配置和部署的编排
[size=1.0625]Heat 提供了多种资源类型来支持对于软件配置和部署的编排,如下所列:
  • OS::Heat::CloudConfig: VM 引导程序启动时的配置,由 OS::Nova::Server 引用
  • OS::Heat::SoftwareConfig:描述软件配置
  • OS::Heat::SoftwareDeployment:执行软件部署
  • OS::Heat::SoftwareDeploymentGroup:对一组 VM 执行软件部署
  • OS::Heat::SoftwareComponent:针对软件的不同生命周期部分,对应描述软件配置
  • OS::Heat::StructuredConfig:和 OS::Heat::SoftwareConfig 类似,但是用 Map 来表述配置
  • OS::Heat::StructuredDeployment:执行 OS::Heat::StructuredConfig 对应的配置
  • OS::Heat::StructuredDeploymentsGroup:对一组 VM 执行 OS::Heat::StructuredConfig 对应的配置
    : n4 d, X2 a0 N& [) W
[size=1.0625]其中最常用的是 OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment。
OS::Heat::SoftwareConfig
[size=1.0625]下面是 OS::Heat::SoftwareConfig 的用法,它指定了配置细节。
清单 2. 最常见的 OS::Heat::SoftwareConfig 用法
7 y4 e' q) w1 F7 b8 m) c$ P8 G# H6 N8 F

# t6 L' }! i, [( t% P) qresources:
! t7 E2 j  o! d3 \install_db_sofwareconfig' {2 a  _4 o5 G% I$ I
type: OS::Heat::SoftwareConfig
# {1 x. r% |3 U8 eproperties:
7 |: ]+ k# m7 A: A7 Sgroup: script
0 I1 Z3 f. z) Soutputs:6 ^0 a2 q& ]' p7 e
- name: result  Y# ]. m4 U+ E4 n' Y
config: |
: M4 c: u& K( f( Y' i2 V#!/bin/bash -v
. q8 g+ w. O8 e4 Y5 y. `; `yum -y install mariadb mariadb-server httpd wordpress
: q/ ]7 Z$ D* G2 R$ n: w! P0 }3 \touch /var/log/mariadb/mariadb.log
& t: O3 D% \3 ^' k7 l: Qchown mysql.mysql /var/log/mariadb/mariadb.log: f2 V- [1 |, V0 y2 |
systemctl start mariadb.service
# I9 _' ?- s7 `* Y8 L) x% B7 M$ F) S' M) s+ ?* ]+ o
1 b# k! F2 _- T7 \  E6 Z9 v
OS::Heat::SoftwareDeployment
[size=1.0625]下面是 OS::Heat::SoftwareDeployment 的用法,它指定了在哪台服务器上做哪项配置。另外 SofwareDeployment 也指定了以何种信号传输类型来和 Heat 进行通信。
清单 3. OS::Heat::SoftwareDeployment 样例" w( p# J- u% ~$ |
; b: R4 U; @2 Z
sw_deployment:& H% d) V# [% l: }& b$ p7 o" _
type: OS::Heat::SoftwareDeployment. c% y! C% P( i3 {5 u
properties:
5 F: F; y/ V  k  Fconfig: { get_resource: install_db_sofwareconfig }+ B$ j0 q- K* E2 A
server: { get_resource: server }: A; t1 R% f! c1 p2 A
signal_transport: HEAT_SIGNAL$ ]2 a' r, [/ T7 k2 i6 C# A
& O- J9 a# `9 M" j

1 e; E) x. u' M+ g& L' _* |OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment 流程
[size=1.0625]OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment 协同工作,需要一系列 Heat 工具的自持。这些工具都是 OpenStack 的子项目。
[size=1.0625]首先,os-collect-config 调用 Heat API 拿到对应 VM 的 metadata。
[size=1.0625]当 metadata 更新完毕后,os-refresh-config 开始工作了,它主要是运行下面目录所包含的脚本:
  • /opt/stack/os-config-refresh/pre-configure.d
  • /opt/stack/os-config-refresh/configure.d
  • /opt/stack/os-config-refresh/post-configure.d
  • /opt/stack/os-config-refresh/migration.d
  • /opt/stack/os-config-refresh/error.d
    5 e/ L+ Z9 ?% @# W6 ?
[size=1.0625]每个文件夹都应对了软件不同的阶段,比如预先配置阶段、配置阶段、后配置阶段和迁移阶段。如果任一阶段的脚本执行出现问题,它会运行 error.d 目录里的错误处理脚本。os-refresh-config 在配置阶段会调用一定预先定义的工具,比如 heat-config,这样就触发了 heat-config 的应用,调用完 heat-config 后,又会调用 os-apply-config。存在在 heat-config 或者 os-apply-config 里的都是一些脚本,也叫钩子。Heat 对于各种不同的工具提供了不同的钩子脚本。用户也可以自己定义这样的脚本。
[size=1.0625]等一切调用完成无误后,heat-config-notify 会被调用,它用来发信号给 Heat,告诉这个软件部署的工作已经完成。
[size=1.0625]当 Heat 收到 heat-config-notify 发来的信号后,它会把 OS::Heat::SoftwareConfig 对应资源的状态改为 Complete。如果有任何错误发生,就会改为 CREATE_FAILED 状态。
图 6. OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment 流程图Heat 对资源自动伸缩的编排
[size=1.0625]基础架构的自动伸缩是一个很高级的功能。Heat 提供自动伸缩组 OS::Heat::AutoScalingGroup 和伸缩策略 OS::Heat::ScalingPolicy,结合基于 Ceilometer 的 OS::Ceilometer::Alarm 实现了可以根据各种条件,比如负载,进行资源自动伸缩的功能。
图 7. Heat 自动伸缩的流程图
) Q! u: X' @2 F( A$ Q9 g+ W清单 4. 定义自动伸缩组) p$ D" e7 Q4 \  e# ]3 G

" x. v$ [7 q, b- ?' n- V0 Qauto_scale_group:- W$ G6 q) W& _; n
type: OS::Heat::AutoScalingGroup7 n8 {% F! p) ~  q; G, C/ |, ^. X
properties:
9 V7 d, c( C  ~5 Y) o+ I, @min_size: 1  S- o+ p, a4 ~7 I
max_size: 41 l2 w* {$ e/ y

) l% ~; A4 W8 f- K
5 X# _6 F' A/ J& }1 e清单 5. 定义伸缩规则
6 R8 ~& s; K1 }3 ^2 Wserver_scaleup_policy:; r  k$ G/ z1 y1 p4 j; g
type: OS::Heat::ScalingPolicy% w) B) P" k1 s7 m: b0 N
properties:
1 m, t4 }! L' R0 dadjustment_type: change_in_capacity
# a" C% Z6 E# c/ J( S8 h  [$ w+ Tauto_scaling_group_id: {get_resource: auto_scale_group}
6 \. s. y: p* V" Ycooldown: 60
! B3 t# M1 I8 s% @3 |' y  Wscaling_adjustment: 16 B, U3 |8 y+ t4 O* d% L
$ D1 e2 \% g; n7 T2 E. r$ t
" `) }# I$ d( _- p1 H3 p; E
' _  U  ~& F( f( s! L$ N
7 ^# o! s3 u. R6 V* ?+ R3 E8 O
1 w5 f$ w) G  I/ Q+ U8 q6 {: w2 E, e

8 v& D0 U0 k/ o( }( \" w9 V3 \6 N' U; U- z' L) G
清单 6. 定义警报
  N4 F& u$ K* q: d. Q# m. O8 [: q% M0 i' n, N; ~# u1 g
9 F' K1 T* A0 y, ~" v
cpu_alarm_high:
8 E. c4 `& }& B8 N. {type: OS::Ceilometer::Alarm
, }7 b& @9 B2 G6 f/ Eproperties:
( b/ m4 a' W9 [" Y: Pdescription: Scale-up if the average CPU > 50% for 1 minute! |4 s1 M* T0 t+ ]
meter_name: cpu_util
2 B* o4 U5 F  T( g7 k0 xstatistic: avg
! i& c1 g8 a% l  Z# L, P& uperiod: 60
- E# z( z7 m8 o6 @evaluation_periods: 1
6 c( r: h; W  y/ _threshold: 50
8 i$ q% v# t3 t  V7 L- Falarm_actions:
; V* i3 k( D% X& F$ A- F9 |7 Y* Q/ j8 S- {get_attr: [server_scaleup_policy,alarm_url]}
5 z, c$ {$ j4 `# G4 v; T7 O% Pmatching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}& Y& T+ }: F3 Z# ^$ S: r" y8 ?* t
comparison_operator: gt
' M6 U; G9 W8 D- P% v( Q5 E8 o8 G  B. V1 {8 M* d2 d
Heat 对负载均衡的编排
[size=1.0625]负载均衡也是一个很高级应用,它也是由一组不同的资源类型来实现的。资源类型包括:
  • OS::Neutron::Pool:定义资源池,一般可以由 VM 组成
  • OS::Neutron::PoolMember:定义资源池的成员
  • OS::Neutron::HealthMonitor:定义健康监视器,根据自定的协议,比如 TCP 来监控资源的状态,并提供给 OS::Neutron::Pool 来调整请求分发
  • OS::Neutron::LoadBalancer:关联资源池以定义整个负载均衡。
    $ n, }3 v. i% `5 p& i/ f4 r# ?7 M
图 8. Heat 负载均衡清单 7. Monitor 的定义8 f' A4 N: g3 @2 p
monitor:  {* c+ ^# z, l2 M2 w; b
type: OS::Neutron::HealthMonitor
" @0 b3 G8 `& T! u. G& }: }7 kproperties:6 G2 D2 t0 o5 Z
type: TCP+ l: ]' H$ b3 Y, S
delay: 3
  t. o/ S9 b. c% p' tmax_retries: 5* @' V- o0 ^5 V1 j5 j$ C
timeout: 3  V8 s. n) h/ k. G. y: R; a

7 G9 h$ E/ z! f: R# m) d  N! J7 n8 E% u8 W. W: d

! A/ ^8 C! `2 @& P2 w0 O7 D5 J清单 8. Pool 成员的定义
, s, W8 S: ?5 f+ e0 \6 F* Y4 Bmember:
4 u, n$ k! S( e4 s8 _" ]type: OS::Neutron::PoolMember   (PoolMember)
1 P' a) [9 j* `' N2 x3 v9 ]properties:
+ Q) Q  i' g9 ?. a) ]$ Z  _pool_id: {get_resource: pool} (pool)/ K! F1 N# \7 l+ m& W
address: {get_attr: [my_server,first_address]}
: E" [: q; A) w' x8 X; hprotocol_port: 80/ E- H( h! @6 R2 @7 K$ D
other_member:2 [! O3 ~% N: \2 d% L! c
type: OS::Neutron::PoolMember  (PoolMember)  n4 p$ @5 b, ~. P
properties:' g0 S* k; j3 K  T# ^9 ], v
pool_id: {get_resource: pool}# c3 S, m5 i0 a# k9 _
address: {get_attr: [my_other_server,first_address]}
. [) g7 `. C3 l$ T5 qprotocol_port: 80
/ q6 v3 |, {  d8 z1 A" M
+ v6 i# X0 ?1 g; y- x/ b7 K( \" J6 z& }3 {" C5 H
! Q* V: _3 `9 y  Y& X2 M; W
清单 9. Pool 的定义
9 w4 }7 ?5 e6 m7 D% F( ~: ^pool:
( V+ Q( `: B+ d  N. \; y! y( Q2 atype: OS::Neutron::Pool (Pool 之间还有冒号)
! e: c* q) z6 X/ Gproperties:
5 m  C2 \3 L8 N% _0 Kprotocol: HTTP! d+ M. O' x! u5 F/ {5 M3 w
monitors: [{get_resource: monitor}]) E3 y5 @  y7 F2 j6 o
subnet_id: {get_param: network_subnet_lb_pool}, j" q1 n4 J7 d9 k) ?
lb_method: ROUND_ROBIN' Z9 p: Q$ j9 j6 Y' u+ s  S
vip:# K, Z5 I/ X2 z. w8 z
protocol_port: 80
, `3 X7 z; o* @* X7 L8 A) W8 O; h2 F. l) [0 |3 B2 e
8 L0 s3 k) F9 }. @" Y' c
0 s0 E4 Y7 a, W! K; w! n, F

% d5 {, i9 F* O, ^清单 10. LoadBalancer 的定义
, u& q0 [  e/ t, h5 Zlb:
' d* M+ c7 L  [5 Ctype: OS::Neutron::LoadBalancer (LoadBalancer); P% Z8 S; |2 C3 q# d8 V, t* _# Y
properties:
7 }3 v. Q9 C; ^% h3 P* `) K  Vprotocol_port: 80
. ^( m' ^' d' t* q: y( r6 }/ jpool_id: {get_resource: pool}
: ?% {. k3 E9 \% L, [0 R1 Q% ?+ q1 H# j
% Y8 ~6 v4 h/ `! x: H2 `6 v

- B. ?) j2 ^2 b) l& C  p% J& d- @, n* V* F' J/ q) u$ ^

3 |4 ]8 P: A4 [8 hHeat 和配置管理工具集成
[size=1.0625]随着 DevOps 的流行,大量配置管理的工具应运而生,比如 Chef、Puppet 和 Ansible。各种工具除了提供一个平台框架外,更是针对大量的中间件和软件部署提供了可以灵活配置和引用的脚本。以 Chef 为例,它提供了大量针对开源软件的 cookbook。各大厂商也给自己的中间件编写了 cookbook,比如说 IBM 给 DB2 提供了 cookbook。有了这些 cookbook,用户就可以通过简单的配置和应用来部署复杂的中间件或者软件应用。
[size=1.0625]Heat 在基于 OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment 的协同使用上,提供了对这些配置管理工具的支持。
[size=1.0625]首先,对于 OS::Heat::SoftwareConfig 而言,需要其 group 定义为对应的类型。比如有 ansible、puppet、docker-compose 和 salt 等。
清单 11. group: ansible 的 OS::Heat::SoftwareConfig, S* |/ L* i% W2 O
config:5 X, [' [1 D9 Q; V$ [
type: OS::Heat::SoftwareConfig7 q# W- X. a" x' z5 I
properties:1 V! v! ~6 W# c5 f
group: ansible0 L# M5 G' Q5 l
inputs:
$ I4 a# _9 X0 N- name: foo
# H+ u+ H; R" F$ I2 N6 Q: G5 j- name: bar
# j. ^& c+ A8 s! N3 houtputs:) c% Q7 }- q# @7 F; z) Z1 L
- name: result; ^1 k$ {2 N) t& n% d5 p) F& w
config:
) Y: Y" v, r2 ^+ nget_file: config-scripts/example-ansible-template.ansible( ~+ l0 w) F9 e9 J

' }4 }  `" R, p' n2 Z% f% D6 I) R+ D/ R1 @; K

& D# Z& r/ \  G) h* S9 B# r  ^! d. i. r* N
: o. S- W/ O% W- e8 a/ a
[size=1.0625]然后再 OS::Heat::SoftwareDeployment 引用 OS::Heat::SoftwareConfig。
清单 12. 引用 OS::Heat::SoftwareConfig 的 OS::Heat::SoftwareDeployment8 X4 r5 o' v! e! ]+ l) q+ a
other_deployment:) ^6 D# x* L! F
type: OS::Heat::SoftwareDeployment
8 |+ B0 j  v" ?/ ^5 n& Qproperties:
# q' ~% F, u1 g. D* `5 }config:- v& h) m/ a6 G! O6 v: s- Q2 A2 Z
get_resource: config! }' t3 t2 @$ W! L& p1 u
server:
' ?/ d. A  P% D! Z+ r4 m# Aget_resource: server
7 N+ q4 ?: E  r" e% z' _input_values:
% K  I6 `* f7 l( i  kfoo: fu- i, ]% F, P# G( \8 f
bar: barmy
+ t+ N5 C- B$ Q0 `2 H. E
. J# E& A9 l. b7 Y: `3 m8 g+ m: ]- S* M. ]4 `- h

6 F4 H2 m+ _" g" [9 G3 G: B1 g. J8 x% q6 I) P# o/ c
  o1 o1 ^% ?/ n! ~5 K8 W
[size=1.0625]这样在软件部署的时候,就会调用对应的脚本钩子 heat-config-ansible 来执行对应的软件配置。
图 9. group:ansible 的 OS::Heat::SoftwareConfig 和 OS::Heat::SoftwareDeployment 流程Heat 和 IBM UCDP/UCD 的集成
[size=1.0625]随着云计算的逐步兴起,各种基于云计算的的部署编排工具开始出现了。从目前来看,主要有跨平台,可视化,强大的配置管理功能等几个方面。其中 IBM 的 UrbanCode Deploy with Patterns(UCDP)和 UrbanCode Deploy(UCD)是一种强大的平台,具备上述的特性。
[size=1.0625]UCDP 是全栈的环境管理和部署解决方案,支持用户为多种云设计、部署和更新全栈环境。该平台可集成 UCD,基于 Heat 来实现对 OpenStack 基础架构自动化来优化持续的交付吞吐量。它具备可视化的操作界面。通过拖拽图标来创建和编辑跨云平台的模板。
[size=1.0625]UCD 将应用、中间件配置以及数据库的变更进行编排并自动部署到开发环境、测试环境和生产环境中。它能让用户通过自助服务方式,根据需要或按照计划进行部署。在 UCD 中,能够按照配置(configuration-only)或者传统的代码和配置(code-and-configuration)来分拆复杂的应用配置进行逐步定义。
[size=1.0625]通过借助于 UCDP 强大的 Pattern 设计能力,我们可以通过拖拽的方式制作一个复杂的模板。其中用到两种类型的资源,一种是云计算资源,比如说网络、安全组、镜像等,另外是定义于 UCD 中的组件,比如其中的 Jke.db、MySQL Server、jke.war 和 WebSphere Liberty Profile.
图 10. UCDP 强大的 Pattern 设计能力
[size=1.0625]通过借助 UCDP/UCP 和 Heat 的集成,可以很方便的点击按钮来生成对应的环境(UCDP/UCD 用语)或者 Stack(Heat 用语)。
[size=1.0625]首先,UCDP 把设计好的模板发给 Heat。然后 Heat 会调用 UCD 扩展插件来解释模板并翻译为 Heat 能够认识的模板,这个过程有可能需要访问 UCD 得到更为细节的解释。接着 Heat 去生成相应的资源,一般肯定有 VM,并在 VM 上安装 UCD agent,并启动 agent。Agent 会调用 UCD 拿到具体组件,比如 WebSphere Liberty Profile 的部署定义细节,然后执行。最终完成 Stack 的生成。
图 11. UCDP/UCD 和 Heat 的集成结束语
[size=1.0625]本文介绍了 OpenStack 和 OpenStack Heat,特别是 Heat 的架构。然后介绍了什么是编排,Heat 在编排的位置,以及 Heat 模板。接着本文逐一介绍了 Heat 是如何来实现和支持编排,分别从基础架构,软件配置和部署,自动资源伸缩和负载均衡等角度进行了叙述。本文最后介绍了 Heat 和配置管理工具的集成,以及 Heat 和 IBM UCDP/UCD 的集成。
[size=1.0625]随着云计算的日益流行,各种云计算平台大量兴起。谁最终能被行业和用户接受,一定是取决于谁能够高效支持用户复杂应用的编排。Heat 对编排的全方位支持将有力地支持 OpenStack 在云计算,特别是在 IaaS 中领导地位。对此,我们拭目以待。

7 ?- @/ L& c5 o9 ?/ m& F% T2 o
+ A3 X$ V" Q7 n

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-11-10 21:54:22 | 显示全部楼层
heat_template_version: 2015-04-30- U) a7 S+ G: V! Q) d9 p0 `7 S
description: >( q1 s  y! j- D# w
  A template showing how to create a Nova instance, a Cinder volume and attach
! [. A; T6 o3 ?, t* z8 H! [! u7 ]  the volume to the instance. The template uses only Heat OpenStack native' ?/ `" P  l5 @* \
  resource types.
+ I1 X( ^4 j9 S2 V  w/ c4 Nparameters:
% w& d$ f, \! E: k  key_name:6 i1 u" i& v- K; i
    type: string
) D' W) V. @) t7 Y    default: linux_key7 ~! f! ]* N* h1 Q% l) \. @$ h6 \
    description:
3 y: L  m! w4 @$ q8 c6 o      Name of an existing key pair to enable SSH access to the instance.
; |# o: B# |4 x6 l% `  instance_type:+ N/ B+ l" ^, O
    type: string! Z6 u; L. s0 s9 c- I
    description: Type of the instance to be created.
+ [8 n$ ~6 E. \! @) t6 P* B    default: m1.small
. M) x" v6 \6 {' f3 e    constraints:
7 _8 w  P  e% @( V2 m      - allowed_values: [m1.small, m1.medium, m1.large]
! Z) T3 O9 c# a) q, n/ ^        description:/ i! |8 N9 h9 ^1 y( W$ {+ C' {6 T
          Value must be one of 'm1.small', 'm1.medium' or 'm1.large'.
/ ^5 \! j, d" y  image_id:
, a3 g4 |3 e! c1 y) W0 K$ Q    type: string
7 b$ R; d8 E% Y- ^    description: ID of the image to use for the instance to be created.; |0 M1 S- S: ?9 C7 d
    default: linux_img0 H/ }* R; E) D" U0 l* H
    constraints:
" v7 w4 N4 b8 K: w      - allowed_values: [ linux_img ]- E) m! b& y( ~5 j; H- R2 x$ N
        description:
2 m5 D9 g! Z) Q/ [# @* ?  M          Image ID must be linux_img+ H5 d# g# ~% g
  availability_zone:1 Q: j  F$ \0 `# \) y
    type: string  V; |) L' G1 B; X$ z, f/ `
    description: The Availability Zone to launch the instance.
& f3 P" x8 @. L4 p" c    default: nova9 a) ~6 l* {4 T, w. v
  volume_size:
% I$ I3 `* K4 B, [  d  R    type: number
& F  I# [) T( _+ ]    description: Size of the volume to be created.
9 \( ?3 L  }* S1 N; g) @    default: 1
  E3 Q5 T" p' a. ~    constraints:8 [( U7 Y) K. G5 y; g2 |
      - range: { min: 1, max: 1024 }' @/ d. R( k; {1 t. k' o, B; ]
        description: must be between 1 and 1024 Gb.: v+ s- M) B9 _9 M2 _: @
resources:; K7 C3 w" A/ B' e+ b2 |( O
  avoltest:; C0 T6 r' @( d
    type: OS::Nova::Server
% j, k1 E1 z7 l8 d6 F    properties:
5 i! U/ [+ T/ g# D# {      availability_zone: { get_param: availability_zone }
  R, f5 W3 a, g5 ~+ v. J      image: { get_param: image_id }0 {2 ?2 I: r6 k
      flavor: { get_param: instance_type }3 k& T. u, I& V6 l  n9 [
      key_name: { get_param: key_name }
% C( b9 J% g% }6 a6 c7 Z      user_data_format: RAW) t6 ^" U# t% w( N
      user_data:
3 X, }. W  x2 ~+ p& H! b        str_replace:/ v5 H5 \9 h7 ~' X- j' }
          params:
( X+ I) I7 ~: X, M* u7 v' f/ a( V            $LOGFILE: /tmp/installlog.log% P) J2 f" |. X0 D) u$ g
            $VOLSIZE: { get_param: volume_size }
. L/ V& N$ _( P/ u( S          template: |
3 a( j# c; F2 c5 A9 {. s( s            #!/bin/bash -v  i0 O5 r4 c6 g- |; ]0 P! ]- d0 l
              die() {1 s& O2 D: [# `( X1 M3 E( a/ ~. u
              _WC-NOTIFY_ --data-binary '{"status": "FAILURE"}'0 t, Q* T/ ?; G% `' y' N; Z3 P
                exit 1
4 ^' A5 s( ~8 m  H' W6 N1 n7 L5 H% Z              }- `! H$ Z7 A( v0 U
            yum install -y lvm2 >> $LOGFILE 2>&1 || die/ X8 \- D' }8 M3 {# T. M- [6 b4 l
            pvcreate /dev/sdb >> $LOGFILE 2>&1 || die  T5 d: _' J2 A# w- P
            vgcreate volgroup01 /dev/sdb >> $LOGFILE 2>&1 || die, Z! }5 n' G) G
            lvcreate -l+100%FREE -n lvol01 volgroup01 >> $LOGFILE 2>&1 || die
+ \$ t9 e6 T5 g            mkfs.ext4 -F /dev/mapper/volgroup01-lvol01 >> $LOGFILE 2>&1 || die
" i- E0 P, S- h  \$ [! q            mkdir /data. n- T! P' y6 ^: r3 r
            echo "/dev/mapper/volgroup01-lvol01 /data ext4 defaults 0 0" >> /etc/fstab
' X: H8 v9 C+ V+ b9 H: d' u            mount -a& B8 |# @! `6 t& ~0 q  r/ m
            df -ah >> $LOGFILE 2>&1 || die
& N: E% O" d' b. d1 \$ ?  \, e7 r  cinder_volume:
# Z, {' k0 R% Y# m  g) W. _! M3 w    type: OS::Cinder::Volume7 T- z8 G# r4 A& j1 r" _5 Z
    properties:
! A* v" |( [5 G1 N  c      size: { get_param: volume_size }
  l1 S7 B  ]+ K6 k6 ?% p) _      availability_zone: { get_param: availability_zone }
5 @% g+ y4 K) ~% N& t  volume_attachment:
% t5 x) k: O2 [) Q! D: s: A) t    type: OS::Cinder::VolumeAttachment
, Q2 m6 Q4 i6 w7 }: }    properties:' Y7 V+ r" f" j1 ?
      volume_id: { get_resource: cinder_volume }7 U0 m! j$ D( k& K, ~
      instance_uuid: { get_resource: avoltest }
# O8 {2 S, n) a2 t& g( _9 J- S      mountpoint: /dev/sdb
" a8 ]" o2 n* Y! n  f- qoutputs:0 H8 j5 L# h$ y* g) t( g$ i
  instance_ip:
1 d" O  u" c. [) X    description: Public IP address of the newly created Nova instance./ K" z/ n4 T# k9 P' W) ~
    value: { get_attr: [avoltest, first_address] }

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-11-10 21:55:19 | 显示全部楼层
heat_template_version: 2013-05-239 J0 C. p* r6 u1 g3 E

% q, G( x$ _; \# D+ \" x5 Zdescription: >5 u% w4 K1 T* |+ p/ |
  This template demonstrates a minimal SoftwareDeployment example
  X4 u1 g: D, y0 `3 z4 r8 zparameters:
% ~, m' D$ n- y4 d  key_name:
; S' Z- B# F; p7 A5 Y( l9 w- e    type: string3 ?+ g3 N! |9 A7 l; I
    default: stack_key: S. V& j" M4 D- P: R5 z/ O/ `
  flavor:
* k# T8 s! l3 P1 n- c. J4 X! ~% }    type: string
: z. X/ h( C1 ^3 h' w5 ]6 V3 ^' j    default: m1.small
* U  ^3 u) K* H" Y5 s$ V  image:$ E% O! U# E# w( B4 f
    type: string% ^9 x+ `/ G7 u' V2 s2 U
  `9 q, W9 ]$ Y8 @$ X
resources:
% `! U' s9 N& t4 j* t( B  g  sc:( j3 c6 Z6 q: f' |% k" z; T
    type: OS::Heat::SoftwareConfig
+ F7 v, p' c( Z; l! a- n1 K    properties:
2 Y0 V% ]& L) C5 ^      inputs:
1 h" W) K: ^& g% I' @3 l( `2 ~        - name: message
+ B9 U  }" c# @) i          default: 'NONE'
; X% G6 d- m" k3 T7 ]4 _3 j      outputs:
/ ]* ~! q- Y) V1 t, c        - name: file_content7 F* v- L6 k1 l" a- v! ^3 i1 g: e
      group: script
) o) L4 T+ y" ]) H* K1 k' D2 J      config: |. L; F$ c( {; |) X; C8 Z
        #!/bin/sh
4 v" j8 y3 G0 e9 ]% t        echo "${message}" > /hello
+ M+ N1 k! K/ v  V& Q; ?        cat /hello > ${heat_outputs_path}.file_content
! s0 |& v& M+ [. h6 t$ w  sd:" s6 }( H+ _5 x: U3 Y6 r7 k
    type: OS::Heat::SoftwareDeployment( Z- A0 i% Z# R! k
    properties:
' k% [9 r; T$ T& S      config: {get_resource: sc}: x' {) [) h2 C
      server: {get_resource: server}5 ]8 u  H# V; z; C4 F9 e
      signal_transport: HEAT_SIGNAL
- o" j( I0 a2 }. ~      input_values:
. j( ?& v4 S! @6 I! ?( z) ^, t        message: 'Hello, world!'4 U8 m, p7 D8 U3 T6 [

5 n, l; O* j$ H& l$ g# H8 _1 h  server:! P/ b  ]9 D3 U6 r% @
    type: OS::Nova::Server) a  u$ h& {+ W( N" B& L/ Z9 K
    properties:, H# u8 z: `1 E$ c
      image: {get_param: image}
) g- }. l" v6 G" }& O      flavor: {get_param: flavor}
; q  P4 _% t$ R      key_name: {get_param: key_name}( A5 G5 `. [, E2 X+ N3 x
      user_data_format: SOFTWARE_CONFIG  u' J" S+ Z. L8 w& c! o3 y) @
      software_config_transport: POLL_SERVER_HEAT
& R' a7 ]- n& Y4 t
: x2 D4 A* O( moutputs:
; C) @: z. ~# d# Z: U  N/ n  deploy_output:) m/ q% J3 h0 R3 v0 ?) _: @
    value:; i, D/ T, v8 \/ h7 m; n
      get_attr: [sd, file_content]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-11-10 21:58:05 | 显示全部楼层
Hi, I want to create heat template that serve the following purpose:
* B# Y4 H, T! `- {( W0 F+ x/ D0 i& B% R: |9 D
Launch Instance from image- m0 c2 d! _3 K! I6 a1 Q" Q! ^  V
Create Cinder Volume
9 R; h9 l; @; N# |0 s  EAttach the Volume to the instance6 ^: L8 R" h" i, ~# }  y
Configure the volume on the instance as LVM, format the LVM as ext4, and finally mount it
, o  O1 T8 P  O+ \So i create something like this:! f5 y9 L* l7 }# L
5 }' z" {4 X0 p
heat_template_version: 2015-04-30
: C& K* l% z2 U* l2 P4 udescription: >" F$ m4 E* {7 K( a5 B( S3 o: _4 @/ N
  A template showing how to create a Nova instance, a Cinder volume and attach
& r, [9 @* m- q  f" h4 ]  the volume to the instance. The template uses only Heat OpenStack native; B" Q7 A$ r% Y1 C8 j) ~' }1 z" N
  resource types.: \4 Q' s; n* y4 [, w; Z; t
parameters:4 C" e: n" o, G  H
  key_name:! V2 Q* x$ @* b
    type: string4 z3 W5 V5 u7 o
    default: linux_key6 F5 w/ ^: A/ J5 G+ j  Q  |
    description:% u) Q  {9 M3 h9 l2 L: p
      Name of an existing key pair to enable SSH access to the instance.
1 M, l  {) M" z9 s' U2 I  instance_type:
" |5 C6 k5 C% o3 [, n    type: string
  W/ Q, x# m, z6 n6 K2 y    description: Type of the instance to be created.0 ]9 ~- ]( z$ C. B
    default: m1.small) A6 j. J+ V  c- c
    constraints:4 q& ~: @9 G8 L! Y3 O
      - allowed_values: [m1.small, m1.medium, m1.large]6 Y! L& e. }5 b5 e; n5 j
        description:) X1 ?/ U- \1 Y( ]) ]6 e: u$ L
          Value must be one of 'm1.small', 'm1.medium' or 'm1.large'.
; \! z5 N6 b8 x  image_id:
4 K1 E4 R& A; A/ m8 R8 [, o    type: string2 v2 T$ u- q, x3 i
    description: ID of the image to use for the instance to be created.' h2 F3 O4 e( @4 e$ H- G6 s
    default: linux_img
( T9 E/ [: ~  Q* @. I    constraints:
* G  d, w$ r% e0 z; I8 i2 `8 p      - allowed_values: [ linux_img ]$ @& V, n) M3 n( h5 r
        description:
- v+ j2 G7 M" r! [          Image ID must be linux_img
7 n" U% d2 o! a7 ?2 t. |  availability_zone:8 Z0 w9 ~7 V. @) L0 ^! R
    type: string2 @9 E) B" J1 j* F
    description: The Availability Zone to launch the instance.7 C' G, @& b3 j7 c
    default: nova$ E$ B5 b/ ]1 ~
  volume_size:
+ N4 x3 K6 c0 ]    type: number
/ r) ~& D" v' S* s$ S  b$ R    description: Size of the volume to be created.
' J! i" ^2 d0 E. `    default: 12 s; Z' E# C! w
    constraints:* H) J* P, ^' X3 }- M
      - range: { min: 1, max: 1024 }1 i6 x' [$ M- b- e1 c* S1 s
        description: must be between 1 and 1024 Gb.; [7 A) y2 f4 s3 }
resources:% i6 `% x" r* J3 j( q; T* N$ c
  avoltest:% r9 E: w6 a* p1 L3 s! F2 }3 n# c
    type: OS::Nova::Server
! W5 R! x, t& I$ o" Q( u# y    properties:* d- N7 f, x1 j( W& \
      availability_zone: { get_param: availability_zone }
2 y& B; j5 m+ }/ H# c      image: { get_param: image_id }
! K) h. g) X' G  z0 }      flavor: { get_param: instance_type }% e& Q1 h' t3 l9 A  K
      key_name: { get_param: key_name }
. S  l# {) L# [( C  }9 H      user_data_format: RAW: W2 ?" n1 {: k. r! a
      user_data:3 f( D* X8 ]$ m% b& N3 s) l! O' P
        str_replace:
# R! i. n3 ~2 V, v8 \          params:$ R( Y$ _! n/ b4 f! H# u/ }; r
            $LOGFILE: /tmp/installlog.log
+ U3 J# e# Q+ Y( _5 S& q. E7 q2 H            $VOLSIZE: { get_param: volume_size }
& Z! }( Y0 w* Y! z5 T7 ~          template: |
5 R5 }: {& y  N5 L6 ?; r1 o& N: j            #!/bin/bash -v
, |5 z7 U2 n4 ^  S  o6 C! \              die() {
! ~" f" f: t! y% Q1 q+ M              _WC-NOTIFY_ --data-binary '{"status": "FAILURE"}'
- N  M; z  h6 h" V. q  j; M                exit 1/ n$ ?# ^: v0 j& N3 {
              }$ A1 s& }# a, p/ @
            yum install -y lvm2 >> $LOGFILE 2>&1 || die
# Q& D9 m2 k( E/ B8 |( v5 |            pvcreate /dev/sdb >> $LOGFILE 2>&1 || die5 L  W. }# _/ c' L3 ^4 R' n
            vgcreate volgroup01 /dev/sdb >> $LOGFILE 2>&1 || die
7 {- ~6 e1 V8 q5 e* e" f            lvcreate -l+100%FREE -n lvol01 volgroup01 >> $LOGFILE 2>&1 || die
( Z+ a7 w$ T- O  [( W! V; j+ B            mkfs.ext4 -F /dev/mapper/volgroup01-lvol01 >> $LOGFILE 2>&1 || die
* o8 k2 O4 n& f1 e            mkdir /data
9 s6 ~# J$ V3 n/ h0 b7 L            echo "/dev/mapper/volgroup01-lvol01 /data ext4 defaults 0 0" >> /etc/fstab0 l* Z. U3 i- Q
            mount -a; V4 L9 P" w$ U! {7 @* x5 P/ [( d  ~
            df -ah >> $LOGFILE 2>&1 || die3 Y1 l6 E& b% u: G* _" Q
  cinder_volume:
1 \) T5 f. ?2 N    type: OS::Cinder::Volume/ V' h% V3 `6 `& G1 a6 r
    properties:
* m& {5 }, W9 W9 y! M2 m      size: { get_param: volume_size }
- e7 U( t0 H" ^      availability_zone: { get_param: availability_zone }* z6 _5 j; M6 `# N
  volume_attachment:
3 t3 J* y2 T" c. a    type: OS::Cinder::VolumeAttachment' W- |( ^7 G; l. `
    properties:) Z7 H- x! w. o/ H& S3 _
      volume_id: { get_resource: cinder_volume }- r5 y% J( W1 y: w# P
      instance_uuid: { get_resource: avoltest }/ k+ i  d4 x5 K" W3 r" o
      mountpoint: /dev/sdb' O5 j9 J; w8 j' @
outputs:
) [& I1 k* g& B. p# d0 H" ~  instance_ip:- i8 u2 A5 D2 b3 U# C
    description: Public IP address of the newly created Nova instance.8 s# `/ X0 ~* A
    value: { get_attr: [avoltest, first_address] }
" @+ x4 j. |; a( d: g. Mbut with that template, the bash command for creating the lvm (pvcreate and so on) is executed first before the volume is being attached to the instance, so it failed.2 k& F" e) v- q1 F$ z! Q% z, T. Q5 W

8 q! N: W: Z7 _" C) P1 FAnyone have idea how to make it in order so that the bash commands on the instance will be executed after the volume is attached? Thank you  B5 O2 [8 [( m: J& V; z  D
add a comment
' Y# m  J: n9 H9 |: u3 c, _2 answers Sort by » oldestnewestmost voted
0 G& B6 A  `( b! ~' c) N0
2 B" d# H* I# [answered May 4 '17
' \/ O* }4 r* ^- S9 ikcd gravatar image( s) K  g" ]0 ]
kcd
- P/ [6 w( o# W+ `6 t4 z$ g# B8 W* A1) w  e* y8 v* b- K( `6 j% O
There need to be more examples on how to do this, it is non-trivial
4 \% `' G6 W  u4 j: L4 J- O9 e4 V7 J0 ~- f1 R/ F: M) t
Here's mine3 p/ z7 Z. A6 l2 \) C" M% ?3 E
2 ]/ \* k3 \1 p8 w& z2 Z. o$ N6 Y6 J
  config_mount_volume:+ N9 a6 U$ R! G( v4 @9 B
    type: OS::Heat::SoftwareConfig
& d6 |7 o& E4 x  Y" k2 l    properties:
8 c6 @" n- R( ~      group: ungrouped
9 v6 g7 k4 U9 w; u) d      config:
7 M, H. ]+ a0 k: b" Q, V7 k- ]        str_replace:
- n& I, y2 E2 V( @- d          template: |
+ l' W  ]( K# P" G/ Z4 v            #!/bin/bash& k" U$ ?! _1 a6 y  J% S3 i, {
            set -e
( t4 m: H# V- Z; E            voldata_id=PARAM_voldata_id
: d) {6 N  G& n5 {# r, |% P            mount_dir=PARAM_voldata_mount/
% R/ o$ ^9 E( Q5 @  P% f' a+ U  F9 n            echo "Mount volume ${voldata_id} to ${mount_dir}"" p" A- N1 t: A0 Q$ e
            voldata_dev="/dev/disk/by-id/virtio-$(echo ${voldata_id} | cut -c -20)", p5 v1 Y0 ?) @5 H: Q6 p/ a% Z. B
            partition_dev="${voldata_dev}-part1"
1 k: l. |5 ^! G
) f1 g4 G  B' ?6 n  S; f+ c            while [ ! -e ${voldata_dev} ]; do echo Waiting for volume ${voldata_id} to attach; sleep 1; done  {5 [, O& u, V% B3 K  X& B3 E8 u; H
9 X* x! y) K. |$ f' y4 W% O; [
            if [[ ! $(ls ${voldata_dev}-part*) ]]; then: y8 [+ D( o- ?* f7 I
              echo "No partitions found, create ${partition_dev}"
' F! m  U0 ^% f+ w; g" ?              echo ",+," | sfdisk ${voldata_dev}
; w0 v1 @: _/ \( k            fi
6 }. }. r  |9 q$ E! C/ O, ?0 J- c  }0 _2 s4 c$ n$ j
            if [[ ! $(file -sL ${partition_dev} | grep ext4) ]]; then
  p& s  f" t% ?7 ^3 h, A) C              echo "Partitions not formated, format it as ext4"* |  G+ f1 o2 B, w' Q" ]5 f0 d
              # yes /dev/disk/by-id/, partprobe and hdparm show it is there, but no it is is not ready+ ?  K* x/ q& [0 D& Z0 I# r- i
              sleep 1
1 O* X. J  C  c% g- ]/ @( _4 r              mkfs.ext4 ${partition_dev}) t" O" k3 U4 t
              file -sL /dev/disk/by-id/*& ~% A8 P# i. N9 M) x. ?
            fi
  |2 X6 I5 j$ O% S            mkdir -pv ${mount_dir}
* ?5 i, b5 v) p7 N: J4 W, V+ t0 a            # mount on reboot  z) y/ ~, ~1 S
            echo "${partition_dev} ${mount_dir} ext4 defaults,nofail 0 0" >> /etc/fstab6 ^2 [. h) B" P' F
            # mount now
$ Y  q( W& [: e            mount ${mount_dir}; ^4 \# U# J) w5 N+ g
          params:
/ U- w* X! b! x5 I! v1 I            PARAM_voldata_id: { get_param: data_volume }$ e/ j# O. Y& H: @9 y
            PARAM_voldata_mount: { get_param: data_dir }3 ~3 J5 k2 [+ c& \" v! ?. e: S
link/ ^6 M/ o1 u3 t: j( u- }
add a comment6 ]$ W& c$ Q1 K+ G
0) C+ h5 Q7 Z+ h7 V  @' v
answered Nov 23 '15; F3 t: b( e7 x* i
jayaprakash gravatar image' w# ?- h* z0 |7 U/ c9 z5 L- B
jayaprakash flag of India 1 _3 e9 l! Z2 Q
171 ●2 ●4 ●11 https://in.linkedin.co...! |+ L2 @; G- k+ \0 I. f3 F1 A
Hi boniamd,0 k% `) g! P  ]  E
' e+ `  X4 A6 g6 Z+ X7 X
In your case instead of executing custom script as part of User-Data on launching a VM, it can be executed by defining a separate resource software-config/deploy and make it as dependency to volume attachment task so that the script execution will be done only after volume is attached./ Y7 K9 o3 X9 v0 S( r  }1 A& l$ U, c$ g

" @; r. O* l. h2 V2 `% \Please refer cirros-hello-world.yaml heat template on how to define a software config resource to execute shell script.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 00:16 , Processed in 0.026691 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表