易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 2408|回复: 1
收起左侧

使用Ansible 在OpenStack平台创建实例

[复制链接]
发表于 2021-8-2 10:30:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x

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


0 c% r* q/ S8 f& y* oyum install -y epel-release
' k0 u7 n8 Y' c1 F5 nyum install -y  python-devel libffi-devel openssl-devel gcc ansible
7 u  c# B3 n; g' C& Ypython get-pip.py& T3 d' V/ @# {  o- ~) J

' b! N. ?5 c. c+ b$ |  F
pip install -U pip    ##当前python2支持pip-20.3.40版本
9 r2 O6 t( ^: |* [, l2 u$ X; Y
) v- D0 d1 F/ {' h; F, g
- d, W3 d* F5 a1 |pip install shade; x, e2 u$ n" a" v4 [. [2 w8 J

0 X! H* `- M( s8 q' p) t
/ c, I3 S* O) k

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

./openrc.sh

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

$ i, K  ]' d; x' g0 {8 r
vi openstack_deploy.yaml0 r/ e/ E3 B' a7 m: P
- J3 v! p. @9 D$ I

! c- G; y  E3 H- _---
# l6 Q9 m$ O: K+ g+ K0 I* N) r- ]

9 P4 n. w9 h- ?% g! h3 @- ! |2 W: l& n, U( K

! h8 [4 o( V0 J0 a4 A# T+ ^+ X: B
$ |6 R# N: Y  N+ G  gather_facts: false& }* t) b( c9 }" p) N. d

* K' W* C( L5 j4 `! i' _
3 k/ w' Z- F% h3 Z! a% W" {- n9 J  hosts: controller  U( w' x- o! m& z2 f3 B' P0 ?: c
* G, ~& C/ {% V3 ~2 H7 W# \: O3 l6 p

0 H+ ~: T  h" H6 L- c0 Z1 I  name: "Deploy on OpenStack"2 u8 Y# \# A5 R' s2 x
- l# H  ?" O; ]) B2 \4 n9 m2 q+ d
: G! ?1 C2 l* K9 T( E
  tasks:
5 W+ `% n3 _- l( g: _' |) a$ R
9 S! v/ U( r- Y( d" H4 I4 v2 @  T- b
   - / Q4 Y6 a7 F$ r: S. D6 d

8 Z, Z/ Q0 e3 U- F  q) O
0 |- v4 Q- u4 d5 n$ g9 f7 t     os_server:
% \' P# ^1 }. M
1 n9 l0 e% ?# {1 h3 _1 N+ u9 f6 H/ i; j  H; |! j9 ]/ @1 d8 Q5 e  _+ x
       auto_floating_ip: yes) r: e/ x* n2 ?6 ]# D

+ }  ~" [1 G' L% ^) e
) G. O, T. r! B+ m       flavor: 1C_1024M_50G
, P  g( l0 K. D( f9 m% `2 c# p* y4 \; }7 \" Q
9 s+ I) P* Q! v
       image: 69e26018-2456-4f5b-aaeb-8821f23a43293 i8 k' x* m9 [" H; L" X
6 z2 R+ X  x8 h8 C5 ?& ^6 F

, a4 w" O" X- E& P1 K       key_name: ansible_key  ], h% M4 \, \0 z4 }
. ~  W4 e6 h1 P- `5 L  X/ u
9 A7 f4 t( r8 e) ^5 P3 q0 h
       name: testopenstack
1 _2 q3 Z8 \) H0 J% }5 k$ w, q* g7 E. p! m: d2 A

- [1 l* L- `% T7 F. E: n       network: linuxbridge
8 z9 `+ H) s1 p6 K1 m2 _8 V: D$ [* q; R

) E; u" b9 p7 P       security_groups: default
& Y  A, B+ D0 `/ O/ b3 L
3 d5 y% _4 p3 x2 A+ C! P& C, U, u% w5 Y/ Z6 S* k2 H
       state: present
& w& E9 ^, [# \9 u" ~$ L
. F3 i" ?. v1 T+ y# w. b' C- C: P, v8 i
       wait: true) @5 S! i1 \! d2 f. {4 V8 t

3 k) E  r' k3 x1 r  [
: A& e7 B8 O, V( @2 U
/ G# ^; X/ ~5 Z

运行测试

# . admin-openrc.sh8 j# i' e* @' g. N

# ansible-playbook -vv openstack_deploy.yaml/ k5 o. R7 E5 x: X4 R4 c

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


7 i) H1 ?7 R2 Z# A: c6 g! |Using /etc/ansible/ansible.cfg as config file) B' [. Q& ?5 v$ j+ |5 H, W5 c

) U: q/ m0 A% p; u% @$ A4 g$ @; s+ g8 H8 l
* N/ R% [8 o* Z$ b, \
  Q: M3 A1 i$ A: Q1 H
PLAYBOOK: openstack_deploy.yaml *******************************************************
" k! p0 o# a# p+ c! U9 t4 [# B# |
1 B% }0 s) x2 y1 Y4 q- n
  @% h" v! a$ h: j5 Y' t1 plays in openstack_deploy.yaml4 G% l; w9 p# y% |& X

2 M; [# `/ R# t3 d, ]$ L$ C) A8 E$ D1 R. A5 X% F; Q$ g. G
PLAY [Deploy on OpenStack] *****************************************************6 j8 s; ?, `* O) N: g+ d4 H

* N6 r5 K$ \( ?. h0 Q1 q8 p' N9 g2 W1 \
TASK [os_server] ***************************************************************
1 `9 G' ?( E" r+ g' @3 ]; \
: D* L6 U7 t$ f! X; H
2 |+ f. z# Z* |( \9 ftask path: /root/openstack_deploy.yaml:8. N, @; g9 i: |& I- R9 K
: C$ L; f2 I( b
! e% e# [* L: v7 l& \
4 @& V, A( ~7 N2 S. M  q8 o3 V6 Z
... ...
0 F4 G1 H$ Q( U8 k& U
- _' i3 q' r$ T: u% u
+ b* G+ |9 |) E, x( B3 j
% i+ o9 N. j# i+ j6 G% xPLAY RECAP *********************************************************************  A: I8 l$ a' E! s6 {8 V) D3 S2 o  F

9 v. I* q* D) f1 S+ X
. e1 o% B; I+ y# v5 K9 A3 y3 V: J; j* g3 r8 d: A  @
controller                 : ok=1    changed=1    unreachable=0    failed=0  + l+ I/ I' K1 t3 a

- A( h+ e0 @- t! W$ s: {. x, N7 @' F1 q

& m# @, r8 Y0 y3 S9 v

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

 楼主| 发表于 2021-8-2 10:51:52 | 显示全部楼层
1 Ansible管理docker
  }' Q7 p( `' n& p0 k0 M近年来Linux容器技术越来越受欢迎,通过容器技术,可以保持程序运行环境的一致性,快速启动并高效率运行,涉及到的开销也比较小,此外,在系统层次上完成容器级别的资源隔离非常快速。1 J: P, L# h$ G) _
Docker是管理Linux容器最流行的工具,它为管理Linux容器提供了许多方便的工具,比如创建、销毁Linux容器,还提供了一些除管理Linux容器之外的工具,比如管理镜像、编排。通过它的易用性,Docker已经成为管理容器的最流行的方法之一。
- F+ h' O0 J$ Z题外话:关于容器和Docker& S+ ]5 f* [5 K1 @  p: D
Linux容器是内核的几种功能组合在一起实现的。换句话说,Linux容器技术是内核层次的功能,Docker只是提供了一系列工具,包括从底层和内核交互到高层和用户交互的一条龙。除了Docker外,也还有其它操作Linux容器的工具,只是对大众来说,Docker是最流行的。/ D; `% u  z4 Z6 c. o) Z
Ansible为Docker提供了一整套工具,包括相关模块、连接插件(ansible_connection: docker)和inventory脚本,因此Ansible可在许多方面与Docker进行交互。例如Ansible可构建Docker镜像、启动或停止容器、组合多个容器服务、连接到活动容器并与之交互,甚至可以从容器中获取inventory。
5 c7 G) e$ y# k* k( w如下是Ansible官方目前提供的和Docker相关的模块:
, q6 y6 B  c2 K8 A! L* TCode
0 r3 b1 T3 n6 t' x7 K/ |& D# n1 I
- k9 A# K" a5 D# |/ W7 M3 Gdocker_compose – Manage multi-container Docker applications with Docker Compose
! q7 C) L  m) ]: [" U: Adocker_config – Manage docker configs
$ l! y8 K8 r# X5 u, `docker_container – manage docker containers  a, ~; `3 l0 s3 X! C: t
docker_container_info – Retrieves facts about docker container
! B6 u( J! W) D* C( Idocker_host_info – Retrieves facts about docker host and lists of objects of the services
/ ~. ?, v% M, m' L' ydocker_image – Manage docker images
( d0 z' E. w: R8 Idocker_image_info – Inspect docker images
: w9 s  R+ |0 A3 G3 t& Zdocker_login – Log into a Docker registry2 k9 b" P0 }5 f& `
docker_network – Manage Docker networks
" Z& e' j+ C! N, `( h5 @' n' |+ o- Wdocker_network_info – Retrieves facts about docker network
( E8 w; D' b" X: p. f2 C1 |! adocker_node – Manage Docker Swarm node
7 h" f) Z0 b2 }/ jdocker_node_info – Retrieves facts about docker swarm node from Swarm Manager! g# e; M. |* j, M1 H3 A7 s
docker_prune – Allows to prune various docker objects; K/ C% S6 P5 @+ Z- C; P  |% n
docker_secret – Manage docker secrets: m+ Y; x( I2 P# d$ c! M
docker_stack – docker stack module
/ U. G, _: S" Z8 S  o# C0 ^2 ddocker_swarm – Manage Swarm cluster3 D# o" b' [+ f$ f( P/ l
docker_swarm_info – Retrieves facts about Docker Swarm cluster
4 \6 r3 t. v# E; Edocker_swarm_service – docker swarm service4 B  D% U, N& @- e: P1 E; n+ w9 @
docker_swarm_service_info – Retrieves information about docker services from a Swarm Manager( U. ~$ Q3 C; s& b" A0 h
docker_volume – Manage Docker volumes7 E! I% B9 n4 j  L/ z0 E7 O  i, P
docker_volume_info – Retrieve facts about Docker volumes
! _8 D( X. T6 `! F, G! k% R: s8 X要使用Ansible管理连接Docker,要求安装如下包(注意:Ansible端和docker端都安装,这一点和其它模块不一样,如报错,请自行在两端安装、卸载、升级调试):' M$ i* }$ ~! Y. A/ T7 d
Shell
8 g3 |' Y; z6 E9 @6 q2 i% ~6 u
6 L; p7 ?! O9 P' r! a# 两端都安装,如果已经安装了,则在报错的情况下按需更新5 J4 }( I8 j* R# s3 H' h
# 此外,根据Ansible使用的python解释器版本,按需决定使用pip还是pip3,
2 s& a  s, W: w0 r; z# 如果需要的是pip,则yum install python-pip
: R) n" ]6 k4 O* U; [; g$ pip3 install docker requests, [/ z9 a7 w- H5 @" ?6 g8 B
如下是其中两次报错信息,注意其中的结尾:No module named ‘XXX’。
6 {- u' d( G8 v0 \) b4 A- FCode
9 `1 }2 x1 ~# ?5 h3 b) |+ R
2 {3 v: Q3 i: @7 N# C' s  bfatal: [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'"}$ l' R, S) O& O0 a8 _8 c
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'"}
/ n- J) @( B9 i5 l, j0 L2 Ansible构建并运行Docker镜像8 B8 K  i( y7 a% E% `- H
通Ansible提供的docker_image模块可管理Docker镜像(比如构建、移除、pull镜像),使用docker_container模块可管理容器,比如将镜像运行起来成为容器。- [5 W% \! j( o7 B3 n; n/ e
对我们而言,一般都是在已有镜像的基础上通过Dockerfile来定义新的操作,然后构建出自己的Docker镜像。所以需要提供两个文件:一个基础镜像和一个Dockerfile文件(基础镜像不存在时会自动下载)。如果使用Ansible来构建镜像,那么这个Dockerfile文件需要能够被Ansible读取,比如可以放在Ansible playbook文件的同目录下。
' Y. n7 x& i0 |为了演示以下Ansible构建Docker镜像,此处已经写好了一个非常简单的Dockerfile,该Docker镜像是在CentOS 7镜像的基础上添加nginx,然后让nginx运行起来并提供cowsay页面。
/ C' d) {$ K: {; BDockerfile内容如下:
9 ?' g8 Q: H1 K- G  C' nDockerfile  s6 x# ]) p) }
7 S; `) y+ `' h4 ~* V% B+ Q
FROM centos:centos7  ]! x3 k9 c3 o" u5 G; w. S
LABEL maintainer="test.com"8 z8 S% [$ S% z* @# K
RUN rm -rf /etc/yum.repos.d/*.repo && \' f' }$ t2 Z, r  f/ E
    echo -e ' \
8 d, Q  j# d  m9 @0 ^[base] \n\9 _, Y$ z, C9 b# B; K  ^+ I3 K5 {" G
name=os \n\
7 t( c8 z3 Q( ~& r9 a% _baseurl=https://mirrors.163.com/centos/$releasever/os/$basearch/ \n\
5 P/ `0 B6 d4 p4 Jenable=1 \n\  f6 I/ v/ P: g  F
gpgcheck=0 \n\
4 j- I+ \5 m6 L% N[epel] \n\
- ^, }6 i" n/ ^% \+ N9 X' Pname=epel \n\
' }' \* r; `5 T( ^+ ~4 A5 _baseurl=https://mirrors.163.com/epel/7Server/$basearch/ \n\
  F" q+ Q+ C7 ]+ a7 G; Uenable=1 \n\
+ q# a4 `% r) y- ~gpgcheck=0 \n\
' `. _+ V6 G5 T' w' >/etc/yum.repos.d/base.repo && \) u* M2 S1 [7 v2 r$ s" o
    yum -y install cowsay nginx && \
# x  x! M6 w. E    rm -rf /usr/share/nginx/html/index.html && \
: n$ Z5 o) }9 Q0 N4 u* n0 a    cowsay test >/usr/share/nginx/html/index.html && \- m% ]( f+ X: b# a2 u
    echo 'daemon off;' >>/etc/nginx/nginx.conf && \
  t6 O- |& ~3 r; S- R5 I    yum clean all
# p* v7 f- F4 J3 C2 Y    9 x/ R0 Z9 R( F( Z
EXPOSE 80" ~: j$ v; L! j0 ~, S) Z- b
CMD /usr/sbin/nginx4 d, R5 v# A+ ?$ |( V4 g$ j- N+ H
然后写一个Ansible任务文件,假设名为build_and_run_image.yaml,内容如下:
  [1 T: c: O' K: E' M' H" C3 kYaml
" e1 R. x5 E- X4 U+ B! Y- n% C- x2 S  Q& m+ Y+ }
- hosts: docker
6 U# Q0 ~& E. |6 ?6 N  gather_facts: no. P; |" o7 m3 A$ I9 N, `; d3 e
  tasks:
% w7 W: N0 ^4 z9 o! t3 H+ e. S    - name: scp Dockerfile
+ @, d4 U2 r; t      copy: ) r& Z" u7 P3 I* Z/ a# r  i
        src: Dockerfile. w# _5 T% r% M% e% m9 e
        dest: /tmp/Dockerfile
# o1 f9 r& z: y/ Z0 z$ O; Z    - name: build Docker image centos_nginx:v0.1.1# b8 y% h; O- d. D& x; [/ o
      docker_image:
2 ]5 E) a5 N  P1 _& s3 I" u6 D. N        name: centos_nginx
8 k/ t% Y4 m& l, ^$ u        source: build" M1 e; ?2 P1 U7 d4 ^8 O
        tag: v0.1.1
7 l7 l+ c. y$ r, a4 P3 z7 m        build:; R2 T* y* m0 A$ R. `
          path: /tmp
2 A$ w. d) ~) g          pull: yes5 P8 [' G! k# v, f: D2 ?& ]- Z
    - name: start centos_nginx3 {2 [- D& h( b8 o: W
      docker_container:
, r4 }% x( k% X6 Z: j" \        name: cng: v, }& \8 z' z, t& a
        image: centos_nginx:v0.1.15 r7 B1 ~  E) U, H3 V
        ports: 8080:800 B' R$ z9 M0 I. @8 G' I
        state: started
8 u8 O) g6 V; t4 r7 O) h+ ]0 hAnsible执行完成上述任务后,可直接在Ansible端使用curl来测试页面是否可获取:
( S7 a' B& h1 v  A' Z! LShell& Z6 I1 ^, K, _/ z  L" _4 \! t

2 @" D9 I) M$ y4 e# }$ curl 192.168.8.65:8080" z* j5 m6 ^4 T8 H1 i. ^, j
______________
/ s4 r+ ^0 z9 R, o  `& G< Junmajinlong >
8 Y) [0 ?- x: ~& n --------------! K' @7 @) [6 u0 Q
        \   ^__^2 m2 u; A% D0 y3 t+ i
         \  (oo)\_______
% l4 b% O  h3 W! x            (__)\       )\/\
. G: ?* Z9 f2 \! _3 {                ||----w |0 f* }7 c" |$ S3 W1 T. H
                ||     ||3 v! K2 G; M- L8 ^& o; o; P
这里对上述两个模块稍作解释。
+ k! c: Y4 y( c对于docker_image任务来说,通过sourec: build指令来表示这是一次镜像构建操作,source指令可包含如下值:
  q( {  S9 I+ \# F6 kbuild:根据build指令的path参数指定的Dockerfile构建镜像
! [+ O/ c0 Q6 N8 u. J( D: yload:从镜像tar文件中提取镜像
7 W7 b6 j0 u3 N9 b2 kpull: 从registry中拉取镜像
: F4 c/ o* m  \# wlocal:保证docker端已经具备指定的镜像
% b; u; A7 j3 s5 [对于build指令来说:% F7 }- s1 u6 Z& w+ d
path:指定构建时的上下文目录,该目录要求包含Dockerfile文件
& p9 f! a+ F+ D- F8 ~: `6 Idockerfile:明确指定使用哪个Dockerfile文件,而不是默认的上下文目录中的Dockerfile文件* g* T3 B0 I" @4 J" S: X
pull:构建时是否从registry中拉取基础和中间镜像镜像
/ G4 B& a. F; @8 Ycache_from:构建时使用缓存的中间镜像! p: O# Z* j% p5 @( j
args:可按照key:value方式指定镜像的参数,对应于Dockerfile中的ARG指令,例如listen_port: 8080
3 n# h9 j& A9 O) ]) O- m其它指令应该都通俗易懂。
0 E( p# J1 W! A, \6 i- Y构建镜像完成后,可使用docker_container模块启动该镜像。该模块指令非常非常多,几乎包含了docker container命令的所有选项功能,但是熟悉docker命令,这些指令的用法也通俗易懂。比如,指定卷和环境变量:
3 l9 u& ^7 U( |* h2 q! eYaml7 c$ \0 w+ L2 u' C% h
$ w& s7 F8 a: a- L* U* h

' e+ \( v3 M* K6 E2 |) s- name: Create a data container' v; z. W6 {; s  G, z0 G0 N) o6 K6 p
  docker_container:, T, B1 p0 v$ a
    name: mydata
: p4 o* W( J- W$ P5 a    image: busybox4 L* A: }: {3 p1 H4 i  \( a9 W
    volumes:, c/ Q( }& E- ]0 `/ T- e: [: T: q1 Q9 X
      - /data
$ R, x3 C' A) i* g% ^& q- name: Restart a container5 P8 i5 j; B% Z, [1 Z) z
  docker_container:
1 T# q* Z6 n1 m! k# `    name: myapplication
/ V" q! v' _- W) B7 B    image: someuser/appimage
3 |5 U. B3 d: y$ b$ V, [- F    state: started* I' r2 l  ?/ K% o6 z
    restart: yes
, h3 o4 W* I9 L8 Q" p4 A+ m    devices:; A% x1 b  ~' g5 e/ r. v& ?
     - "/dev/sda:/dev/xvda:rwm"
' h6 L( ~5 t# M) l* ]$ b: Z. ~    ports:
7 v1 m9 a* s6 {* X& ^% v; @, L% v     - "8080:9000"3 l& h3 _: f# @) |) s$ \* u' x7 R
     - "127.0.0.1:8081:9001/udp"* g) u' J/ J/ O7 D2 L
    env:5 i/ A/ r+ s0 ]' O2 }6 h
        SECRET_KEY: "ssssh"0 `+ [8 m. }' g6 \1 Y) g1 U" K
        BOOLEAN_KEY: "yes"  x# H$ M+ T; A+ ~% r8 z; P
3 无Dockerfile启动镜像并连接容器
) b% w3 o! P9 `7 w. K' \在上面的playbook中明确使用了Dockerfile来构建镜像并启动镜像提供服务,但因为Dockerfile自身也是基于基础镜像构建的,所以可以省略这个构建过程,而是直接启动基础镜像并连接到启动的容器进行操作。5 E  \8 E2 X- B+ E
下面实现与上述示例相同的效果,只是不使用Dockerfile构建。
0 E2 B8 g  C( iplaybook文件内容如下:# o) a3 F! l6 L
Yaml
4 {/ ]! o0 U, {7 F5 u2 b. U- {& H, }; V' ^& z! R0 w1 ?
---2 `) H! t- g  ]6 B7 j
- name: start image ' S# j% [0 O9 ^* \  ^% H  n
  hosts: docker! m! C, Y; R, p
  gather_facts: no
; z# y$ S2 g7 X8 D  vars: - U2 ~, l$ o# G+ w9 t0 Y- P
    container_name: "centos7"4 F3 Z( x5 y( \" L
  tasks:6 ?6 W$ z* p( p
    - name: start basic container "centos7". @5 B$ V, d+ t* a$ J$ N
      docker_container:
9 m# y# n/ S1 s/ Q        name: "{{container_name}}"4 g. _) c6 ~$ u3 W1 D9 A4 N! W
        hostname: "{{container_name}}"
8 M3 ~# v+ f+ b# W2 O# q/ M* |        image: centos:centos7
4 ]7 F/ W( y' }. N6 t        ports: 8080:805 R3 F( o8 T- g6 X* G4 U3 M
        state: started
2 ~$ N- M& R9 ~( O/ L& A& R        auto_remove: yes
; h6 S9 @, _: M6 Y        command: bash
. e3 \3 O- t* N( o4 t2 B        tty: yes' I5 H1 O4 t) R9 H6 \! }7 k
        
- K+ |# c2 z* T3 N$ ?% r    - name: add container to inventory
: q1 v0 W9 K" T  c9 g2 F      add_host:
' P0 j/ A! J6 s5 K2 w: c* g% G        name: "{{container_name}}": u1 ?1 `/ t8 }* v/ Q% B& L
        ansible_connection: docker
& F7 Z' M. @- k        ansible_host: "{{container_name}}"4 ]. S7 V9 i7 x& g6 ?* l
        ansible_user: root/ m# M7 @( T4 N  K5 }2 p' d4 {' C
        groups: containers* A% |& K4 D7 ?9 |# k, K
        
6 ^  d& D7 O1 d$ Y( |- name: do something in container8 O3 G0 ?1 c+ I
  hosts: containers! t/ L' M2 Z8 e% R/ s
  gather_facts: no* N& E: P: c0 B1 A# ]# d! m
  tasks:
# @; A8 q8 l, o- F$ z    - name: install python if needed
  Q# T; c# O+ Y* t- ?; r. W$ i' z      raw: yum install -y python) y. l2 N1 B# L+ ]; J% m/ \1 I
    - name: remove all repos exists
9 u/ [* n, D1 Q& k& Y( W      shell: rm -rf /etc/yum.repos.d/*0 v* H& \! K- y6 Z
      
4 O) u4 L& |, k    - name: add os repo and epel repo8 {5 h: z7 K. o+ P" y% {3 O
      yum_repository:
" K/ t" v! b, O7 a% t        name: "{{item.name}}"0 i0 P% v+ H  a& E$ S
        description: "{{item.name}} repo"+ }) d; M/ L: P# O% ^
        baseurl: "{{item.baseurl}}". x, T5 R0 Q% ]5 c. W  j; S8 n% W! V
        file: "{{item.name}}"
" H% Q" D6 @$ \' g7 S        enabled: 1
/ L& e9 p0 d: i  q( `; b* l& t        gpgcheck: 05 c4 I* ?% H4 M7 l5 n- f
        reposdir: /etc/yum.repos.d0 C- e+ V. u. J1 y: a9 p9 r
      loop:; H7 `/ l3 y$ p; C5 I: S, i# U' R
        - name: os6 L: ^. }; P6 D! s% Q
          baseurl: "https://mirrors.163.com/centos/$releasever/os/$basearch"# B9 G  s: T  Q9 c8 E" C
        - name: epel, k' l) @' G+ E' v) D
          baseurl: "https://mirrors.163.com/epel/$releasever/$basearch"      - n0 {& c& O2 |4 W' b- @
    - name: install nginx and cowsay  
1 N+ y* R- \$ _" [7 M      shell: yum -y install nginx cowsay
' r# |# V5 |) G% [5 \      
" [" @* g$ h% n3 M; |    - name: configure nginx
" B( T3 z) E7 r1 c      lineinfile: ! B& k; m6 X) ^- m# e
        line: "daemon off;"
  ]  z- f, V/ Z9 V0 R# J  }9 G        dest: /etc/nginx/nginx.conf
8 @% z, s  s4 z! r7 H6 A# R; q. q        8 O9 v8 L9 g4 ~' `8 n+ }/ L4 b4 C0 q
    - name: change index page
, M- `$ ~" w- Y5 i      block: 4 G8 b, @" _* M7 q/ a" a" J
        # 先移除index.html,因为它可能是一个软链接
0 P1 p, O- j' N6 w$ e5 S0 K+ F        - name: remove old index.html page
0 G* T4 j& N" B/ l) _- `$ p7 q          shell: |
* v4 b8 l& d, a  B: t& J            rm -rf /usr/share/nginx/html/index.html$ S- P! ^& X# T6 Y, j" h1 Q! n3 K
            cowsay test >/usr/share/nginx/html/index.html! s0 d/ f2 Y& R' D/ g; ?7 l6 S, w
    - name: run nginx
, n0 R% E! N9 {! {* c0 {4 |+ W      shell: nginx &
3 l" E0 v/ n7 F+ M+ w在执行上述playbook之前,需要先在Ansible端导出连接方式docker所在主机的环境变量,比如Ansible连接到远程docker时,使用tcp:+ c- V1 H: T6 g: W% d
Shell/ p7 k  S# I1 P! n
( Y8 a7 \1 S* \3 w3 ]' r$ v( k: B

2 N. K  \' k' E$ export DOCKER_HOST=tcp://192.168.8.65:2376% M9 Y8 W% a: i: X5 u
$ ansible-playbook -i inventoryname playbookname.yaml+ Z- F0 N4 p& d2 S. r* V
上面的playbook任务中,首先启动docker容器,然后使用了connection: docker连接器添加该容器到containers主机组中,以便后续的连接。之后在第二个play中连接到containers组,安装Python(CentOS系统都会带有python),配置yum源,安装Nginx和cowsay,并启动nginx。任务流程比较简单。; h. ]% p1 Y& H9 O* w
唯一需要关注的是add_hosts添加容器节点到inventory时指定的docker连接方式,这里不能使用默认的ssh连接方式,因为目标容器不一定开启了ssh服务,也不一定能和外界通信,而使用connection: docker连接方式,Ansible将会先ssh连接到docker服务所在主机,然后通过docker container exec的方式连接到容器内部。) h, ~+ v4 {" k5 @8 }9 y
     docker inventory2 w8 W! G( \3 ?4 `8 @: T3 R. s+ Y
Ansible为Docker提供了动态inventory的脚本。可下载该脚本:' p, }' p  U+ X7 X# u+ m' X, H5 r7 e. i
Shell
- D7 L  a+ m1 j) M' i9 f: ]9 t0 P0 N$ V# k8 n

% w; B8 A% f/ v, T) Dwget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/docker.py6 J; }: e" w# K4 h5 a+ K0 N
chmod +x docker.py2 p% @% e2 Q7 [, J5 O, W+ m3 P
执行该脚本测试:0 R' i- s% ~8 ~' Y! G7 V
Shell
2 K& O7 @+ }) E
' [% R0 D# g5 U4 S) g" M! D8 L4 zDOCKER_HOST=tcp://192.168.8.65:2376 ./docker.py --pretty% Y; j+ [( ~- h: A
或者直接在ansible命令或ansible-playbook命令中使用-i选项指定:% P4 c0 k' z( O, j
Shell
1 G3 x  m" M! t
' N% m5 F2 s) H2 n  cansible-playbook -i docker.py docker_containers.yml
5 S' x! M, q; H4 其它Ansible容器管理工具
% @, n' l7 b% Y+ Z8 k2 b# D; gAnsible除了在官方提供了docker相关的模块外,还有一些第三方的工具可用来管理容器。: l) }: E6 r& a+ a% M
比如ansible-container、ansible-bender、Ansible Operator,它们需要单独安装,对于ansible-container来说,在之前几年比较知名,但是作者现在已经将该项目废弃,据作者本人所说,ansible-bender和Ansible Operator更好。6 y, U' l9 d! a. h' X% [
ansible-bender:0 L( [& v2 o0 Q" _2 n$ U
简化Ansible Playbook构建容器(注:此容器是符合OCI标准的容器,docker所构建的底层容器也是OCI容器)- K! E' ^, r& n* j
地址:https://github.com/ansible-community/ansible-bender
( u, g5 h- @8 x1 k1 Z9 \" uAnsible Operator:
2 ?" n  d' N/ i是Red Hat Ansible Automation和Red Hat OpenShift团队联合开发的用来将容器部署到K8s上的工具
: P, ~6 A: u! D. G$ V. R' R地址:https://learn.openshift.com/ansibleop5 z3 P. f8 }- _  c7 S
5 Ansible管理OpenStack: T2 S6 y% d  _0 A# D
OpenStack可整合一台或多台物理计算机的资源来按需创建、管理、配置、删除虚拟机(在OpenStack中,虚拟机对应的术语是”计算实例”,但后文都以虚拟机来描述),对OpenStack提供者来说,提高了硬件资源的利用率;对受益用户来说,可按自己的需求申请带有各种性能、各种资源配置的操作系统,比如公有云的模式,就像去网吧上网一样,想上多久、想体验什么配置的主机都按需付费来享用。! }6 |, L* x& ~$ [0 f  u! I
对于OpenStack来说,Ansible几乎是全程参与其发展的,因为从OpenStack很早的版本开始,就已经逐步支持通过Ansible来配置管理OpenStack,而Ansible管理OpenStack相关的模块也随着OpenStack的版本迭代在不断更新。目前为止,Ansible官方提供的关于OpenStack的模块已经有五十多个,下面是Ansible官方目前提供的模块列表信息简介:
, L2 f; B- l8 PCode
5 S  }, i4 n% u! P' `$ K9 F. Y0 \9 N
os_auth – Retrieve an auth token
( M! M9 k# Y- D+ z( e/ c" yos_client_config – Get OpenStack Client config! [3 X: F8 A+ D8 q/ I! J
os_coe_cluster – Add/Remove COE cluster from OpenStack Cloud
* G; Z% R. _4 V+ [% m4 ^; fos_coe_cluster_template – Add/Remove COE cluster template from OpenStack Cloud
" o# |6 F. ]% Xos_flavor_info – Retrieve information about one or more flavors
3 d6 S0 I. G0 F! R9 |os_floating_ip – Add/Remove floating IP from an instance
9 N" s6 B0 [0 R' Q. o: V8 Cos_group – Manage OpenStack Identity Groups% t7 h/ o1 c* u8 H
os_group_info – Retrieve info about one or more OpenStack groups! o' }& S' F1 d, E, \
os_image – Add/Delete images from OpenStack Cloud
' P- x4 k) L/ Z+ u- n$ A7 U' uos_image_info – Retrieve information about an image within OpenStack
* d# y& \" X2 m1 K1 _) k6 xos_ironic – Create/Delete Bare Metal Resources from OpenStack  R5 ]- ^$ h: ^6 L6 ^
os_ironic_inspect – Explicitly triggers baremetal node introspection in ironic4 M0 ]( i8 ]' |
os_ironic_node – Activate/Deactivate Bare Metal Resources from OpenStack
5 b8 I( c( R, f0 i) n) n( D/ Xos_keypair – Add/Delete a keypair from OpenStack( j; M, p# u2 B9 i
os_keystone_domain – Manage OpenStack Identity Domains0 {+ x: r4 e2 c% ]: e0 K2 Z4 N
os_keystone_domain_info – Retrieve information about one or more OpenStack domains
& U4 X/ p8 _% }$ |$ Z. P1 oos_keystone_endpoint – Manage OpenStack Identity service endpoints! G1 r; E% Y# c) C1 w2 q5 K
os_keystone_role – Manage OpenStack Identity Roles) B( k7 O8 U7 M) Q
os_keystone_service – Manage OpenStack Identity services( y  S* G1 I7 e
os_listener – Add/Delete a listener for a load balancer from OpenStack Cloud* T( P5 {) d6 A0 ]% @
os_loadbalancer – Add/Delete load balancer from OpenStack Cloud
5 y9 g. a! j* T. |4 F1 Kos_member – Add/Delete a member for a pool in load balancer from OpenStack Cloud
% f- f6 M: h: X: w1 w" Bos_network – Creates/removes networks from OpenStack
) y0 l; Z+ U( _" a0 @os_networks_info – Retrieve information about one or more OpenStack networks
& J" A* _  s5 s  q4 c- ]os_nova_flavor – Manage OpenStack compute flavors7 k8 f- v. M  g) I
os_nova_host_aggregate – Manage OpenStack host aggregates
3 h9 C6 j# t/ K* }os_object – Create or Delete objects and containers from OpenStack
9 i; v( H: u  a* ?' ^0 Gos_pool – Add/Delete a pool in the load balancing service from OpenStack Cloud2 }: U# E" g% Q7 C
os_port – Add/Update/Delete ports from an OpenStack cloud
1 s* `, x: A# W, P$ A) K3 qos_port_info – Retrieve information about ports within OpenStack
! M; R4 ?, o' kos_project – Manage OpenStack Projects
3 j; A! w- \7 p+ c! Qos_project_access – Manage OpenStack compute flavors access
, ?  L7 V. A, @- b4 J, Ios_project_info – Retrieve information about one or more OpenStack projects4 \4 O8 x8 K0 t0 L
os_quota – Manage OpenStack Quotas9 A" \5 v2 p! ~* Z% u3 R
os_recordset – Manage OpenStack DNS recordsets
0 A2 p5 @; \) E" q% y/ x) B7 k" b. \) Ros_router – Create or delete routers from OpenStack0 ~4 c* x4 h& I# V+ H
os_security_group – Add/Delete security groups from an OpenStack cloud
. k: o  f7 L, @$ B$ ^os_security_group_rule – Add/Delete rule from an existing security group
5 Z1 P! A# w# u2 b% gos_server – Create/Delete Compute Instances from OpenStack
5 X" ?  r' w2 ~os_server_action – Perform actions on Compute Instances from OpenStack
; ^/ n. ]- I+ n3 Z  U0 k* D8 Gos_server_group – Manage OpenStack server groups! x  {4 n: w' n4 O' A- x3 M7 k  Y2 n
os_server_info – Retrieve information about one or more compute instances. |/ \  g8 j% [0 I$ I0 N7 e
os_server_metadata – Add/Update/Delete Metadata in Compute Instances from OpenStack$ k; k- v, E* E  G
os_server_volume – Attach/Detach Volumes from OpenStack VM’s
' f: z  Q2 x" z% J. z+ Ios_stack – Add/Remove Heat Stack: }4 C( j- v5 ^% ^9 a5 Z% c" D# Z
os_subnet – Add/Remove subnet to an OpenStack network; O+ T" L; o, D; E/ L
os_subnets_info – Retrieve information about one or more OpenStack subnets. ]: j# M. X7 r" @/ e8 M
os_user – Manage OpenStack Identity Users( E2 t9 E  e4 u1 ?+ P2 d9 V' W
os_user_group – Associate OpenStack Identity users and groups2 i& g$ f1 O) K' ^. ]
os_user_info – Retrieve information about one or more OpenStack users
) H& `: f1 V% h" p/ \7 O$ c9 R9 Hos_user_role – Associate OpenStack Identity users and roles! e. T* b' o* \: G
os_volume – Create/Delete Cinder Volumes2 E+ \3 F* ^0 I9 y
os_volume_snapshot – Create/Delete Cinder Volume Snapshots
9 T( ~# c! s  r9 P5 y# ?" Uos_zone – Manage OpenStack DNS zones
$ \, g5 f# }  R" w" i虽然看上去很多,但大致可总结为Ansible可对以下资源做管理:
8 c* u( O& @1 H, p" F(1).计算资源: `" D& ?. A) y3 o1 H: ?
(2).镜像管理
* U9 [- X: w, s(3).账户管理和账户认证
8 @% E2 [+ J8 v& K9 n7 A(4).网络管理/ b/ ~/ e/ ?# t) E. u2 s
(5).对象存储管理
7 G4 `- U+ s0 ]" ]% Q2 L(6).块存储管理
& K8 d! }! w& t5 Z$ y对每种资源的管理可分为四类操作:
5 Y# m5 N/ X7 K! ]; E(1).获取管理目标的信息
9 U8 P% g; d4 J3 x8 b0 H! n- |(2).添加管理目标7 t$ H  ^$ B1 a6 A/ O
(3).修改管理目标的属性
1 \  S1 e( [2 j3 v3 T  }(4).删除管理目标4 l+ s. p! S% Z3 _
即增、删、改、查。
/ \# c1 O# B: V0 o5 M" U% Y: I/ q* U4 K此外,由于OpenStack自身已经跟踪了其创建的每个虚拟机的信息,所以Ansible还可以直接从OpenStack中获取这些虚拟机的信息,比如从OpenStack取得某些虚拟机信息来构建动态inventory,这样就免去了手动提供虚拟机inventory的麻烦。
6 |9 X+ }2 n6 g! M) p$ J+ P本文不会介绍Ansible如何操作OpenStack自身(比如添加网络、上传镜像等),这和管理普通服务做的一些基本操作没任何区别,不同的仅仅只是做不同操作而已。本文会介绍Ansible管理OpenStack虚拟机时最常见的两种场景需求:$ x7 d" V. ]7 ^! O: v
(1).使用Ansible创建虚拟机,然后像平时管理远程主机一样管理这些虚拟机,最后删除这些虚拟机
7 H& r3 D  o4 m, }. H(2).从OpenStack生成动态inventory
& z+ Y' C( V9 C% ]* x% r14.2.1 创建虚拟机
3 D' x! K4 }1 {: e( c- eOpenStack管理虚拟机相关的模块都以os_server开头,目前包括如下6个模块:本文大概只会用到os_server模块$ T4 Z  g" }0 L- D
Code+ y5 M5 H8 @4 c+ `6 e9 s

/ @, U+ s8 I- n; |% M* |" vos_server – 创建或删除虚拟机9 `; N; d; P/ x& W8 U/ Q
os_server_action – 对虚拟机做一些操作,比如虚拟机的关机、开机、重启、暂停、恢复等操作
- \& w- M6 I. _- D" vos_server_group – 管理OpenStack虚拟机分组,比如测试环境的虚拟机可属于test组,生成环境的虚拟机可属于prod组  . ]( |' [# m9 W( {9 N( [: \
os_server_info – 检索一或多个虚拟机信息,在Ansible2.9之前,该模块名称为os_server_facts,用于检索虚拟机facts信息
( ~6 B  k8 e) r  q" u) P% ], Hos_server_metadata – 增、删、改虚拟机的元数据信息,比如设置虚拟机的主机名、虚拟机设备信息,如网卡配置、磁盘路径/dev/sda  
4 l( r. }2 d" n  h+ z5 xos_server_volume – 附加、剥离虚拟机的卷5 i* T" f% }" S
这6个模块都要求先安装好版本高于0.12的openstacksdk包,在CentOS 7中只需执行如下命令即可:
: \% r5 }) ^# x) _* CShell: {0 _9 F7 y, K9 g
% r6 [- c/ |" m" `( U
$ pip3 install openstacksdk8 x  ^0 x. L4 u2 v1 s- @3 u
为了让Ansible连接到Controller进行管理,需要添加Controller的inventory信息。假如OpenStack的Controller的IP地址为192.168.8.65,可inventory文件openstack中添加如下内容:' r2 |: b' e- h7 A+ B  p: a
Undefined. N4 y8 y% V2 p

* N6 T+ U* T& E% d2 X, D[openstack_controller]
4 g! m. T1 h' ^0 ~7 `192.168.8.65
& w& Z; q; O5 X配置Ansible段和controller的ssh认证互信可自行配置,此处不赘述。! |0 X( R! q1 v- K& |) e9 B
然后就可以编写playbook来创建虚拟机,假如playbook文件名为create_vm.yml,其内容如下:
% u6 O& }% P+ @% H( z( [. _Yaml3 _* m3 {7 T- c7 J

. o( N0 Z+ k( Y. j: G: J: O! S5 x6 S- name: create vm
/ u9 v! z+ ~$ @% n5 R4 b  hosts: openstack_controller
7 M8 L9 }) m0 N  gather_facts: no
+ h+ _3 H# s8 Q* q' k2 q  tasks: * U9 a4 ]6 C# P$ L/ W+ C1 j
    - name: Create a new instance) _7 D5 F5 x  w, `! v0 q/ _
      os_server:' X3 E& E7 w  H+ z/ z5 U
        state: present, Y) W( C9 b" G* A2 K3 k1 s) z
        auth:
9 h' ^3 l- x" p% m6 X          auth_url: http://192.168.8.65:5000/v3) y" ]8 K. G- G0 V- B
          username: admin
6 L% H6 \6 P: j/ e$ n          password: admin123
) Z! G% v6 p5 `, A: b& r5 R! w( b+ F          project_name: admin
; |  ?8 I1 z$ C  }          project_domain_name: "Default"
4 N% {3 [7 X8 W' b2 G          user_domain_name: "Default"# z9 w: G) F) ^7 s& B8 L
        name: vm1
; U+ ^$ X* t7 W$ n        image: "CentOS-7.9-x86_64"
4 ~' S8 M. k8 |        key_name: ansible_key
' }( Q0 ~  e. [9 `2 e4 @2 D8 ]        timeout: 200
+ x2 [% r' l) T) _" _, b        flavor: m1.small8 E7 H( }* Z- x% a# h# [% q
        network: 'ext_net'
/ d4 s2 m5 }. _& W. E" C        wait: yes/ N5 X( P: m, _+ `- O
        meta:" O* `4 N' p1 Y) n, W# B
          hostname: test1
1 N9 L% k# d1 j6 Q' n7 t2 W$ Q5 T" }          group: test_group
" @+ z- b: l$ l' \) @  _! Z! ?, C          userdata: |( ?+ V! c" {9 M9 e% }
            {%- raw -%}#!/bin/bash
6 Z& ?6 P- L. J1 B& N5 M            cp  /home/centos/.ssh/authorized_keys /root/.ssh/$ n3 L1 L& o4 F0 X
            {% endraw %}
: O- y5 `' }( n. x9 ?' t' y1 T' Nauth部分是认证相关信息,name1表示创建一个名为vm1的虚拟机,image、key_name、falvor、network都是OpenStack中已经配置好的。这里还同时设置了虚拟机创建出来后的主机名为test1,并加入到了test_group主机组。
' Q. D6 _) [9 U. O! U6 W因为是CentOS镜像系统,该虚拟机创建出来后,默认登录用户名为”centos”,而且默认不支持root登录,为了后续可以使用root登录,上面使用userdata定义了该虚拟机创建后自定义的操作,即将保存的公钥信息拷贝到/root/.ssh目录下。
; {4 z& w9 g6 Y  r4 n注意os_server创建虚拟机任务中的一项wait: yes,它是默认选项,表示Ansible会等待虚拟机创建完成才会继续执行下面的任务。5 L/ n( A+ Q" `! y+ B
因为所有的模块在连接OpenStack时都需要进行身份认证,为了简化playbook中的认证内容,将上面的auth选项段落的内容保存到OpenStack Controller的~/.config/openstack/clouds.yaml文件中。例如:7 m9 U4 d9 V/ _* }8 N& @
Yaml
8 R8 j. b1 M* Q3 y3 j7 l( M0 e# f# V$ X. N  r
clouds:
+ g1 E% ?) ]' S5 z  mycloud:
  r7 U# \  ?6 C) s: p    auth:7 }* ^3 ^) O# I7 Y( X0 p& O
     auth_url: http://192.168.8.65:5000/v3* E" w1 Q# n2 R( V8 n
     username: admin  e0 F( P) X/ z! O# v
     password: admin123
! J2 B4 d# R) D5 \3 Q     project_name: admin
( f) G, G( y8 v0 N& w% A3 I     project_domain_name: "Default"$ f) i+ ]1 i3 D& [( R7 i
     user_domain_name: "Default"  @  o3 k) H  h
以后在模块选项中就可以省略auth,而使用一个cloud: CLOUDNAME即可:
, D( ]" C, A, ?: f; @Yaml
) s9 l$ F: L2 S9 A. G! o
, l6 X: A5 a$ i  wtasks: ! m5 \  v  T" d- R* g
  - name: Create a new instance! O- b, f) Y% F3 j9 k5 H/ h7 M. g
    os_server:
( |* Z: I, Z1 G* f/ E2 E9 e      clouds: mycloud
  E0 R! E; X# _0 y/ x5 q      state: present
6 F! C! }4 `8 {0 y6 M      name: vm1
$ O2 }) ], m* {5 T# B      image: "CentOS-7-x86_64"! ~1 e8 `# n. l% f' m
      key_name: ansible_key1 o) z9 X8 N! `7 F) N+ t
      timeout: 200
5 Y) [) s* N1 w  [/ G  D8 h      flavor: m1.small
* m) h, |+ _- X  N/ Q      network: 'ext_net'
) }$ v) }5 F3 j& {( v$ \9 v) v3 L      wait: yes
  C+ {- W2 B  z( p' x      meta:* [; \% _% ]' u$ p. o* O
        hostname: test1- f6 o' L  ?+ B2 ?. b5 ~! i" J7 P- R; S
        group: test_group
, a2 i" r7 i( v" }) ^, V但是要注意,将认证信息以明文方式写入文件是不安全的,可以使用Ansible的Valut加密。不过OpenStack的dashboard中也已经提供了一个环境配置文件,可以先按照如图所示的位置下载:
* @5 i% `9 T, T  e6 ?4 P1 u' n# I
4 z2 n0 c$ c. a- l2 O2 O) G) D然后以source的方式执行下载到的admin-openrc.sh脚本文件:
( K" R9 g0 R- SShell" t4 r: m! x  n# |/ b9 [
$ U( [' }; A- S( `2 u
source admin-openrc.sh
8 @: f. r, B3 T. B2 _* s执行完后,Ansible的OpenStack相关模块执行时,auth和cloud指令都可以省略。7 |1 w. ~7 e# G9 ^% |
上面只是创建一个虚拟机实例,但很多时候可能需要一次性创建多个虚拟机。可以将每个虚拟机相关信息定义到一个变量文件中,然后去遍历想要创建的虚拟机实例。例如:8 s$ o, q5 D$ s5 Q. H. A& w
Code
% K. E  B% t6 U8 c! c/ N, n2 S7 q( k4 c0 i6 l) |( _2 t
---+ m3 Z5 K+ w0 k# @6 n
servers:5 ]: z7 O8 d+ g5 E# j
  - name: vm1
4 \- I1 y* g$ e( L& b* J( c8 k    image:
6 J8 Z9 {- ^" J2 y9 i) r/ c9 n1 u    flavor: 9 h) O# Q: a" m! u
    key: 5 A" |3 V2 Q4 Q& E
    nics: / ~+ X4 \! S3 w4 _4 E  U
    meta:
# m4 |: j* V$ U5 ~1 C7 W5 y+ c      hostname:
! A0 F  c, t# C# x) C      group:
& b3 @3 u2 h' ?  - name: vm2
$ W5 Z5 E2 F7 P    image: + m# x1 W0 ?7 T, Y/ q/ g- X( a
    flavor:
( i! m4 L  e  \# M* I( ]: Q/ e    key: : c/ j6 _( i" N6 `
    nics:
1 G( o- {; G& _, H- y! o    meta:
5 k% M: |' ?1 a. {# I  X/ p      hostname:
5 x( M: Z; M3 i: s      group:- p2 L8 N% L8 Y( q
有了前面的Ansible基础后,此处批量创建虚拟机应该毫无难度。
  u  G6 [3 L# |! V0 V: r% }9 j, q创建虚拟机后,可以将os_server的任务注册到一个变量,从而可以获取该虚拟机的信息,包括该虚拟机的IP地址:
; t2 X& L5 {  ^, L. \6 z0 d7 vYml
4 D' Q( |  l3 T- L  q  C7 ?, r: q' ~2 c% ^4 [& v  Z
tasks:
# P; \. B# t8 [9 [& u  - name: Create a new instance. v+ e/ k3 j, K7 y7 c0 T
    os_server:8 ?, Q% f0 K; }. A$ @# L# i
      cloud: mycloud7 D- L5 p8 ^, F; s5 w
      state: present
; ]# F, _& J4 M! X4 H4 W# R      name: vm1
5 Y7 _( r- q( F) W0 o  k8 c      image: "CentOS-7.9-x86_64"' w- B5 ~  H2 ~6 ]
      key_name: ansible_key
- _( D2 U9 R1 ?9 Z4 L: J5 F( C      timeout: 200$ h# V/ g2 J; J
      flavor: m1.small
& e5 n) b3 A' [  `      network: 'ext_net'
( i6 t! k/ _) S- Y      wait: yes
, I2 K1 ]0 }/ m      meta:3 i; p3 Y# R- A% t3 }5 ?
        hostname: test1
& l  C. a# e8 i4 R0 `, _        group: test_group
) u" M- @5 e: q7 O. b' `    register: newserver% }+ P0 Z: h# B# v$ e+ }3 o
    / ~+ _1 C( \8 N0 m7 y/ F: k
  - name: get instance ip
) R: l( `0 r2 U    debug:
0 M0 Z+ \4 H$ A; Q9 ?7 ~# k      var: newserver.openstack.accessIPv42 M. h' z3 T2 N; r/ [1 q
有了IP地址,对Ansible来说就获得了最关键的信息,因为只要将新虚拟机添加到Ansible inventory中,新虚拟机便像普通节点一样可接受Ansible的控制。8 }0 u+ ^9 Q: j* f
6、将新虚拟机动态添加到inventory; u$ F( j( \# ]- h
获取到IP地址后,可以将该节点通过add_host模块动态加入到inventory中:
! ]4 q: d# {* n) E; T1 f/ CYaml4 G2 P$ X; S$ A

: z( r! u7 O" k4 G! b" }8 b- name: add new vm to inventory5 A7 Q$ t! V5 J1 i
  add_host:! p+ V3 z$ Y7 }5 `" J) D
    name: "{{ newserver.openstack.accessIPv4 }}"  i: @! y6 o* C. i4 A# m* q
    ansible_host: "{{ newserver.openstack.accessIPv4 }}"
* L0 H1 E# ]; u8 Z    ansible_user: "centos"
1 x$ u; B# U! }& y3 r0 y2 a8 W    ansible_port: 229 d0 L8 ^, Z( O) i2 L* p
    groups:
# m! E5 ^; r; y" D$ X" a      - vm_hosts! @+ \# a# o9 B7 M8 l
似乎这里的逻辑不太良好?如果虚拟机启动了但是不可连接呢?对于OpenStack创建的虚拟机来说,完全不用担心,因为os_server创建虚拟机成功后会等待该虚拟机可连接才真正返回。但对于非OpenStack的其它云主机实例则不一定,这时应当使用wait或wait_for_connection模块定义一个等待任务。尽管OpenStack中可以省略该步骤,但在脑海中应当要知道有这个步骤。
% J5 g) F" X2 g( |9 M  u1 M+ U9 a此外,OpenStack安装的镜像系统可能是比较精简的系统,甚至没有安装Python,所以为了能管理这些虚拟主机,应先使用raw模块安装Python。
1 ~9 Q8 P( i# g. |. E  Z" b+ HYaml% v) b9 I9 a+ \: b) m
- name: for new vm host* I. E% a6 z+ @& Q
  hosts: vm_hosts3 ?7 H' I& R4 N- S9 ?' P) \
  gather_facts: no5 D$ c1 i1 J0 x( |. z
  tasks: * R: |! Z# u) S3 X  q5 F% ]
    - name: install python if needed
0 {7 N! b7 p% _  W- R6 @      raw: "sudo yum install -y python"
) I) ], ?; g4 e8 A* {, V7 A2 E. A如此,Ansible便可以像管理普通主机一样管理OpenStack虚拟机。
, ?9 Y5 B9 f" N5 V; a0 h4 J, b( t, B7、收集OpenStack虚拟机的动态inventory
6 N, h4 j8 L, R8 y动态inventory一般需要写脚本(几乎是Python脚本)来收集,但即使不会Python也不用担心,因为对于OpenStack来说,官方已经提供了openstack插件,还提供了openstack_inventory.py脚本,该脚本位于Ansible官方github仓库的contrib/inventory目录下,查看文件时记得先选择对应Ansible版本的分支。: L" G: H- w2 {4 j6 v5 X
下载openstack_inventory.py并设置可执行权限:! {4 J, u9 G3 d: ~
Shell
6 ]- s1 v4 P( k( j& n) \" F; t% S+ @% y7 o
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/openstack_inventory.py2 i) Y: f. j; x  V, U2 m& V
chmod +x openstack_inventory.py
5 Y# {- |8 p# b/ x0 U  e" ^然后source以下admin-openrc.sh脚本,再执行:
# o. V7 P3 W% {$ [Shell0 a7 S1 @8 G) N6 ?! R/ B& C

. j* X) z& D3 ?- Y/ lsource admin-openrc.sh
, \4 ^0 W; T; }: {1 \/ s./openstack_inventory.py --list% @, y( {0 E4 k; W
可查看inventory信息。( \% I# F! t9 m2 X0 v# E- j, y" p
之后要将该脚本在ansible或ansible-playbook中使用,使用-i选项指定即可:, @& I3 F1 o2 v% l# Z6 u
Shell
7 m0 Z1 D& G7 @* b0 X1 u  _
& {/ h: W( X- }8 m7 Q, wansible-playbook -i openstack_inventory.py -m ping! C4 i/ y: I# h+ i' ^
除了使用openstack_inventory.py脚本动态生成inventory外,还可以使用名为”openstack”的inventory插件。要使用openstack inventory插件,首先要在/etc/ansible.cfg中的[inventory]段的enable_plugins中开启script功能:/ W) m4 c& u5 q3 {, a
Shell' h, g0 O. |/ O, b
+ D3 B  }/ _" m& j3 v0 Y
$ grep 'enable_plugins' /etc/ansible/ansible.cfg
* p4 G6 c8 U+ G  l, P0 Y/ ~#enable_plugins = host_list, virtualbox, yaml, constructed/ J! q9 p; m( h
取消上面的注释,加上script:* j! u( U5 u2 A5 r  A! G
Ini
9 n4 r' c  ~) {! J; m6 e) {1 F
8 l& c6 t8 r1 |+ m8 o4 P1 m+ |[inventory]) F+ P3 P$ F( g* H8 h/ ~, K
enable_plugins = host_list, script, ini, virtualbox, yaml, constructed
; K+ k$ F9 l, ^6 c% Z) ]以后只需在yml文件中加上如下plugin指令即可:
+ P5 B5 L1 h+ E* U( ?Code
% {- T- i8 ~3 U8 S7 x) `4 {. [1 v+ k2 Q' q- H0 _: T$ |% H
plugin: openstack
& v0 C& R) o/ m2 _  f
/ a" @1 t' a& S* ]- u
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 21:22 , Processed in 0.061704 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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