找回密码
 注册
查看: 2409|回复: 1

使用Ansible 在OpenStack平台创建实例

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2021-8-2 10:30:56 | 显示全部楼层 |阅读模式

Ansible 中的新模块使用Python Shade库 。 Shade目前不为CentOS或Red Hat Enterprise Linux打包,如果您使用的是其中一个发行版,则需要使用pip安装。 Shade可用作最新版本的Ubuntu和Fedora的操作系统软件包,并且可以通过常规机制安装。


; N, P$ z7 `! f' i& p, R7 @yum install -y epel-release
% D) n# s4 g. U( f$ G$ j8 gyum install -y  python-devel libffi-devel openssl-devel gcc ansible
3 {$ ]6 ~: E( S) N5 |3 E# e  Spython get-pip.py
. `6 I, T8 I* W& S. X% V& \


! A2 J7 C7 H* y9 `+ @pip install -U pip    ##当前python2支持pip-20.3.40版本- ]! \8 n# F+ c+ H! {7 I2 W6 A- @
1 ~% Y) s$ \8 S" t9 Y4 u

. F' Z1 B# E5 E, ?pip install shade! `1 I4 U# o; x! n

& T7 L* d6 ^* M( H$ [% J$ Z& X9 l& n

这二个模块最大的变化是认证。 使用nova_compute模块,在任务中将认证详细信息指定为选项。 使用新的os_server模块,认证是从由“openrc”脚本设置的环境变量中提取的。 大多数OpenStack安装有一个选项,可以在Horizon的“访问和安全”下为您的特定租户下载openrc。 要设置这些变量,只需在运行playbook之前先运行openrc脚本,如下所示:

./openrc.sh

编写一个在OpenStack云中创建实例的例子:


' ]1 k/ W( E# yvi openstack_deploy.yaml
! b% r8 w& \% I' V4 r  h  `  t" r9 D0 L
7 r& x  E9 R2 `: }. i+ f/ P: j
---
2 W0 C6 l  l4 w; D& d
& ~2 F2 n" O" a/ ^! r! |3 }% \3 {1 y5 f* O" _+ S
- * C: U$ v9 u1 o7 T/ f3 t8 s

/ R2 F. `2 E& Y/ ~1 ^( ?( `
0 r4 B/ @" y; `' b. E1 F  gather_facts: false7 R# ?3 s9 i* L0 ^
5 W* \( o$ b( H# @7 A* h3 Y
" a/ f" g5 M  G( {
  hosts: controller
- _5 {' f$ ]+ A1 W& l
5 S6 {/ a1 n8 c9 ]: r) B1 C* }# A" F% `  {
  name: "Deploy on OpenStack"2 C9 e# C3 o7 g. E% R

, J/ Q) H; c  b- i
/ c  l  ~( s9 \5 ^- V+ c- I  tasks: 7 P! j/ `0 s; @' W' W' T

& X0 q5 e1 Q+ ?& W+ Y) `! b4 b& [; d
   -
8 r3 t( F6 ~) N' c1 s' J$ m; l2 E8 m4 ^0 ?1 W4 p
% X: C% r$ @) `* E5 L$ u! \
     os_server:
- Q2 D3 o# M5 q0 a. s4 G/ o& ^, t3 y4 A" x6 q. k% x1 J

# E5 C* ~3 Y0 G6 u8 V% M       auto_floating_ip: yes2 ]" [- B+ ]# `0 x7 v
& i  t- u. ~& t9 \& G# ~+ z3 F0 C6 E
' x2 |1 \. `! ]9 F, z3 x
       flavor: 1C_1024M_50G6 B& L4 o# o% o) E+ _) ~" K
& D, O9 m' p7 q; x6 R& E3 Z
3 C4 s; R/ q" `' u
       image: 69e26018-2456-4f5b-aaeb-8821f23a43292 e1 A% N# J' `4 H& d

; l; U  l0 a# a0 ?, V, |6 `' ]$ c
$ x; N3 n; f3 S& g" V       key_name: ansible_key
9 P- I; X% Z  U0 P3 Q
) ^* ?( [! Z! @; T' R4 V" k- Q/ m5 S! R) x  m- z
       name: testopenstack' C* G( G( B3 M3 J. R

" w  l/ X6 E; O3 A9 m. a
# {" ~, U5 N$ f$ M- h8 y' I) F       network: linuxbridge
" n' b2 i5 h3 Q, C
  w7 j. P# o! c" T$ R; j7 @& s2 D( }+ {$ y
       security_groups: default- H8 F% o+ Y+ Y
/ N' Q, m  Q# }  }3 n4 j. m) u

1 b. _3 }( a( u2 U  O# _7 n       state: present* |/ ~9 w* L7 a1 H- K9 y5 R

+ F+ b" r1 B) p4 T
( K9 q' f% m/ ~) p( I* w: e       wait: true
5 v4 ]4 B# u7 }
0 b" p. b' v) k8 C" c4 z6 ^/ i. h1 l
. s) {8 ^4 F3 {( r& Y8 s$ U" G

运行测试

# . admin-openrc.sh0 A. u8 A% H7 W& G- H

# ansible-playbook -vv openstack_deploy.yaml
/ J9 B0 ?( p- P7 p9 N$ o

这应该在OpenStack上部署名为“test142”的实例。输出将如下所示:


# t- n/ I4 y$ o2 f# P; vUsing /etc/ansible/ansible.cfg as config file* {% [2 w* g# Z0 q+ Q
9 u9 F! N2 d8 O) F8 a. P# Q4 _$ [

8 K! @9 T. K; Z+ z, s- g
) H5 d: u8 i2 ~
2 N) S" s- p' M1 }( cPLAYBOOK: openstack_deploy.yaml *******************************************************
+ T2 ~+ _" b! T' ^" Q- O
& U# a9 Q- A2 }$ l: o
% c2 T* p7 Z  j" n  f# `# J1 plays in openstack_deploy.yaml
: V& p& C4 R$ m- D! t5 e. O$ \5 `% L! T5 r- ~) J! K% ]+ [
' C! x6 H' S: M/ ?
PLAY [Deploy on OpenStack] *****************************************************
9 \2 R7 n/ D+ a
) y7 B* R/ K. Q3 m) O( P  P& D9 H7 @+ r
TASK [os_server] ***************************************************************
( M. D, w0 H/ p1 o2 w5 O$ @8 S  `% @$ R/ Z( A1 u
) y- f, ]7 D, [& W4 y# P
task path: /root/openstack_deploy.yaml:8: U) v; E! q1 |" Y

! d2 O3 ?* C* k$ p: |
' y7 J& V" W' y4 v+ t: w# k, g& t( G* C3 j" h
... .... m' y( k/ B# Z! ]& d, j
0 z# a4 z$ u" ~) S' x7 P

) }) [: t' e8 l% Q9 n6 C+ y
! ]1 M5 n( U+ r; l. kPLAY RECAP *********************************************************************3 f' ]  V; G' G( x. E  U
* M, S& e& W  S& r* T$ W# a

) R0 n  q, c, t8 [. z9 q+ ]9 v1 b' w" s: c/ V7 r- n
controller                 : ok=1    changed=1    unreachable=0    failed=0  , `  v  ]- `: E9 h: D# c8 T1 r
1 Y9 i4 R1 A- Q
6 E' S: A, |& S5 ^4 k0 y" I8 S

8 V8 S% `) F3 l

在Openstack云中检查实例是否已创建成功。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-8-2 10:51:52 | 显示全部楼层
1 Ansible管理docker7 Q, V  L7 O$ I+ U
近年来Linux容器技术越来越受欢迎,通过容器技术,可以保持程序运行环境的一致性,快速启动并高效率运行,涉及到的开销也比较小,此外,在系统层次上完成容器级别的资源隔离非常快速。
% B3 I$ U3 v) k3 x- DDocker是管理Linux容器最流行的工具,它为管理Linux容器提供了许多方便的工具,比如创建、销毁Linux容器,还提供了一些除管理Linux容器之外的工具,比如管理镜像、编排。通过它的易用性,Docker已经成为管理容器的最流行的方法之一。
7 `' w8 L6 j! T9 c! H, x0 _题外话:关于容器和Docker
5 w( |7 f. H* D: f! _Linux容器是内核的几种功能组合在一起实现的。换句话说,Linux容器技术是内核层次的功能,Docker只是提供了一系列工具,包括从底层和内核交互到高层和用户交互的一条龙。除了Docker外,也还有其它操作Linux容器的工具,只是对大众来说,Docker是最流行的。2 `, |% d+ s( S+ o
Ansible为Docker提供了一整套工具,包括相关模块、连接插件(ansible_connection: docker)和inventory脚本,因此Ansible可在许多方面与Docker进行交互。例如Ansible可构建Docker镜像、启动或停止容器、组合多个容器服务、连接到活动容器并与之交互,甚至可以从容器中获取inventory。
0 }% s- C! I- P# Q5 [$ {+ k如下是Ansible官方目前提供的和Docker相关的模块:% Q' `/ ]7 y) o0 N0 o6 }
Code
% ?0 ^2 V6 \5 a, `+ I0 S* O5 T- B- k$ u5 s/ a
docker_compose – Manage multi-container Docker applications with Docker Compose
. H* n, c9 T# r4 F( L. e6 jdocker_config – Manage docker configs; @( G  |8 D2 P+ ]4 _
docker_container – manage docker containers) B- ]. c* o& a
docker_container_info – Retrieves facts about docker container! V& n' a0 p: t9 ^  c
docker_host_info – Retrieves facts about docker host and lists of objects of the services
8 ^" h! P) R0 L  Edocker_image – Manage docker images
) \! h1 x$ i+ k) C+ s* Qdocker_image_info – Inspect docker images
: ~$ h9 F; G8 P$ y$ M( Xdocker_login – Log into a Docker registry
4 \1 v  K( l; K, T! o! }docker_network – Manage Docker networks
/ q8 B, m) _" l3 M" vdocker_network_info – Retrieves facts about docker network! e( r4 r8 t1 y; u$ F8 m
docker_node – Manage Docker Swarm node) i: s7 p) b* u0 K, f4 x( _
docker_node_info – Retrieves facts about docker swarm node from Swarm Manager
& q( r9 i, l8 n7 {7 I" i' I' Qdocker_prune – Allows to prune various docker objects
7 t- P: k+ ]" v6 j9 H7 m9 w' Xdocker_secret – Manage docker secrets* k0 r, G; m5 t3 n5 G
docker_stack – docker stack module5 H$ L7 y8 ~- s6 C" F) e
docker_swarm – Manage Swarm cluster
) s8 M6 I2 ~2 o* sdocker_swarm_info – Retrieves facts about Docker Swarm cluster
+ Q; K; i5 J, q3 @# F2 {  ]docker_swarm_service – docker swarm service" k1 F; Z8 B* b' b( a
docker_swarm_service_info – Retrieves information about docker services from a Swarm Manager. J) m& C3 |) l$ p0 G! E, p
docker_volume – Manage Docker volumes
) W* ^2 m: u+ O  G- x, E3 u; ?/ c: ]8 Jdocker_volume_info – Retrieve facts about Docker volumes7 k  j# F+ V1 L! ?; ?
要使用Ansible管理连接Docker,要求安装如下包(注意:Ansible端和docker端都安装,这一点和其它模块不一样,如报错,请自行在两端安装、卸载、升级调试):8 |9 w3 l8 b' g1 O
Shell6 N5 q+ f) L0 P2 g5 i
5 b8 Z( {8 ~& x" j6 i
# 两端都安装,如果已经安装了,则在报错的情况下按需更新
; z4 R) e6 V- o  [$ R3 m* j+ n4 K# 此外,根据Ansible使用的python解释器版本,按需决定使用pip还是pip3,
1 ~1 U: @2 z$ y0 ^$ p8 b: M. _# 如果需要的是pip,则yum install python-pip
/ m% F7 [" z% E% [$ pip3 install docker requests8 W/ G( o- f0 f3 U9 G8 m8 m
如下是其中两次报错信息,注意其中的结尾:No module named ‘XXX’。
7 P" i* {6 s9 O1 b% SCode
$ s5 O8 H$ K% i( ]% a/ u# |) Z" l$ P$ R# n1 R/ H1 S/ L
fatal: [192.168.8.65]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.75)) on controller's Python /usr/bin/python3. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` or `pip install docker-py` (Python 2.75). The error was: No module named 'requests'"}2 C( ?# c, h, i" p
fatal: [192.168.8.65]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.75)) on controller's Python /usr/bin/python3. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` or `pip install docker-py` (Python 2.75). The error was: No module named 'docker'"}
" L7 ~8 ~+ V; Q7 t  k3 N2 Ansible构建并运行Docker镜像
8 t/ }* S# _# }+ X通Ansible提供的docker_image模块可管理Docker镜像(比如构建、移除、pull镜像),使用docker_container模块可管理容器,比如将镜像运行起来成为容器。8 W8 s$ X$ ^5 x  U6 k" T' x/ Y. t
对我们而言,一般都是在已有镜像的基础上通过Dockerfile来定义新的操作,然后构建出自己的Docker镜像。所以需要提供两个文件:一个基础镜像和一个Dockerfile文件(基础镜像不存在时会自动下载)。如果使用Ansible来构建镜像,那么这个Dockerfile文件需要能够被Ansible读取,比如可以放在Ansible playbook文件的同目录下。2 g5 `3 A/ Q% @' Q
为了演示以下Ansible构建Docker镜像,此处已经写好了一个非常简单的Dockerfile,该Docker镜像是在CentOS 7镜像的基础上添加nginx,然后让nginx运行起来并提供cowsay页面。* T8 j7 S- O9 O( N
Dockerfile内容如下:
1 N% R5 z" E. h' l; qDockerfile: ?1 r& X# G8 K9 e+ R6 l6 \$ R9 T2 k
& q( v8 T+ o8 {* k+ Q, U1 ^
FROM centos:centos7/ E, I( c1 h1 i6 |7 {
LABEL maintainer="test.com"" p# k+ D2 G8 R4 i0 E
RUN rm -rf /etc/yum.repos.d/*.repo && \
! J; a$ ]# u/ \  @+ O+ {    echo -e ' \
! q! j2 @4 q. r" s3 V1 e  U: ]3 {[base] \n\2 l" o  d4 v# d" M$ f9 z
name=os \n\7 @8 y! y9 P3 n
baseurl=https://mirrors.163.com/centos/$releasever/os/$basearch/ \n\
, x' j7 Q6 u) B$ _. Menable=1 \n\
5 \% m. \  F! o8 t; |$ `gpgcheck=0 \n\
! F! m  _7 a5 L+ F' |* P; s0 n[epel] \n\
: a+ l+ ]2 {- d7 @name=epel \n\3 D0 V, g9 d" Z: w
baseurl=https://mirrors.163.com/epel/7Server/$basearch/ \n\
( \$ y, \% E+ v2 w( s0 Cenable=1 \n\! d. G$ W( |# u, Z" w; {. ]
gpgcheck=0 \n\
3 O" \' @( Z2 y# P' >/etc/yum.repos.d/base.repo && \
% X. A+ J4 L0 E( S8 D" H. z    yum -y install cowsay nginx && \
8 n- M! [7 F: n    rm -rf /usr/share/nginx/html/index.html && \/ N' c' r3 u9 t
    cowsay test >/usr/share/nginx/html/index.html && \
% N" g+ j# L3 }4 L/ U+ K) x& ^0 x: R    echo 'daemon off;' >>/etc/nginx/nginx.conf && \
$ _/ i, `/ V7 \    yum clean all% ~2 U  M- ^$ f0 Y, w  w
   
% H1 z) V: L$ H9 @  N: sEXPOSE 80
( l& J7 U) ~# ~1 a* f) A: i& [CMD /usr/sbin/nginx
  N8 i6 r+ x* u! M. Z8 @然后写一个Ansible任务文件,假设名为build_and_run_image.yaml,内容如下:
+ x% H! ^7 @& yYaml6 A  Q) S1 D7 |) I

# M3 Q. c0 Z3 S! g$ y1 I- hosts: docker
7 h5 R2 I3 P- ?7 @. ]9 ^  gather_facts: no7 {, |* v; `4 r& m: D. p. R
  tasks:
  {4 y& \- K9 a% J    - name: scp Dockerfile
- u% I7 H: p; i: g- T% V      copy:
  p1 N. R5 w9 P3 ~% N* M  \        src: Dockerfile4 g* ~& u& L0 R' a# Z" T
        dest: /tmp/Dockerfile7 L" {. T6 `( w6 j
    - name: build Docker image centos_nginx:v0.1.1
" ]9 ~6 |- h9 Y) `1 p      docker_image: : J- I5 h8 F( x7 }* k5 R4 y# y
        name: centos_nginx$ N# z8 Y+ ?( p
        source: build6 {& O9 z+ n$ r
        tag: v0.1.1) y* U% M' ~9 \" t' I
        build:
& u& Q) k: R4 V/ I' P/ L          path: /tmp5 p8 _0 I9 j+ W& s6 Y( H
          pull: yes
- G% U% d7 @3 ~    - name: start centos_nginx
9 u& \9 ]1 V. o. b/ e) q' E& _      docker_container:
$ a& c+ j  j1 s& \. D& {        name: cng& _+ a; i. p, u4 i
        image: centos_nginx:v0.1.1! h( Z, j/ |) ]8 O/ D! f& H
        ports: 8080:80
( a1 J# j; u6 n# v* @        state: started# g" G6 U% e4 ~6 x: v; h# ?8 D
Ansible执行完成上述任务后,可直接在Ansible端使用curl来测试页面是否可获取:
) b$ ~  E6 W: PShell! c& N4 p" P, K3 m7 I9 ~

/ c+ f4 @; K8 z; o4 i$ curl 192.168.8.65:8080
% ~) i* ~* L+ g ______________: q. b, r/ m- Y4 m) ^5 h
< Junmajinlong >
% b2 {2 q4 @. V# b --------------% {$ k' {6 N8 f. F% Q( E# B
        \   ^__^
1 V* Y* p- K. p4 p, j         \  (oo)\_______+ y1 ]1 u; n! T0 K. T0 _
            (__)\       )\/\2 H4 k! I- i2 ~$ B4 E
                ||----w |! L7 H$ V9 P5 E0 l* E
                ||     ||
# P0 ]% `. u5 X' x0 T/ F1 [+ p这里对上述两个模块稍作解释。
. Z& L( ?: y* r% G( X对于docker_image任务来说,通过sourec: build指令来表示这是一次镜像构建操作,source指令可包含如下值:2 w% E- p0 b( b7 S
build:根据build指令的path参数指定的Dockerfile构建镜像
/ ]$ w6 u* {( }1 D/ D; H( _load:从镜像tar文件中提取镜像
: N: t7 H6 I2 M  |pull: 从registry中拉取镜像* R$ P5 u5 P2 a" v& _( \3 N
local:保证docker端已经具备指定的镜像5 a5 I& Z/ h9 s0 l- @3 Q9 V
对于build指令来说:
/ S0 c* A  ^+ N, E# ?: w6 x* z1 A& ~path:指定构建时的上下文目录,该目录要求包含Dockerfile文件9 Y* j9 C) v0 W* V
dockerfile:明确指定使用哪个Dockerfile文件,而不是默认的上下文目录中的Dockerfile文件
& \- h( V4 v8 R, zpull:构建时是否从registry中拉取基础和中间镜像镜像
, M# H" x6 W$ k7 n/ j4 s: O: C4 ~cache_from:构建时使用缓存的中间镜像% ~7 t" U- R# [+ _1 w; b- w7 b
args:可按照key:value方式指定镜像的参数,对应于Dockerfile中的ARG指令,例如listen_port: 8080
4 H+ ]6 c" s' I' F其它指令应该都通俗易懂。* N. H5 T/ V$ q, g6 Q2 R  ?1 k
构建镜像完成后,可使用docker_container模块启动该镜像。该模块指令非常非常多,几乎包含了docker container命令的所有选项功能,但是熟悉docker命令,这些指令的用法也通俗易懂。比如,指定卷和环境变量:
* u2 {0 r8 k! ?/ r" }Yaml1 f8 C3 @8 O1 d3 T$ m' N
( k* f1 L3 E% _9 T* J5 T

9 M$ i, L  k% [6 f+ z8 S* m- name: Create a data container
' @) ]: G1 q+ k+ \, _  docker_container:
! P& m9 x' j9 t4 C$ K    name: mydata
/ t9 k6 e& `; i3 M3 w$ [    image: busybox# _- [+ M$ y) u  }' r
    volumes:
: A0 g' e' g$ s+ G- b" @& c( [      - /data8 Y3 m  C# c, `9 B6 t# w* Q
- name: Restart a container
. A& ]: c$ T+ f) Q9 a% ~; x  docker_container:
' s7 v! H3 I) M5 O$ S$ b    name: myapplication, Y4 A* x' f% A; U
    image: someuser/appimage
! e2 c" k, Q! T3 N( `8 w# u    state: started
# Y$ d0 x, f, ?: e) i    restart: yes0 [$ j; z- B$ ?) ^6 k+ a# P) V% m
    devices:
: U2 o$ \. O" K6 A- L( u4 E     - "/dev/sda:/dev/xvda:rwm"  w4 m" O( e5 b
    ports:$ L, O( ?( l9 W5 u  S; u: w) v% ~8 A
     - "8080:9000"9 e. w$ B( J7 d+ @! \* C
     - "127.0.0.1:8081:9001/udp"
7 ^. F- I% _8 q. a8 n9 c    env:+ P$ T( I7 S# I/ E  c
        SECRET_KEY: "ssssh"8 y6 f8 a( {0 _6 q% y8 I
        BOOLEAN_KEY: "yes") q  `3 h8 F- c8 Q/ U- w* \
3 无Dockerfile启动镜像并连接容器
! v; r7 r% w5 j在上面的playbook中明确使用了Dockerfile来构建镜像并启动镜像提供服务,但因为Dockerfile自身也是基于基础镜像构建的,所以可以省略这个构建过程,而是直接启动基础镜像并连接到启动的容器进行操作。1 g& w* m5 a+ Z+ d6 W1 q. ?" v
下面实现与上述示例相同的效果,只是不使用Dockerfile构建。  X$ R$ ]+ T1 n+ p( Q
playbook文件内容如下:
; b1 r; K4 J$ }/ h4 x$ F6 i7 ZYaml
+ p5 n0 A0 _: e# [. |  Y2 \2 _- y7 @# Y+ }  o
---
' g0 g( u5 U' {5 U- name: start image
# U- d" c4 q/ c9 g' S8 O& E4 ]  hosts: docker/ ~9 N: G' \: e, h4 L1 i$ X
  gather_facts: no
, {5 _' K0 }7 P  vars: 4 a, m& ?! T& \
    container_name: "centos7"( \6 n% v2 h/ r) z: Q+ E& N9 Z
  tasks:
0 e& L# o- {. T% R9 k; B  j    - name: start basic container "centos7"
9 {& }8 z8 P. Y      docker_container: , R( e4 U8 W% q3 d7 d7 `
        name: "{{container_name}}"
+ `" I4 `0 V" B1 v  V; l        hostname: "{{container_name}}"  m& `' Z( [% c* N
        image: centos:centos7
7 ?$ ?. l2 ~8 ?* L. T( Z+ E% h: @        ports: 8080:80
5 H+ |/ W# R8 z' R- R        state: started! z5 e, X. z% o/ Y- I1 p
        auto_remove: yes
8 ?8 E6 h! \0 Q# I        command: bash
+ v! ~$ \/ _! {: d/ l        tty: yes
* i7 W* z7 }" [" O0 x5 v        , j0 T* D8 s- q  `) @) v) e7 a% q
    - name: add container to inventory
; ?' C3 N  T2 [* q) O- q      add_host: / h( D; Z' P* v. ~
        name: "{{container_name}}"
; d$ t: o& U: `* \! f        ansible_connection: docker2 S# [' L) t' ~+ a, [/ s6 H
        ansible_host: "{{container_name}}"
. C( i  t( M; U        ansible_user: root( G5 O9 n) s: U: m
        groups: containers
. x# p* f# y) x* e        
4 i, g  {+ X/ ^/ [7 J' }- name: do something in container
: y0 w) f1 C1 T  hosts: containers
/ `$ @9 J$ M1 p: x' o; t% O  gather_facts: no" y: N4 Q7 o/ C8 g
  tasks:
* h: z: P& N- }4 }; l    - name: install python if needed( d" [( ?2 Y( o: A: F3 I
      raw: yum install -y python
( w! Z+ ?6 C" `    - name: remove all repos exists
  c' T- }" |. p7 J. L- F9 F6 Q  _      shell: rm -rf /etc/yum.repos.d/*
) ^1 |1 L0 u& I8 o( c      8 f& g6 I: S3 {, T4 [
    - name: add os repo and epel repo
7 R: |' Q" E$ P      yum_repository: & h2 ]) F  x6 v. O2 x3 U3 G3 F! P
        name: "{{item.name}}": Z% Y( u8 |4 X, Q
        description: "{{item.name}} repo": @0 h9 k1 |, g" W% X! B
        baseurl: "{{item.baseurl}}"
( b& k) {* }# x) [) u        file: "{{item.name}}"  b, Q  ?& ?" g/ S# W; D; C+ E' |
        enabled: 1( k: }; `" Q6 B/ |8 _
        gpgcheck: 01 `- y' c! `, d% D- S" J
        reposdir: /etc/yum.repos.d. Z' e% N. }& O8 J
      loop:" M# e- _; r, z) q/ @2 z
        - name: os% _# \, u( A, D4 Y
          baseurl: "https://mirrors.163.com/centos/$releasever/os/$basearch"3 B# C2 Y0 r. c8 y. L6 l
        - name: epel/ n/ l1 X# X5 Y; F
          baseurl: "https://mirrors.163.com/epel/$releasever/$basearch"      
1 c1 g' ]* ^8 v* o# d& M    - name: install nginx and cowsay  
4 H, P+ p1 i& |: c- k      shell: yum -y install nginx cowsay7 V# A- R4 q/ x* L: X, z
      4 |/ }% }* L7 K" m2 \1 {
    - name: configure nginx
$ K4 \5 u& X6 B& T- t8 }      lineinfile: 2 }8 x& r- t- D7 Y( j
        line: "daemon off;"
2 h7 ]3 \' Y; c& B6 Q8 U- A# g  w        dest: /etc/nginx/nginx.conf, Q  d- n. H) y1 e- {3 p: g
        
" p% ^3 i( ]& D  V0 V    - name: change index page: F) D) W. T; `4 M8 P5 ]/ q: k7 b
      block:
+ ^1 \5 b) l: ]) V8 F0 m4 L. q        # 先移除index.html,因为它可能是一个软链接
/ O3 v. E  T3 X1 P        - name: remove old index.html page; I" U* }3 z% |# ^2 s+ K
          shell: |, `6 ]3 p/ z7 N9 T# w
            rm -rf /usr/share/nginx/html/index.html
: [8 k" U: Q! F            cowsay test >/usr/share/nginx/html/index.html
% S2 H4 O* F# t# T0 j& |7 P    - name: run nginx! ?4 v* I, l* P6 C& ]; p
      shell: nginx &
' U4 t% `" z7 b! B& h+ d在执行上述playbook之前,需要先在Ansible端导出连接方式docker所在主机的环境变量,比如Ansible连接到远程docker时,使用tcp:
9 n# B; c0 j& g4 }Shell7 f+ k6 m( I& Z& w# v3 k

- A  x% N" j* K" e
6 n: q) Q7 s1 ^: F( w$ export DOCKER_HOST=tcp://192.168.8.65:23765 Y/ Y  h# z; ^* B: j) P; ^
$ ansible-playbook -i inventoryname playbookname.yaml# F0 C0 B( g1 c# a% _
上面的playbook任务中,首先启动docker容器,然后使用了connection: docker连接器添加该容器到containers主机组中,以便后续的连接。之后在第二个play中连接到containers组,安装Python(CentOS系统都会带有python),配置yum源,安装Nginx和cowsay,并启动nginx。任务流程比较简单。
6 X! P5 {- N2 Q唯一需要关注的是add_hosts添加容器节点到inventory时指定的docker连接方式,这里不能使用默认的ssh连接方式,因为目标容器不一定开启了ssh服务,也不一定能和外界通信,而使用connection: docker连接方式,Ansible将会先ssh连接到docker服务所在主机,然后通过docker container exec的方式连接到容器内部。
/ U' r# F0 ~/ U" d8 J     docker inventory0 x& V5 ], \# U
Ansible为Docker提供了动态inventory的脚本。可下载该脚本:8 g& J# z" l) g+ N7 K5 `; d
Shell$ V1 w9 w$ ?/ o: K

, ~: N& e1 S3 `1 [- |% ^, a6 c3 J% x  ]1 p. v! N
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/docker.py+ Z+ H% r( @" w- O: v3 q
chmod +x docker.py
6 G/ t+ A- L+ q, l3 O; p执行该脚本测试:
2 A3 w% S, I3 l; ~. N4 oShell
' \- J$ p) U2 [2 l, n
2 J  |$ t7 f8 `' \0 S2 xDOCKER_HOST=tcp://192.168.8.65:2376 ./docker.py --pretty9 ], a5 z, N7 C# E
或者直接在ansible命令或ansible-playbook命令中使用-i选项指定:, i; \, t6 h3 C& F) U: s
Shell7 }/ Y& y* e% L; p3 O; |9 S

+ Z( a4 @+ X1 Jansible-playbook -i docker.py docker_containers.yml' D" l; n* D& g" W( C
4 其它Ansible容器管理工具" \5 U$ @8 ?- F4 f: l. F
Ansible除了在官方提供了docker相关的模块外,还有一些第三方的工具可用来管理容器。+ Z, _. D8 J+ i
比如ansible-container、ansible-bender、Ansible Operator,它们需要单独安装,对于ansible-container来说,在之前几年比较知名,但是作者现在已经将该项目废弃,据作者本人所说,ansible-bender和Ansible Operator更好。
+ n4 j, ]( c# V' Xansible-bender:, N6 J; [' T" ~. q
简化Ansible Playbook构建容器(注:此容器是符合OCI标准的容器,docker所构建的底层容器也是OCI容器)
" C8 t3 I2 Y& p: h地址:https://github.com/ansible-community/ansible-bender" K9 ~0 o) d2 ^" {' P3 u  ~
Ansible Operator:
# G1 S+ B, B1 Y* }是Red Hat Ansible Automation和Red Hat OpenShift团队联合开发的用来将容器部署到K8s上的工具
) s, d6 g- S' z% E地址:https://learn.openshift.com/ansibleop
  {, J( X0 s  w) g8 j: X5 Ansible管理OpenStack3 _$ B8 x" k- {) p3 ^. j
OpenStack可整合一台或多台物理计算机的资源来按需创建、管理、配置、删除虚拟机(在OpenStack中,虚拟机对应的术语是”计算实例”,但后文都以虚拟机来描述),对OpenStack提供者来说,提高了硬件资源的利用率;对受益用户来说,可按自己的需求申请带有各种性能、各种资源配置的操作系统,比如公有云的模式,就像去网吧上网一样,想上多久、想体验什么配置的主机都按需付费来享用。, I# Y) [( m- S4 @$ i# ?7 E. a
对于OpenStack来说,Ansible几乎是全程参与其发展的,因为从OpenStack很早的版本开始,就已经逐步支持通过Ansible来配置管理OpenStack,而Ansible管理OpenStack相关的模块也随着OpenStack的版本迭代在不断更新。目前为止,Ansible官方提供的关于OpenStack的模块已经有五十多个,下面是Ansible官方目前提供的模块列表信息简介:% @& G% p. g7 Q9 r$ n/ v
Code! u2 Y7 Z8 A' ^# M  I

0 P! d2 L( e; ^5 f, Xos_auth – Retrieve an auth token
5 m' c" S6 U3 L; M. Z: B4 k" P2 sos_client_config – Get OpenStack Client config
6 ]. ^9 ^7 U8 Y" J1 [6 _  \! dos_coe_cluster – Add/Remove COE cluster from OpenStack Cloud5 h: T; z* K9 N. Z% l
os_coe_cluster_template – Add/Remove COE cluster template from OpenStack Cloud
5 H' U6 U* y  j$ z+ R" B4 Aos_flavor_info – Retrieve information about one or more flavors
' C* u/ q+ n  O: y1 E0 Dos_floating_ip – Add/Remove floating IP from an instance
7 V# D( h! n$ e: e" |os_group – Manage OpenStack Identity Groups, E  @' R3 m5 o+ G3 _2 ?
os_group_info – Retrieve info about one or more OpenStack groups$ O! \& x+ n7 V4 Y9 e: E' ]' b/ v8 n
os_image – Add/Delete images from OpenStack Cloud  h/ B" D# H) U% N$ z
os_image_info – Retrieve information about an image within OpenStack; |( @/ E! x1 @% k
os_ironic – Create/Delete Bare Metal Resources from OpenStack1 `1 k! Q  k. O4 R- `1 x
os_ironic_inspect – Explicitly triggers baremetal node introspection in ironic$ y9 Z) {4 x: H& n7 ]
os_ironic_node – Activate/Deactivate Bare Metal Resources from OpenStack" r9 T( j0 _1 R5 V& F
os_keypair – Add/Delete a keypair from OpenStack# r; T& U# u. v% h' D: P7 n
os_keystone_domain – Manage OpenStack Identity Domains! e8 J  v; z% a
os_keystone_domain_info – Retrieve information about one or more OpenStack domains
6 X: O- l# [* ]) uos_keystone_endpoint – Manage OpenStack Identity service endpoints; V' v4 I9 v/ X! \7 ]. _
os_keystone_role – Manage OpenStack Identity Roles! A7 a. l) j/ ~3 q! {9 u& C
os_keystone_service – Manage OpenStack Identity services
7 W7 Q' E' V$ Fos_listener – Add/Delete a listener for a load balancer from OpenStack Cloud
/ u; G( O( w) _+ t/ u0 x4 ros_loadbalancer – Add/Delete load balancer from OpenStack Cloud
+ n9 H( l! a( }* [! Tos_member – Add/Delete a member for a pool in load balancer from OpenStack Cloud. r4 J1 P8 p% s  z
os_network – Creates/removes networks from OpenStack
) w5 ?- p8 W. V9 x# D0 r' Eos_networks_info – Retrieve information about one or more OpenStack networks
# h2 z4 i( W  z% Tos_nova_flavor – Manage OpenStack compute flavors
0 l/ G+ x; b& i0 A# C) r" W! I& \' kos_nova_host_aggregate – Manage OpenStack host aggregates
6 L" H4 [( \! w0 R% l% [7 A5 O; k2 Aos_object – Create or Delete objects and containers from OpenStack) ~4 P  S2 ?: H  `5 [; {8 I
os_pool – Add/Delete a pool in the load balancing service from OpenStack Cloud
* A* N8 ^9 Y2 o! los_port – Add/Update/Delete ports from an OpenStack cloud
0 X' B$ l6 C/ F! pos_port_info – Retrieve information about ports within OpenStack
7 d0 O1 \7 N% D* L" i/ q. Oos_project – Manage OpenStack Projects
1 F1 s" z$ ?4 w2 ]9 Bos_project_access – Manage OpenStack compute flavors access
9 Y3 w* N* O' D) @$ P8 Yos_project_info – Retrieve information about one or more OpenStack projects
; o8 @+ i  @6 B1 r! q* E! B7 Wos_quota – Manage OpenStack Quotas& w" F3 O5 V; Y9 V6 D$ W! F+ e! |
os_recordset – Manage OpenStack DNS recordsets
& k, \/ ]# s, k' Z9 _6 p" t; q* hos_router – Create or delete routers from OpenStack
$ |1 p" t) S, A  e" U5 b3 Ios_security_group – Add/Delete security groups from an OpenStack cloud
9 J2 b7 m* E' Wos_security_group_rule – Add/Delete rule from an existing security group5 U5 R7 D' m. ]1 N
os_server – Create/Delete Compute Instances from OpenStack
& {1 Z0 l" T( b5 {1 ros_server_action – Perform actions on Compute Instances from OpenStack' o- \4 t/ L! \' S" ~/ E
os_server_group – Manage OpenStack server groups; [9 T3 k" n8 J3 I4 f9 t! B) M
os_server_info – Retrieve information about one or more compute instances& a0 |5 e$ t' Y* l5 d
os_server_metadata – Add/Update/Delete Metadata in Compute Instances from OpenStack
1 Z+ e7 `6 h3 P: [2 l& sos_server_volume – Attach/Detach Volumes from OpenStack VM’s
6 @3 v, U  b7 K5 D! a. Nos_stack – Add/Remove Heat Stack$ [; t3 e) Z  N9 P
os_subnet – Add/Remove subnet to an OpenStack network
6 E& d# D( a* `4 _0 [  L- G5 Nos_subnets_info – Retrieve information about one or more OpenStack subnets4 B( V/ w: K! u( u- j+ o
os_user – Manage OpenStack Identity Users& j+ O! m& X' [" U5 ?5 W5 p
os_user_group – Associate OpenStack Identity users and groups
; L  k1 c3 t' x* dos_user_info – Retrieve information about one or more OpenStack users$ n2 W4 c6 |% S* g6 J1 l
os_user_role – Associate OpenStack Identity users and roles( J$ Y) a8 {! Y5 Q3 {
os_volume – Create/Delete Cinder Volumes
% Z  _. j; _5 H. A& ^. a! U/ B  Tos_volume_snapshot – Create/Delete Cinder Volume Snapshots) @8 K9 c3 T) {$ r
os_zone – Manage OpenStack DNS zones
' t/ e) z& X1 H虽然看上去很多,但大致可总结为Ansible可对以下资源做管理:
: {- M7 ^  }9 b(1).计算资源
9 A4 P9 d& N, B+ k/ i(2).镜像管理
6 z2 [# R$ }6 J- }( n(3).账户管理和账户认证5 s$ y9 _4 |* b* ]
(4).网络管理
$ O6 }6 H0 @. }6 A) ?8 s, V(5).对象存储管理$ b# ^/ L# a* n5 n$ u' A. b
(6).块存储管理8 t- g2 I* b9 k+ o
对每种资源的管理可分为四类操作:
2 s& e- }8 U- p3 P1 o) Y(1).获取管理目标的信息+ A+ P4 f' K$ H' c2 }* @6 k. N
(2).添加管理目标
3 Q( G# Q  N/ l& p(3).修改管理目标的属性
' S/ O- v4 }$ T# F1 ~$ Z(4).删除管理目标6 K' U' x  N' a
即增、删、改、查。
+ _, l) [2 o8 x# |8 r! a" {. l此外,由于OpenStack自身已经跟踪了其创建的每个虚拟机的信息,所以Ansible还可以直接从OpenStack中获取这些虚拟机的信息,比如从OpenStack取得某些虚拟机信息来构建动态inventory,这样就免去了手动提供虚拟机inventory的麻烦。7 q% \% K: u& r" J
本文不会介绍Ansible如何操作OpenStack自身(比如添加网络、上传镜像等),这和管理普通服务做的一些基本操作没任何区别,不同的仅仅只是做不同操作而已。本文会介绍Ansible管理OpenStack虚拟机时最常见的两种场景需求:
" w$ ~& Z: Q# H. \# p& h(1).使用Ansible创建虚拟机,然后像平时管理远程主机一样管理这些虚拟机,最后删除这些虚拟机# `* N9 m( f  ^, i4 l6 r) S
(2).从OpenStack生成动态inventory/ Z2 t* D, Q3 `& N: A0 w
14.2.1 创建虚拟机& |' B0 E: u: e3 z4 \9 ]6 |8 z
OpenStack管理虚拟机相关的模块都以os_server开头,目前包括如下6个模块:本文大概只会用到os_server模块) G9 |3 T- e/ a' c; p
Code
% C7 e! B# B, y3 C! t2 M! u  B
5 N* J+ p* k" N1 U. _os_server – 创建或删除虚拟机
" _- i7 h4 n. {- a. F% T! w; [os_server_action – 对虚拟机做一些操作,比如虚拟机的关机、开机、重启、暂停、恢复等操作" M5 ?1 g$ m+ s. M6 J+ [5 h
os_server_group – 管理OpenStack虚拟机分组,比如测试环境的虚拟机可属于test组,生成环境的虚拟机可属于prod组  
2 e  ]* ?7 t* `: L( k: ^2 ?7 Xos_server_info – 检索一或多个虚拟机信息,在Ansible2.9之前,该模块名称为os_server_facts,用于检索虚拟机facts信息
8 A! J" U3 O/ ^" Los_server_metadata – 增、删、改虚拟机的元数据信息,比如设置虚拟机的主机名、虚拟机设备信息,如网卡配置、磁盘路径/dev/sda  4 l$ ^! o) {0 h% V( Y+ w  N
os_server_volume – 附加、剥离虚拟机的卷
& N! p; _" S2 U这6个模块都要求先安装好版本高于0.12的openstacksdk包,在CentOS 7中只需执行如下命令即可:+ O% H" A' V+ n) ]4 k5 E7 B
Shell
/ H1 d1 `1 w' S; o' b4 I
, J9 ]8 B' k% Z; C  j+ b1 t. ?/ }$ pip3 install openstacksdk5 p; Q) z: @, ]! [+ _+ U
为了让Ansible连接到Controller进行管理,需要添加Controller的inventory信息。假如OpenStack的Controller的IP地址为192.168.8.65,可inventory文件openstack中添加如下内容:
8 ?# R0 V, I8 j0 w! |Undefined
9 l3 W, y  ~& R' v- Z. V7 x' ?) R. l( U
[openstack_controller]
# p' S! L8 p+ x4 G: M$ I6 r192.168.8.651 ]1 K% R( I' m# _& }
配置Ansible段和controller的ssh认证互信可自行配置,此处不赘述。# M! l& f+ a- @+ N' D4 {' o
然后就可以编写playbook来创建虚拟机,假如playbook文件名为create_vm.yml,其内容如下:
( a$ H  D0 u* ]' |5 {  ~9 j# EYaml- S5 z: Z! [2 W) x& p8 a

! ?9 l# E* O$ {, L4 F8 _* ?/ z( L9 Y* R- name: create vm
! v# K1 p  `6 J0 B; b7 E3 }  hosts: openstack_controller9 P* @$ ]' P: N, Z& F, o, p+ A, ~
  gather_facts: no
- \8 }8 V# a5 t- e0 Z3 w$ m2 R  tasks:
' T' v4 y! x" Y# |5 L    - name: Create a new instance! \$ T, Z2 Q) @* U, y2 {2 Z
      os_server:5 s5 {' j$ r' o; k. o9 R2 P( Y" ^' ^
        state: present
+ E2 j" w5 s# _$ k9 k        auth:
7 F1 H9 W/ ^$ q: i* J          auth_url: http://192.168.8.65:5000/v3
0 A$ i$ j5 C9 W          username: admin& v! b3 c; y+ X  s  y
          password: admin123
; F7 a- E. ?) E          project_name: admin
4 h/ U  s! i$ q" e6 k: x          project_domain_name: "Default"0 c+ W9 J* b) r8 A$ H
          user_domain_name: "Default"
1 s7 h+ I1 C+ A) {0 {3 J, t' }4 [6 r        name: vm10 P  N* Z4 f( u# n& J
        image: "CentOS-7.9-x86_64"- P4 [2 `* A  `1 @" x  U
        key_name: ansible_key: w( U0 p  M; v) H- e* m- G9 O
        timeout: 200: ]8 X- r* L* }8 r) k5 I
        flavor: m1.small7 j; F+ q/ t% k
        network: 'ext_net'; p1 d! w7 B; X8 N" m$ n8 p# ]
        wait: yes4 n. H3 I+ x- E6 I/ `# s
        meta:: @1 r- ]3 H0 k) \1 f) u" Y& s9 X
          hostname: test1) `7 @1 v' v, ?7 p- R* }/ U; D
          group: test_group6 f; M' \/ V7 Z$ i8 Y# a( y5 h
          userdata: |
3 I, p3 p& X# S- f) z- F1 b8 j            {%- raw -%}#!/bin/bash
' N' F) l( m4 L7 }            cp  /home/centos/.ssh/authorized_keys /root/.ssh/+ a% @: C! N/ x* q0 i1 P8 j
            {% endraw %}
% j: a2 Y. B0 s8 b) E8 Q6 R% lauth部分是认证相关信息,name1表示创建一个名为vm1的虚拟机,image、key_name、falvor、network都是OpenStack中已经配置好的。这里还同时设置了虚拟机创建出来后的主机名为test1,并加入到了test_group主机组。
: C2 n- E# e5 E因为是CentOS镜像系统,该虚拟机创建出来后,默认登录用户名为”centos”,而且默认不支持root登录,为了后续可以使用root登录,上面使用userdata定义了该虚拟机创建后自定义的操作,即将保存的公钥信息拷贝到/root/.ssh目录下。+ V& {0 q+ ^+ ~' I% a9 T
注意os_server创建虚拟机任务中的一项wait: yes,它是默认选项,表示Ansible会等待虚拟机创建完成才会继续执行下面的任务。
) m6 M$ Y3 o: A. W* K因为所有的模块在连接OpenStack时都需要进行身份认证,为了简化playbook中的认证内容,将上面的auth选项段落的内容保存到OpenStack Controller的~/.config/openstack/clouds.yaml文件中。例如:" ^3 p7 }( E/ a
Yaml3 X) d7 H/ ?: `  ~& T
, g3 B; n2 |! e* B7 b
clouds:
. u4 A8 a7 q$ S+ Y  mycloud:
* [' g! C5 u3 p! u6 Y    auth:
2 E# E* \6 {- q1 H4 y% V     auth_url: http://192.168.8.65:5000/v38 v6 {' b- |% o7 R
     username: admin; p: I# O+ |$ M# I4 E
     password: admin123
3 Z# w. ?1 n; {/ C# K     project_name: admin
. o3 ^% _: ~. Z& m6 I! N     project_domain_name: "Default"0 h2 B$ e. M$ @. r9 l. {% d
     user_domain_name: "Default") ?4 n3 C8 ^/ c5 i. Q- R
以后在模块选项中就可以省略auth,而使用一个cloud: CLOUDNAME即可:
' u7 _( n" Q+ l; ?Yaml
  F/ G7 w& o, B$ a: [' b# S7 H9 e/ N1 e8 U
tasks:
, G8 j4 g. @4 l6 `  L  - name: Create a new instance
) m- Y  M  [5 I6 S( o) i    os_server:
% l6 @  N( F* _. G( ?      clouds: mycloud5 G" H0 Z$ |. X0 R# j- [
      state: present
6 m# K; Z& U0 l; S' j0 m      name: vm15 Z/ o; ?6 t. D# X
      image: "CentOS-7-x86_64": m- U+ z- o) Q4 h2 t  ~0 r9 H+ t
      key_name: ansible_key4 e/ @; z' a7 w; Z+ I- S7 d) E
      timeout: 2006 A/ b( Y+ h/ `1 s0 U! w4 b6 ^
      flavor: m1.small
! a4 a9 f3 u7 `+ @: }2 M2 @; D, u      network: 'ext_net'
: w6 q) ~# Y( g5 J% Z- |      wait: yes. A% X# `$ f2 M: T" {
      meta:: y( N+ I" n- |1 C; s2 A0 U: D
        hostname: test1$ M9 |5 M, o% d
        group: test_group
; E- ~8 N' G( U3 |但是要注意,将认证信息以明文方式写入文件是不安全的,可以使用Ansible的Valut加密。不过OpenStack的dashboard中也已经提供了一个环境配置文件,可以先按照如图所示的位置下载:9 o# x4 A3 }1 O; d- d
0 g. [& Q# U; }6 r
然后以source的方式执行下载到的admin-openrc.sh脚本文件:5 D0 Y4 b% k0 ]2 q
Shell
, }( g5 `# [) S* k8 T
* z+ N5 |/ A1 t1 O: q! E) d3 V/ bsource admin-openrc.sh$ e3 y* Q: W- X
执行完后,Ansible的OpenStack相关模块执行时,auth和cloud指令都可以省略。
1 m3 m" |& R( w& f. N上面只是创建一个虚拟机实例,但很多时候可能需要一次性创建多个虚拟机。可以将每个虚拟机相关信息定义到一个变量文件中,然后去遍历想要创建的虚拟机实例。例如:
' C& ?+ [  S) ~/ t; V% YCode- @  D. V: E) M4 h2 g1 ]
% y) T8 o' [. X: S" H5 X
---- n- r6 J3 `" U+ K8 T
servers:. n7 u# t: R0 O' H# Z
  - name: vm12 r% A+ D- d, F# D! N* u/ c
    image:
9 d% K- ~# M8 ?" Y* I& t6 O    flavor:
- O- Z5 ^4 v0 P- x    key: / [7 ?0 I( f0 a- I5 y, a+ y/ c3 [
    nics:
$ B) o0 H8 o% h8 [! \( |    meta: 1 A! t; G- [2 l9 e8 }( O+ q& i7 Y
      hostname:   T6 e$ y/ O6 d$ e* f% Q7 E: c
      group: ) _7 T, n. ?, n
  - name: vm2
, J& k& K) y; }; h( v' \% S( k    image: ' B- \  h! w6 h9 v
    flavor: 7 f4 D/ r- d  R$ J
    key: ! n- _* d: n. n: C
    nics: % C( K$ `& D& C, ?- l
    meta: , b8 Y8 L# Z" j7 S/ z% r1 ^
      hostname: ; [, w" m5 @9 C
      group:
+ u, h- Y' {+ ?# I, k7 e. {* n有了前面的Ansible基础后,此处批量创建虚拟机应该毫无难度。
; U: s2 V8 t: o: k8 {- _: r创建虚拟机后,可以将os_server的任务注册到一个变量,从而可以获取该虚拟机的信息,包括该虚拟机的IP地址:  ^- I1 P( G$ A" T/ A! @
Yml
# V4 \) s3 y1 N+ \; E( Q
9 K: f4 E, D: x4 C7 ~9 _2 ltasks: 1 V8 n. H7 T# k1 h5 l1 N0 a
  - name: Create a new instance8 l8 A# l; N5 w4 a# F3 O0 c
    os_server:8 N) B" p4 W% k7 ~/ m2 ~
      cloud: mycloud( Z/ ~0 {, K% a. ?/ A2 n( G
      state: present
  y; N. w3 C7 x7 S8 ^1 p      name: vm1
$ P4 @3 M) ^* R1 h      image: "CentOS-7.9-x86_64"
% @9 M# p; x/ }2 T$ z- m      key_name: ansible_key/ B" ~  S$ k% M9 k
      timeout: 2003 K/ V* Y# E2 g+ \- ^9 b2 ]
      flavor: m1.small* U7 h+ V! Q: y9 E$ U
      network: 'ext_net'9 c) W% h! l' H8 B
      wait: yes- I9 @5 K% T2 {6 Z
      meta:! l1 z5 g# C. h  n) g
        hostname: test1
8 ?1 N) c. A$ j; b        group: test_group( m4 N4 I; I$ B3 G  h* N; I; Z' \
    register: newserver
9 [0 {: j8 \) U' }    / W$ B; O! a4 f: N- j
  - name: get instance ip7 D* [1 P% N; [& ^7 p3 k
    debug: 3 F4 ?  U7 F8 h
      var: newserver.openstack.accessIPv4! g3 z) J/ U' M% A$ `- X1 U
有了IP地址,对Ansible来说就获得了最关键的信息,因为只要将新虚拟机添加到Ansible inventory中,新虚拟机便像普通节点一样可接受Ansible的控制。
6 M9 A: h' Z* c2 e6、将新虚拟机动态添加到inventory
. L8 b( }  \+ C获取到IP地址后,可以将该节点通过add_host模块动态加入到inventory中:
( j: h* E4 n8 M, OYaml+ |: u/ j) t4 u+ p0 b9 n1 N0 Z
" ]  c) }$ R7 p4 y% Z
- name: add new vm to inventory8 o( ?' ^. {& ?1 C
  add_host:
( l* I( h/ i1 z9 c( j$ X/ V) G* \8 R    name: "{{ newserver.openstack.accessIPv4 }}"
0 ?! U/ T1 l/ h    ansible_host: "{{ newserver.openstack.accessIPv4 }}"
/ o1 L4 P- D, \% d# E# s$ B    ansible_user: "centos"
9 f9 o+ i: `+ Q    ansible_port: 22
1 Q0 H+ ~  f; K2 _    groups:
) Z6 b0 `( y7 B: [5 |      - vm_hosts: i. }& O  G7 p* i
似乎这里的逻辑不太良好?如果虚拟机启动了但是不可连接呢?对于OpenStack创建的虚拟机来说,完全不用担心,因为os_server创建虚拟机成功后会等待该虚拟机可连接才真正返回。但对于非OpenStack的其它云主机实例则不一定,这时应当使用wait或wait_for_connection模块定义一个等待任务。尽管OpenStack中可以省略该步骤,但在脑海中应当要知道有这个步骤。
8 o8 K& Q7 j6 D$ }" ]此外,OpenStack安装的镜像系统可能是比较精简的系统,甚至没有安装Python,所以为了能管理这些虚拟主机,应先使用raw模块安装Python。7 Q! F5 b( {5 {4 E
Yaml+ n3 ^% p) s% {6 d# z! s" a( Z
- name: for new vm host2 g4 t4 y1 ?& U5 Q! G1 {% D
  hosts: vm_hosts2 c8 d5 `* W, l  c: \
  gather_facts: no1 K- |/ g8 G) p
  tasks:
% v) R/ J  J8 `: _    - name: install python if needed
7 G9 f' z2 r( V4 H4 a      raw: "sudo yum install -y python"7 Q- ]: ]2 e9 H2 J, b) ?
如此,Ansible便可以像管理普通主机一样管理OpenStack虚拟机。
% ?+ C/ G. U- \/ {9 O3 @; B3 N7、收集OpenStack虚拟机的动态inventory
6 b6 Q. Z0 l- F/ Q9 t6 o+ W动态inventory一般需要写脚本(几乎是Python脚本)来收集,但即使不会Python也不用担心,因为对于OpenStack来说,官方已经提供了openstack插件,还提供了openstack_inventory.py脚本,该脚本位于Ansible官方github仓库的contrib/inventory目录下,查看文件时记得先选择对应Ansible版本的分支。
7 L2 Y2 w& \2 H" c% C# ?. x* L; v下载openstack_inventory.py并设置可执行权限:
/ T- i( v$ \+ ~, a% k/ d6 rShell
* J/ k8 |* q" W6 K2 U: c: l4 u  P5 g' L* o
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/openstack_inventory.py
) r4 V/ o3 b# Nchmod +x openstack_inventory.py+ L. s# k+ q* q. t: j' E
然后source以下admin-openrc.sh脚本,再执行:: _9 j" M+ n/ @/ C" K' N
Shell. N: x5 l) q6 S
# t9 N! R/ [' \- [* ^- d/ ^3 j
source admin-openrc.sh
# c# e! w4 L- X& p./openstack_inventory.py --list
; D$ d& \; D" F: S1 }3 E4 ~5 u可查看inventory信息。9 Q0 p. g! }! ^3 J& H% b4 N
之后要将该脚本在ansible或ansible-playbook中使用,使用-i选项指定即可:
0 Y4 b7 a2 B& Q3 S* HShell
! Q9 Y' c7 f) h: Z! M% z4 f. q1 h$ k4 \* g( B" D
ansible-playbook -i openstack_inventory.py -m ping
9 k% P1 J) W- X/ Z( P1 n7 Y除了使用openstack_inventory.py脚本动态生成inventory外,还可以使用名为”openstack”的inventory插件。要使用openstack inventory插件,首先要在/etc/ansible.cfg中的[inventory]段的enable_plugins中开启script功能:. B5 z! p8 C* `8 x* u; L: d6 n8 x
Shell" g$ q5 b. Y% o4 ]5 X

5 w& q. Y# s9 a2 w) l$ grep 'enable_plugins' /etc/ansible/ansible.cfg ) j$ n3 q8 L* j% b$ J7 f
#enable_plugins = host_list, virtualbox, yaml, constructed
; q4 ~# s# K& M) T3 [! @7 a- E取消上面的注释,加上script:3 B9 p  V# \* |& J7 x% _
Ini
6 N8 q( B$ V$ X$ N1 E) Y1 j1 r4 j& O# W% h" [9 r
[inventory]
( D6 n) v, H" `* N, ^! Eenable_plugins = host_list, script, ini, virtualbox, yaml, constructed/ Y3 N% O% b1 z& D
以后只需在yml文件中加上如下plugin指令即可:
) x/ c  R# S! @- `; k6 e: ICode" }0 ?2 H( j- t/ [) |

4 M7 K7 i2 G) F2 z2 U$ f, T1 _  ?plugin: openstack4 \, r  L3 L" b5 d5 y

5 {6 D1 r' L$ _
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 01:01 , Processed in 0.024739 second(s), 23 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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