找回密码
 注册
查看: 2410|回复: 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的操作系统软件包,并且可以通过常规机制安装。


. U# ~' \6 z, h3 u( @/ Ryum install -y epel-release: R' I' L! [" P, M# t6 c: s
yum install -y  python-devel libffi-devel openssl-devel gcc ansible; I2 @5 l9 ?8 m1 W; X0 I/ u% g& r3 B
python get-pip.py* J% X1 G9 Z  E1 g


1 S  r0 D) b) ], Zpip install -U pip    ##当前python2支持pip-20.3.40版本
2 Q# [2 K, L* `8 Q# s' F( }7 I! Z
6 h" v5 m6 i# u3 d4 P7 m) n2 @, [7 b4 f4 r6 J
pip install shade
( R$ H  G3 s2 I/ |& l2 Z. W& v; X: v+ b: S0 I0 a: m. j
, N  V4 e! F' E/ Z7 M/ H( W

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

./openrc.sh

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

' r# l/ B& @! w7 b
vi openstack_deploy.yaml+ F, B7 O5 O5 j8 U$ K. W& J+ Y
3 Z! W" J, W  u$ B6 q3 y

: u% [% r4 {( T---
) x0 H! o0 C! X1 N* q8 \3 }1 r+ t8 b+ a- o, h: m! f  s
2 d: v  ~, _* Q7 i% C4 G. x. N% M
-
; w. W  r( e+ q* z- y/ z- B: {, Q) y9 @: N, }6 @1 ~$ n7 C. e
* q* g- c5 S# T" V  u# a
  gather_facts: false
$ d6 C: _9 d( O8 ~  w# A0 a- m. c8 u! t4 }) y3 H+ G: h6 E  ^
# H8 P4 `; k6 f
  hosts: controller8 \1 J8 S, x( M7 O9 ^

5 v" D' K3 W( C6 S- v# R+ |9 e/ ^5 e1 `$ \9 u5 r
  name: "Deploy on OpenStack"
  n2 ^# w8 [4 L; o' F
0 O: j; ~0 g8 u8 f4 w8 I' ~- v
- F  a) j, Q" o( ~9 M9 Y1 S. O, f$ a  tasks: 1 B3 G) I  q. v% E. r' P: g
" c* T. v/ q8 Z8 J

3 w' o& L- w# \, d7 _$ T& e+ J0 O   -
; O5 G4 @& G2 @1 z& B' y7 F2 b: V! e5 G& c* w

7 x' q% Z) o/ T4 V' D- u  F     os_server: : ~2 A8 z( i& ~- B, ?. o+ Y
" j: U& a) l) I# p, P2 \. z( i
$ L" V/ x6 G+ ^% L, r
       auto_floating_ip: yes5 ^3 w6 s; o3 C8 c$ `, V' b. N

7 @# ]3 p. G1 l% T3 l! s; Z
2 j7 G7 o: J" Q/ `* n$ G& L% Y# j       flavor: 1C_1024M_50G
% P( d; I8 w% Q9 ^4 `
8 h! {1 H# U6 n* O; N. ~
5 J5 b: m, \; Z/ N7 M0 d- c% e; E# n       image: 69e26018-2456-4f5b-aaeb-8821f23a4329
* w8 X- X8 j" p: T) I' ]
; Y% Z+ o" g% H* D" b2 T, s5 _6 V( o& h" K
       key_name: ansible_key5 h/ ?1 c" V2 p# X- s

0 }. Y! @1 b# t) X* I& E, i4 k
, n. U- {' e! E" \% n3 }. c% ~       name: testopenstack) w4 \: ?, i6 T7 A" {
  o, A/ ~; ~' n) a3 r/ T; P

* c5 s8 U; U1 e, W5 t       network: linuxbridge2 w1 L3 L$ t# B6 e+ x+ o

5 L2 E% l1 k. f7 Q; o( W  [
6 v8 Q/ P+ \' m/ {; J& z       security_groups: default9 f5 u' w- G3 q/ T" U5 C+ P
% F5 d, [( ^- j, h# s" Q( g  E
; d8 G7 c& B2 K- s: \
       state: present
( s% a; `( n( e" a& X
" W) n& \/ E- P8 p) g& _; F8 D- N6 n; L3 _( P3 |6 s
       wait: true
$ B1 k" i4 l" W/ }$ N$ N8 x# T1 I7 L3 Z* W- T

% ?5 x( a' ?+ N( G. h; c. R+ U0 y+ _5 N! s" S; K

运行测试

# . admin-openrc.sh
7 p: E# a8 T  P# p

# ansible-playbook -vv openstack_deploy.yaml
. r! `) `/ |3 \. ^: T% C: ~

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

! y1 A. m/ {8 H* M& n4 z$ u
Using /etc/ansible/ansible.cfg as config file
' P- W9 H9 k$ e
& q. x! N/ }6 E4 ]/ V: \  {/ J) g, _: z4 e# N4 ~, C* |

$ Q- K/ T- s+ L" z9 J; e- v7 c  u+ A$ ]6 L- Z) d" Q, A
PLAYBOOK: openstack_deploy.yaml *******************************************************
5 k1 A9 x, w' M5 @, K1 {5 j
% r+ }( c: N5 C" H2 w" Q9 b+ V1 w( Y4 v
1 plays in openstack_deploy.yaml8 d4 ^9 {. B* m8 G9 n% P* y
& w/ y, l: Z+ W- M, g% F

* S0 a- Z1 Z* @PLAY [Deploy on OpenStack] *****************************************************
0 }* X1 y! _# E! ~" |3 J, J1 S- ^% n

! }- b# t$ c4 B! ?" r- gTASK [os_server] ***************************************************************
% l) e4 b1 E* [% j6 s6 [# w
. p# ?* i8 Q: Y
- ?1 G: R5 J0 Z& |) b  etask path: /root/openstack_deploy.yaml:87 s6 @7 T; ?; {

. w3 g8 b& I* u8 I' B6 l% _4 \. J, w" _5 W. d. ~) G( t
/ \/ q/ B1 ?" J6 U3 e# B) }
... ...
& `- s! D9 L, H' p7 r0 J5 _3 s4 q3 f: }, [$ ~1 T. a2 c
4 ]. q7 A6 S5 y$ ]% ^( R
6 V5 s0 a: z; t/ a
PLAY RECAP *********************************************************************
2 y2 X! K, P/ @( R  K  h7 }$ w+ g8 R+ D: I! j# j( h

0 l. j0 D6 V- J/ ~& ?$ ^. v4 C! f' c
controller                 : ok=1    changed=1    unreachable=0    failed=0  0 [+ I2 D" k: S

* x5 N2 N; @9 }1 ?% E
4 R' ~; j3 b  Q! K  Q- U- R; U9 B. B  t8 l

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

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-8-2 10:51:52 | 显示全部楼层
1 Ansible管理docker
# h8 L# s1 n4 e4 A, J近年来Linux容器技术越来越受欢迎,通过容器技术,可以保持程序运行环境的一致性,快速启动并高效率运行,涉及到的开销也比较小,此外,在系统层次上完成容器级别的资源隔离非常快速。
1 ]* k& U: u5 t( DDocker是管理Linux容器最流行的工具,它为管理Linux容器提供了许多方便的工具,比如创建、销毁Linux容器,还提供了一些除管理Linux容器之外的工具,比如管理镜像、编排。通过它的易用性,Docker已经成为管理容器的最流行的方法之一。
) e$ q- t1 \+ {" m% G题外话:关于容器和Docker- d$ U3 `) }1 c# j
Linux容器是内核的几种功能组合在一起实现的。换句话说,Linux容器技术是内核层次的功能,Docker只是提供了一系列工具,包括从底层和内核交互到高层和用户交互的一条龙。除了Docker外,也还有其它操作Linux容器的工具,只是对大众来说,Docker是最流行的。, s4 T! q- A! f% `+ A6 }
Ansible为Docker提供了一整套工具,包括相关模块、连接插件(ansible_connection: docker)和inventory脚本,因此Ansible可在许多方面与Docker进行交互。例如Ansible可构建Docker镜像、启动或停止容器、组合多个容器服务、连接到活动容器并与之交互,甚至可以从容器中获取inventory。9 W+ ]0 F: m* U* K
如下是Ansible官方目前提供的和Docker相关的模块:' M7 D% D/ y5 D* ~4 O/ l# d
Code
3 F3 H& z( v$ |6 h
. J- T+ h* A9 W9 e0 y: Xdocker_compose – Manage multi-container Docker applications with Docker Compose
5 A! v) f" C* S  ]docker_config – Manage docker configs/ G4 v# q" U, m4 S: k# _
docker_container – manage docker containers2 b- {7 }) j' i5 K  J1 N5 {4 G$ \6 [
docker_container_info – Retrieves facts about docker container
; x! D- y4 ~' o3 v3 Wdocker_host_info – Retrieves facts about docker host and lists of objects of the services; y% F! Y: o( _4 \6 v( g
docker_image – Manage docker images
; @/ y7 D- \% Ydocker_image_info – Inspect docker images% |3 a8 p& @% r% U0 I+ O7 C6 U
docker_login – Log into a Docker registry$ l. P0 `8 V9 y5 [) S6 ^7 i% P) |
docker_network – Manage Docker networks! x# I9 U+ E7 z5 \
docker_network_info – Retrieves facts about docker network2 {) x. i9 P3 Z, E+ |. M) l9 ]
docker_node – Manage Docker Swarm node
4 w" @2 Z6 Y/ E- Z2 T6 A+ v3 adocker_node_info – Retrieves facts about docker swarm node from Swarm Manager; K8 J0 U$ W; I0 ]$ i9 D- P
docker_prune – Allows to prune various docker objects
0 m9 r  ]0 g0 p; v( a  Q& g* Kdocker_secret – Manage docker secrets8 t6 \5 P, N5 n- a/ p' z
docker_stack – docker stack module3 Q' K1 C9 K' b! L" j
docker_swarm – Manage Swarm cluster$ |/ e% S: ?9 O+ B
docker_swarm_info – Retrieves facts about Docker Swarm cluster
; r2 t3 l/ `* ^docker_swarm_service – docker swarm service
' p) I6 K' ^, Pdocker_swarm_service_info – Retrieves information about docker services from a Swarm Manager
1 w7 _  k$ I+ i" T. Y( kdocker_volume – Manage Docker volumes
. [/ }& V8 O8 Z0 U" X) f7 B7 Odocker_volume_info – Retrieve facts about Docker volumes
, b3 }! o. Y$ Z要使用Ansible管理连接Docker,要求安装如下包(注意:Ansible端和docker端都安装,这一点和其它模块不一样,如报错,请自行在两端安装、卸载、升级调试):
& D0 o( _! W  @: d* M& ]Shell
9 s/ x5 w  A  _& {7 K& k/ ]6 k! a" e# E0 F$ _! Q7 l' F
# 两端都安装,如果已经安装了,则在报错的情况下按需更新) ]  T- I$ D7 U. l
# 此外,根据Ansible使用的python解释器版本,按需决定使用pip还是pip3,& b" v8 P+ a; f: L3 E6 ^9 `
# 如果需要的是pip,则yum install python-pip
& L( }" Q' q$ d; M/ o9 F- o* L$ pip3 install docker requests6 B. w$ `! o/ L& r: Z
如下是其中两次报错信息,注意其中的结尾:No module named ‘XXX’。2 C& f/ z: p, M: T8 D5 \9 M/ s3 w8 U
Code
$ w1 _$ }; W2 K% _0 E2 Q! Z  v; D$ [
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'"}
" `! z  y! H% X  z1 Gfatal: [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'"}
7 M9 Q. `! q; Q2 Ansible构建并运行Docker镜像, H' n( T* E: ?7 `# P0 m- a
通Ansible提供的docker_image模块可管理Docker镜像(比如构建、移除、pull镜像),使用docker_container模块可管理容器,比如将镜像运行起来成为容器。
- u: w7 A. Z8 K% u. Y. M: z: y对我们而言,一般都是在已有镜像的基础上通过Dockerfile来定义新的操作,然后构建出自己的Docker镜像。所以需要提供两个文件:一个基础镜像和一个Dockerfile文件(基础镜像不存在时会自动下载)。如果使用Ansible来构建镜像,那么这个Dockerfile文件需要能够被Ansible读取,比如可以放在Ansible playbook文件的同目录下。
- j8 W1 y" x5 g* a/ n- N8 O为了演示以下Ansible构建Docker镜像,此处已经写好了一个非常简单的Dockerfile,该Docker镜像是在CentOS 7镜像的基础上添加nginx,然后让nginx运行起来并提供cowsay页面。4 t2 {! @8 G. @' |8 Z
Dockerfile内容如下:
3 D3 _9 r, e5 i4 aDockerfile- p3 e, _4 S) D: A9 D  ?, c! z
2 C* K& {) C9 R
FROM centos:centos7& v) S9 s/ `4 |( r0 L
LABEL maintainer="test.com"1 Y( P, d" w8 J  p
RUN rm -rf /etc/yum.repos.d/*.repo && \- p# f8 @# G/ g5 ]. W) _% w
    echo -e ' \. _# n2 j, V% w% h3 g; c) B
[base] \n\
1 K3 K: W" t3 u% Aname=os \n\% B* O' D5 x9 N2 k' F
baseurl=https://mirrors.163.com/centos/$releasever/os/$basearch/ \n\# j" O) l* k4 e/ t
enable=1 \n\
/ @/ b: G0 p$ F- b3 Ugpgcheck=0 \n\
& w! F! E9 Y2 S! a6 _$ S% i( S[epel] \n\
) u' L9 S4 @& t/ g1 L) Y8 g3 }name=epel \n\
4 ?* [7 s6 @/ s  U( i6 i% u2 \baseurl=https://mirrors.163.com/epel/7Server/$basearch/ \n\  j% a4 d" _. S  t
enable=1 \n\: V! x9 L( n9 \6 |6 K4 x7 ~5 y
gpgcheck=0 \n\
; u9 T& R% P; u0 m' >/etc/yum.repos.d/base.repo && \
" n1 @4 f4 }' R2 @. d0 w    yum -y install cowsay nginx && \
" N" s& r& f  S% |    rm -rf /usr/share/nginx/html/index.html && \
( k; ?2 D  d7 F1 b6 Q2 O  P    cowsay test >/usr/share/nginx/html/index.html && \4 g4 F* O3 Y1 _1 \% A7 A
    echo 'daemon off;' >>/etc/nginx/nginx.conf && \
$ t+ d: `- ?' m    yum clean all
2 e7 ]& ]6 U: G* U3 {& K    - t& E( t( p  `- R5 {; i
EXPOSE 80
* C" {) O6 F- N6 x4 QCMD /usr/sbin/nginx  [7 W" D  ?! V" W) Y4 J
然后写一个Ansible任务文件,假设名为build_and_run_image.yaml,内容如下:- E# @! P  D2 z6 S
Yaml
: |2 c. o; k# `; C8 {" o6 h% e0 Z9 Z+ T& f! i  d2 E+ g( I
- hosts: docker# }( G5 Y, K1 h4 ^
  gather_facts: no+ W  G1 Q) u$ L* z8 A
  tasks:
4 I2 P: X# V: {2 w( a* ?% A" M( c, F    - name: scp Dockerfile+ b# w- d, t2 S6 K- p, F. G8 Y
      copy:
/ P; Q+ x7 J/ m        src: Dockerfile" ]- c) e1 }: e/ |( x( c
        dest: /tmp/Dockerfile& }- E3 u, ^0 d4 S; Z' P" l! |
    - name: build Docker image centos_nginx:v0.1.1
% Y+ @$ f% x3 |+ E& g      docker_image: 0 i% [' e+ z8 }& v
        name: centos_nginx7 T1 C. k! O( l, e& ^/ A# J
        source: build  R( \; O) z1 K- E# R7 Q" {2 p: l
        tag: v0.1.1
5 s' ]9 {1 M3 B+ U1 g        build:
3 }$ q; V; o# f$ t          path: /tmp* r3 g+ b0 P& g/ I' A8 Q9 [
          pull: yes1 W1 F- N# p  x6 @3 S
    - name: start centos_nginx# y4 r0 ^7 L5 P: r) ^& @
      docker_container:
5 L, j/ F$ F; d7 n( ^% ~        name: cng
% ]' `; M7 C, a* E1 A8 ?        image: centos_nginx:v0.1.1
, [6 i6 N) @! i7 a" N" G7 X        ports: 8080:80
  |* j8 s" b, ~% M# h9 W$ f8 J        state: started7 |2 g! K5 w! @$ s) l
Ansible执行完成上述任务后,可直接在Ansible端使用curl来测试页面是否可获取:( m4 H# T6 \% D( C7 I6 O8 ?
Shell
2 S7 I, ~$ _. Z4 m# J3 o. V5 C4 y# }: Z
$ curl 192.168.8.65:8080- F! n2 m3 _" [. T
______________$ \9 l% ?; j0 r) ?5 _0 n
< Junmajinlong >& `* e/ s: Y. L1 X1 l& l6 i
--------------
* T0 H  a7 Y  U2 X! ^        \   ^__^
3 E  z- I$ H  r' Z' z) J2 s         \  (oo)\_______# Z' v5 G% S2 c3 I, N% y
            (__)\       )\/\
7 S, B# c0 u( [0 H                ||----w |
2 w4 C4 U9 y3 g8 Y) w# T0 S' a                ||     ||
& X; P1 f3 ?9 j5 g这里对上述两个模块稍作解释。
1 u- o- [" L' {8 Q$ w% `8 W对于docker_image任务来说,通过sourec: build指令来表示这是一次镜像构建操作,source指令可包含如下值:* D, g+ h/ \! }8 n  b
build:根据build指令的path参数指定的Dockerfile构建镜像; Q' |; m' b6 T0 n
load:从镜像tar文件中提取镜像( T$ _. x# ?5 U$ v( o
pull: 从registry中拉取镜像0 N9 Y! c, [. _
local:保证docker端已经具备指定的镜像
" h! ^, b; g2 q6 v+ s- }: C2 M对于build指令来说:
7 U- l8 {" g, K5 e/ r! Ipath:指定构建时的上下文目录,该目录要求包含Dockerfile文件
- v" X! b$ C1 F# V5 q' Kdockerfile:明确指定使用哪个Dockerfile文件,而不是默认的上下文目录中的Dockerfile文件
0 l6 d/ f0 C" k+ {pull:构建时是否从registry中拉取基础和中间镜像镜像  L. ^% }( P+ v$ c3 u) ?9 P
cache_from:构建时使用缓存的中间镜像
/ a8 i5 y7 g$ V: K* I3 X7 o" |args:可按照key:value方式指定镜像的参数,对应于Dockerfile中的ARG指令,例如listen_port: 8080. }7 u, W2 w/ @/ v; i
其它指令应该都通俗易懂。
1 `& N9 C$ q* W( y* H6 u构建镜像完成后,可使用docker_container模块启动该镜像。该模块指令非常非常多,几乎包含了docker container命令的所有选项功能,但是熟悉docker命令,这些指令的用法也通俗易懂。比如,指定卷和环境变量:8 A! _5 E: {9 d+ o" F' D+ P
Yaml
6 P' z/ D( {5 {- N( \' x6 ^4 |6 @* l5 H
0 ]2 E9 I9 Z; a
' p! X. e6 B/ o- name: Create a data container0 y- f& X+ J8 r7 o) n/ A  P  v  H
  docker_container:( X/ f$ ?( b5 z5 b3 L- V
    name: mydata
3 N+ s" b% ]6 _% J4 c  O1 @: g    image: busybox) r  x) B7 u: l, N. s- w. s1 Y
    volumes:
3 P: f% g+ g  |" d# M% U1 ?      - /data
  e! U  S2 b4 \% n- U6 i- name: Restart a container1 K3 G6 O, F+ j1 S
  docker_container:
! P, z. D% y4 n( R& R! N    name: myapplication
2 h' C9 m  K+ ?- [! e    image: someuser/appimage7 ?  ]# o) B+ {6 e* V; a
    state: started
* n) T( k6 o2 y2 r    restart: yes
/ Y  }/ q" Z1 u    devices:
$ D- {/ [3 H: D5 U* u% y     - "/dev/sda:/dev/xvda:rwm"5 |4 v9 n# g) Y
    ports:
0 h6 R  ~" D+ d" @7 @" `9 x     - "8080:9000"
/ j( E: T* i7 G! e( y. N: W) S: U     - "127.0.0.1:8081:9001/udp"
8 D+ k3 F$ k& a    env:
- u: X2 w, e6 K  ^9 P        SECRET_KEY: "ssssh"
7 t" \: r$ [  m  m" f% ~3 o        BOOLEAN_KEY: "yes"' D, C, k- i. u6 |2 v3 W; N' p
3 无Dockerfile启动镜像并连接容器7 e9 o. m, r! O8 ?2 s5 S4 W
在上面的playbook中明确使用了Dockerfile来构建镜像并启动镜像提供服务,但因为Dockerfile自身也是基于基础镜像构建的,所以可以省略这个构建过程,而是直接启动基础镜像并连接到启动的容器进行操作。& q2 R/ `+ r$ y8 \1 [+ n
下面实现与上述示例相同的效果,只是不使用Dockerfile构建。5 s2 j+ V9 B$ l8 S1 A
playbook文件内容如下:
3 h5 w( T  ^) _Yaml' q) t  G$ F0 s  _7 R; o0 N$ k
* l% [3 K6 z- y9 x$ p. `
---
. p; y  m# f5 w- name: start image # i! y1 Z0 i9 L
  hosts: docker
" K- B, ~- m. s5 a7 x  gather_facts: no
* m: g* y7 }% t) y' A  vars:
9 I0 W2 B5 g0 M1 c0 _    container_name: "centos7"* {% ]& F. d  Q$ w8 a
  tasks:- o8 Y/ z& A5 K$ t6 \. S* y
    - name: start basic container "centos7"
+ Q/ G, E. b7 }9 l/ t3 O$ G      docker_container:
) C; N% f. y% t7 H/ Q        name: "{{container_name}}"- l2 j3 g! d& Y4 d/ I. a
        hostname: "{{container_name}}"5 X4 O7 |1 v5 ?! m6 F1 |8 N
        image: centos:centos73 n! D3 D! ^: s9 o/ q. F, W# V2 b( u
        ports: 8080:801 V5 u+ \( y. ~  @4 \- u
        state: started
' a+ C! p6 M( j: A' ]        auto_remove: yes
& p8 N( }. O0 j% o( F- y        command: bash
+ A6 y' V5 }- N; g" Y! X        tty: yes
; ^3 Z' d% M. w+ [9 A% u        . a- ?5 l: ~7 s5 o4 L, \
    - name: add container to inventory0 B, ?& n* s, V: R% x
      add_host:
' M) o: t4 m& {( _' @        name: "{{container_name}}"
* {8 s8 F9 {/ F9 [2 X# N. s8 T: o        ansible_connection: docker
+ _% o4 x4 w# o$ L; g        ansible_host: "{{container_name}}"
: I8 a& w) Z: x+ X0 C) S        ansible_user: root
. C  [  \: ]- [        groups: containers( a) b" ]. n7 d- L& @; K
        
' D  E3 u/ I3 h" s% \- name: do something in container: E, e+ l9 m& e- E; t& a
  hosts: containers1 A& f; w  C/ \* S; l" w
  gather_facts: no3 G# t: G0 w9 G# Z1 w, y  j
  tasks:
# I, ?) m% A. {    - name: install python if needed
$ v3 G0 \  n1 L      raw: yum install -y python$ P! B: D- S6 q9 i
    - name: remove all repos exists+ z+ U# ~- s6 r, U
      shell: rm -rf /etc/yum.repos.d/*" K% X3 t# M% o6 J0 `' H
      + G8 d  F6 V. L' b$ R
    - name: add os repo and epel repo/ R2 P) v6 M8 }; A, Q% ~
      yum_repository: 9 e5 V& w% M, R* {+ e1 j
        name: "{{item.name}}"8 a! y! G) V  p# k7 A4 \
        description: "{{item.name}} repo"1 p1 t9 Y# w5 h4 P8 W. {
        baseurl: "{{item.baseurl}}"
5 j% B' C3 k" M# a1 T        file: "{{item.name}}"& b& D3 H5 A2 u8 l& p+ n8 P  z
        enabled: 1
# c, G  _# V% J3 [5 O: P8 l        gpgcheck: 0- {, D- G- Q1 S  Z9 n8 A; ^3 @) \  b
        reposdir: /etc/yum.repos.d
. S5 U& A, A. d9 I      loop:
+ T4 _$ J7 V8 O2 T        - name: os
2 c1 Y# ~  u: D0 \' z8 M4 i" H          baseurl: "https://mirrors.163.com/centos/$releasever/os/$basearch"
) c9 _: s; i+ W* z3 D. G2 P1 q! B: ]        - name: epel6 J1 p9 L5 E* _3 m5 t
          baseurl: "https://mirrors.163.com/epel/$releasever/$basearch"      7 r! ^4 l2 U4 u! y7 w; V
    - name: install nginx and cowsay  0 c0 Y3 g& f" d  g0 F
      shell: yum -y install nginx cowsay
3 e% G0 A0 r* d- k/ Q      . z3 U# u' a/ B3 {+ m- q) ^+ v. r
    - name: configure nginx
# s4 e& G5 A* k- q7 s/ y6 @: Q0 v      lineinfile: 6 m) V+ R/ i1 b- D# S7 K- s) T
        line: "daemon off;"
* p' X; b# a" `* c        dest: /etc/nginx/nginx.conf
" y7 V- I, E+ A6 d0 Y        2 S  L" \6 v& f* q; C. k" O8 S
    - name: change index page- q5 [2 f" m; B7 u5 [0 Z
      block: ! u: s  w# O, n
        # 先移除index.html,因为它可能是一个软链接
% e7 ^; U' }/ ?) _& \        - name: remove old index.html page3 H# a$ U( h) T/ I" O1 ~
          shell: |' U5 M  {: a( t( m; @6 r5 l' ?
            rm -rf /usr/share/nginx/html/index.html
6 m" u8 c8 v# M3 U& u0 p            cowsay test >/usr/share/nginx/html/index.html
! d  ]: W4 [9 \2 d9 R8 _1 O. R3 g3 X" X    - name: run nginx
; [3 [4 K' I: @* X9 s; @      shell: nginx &4 X3 Z# A6 J# q# A/ U
在执行上述playbook之前,需要先在Ansible端导出连接方式docker所在主机的环境变量,比如Ansible连接到远程docker时,使用tcp:$ W( I0 p- w0 ?. v6 v4 X
Shell
3 G; e8 k# x* X
+ r5 ?7 Y' U' U' ?- a* `+ i( a' D
$ export DOCKER_HOST=tcp://192.168.8.65:2376
; F7 j0 e) X* f6 f8 y% y8 R, \( l$ ansible-playbook -i inventoryname playbookname.yaml
( B9 L6 X/ O; v3 z: F' e4 c上面的playbook任务中,首先启动docker容器,然后使用了connection: docker连接器添加该容器到containers主机组中,以便后续的连接。之后在第二个play中连接到containers组,安装Python(CentOS系统都会带有python),配置yum源,安装Nginx和cowsay,并启动nginx。任务流程比较简单。$ f2 y- ^  A* B+ J7 n2 K
唯一需要关注的是add_hosts添加容器节点到inventory时指定的docker连接方式,这里不能使用默认的ssh连接方式,因为目标容器不一定开启了ssh服务,也不一定能和外界通信,而使用connection: docker连接方式,Ansible将会先ssh连接到docker服务所在主机,然后通过docker container exec的方式连接到容器内部。2 F5 u8 G4 Q9 h% L
     docker inventory
. q* y/ W/ e& f: D$ I. f" G1 Y8 y& iAnsible为Docker提供了动态inventory的脚本。可下载该脚本:
5 O7 f. }6 J. v, S, S" bShell% u- Q1 r& \# B* S5 v- q- w( c/ K

$ |& F1 N6 @( g4 y  x9 z3 o0 Q5 F0 V/ d7 q( ~
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/docker.py
4 J) c6 a! D. o" O- H& |chmod +x docker.py4 w% x# L/ G. z
执行该脚本测试:6 E. _9 u, _. B) ~8 C$ Y
Shell. s8 T6 Y6 Q* e1 D

$ i1 M% Y5 [* z) y8 aDOCKER_HOST=tcp://192.168.8.65:2376 ./docker.py --pretty
5 V1 r% e; _. X( q% a6 F或者直接在ansible命令或ansible-playbook命令中使用-i选项指定:, X, v7 c" A: @: ]
Shell
* Y6 t( a' ~2 S0 q: f9 ~6 O
5 B5 R8 S7 w6 U& ~6 v5 N  h  {ansible-playbook -i docker.py docker_containers.yml
; n! b4 f$ }, w) k4 其它Ansible容器管理工具5 O1 q, K2 E& h2 W2 U
Ansible除了在官方提供了docker相关的模块外,还有一些第三方的工具可用来管理容器。. q$ ]0 [; K6 A; S. N2 O4 F
比如ansible-container、ansible-bender、Ansible Operator,它们需要单独安装,对于ansible-container来说,在之前几年比较知名,但是作者现在已经将该项目废弃,据作者本人所说,ansible-bender和Ansible Operator更好。1 q' V* e, i) K" E# |
ansible-bender:* O" e4 N2 `3 U* c1 E4 ]+ w' v. R
简化Ansible Playbook构建容器(注:此容器是符合OCI标准的容器,docker所构建的底层容器也是OCI容器)0 m: Q5 @# f# ~: H- r+ @
地址:https://github.com/ansible-community/ansible-bender) K3 ~: O% ]/ f- s: @, t, G* V
Ansible Operator:( |6 c- _: U' C7 ^$ Q3 ?
是Red Hat Ansible Automation和Red Hat OpenShift团队联合开发的用来将容器部署到K8s上的工具
1 g" [1 M0 _; p( p) I地址:https://learn.openshift.com/ansibleop6 |8 X+ a' h3 A. M) G( [3 d
5 Ansible管理OpenStack* m. |! n9 e" U) E- _) r5 |* x
OpenStack可整合一台或多台物理计算机的资源来按需创建、管理、配置、删除虚拟机(在OpenStack中,虚拟机对应的术语是”计算实例”,但后文都以虚拟机来描述),对OpenStack提供者来说,提高了硬件资源的利用率;对受益用户来说,可按自己的需求申请带有各种性能、各种资源配置的操作系统,比如公有云的模式,就像去网吧上网一样,想上多久、想体验什么配置的主机都按需付费来享用。
/ p3 O2 Y5 V9 l7 E2 e对于OpenStack来说,Ansible几乎是全程参与其发展的,因为从OpenStack很早的版本开始,就已经逐步支持通过Ansible来配置管理OpenStack,而Ansible管理OpenStack相关的模块也随着OpenStack的版本迭代在不断更新。目前为止,Ansible官方提供的关于OpenStack的模块已经有五十多个,下面是Ansible官方目前提供的模块列表信息简介:
) M+ q9 Q. v2 W4 B+ PCode
! O9 h' L: ~  T( I7 M! j& g8 G* d
os_auth – Retrieve an auth token
  M% {# t; X* B/ P' jos_client_config – Get OpenStack Client config
; [6 i3 C  h$ k" ros_coe_cluster – Add/Remove COE cluster from OpenStack Cloud
: l7 A8 [: o  `, o" Z* Ios_coe_cluster_template – Add/Remove COE cluster template from OpenStack Cloud5 m$ P* |' J. W( }( g  i  X
os_flavor_info – Retrieve information about one or more flavors
/ K) y( ]; m" E. o- b6 k3 Xos_floating_ip – Add/Remove floating IP from an instance- P0 x* j1 z8 F6 e
os_group – Manage OpenStack Identity Groups
8 W; C9 n2 Z# P" [+ jos_group_info – Retrieve info about one or more OpenStack groups9 X* _# S  z* {0 w( q1 c
os_image – Add/Delete images from OpenStack Cloud
) n. g& q! V- \9 p4 Qos_image_info – Retrieve information about an image within OpenStack  j6 [7 L1 E1 U
os_ironic – Create/Delete Bare Metal Resources from OpenStack+ X" m0 Q! W# L/ }  I; O
os_ironic_inspect – Explicitly triggers baremetal node introspection in ironic; p+ N# T, U# S) }
os_ironic_node – Activate/Deactivate Bare Metal Resources from OpenStack
2 z( g+ z1 I' a$ F7 R! qos_keypair – Add/Delete a keypair from OpenStack
, l, o2 H* m$ n- Pos_keystone_domain – Manage OpenStack Identity Domains" m' @% J7 w# ]0 s
os_keystone_domain_info – Retrieve information about one or more OpenStack domains
  r2 G1 d! Y1 x! J$ Pos_keystone_endpoint – Manage OpenStack Identity service endpoints7 e3 G2 t1 z' ^  @+ H7 j
os_keystone_role – Manage OpenStack Identity Roles* k8 C) S! k( |4 |* V' z: i
os_keystone_service – Manage OpenStack Identity services1 P" `8 t" a) J/ b2 q( o9 C& E
os_listener – Add/Delete a listener for a load balancer from OpenStack Cloud
. U: i2 E, O$ ?" S( h$ o; |os_loadbalancer – Add/Delete load balancer from OpenStack Cloud
/ `4 c* y! M, V+ C9 Fos_member – Add/Delete a member for a pool in load balancer from OpenStack Cloud- M7 u  }4 p6 \+ m- x& Q: `9 |
os_network – Creates/removes networks from OpenStack
( V1 x. j, x( w! Cos_networks_info – Retrieve information about one or more OpenStack networks
; P# w' o+ z5 Q6 }8 Ros_nova_flavor – Manage OpenStack compute flavors
6 m+ ~+ n0 `! w5 `3 O* V& `6 `os_nova_host_aggregate – Manage OpenStack host aggregates/ a9 [' k  L# E/ N4 X
os_object – Create or Delete objects and containers from OpenStack
% ^! G7 V: ?% l1 |os_pool – Add/Delete a pool in the load balancing service from OpenStack Cloud' B7 q2 P$ b& p+ c" N/ x
os_port – Add/Update/Delete ports from an OpenStack cloud
1 Z* z& m  A6 {" h8 L6 |/ pos_port_info – Retrieve information about ports within OpenStack
* M# u0 E6 v) xos_project – Manage OpenStack Projects
: v' ^' L  o! Q+ yos_project_access – Manage OpenStack compute flavors access
6 I! ~0 M; Z0 S8 @1 G" Mos_project_info – Retrieve information about one or more OpenStack projects7 ~2 |2 l$ w/ V- V# b! j0 v9 C
os_quota – Manage OpenStack Quotas5 K( ?" L5 E% h; i
os_recordset – Manage OpenStack DNS recordsets. l6 b' H! }$ ^& [% G" `* J! ?
os_router – Create or delete routers from OpenStack/ ?+ l" U% N' q( y6 d5 B  D  h; i
os_security_group – Add/Delete security groups from an OpenStack cloud' q* s! }) ?& H5 F
os_security_group_rule – Add/Delete rule from an existing security group
. u& {* Y8 |2 \- gos_server – Create/Delete Compute Instances from OpenStack) ~. ~6 q" Z% S3 t0 P" [1 Y, e$ ~" ^% w. y
os_server_action – Perform actions on Compute Instances from OpenStack2 ~7 q/ K6 @! q4 s6 @
os_server_group – Manage OpenStack server groups5 ^% p& C7 ^4 V: ~3 s
os_server_info – Retrieve information about one or more compute instances: ]- S: n8 R8 J
os_server_metadata – Add/Update/Delete Metadata in Compute Instances from OpenStack3 \- G% y; b5 F8 S' s9 |) ?
os_server_volume – Attach/Detach Volumes from OpenStack VM’s7 t9 l# }& ^. x
os_stack – Add/Remove Heat Stack$ Y7 y9 v  B; l/ k% ?9 O
os_subnet – Add/Remove subnet to an OpenStack network: \, X# T; L% q# A4 G/ O/ d
os_subnets_info – Retrieve information about one or more OpenStack subnets
/ I5 u3 I5 ^1 p: Bos_user – Manage OpenStack Identity Users% A( Y( ]: S. ]& X% C5 @
os_user_group – Associate OpenStack Identity users and groups
7 @1 [# z+ a5 {- }os_user_info – Retrieve information about one or more OpenStack users
. \6 ^5 ]8 y3 zos_user_role – Associate OpenStack Identity users and roles
8 Z/ X( j& E: kos_volume – Create/Delete Cinder Volumes
7 [. }% _! b# x3 z, d' Fos_volume_snapshot – Create/Delete Cinder Volume Snapshots7 {0 V7 J- a4 q$ k+ f: H; Z
os_zone – Manage OpenStack DNS zones
0 Z! w3 O, ]. j  R虽然看上去很多,但大致可总结为Ansible可对以下资源做管理:
( U/ v' ^: h1 I$ {5 }  [(1).计算资源
+ I/ a. N* t( s( _8 t(2).镜像管理. s9 N1 S$ b) L; p. n
(3).账户管理和账户认证6 a0 e( b% H" O
(4).网络管理
6 i2 D  k' U0 q. Q" g7 {' w) Y(5).对象存储管理$ M% M9 X/ g$ c( X
(6).块存储管理
# `) q0 \+ L* c对每种资源的管理可分为四类操作:
7 v& R. z6 w% a1 X. k(1).获取管理目标的信息4 A" Q: O9 N* v5 C# E' \6 I! g
(2).添加管理目标
& \3 w5 a& y! T8 M6 n6 o(3).修改管理目标的属性- K: ^% r6 S3 f; c4 S6 j
(4).删除管理目标( B) p6 r8 c! U. @8 ^# ~( q" D
即增、删、改、查。
9 p7 j9 e7 u5 s0 P' G$ X此外,由于OpenStack自身已经跟踪了其创建的每个虚拟机的信息,所以Ansible还可以直接从OpenStack中获取这些虚拟机的信息,比如从OpenStack取得某些虚拟机信息来构建动态inventory,这样就免去了手动提供虚拟机inventory的麻烦。
5 T) A/ B9 N3 @本文不会介绍Ansible如何操作OpenStack自身(比如添加网络、上传镜像等),这和管理普通服务做的一些基本操作没任何区别,不同的仅仅只是做不同操作而已。本文会介绍Ansible管理OpenStack虚拟机时最常见的两种场景需求:
5 b0 S, @. r, G9 m0 ^8 v(1).使用Ansible创建虚拟机,然后像平时管理远程主机一样管理这些虚拟机,最后删除这些虚拟机
3 p. O9 W. V" H(2).从OpenStack生成动态inventory  i) g4 N  X5 I9 L1 A# ]
14.2.1 创建虚拟机7 Q; G* M* p. m1 P/ O$ }" @
OpenStack管理虚拟机相关的模块都以os_server开头,目前包括如下6个模块:本文大概只会用到os_server模块3 }( U& C/ d/ Z! I
Code
9 `7 A6 r% I& r+ U9 j2 F/ n4 F, V
, Z; ^9 [+ y* _+ ]* X: r4 E6 oos_server – 创建或删除虚拟机0 Q, [9 h  M# `1 H' C% C& ]
os_server_action – 对虚拟机做一些操作,比如虚拟机的关机、开机、重启、暂停、恢复等操作& R4 u8 m+ I2 o4 `
os_server_group – 管理OpenStack虚拟机分组,比如测试环境的虚拟机可属于test组,生成环境的虚拟机可属于prod组  
& A1 _: o& J* |! s5 e5 \2 ]6 Qos_server_info – 检索一或多个虚拟机信息,在Ansible2.9之前,该模块名称为os_server_facts,用于检索虚拟机facts信息
0 D- B# F. T$ z. q4 H) _& Z. jos_server_metadata – 增、删、改虚拟机的元数据信息,比如设置虚拟机的主机名、虚拟机设备信息,如网卡配置、磁盘路径/dev/sda  4 m3 D0 ]% w: ]9 }( r
os_server_volume – 附加、剥离虚拟机的卷3 b/ g7 R) W( k# I
这6个模块都要求先安装好版本高于0.12的openstacksdk包,在CentOS 7中只需执行如下命令即可:6 s" D6 @5 @% q' @$ W: ?% ^; j
Shell: d3 `  Y: [6 e
0 A+ U: S5 w/ S+ w' e2 T9 l8 Q
$ pip3 install openstacksdk8 m% U( H4 H$ a3 \
为了让Ansible连接到Controller进行管理,需要添加Controller的inventory信息。假如OpenStack的Controller的IP地址为192.168.8.65,可inventory文件openstack中添加如下内容:( W0 S- b/ G9 N. G5 l# ?/ e
Undefined0 e# z$ L9 [, s( s

1 L. m6 j7 B" H" t9 _[openstack_controller]
# o# [' e8 b- D% l. ^* I6 N192.168.8.65# M0 r/ t" r3 s$ Y& A! D
配置Ansible段和controller的ssh认证互信可自行配置,此处不赘述。
3 i. k9 p9 o" j. b& y然后就可以编写playbook来创建虚拟机,假如playbook文件名为create_vm.yml,其内容如下:
* U9 l5 z6 K3 bYaml9 R# _# o* F. {% [( g

8 J* s9 }- p9 L! W0 v! a- name: create vm
8 s4 U- g1 K: ~. C0 h  hosts: openstack_controller
4 L( [1 M3 `9 x, V  gather_facts: no0 l. B+ Y6 F7 Q5 W% G# @7 R# G
  tasks: 8 m+ y( L# g5 O$ O6 R  \) m1 V$ ^
    - name: Create a new instance
9 P+ w6 t; @- }+ u& m  ]      os_server:
. C9 x3 W1 v" ~# d8 ~6 f& d        state: present# D8 t/ Q7 E% z, O
        auth:
* h5 {' V$ t( O9 \* S8 {) k$ v          auth_url: http://192.168.8.65:5000/v3; z# y5 M. p* j( P, _5 N
          username: admin. v0 k6 G& o8 O8 O- s
          password: admin123
7 W7 `8 L  O3 n- r          project_name: admin( L  \! _$ g+ k; d# J
          project_domain_name: "Default", M* M- W* T# r5 A( d- s; ]
          user_domain_name: "Default"' C* [" D6 U7 h- N- W' d
        name: vm1
6 @7 M" |. t* S( F        image: "CentOS-7.9-x86_64"
4 \2 ]6 L, P: q2 h- q        key_name: ansible_key
2 j6 D3 z# I  \- j9 s" G6 u        timeout: 200
  a$ z9 g. c2 U7 I2 ]        flavor: m1.small9 B+ K+ l, f& u! N1 J( \6 L
        network: 'ext_net'
% y+ _) I+ V  V  D( W5 C$ p        wait: yes
) j, ?$ d1 G! p# ~5 |. A7 v        meta:9 m9 k) p2 F, }
          hostname: test18 K9 N2 G; x( N, a8 V3 h  J
          group: test_group
$ b/ v0 P. u6 Q( }3 v) F8 ?          userdata: |
1 a8 u  `% ?; V- p2 c            {%- raw -%}#!/bin/bash
  Y; z- E- F0 G3 s0 c: H            cp  /home/centos/.ssh/authorized_keys /root/.ssh/
- x+ y" U0 `" z/ C) V0 ]            {% endraw %}
3 C: M; P& {: ^2 Uauth部分是认证相关信息,name1表示创建一个名为vm1的虚拟机,image、key_name、falvor、network都是OpenStack中已经配置好的。这里还同时设置了虚拟机创建出来后的主机名为test1,并加入到了test_group主机组。
0 X, v7 `, d5 A* B# F因为是CentOS镜像系统,该虚拟机创建出来后,默认登录用户名为”centos”,而且默认不支持root登录,为了后续可以使用root登录,上面使用userdata定义了该虚拟机创建后自定义的操作,即将保存的公钥信息拷贝到/root/.ssh目录下。
! L# t# r5 }; ]& [注意os_server创建虚拟机任务中的一项wait: yes,它是默认选项,表示Ansible会等待虚拟机创建完成才会继续执行下面的任务。, |: A7 A! ]# D( B7 D, e1 r
因为所有的模块在连接OpenStack时都需要进行身份认证,为了简化playbook中的认证内容,将上面的auth选项段落的内容保存到OpenStack Controller的~/.config/openstack/clouds.yaml文件中。例如:
$ P: k0 W* X9 d0 V* C' UYaml
6 r* M4 ^. B5 E2 j2 T+ a2 C8 V
! k' n2 I( v' I( Y# Pclouds:
" k* h. T7 M( U8 P  mycloud:
. o* m5 @$ X+ N# t+ M) l  h' |    auth:2 g  b0 b6 g: }7 r) a
     auth_url: http://192.168.8.65:5000/v35 v5 m3 C8 t' t9 r# w8 M+ O) h& l
     username: admin2 a8 x" e. g0 R  t
     password: admin123
6 M) }. \& ^; R9 q- Y( l     project_name: admin
* X- y' ?6 F# g/ J; x1 i     project_domain_name: "Default"
6 y8 k- J' i+ G, G* S  m     user_domain_name: "Default"- ^8 h" E0 N3 D( C( P1 y8 F
以后在模块选项中就可以省略auth,而使用一个cloud: CLOUDNAME即可:
" V# t% }0 `. N0 cYaml. V. E: l6 A" M  u& T, |& @
2 m$ y* F! d, j7 Y1 m
tasks: ( h+ ~  J" T6 w
  - name: Create a new instance- B- {; @# b! M% A+ a
    os_server:
$ ^3 U! {, v! b' n$ X* A$ {      clouds: mycloud. R3 F; Y& Q2 S* {. H+ ^
      state: present$ n# w2 V+ `" f' ~. ~* G
      name: vm1
0 O+ X4 c* W, j; T7 o      image: "CentOS-7-x86_64"! f+ [. l7 g$ M% B1 i
      key_name: ansible_key
: [: U# w  l2 Y2 j9 o      timeout: 2009 H) r8 y% g8 w  z! n
      flavor: m1.small
- d. m1 f/ ^# j" C      network: 'ext_net'" }7 l/ Y5 J8 p: ?+ i
      wait: yes+ y/ f+ N: R/ ]/ U  R$ }3 j6 Q8 T
      meta:: n. D3 h& o& s
        hostname: test1/ [& i1 D, d) J, z+ R
        group: test_group
+ p+ q3 a% Y. P但是要注意,将认证信息以明文方式写入文件是不安全的,可以使用Ansible的Valut加密。不过OpenStack的dashboard中也已经提供了一个环境配置文件,可以先按照如图所示的位置下载:2 k* R* W) u' l( P

+ j" N/ q& {5 Q0 m( r然后以source的方式执行下载到的admin-openrc.sh脚本文件:
/ j  K9 ?" o' }/ L  nShell4 e( b$ |% t6 d& D; G  |. F- r( Z+ a
: l( b* N, x! ?, u: c1 s( C
source admin-openrc.sh
5 u# Y7 G/ b3 G* b$ T" Z& A7 i执行完后,Ansible的OpenStack相关模块执行时,auth和cloud指令都可以省略。# X  ^( _1 [6 T) L6 i( O
上面只是创建一个虚拟机实例,但很多时候可能需要一次性创建多个虚拟机。可以将每个虚拟机相关信息定义到一个变量文件中,然后去遍历想要创建的虚拟机实例。例如:
6 A( I+ r  W+ _- k0 ], {Code
; v) j( R1 H! s5 m( U
$ G- G: \- l# \8 z( R---; X' H/ ]# N0 r; o, \) H5 c
servers:
. [6 j& H" z; i4 G! D  - name: vm1$ j7 x0 q$ t; p7 t4 N, Q, _8 K
    image: $ j2 S( C, G% T) n+ K; e
    flavor: 0 E+ S" {9 w8 z  B
    key:
8 B! g3 d, E* x/ H    nics:
. I, G( K9 }! ~  Y: c( v    meta: . d+ W  ~* M% U( n
      hostname:
" C, K6 Q+ U6 @' u      group:
4 T7 P: \, A) P+ ?' q  - name: vm2
: J* N# R9 r3 N- X* M- p6 x. M0 c0 _    image: % S! a/ _% N  Q* `4 W8 ^
    flavor:
; i: i- d0 j) Z! V' w    key: ! Z3 H1 g  u: ~
    nics:
. y5 l5 C6 r4 K    meta: / M9 @: k2 T% N9 i' `
      hostname:
, q! W- ~: S* y: j; b+ [* v      group:; y  m, }/ s" r. h
有了前面的Ansible基础后,此处批量创建虚拟机应该毫无难度。' k# X+ J, W+ x) B& {" m
创建虚拟机后,可以将os_server的任务注册到一个变量,从而可以获取该虚拟机的信息,包括该虚拟机的IP地址:
$ C0 T6 @4 q  `8 E& UYml
# V9 k3 f! L% d  N
3 _/ ^% J0 @$ mtasks: 2 G  _3 v* P+ I* k; A$ [; e
  - name: Create a new instance& q+ Q9 q- p  ]; w( m. h
    os_server:4 j( _" f; {9 s1 K5 |) w; F  Y
      cloud: mycloud$ _" g' P: d8 i, f+ t6 }: R6 [3 W
      state: present
- S, O- I/ v" s' F      name: vm1
: b& c/ N- D: L2 N      image: "CentOS-7.9-x86_64"
; n8 X: h3 D& n- k: {$ Q; ~      key_name: ansible_key
/ d/ f( k. N! Q( ]$ l" G      timeout: 2008 E- u% e) O5 b; `* j
      flavor: m1.small2 O! y, u( {5 G  e
      network: 'ext_net'
  T# i8 }6 Q( F3 ?      wait: yes
8 R% u+ s# ^! p/ B1 ~  _* u2 |! z2 N) }      meta:
0 H9 e1 r- x7 I6 J) P) n        hostname: test1
2 [  b/ D- |# J! z' D: |        group: test_group
8 H8 ~% ^  i( n% T: {    register: newserver& o  p% y% P- K2 o/ \4 Y. N
    + r4 |1 g$ l1 B5 o, A/ ]
  - name: get instance ip/ z; {  k; r8 }0 d1 A
    debug: 9 q0 ~6 b1 j9 k: z
      var: newserver.openstack.accessIPv4
7 o" l" K/ u- x0 T) b' Y有了IP地址,对Ansible来说就获得了最关键的信息,因为只要将新虚拟机添加到Ansible inventory中,新虚拟机便像普通节点一样可接受Ansible的控制。+ l4 e- K* z  P7 U; ^
6、将新虚拟机动态添加到inventory
, P* T1 x8 q! E. h! v6 U, Z获取到IP地址后,可以将该节点通过add_host模块动态加入到inventory中:
( w: n! A9 o! h* N# FYaml
% q! B0 l( {, A! w+ ~5 r1 c7 L4 a! Q+ E7 y: _7 Z( M
- name: add new vm to inventory
# S$ z/ t1 K/ E/ M% D# ~8 M! c  add_host:
- H8 \& d  |  u* T0 d    name: "{{ newserver.openstack.accessIPv4 }}"+ [. P% W" k. z. G" U* s0 p- }
    ansible_host: "{{ newserver.openstack.accessIPv4 }}"
4 h3 h- Y% A6 n" `* k    ansible_user: "centos"& q/ q) F7 P" e! d
    ansible_port: 22
, Q2 u; E2 K* `    groups: ' A7 f! a0 o& l  E/ T
      - vm_hosts
6 G) Y0 `) v6 F) x- ?似乎这里的逻辑不太良好?如果虚拟机启动了但是不可连接呢?对于OpenStack创建的虚拟机来说,完全不用担心,因为os_server创建虚拟机成功后会等待该虚拟机可连接才真正返回。但对于非OpenStack的其它云主机实例则不一定,这时应当使用wait或wait_for_connection模块定义一个等待任务。尽管OpenStack中可以省略该步骤,但在脑海中应当要知道有这个步骤。
1 i9 P1 ?* W+ q5 r6 G此外,OpenStack安装的镜像系统可能是比较精简的系统,甚至没有安装Python,所以为了能管理这些虚拟主机,应先使用raw模块安装Python。# w( w0 S+ C1 M# L
Yaml
- N. q8 u' {' }/ x) ~" S- name: for new vm host! J$ `+ H3 s0 g& d/ g4 @5 p
  hosts: vm_hosts5 s( }, ?& E  O$ r/ t/ \, T
  gather_facts: no
, i+ i$ h. M1 g" T" ?4 b  tasks: 5 T0 D% f. _" _) R  N, `
    - name: install python if needed9 k7 K$ |; X5 [- G2 H. G8 W+ l' B
      raw: "sudo yum install -y python"4 i8 r4 o. [% f) y& C" Q5 c) z
如此,Ansible便可以像管理普通主机一样管理OpenStack虚拟机。
, [8 x) p2 B( G! A& O! k5 G7、收集OpenStack虚拟机的动态inventory* m$ _% t: T% G/ o! R9 r( n1 i( O
动态inventory一般需要写脚本(几乎是Python脚本)来收集,但即使不会Python也不用担心,因为对于OpenStack来说,官方已经提供了openstack插件,还提供了openstack_inventory.py脚本,该脚本位于Ansible官方github仓库的contrib/inventory目录下,查看文件时记得先选择对应Ansible版本的分支。' O1 F9 d7 R2 Q  {( C! _7 {( T- B+ a
下载openstack_inventory.py并设置可执行权限:4 O" l% S3 u- ~$ {1 V1 Q
Shell
. j* T' c. K4 i+ {
6 v; H) P9 x  W" xwget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/openstack_inventory.py
4 s( C8 S4 I* a9 j% f  pchmod +x openstack_inventory.py8 q) m9 F! B2 y1 c% c8 A& s
然后source以下admin-openrc.sh脚本,再执行:
6 ?% u) l4 Z: g8 V2 [Shell' ~  m  B" ]" p( ~2 r$ H
6 Z" Y- e* N( Q  i- r! I
source admin-openrc.sh
( q( i4 d2 f. ]./openstack_inventory.py --list  U5 q+ d. [; W) B
可查看inventory信息。9 V5 i. X+ x6 v5 W
之后要将该脚本在ansible或ansible-playbook中使用,使用-i选项指定即可:9 I+ W5 e' |2 s% N6 a
Shell% y5 g6 T! ~* ~3 T& G8 Z

' T; n3 T7 m6 Q9 y" uansible-playbook -i openstack_inventory.py -m ping
- u% }1 x7 y- u$ }0 t除了使用openstack_inventory.py脚本动态生成inventory外,还可以使用名为”openstack”的inventory插件。要使用openstack inventory插件,首先要在/etc/ansible.cfg中的[inventory]段的enable_plugins中开启script功能:1 l' d) A7 S; L
Shell
# {  s. h$ O# d
2 Y+ o, h9 }* v7 h$ grep 'enable_plugins' /etc/ansible/ansible.cfg
# l& t3 r- E% d9 h, t#enable_plugins = host_list, virtualbox, yaml, constructed
( A# ]& _3 s4 C; M& O8 {取消上面的注释,加上script:9 ?  [3 K! m8 C/ B" |2 L% Y
Ini
8 c7 N: D! f3 V, P( i* ?: ^3 i4 \& o" N, t, d% u# ]9 p7 C! E
[inventory]
% _2 T3 _( C4 W# A$ |( M. C% E5 Fenable_plugins = host_list, script, ini, virtualbox, yaml, constructed
0 a5 l. r& A2 U5 K/ R# V以后只需在yml文件中加上如下plugin指令即可:
2 w+ d$ q8 n0 Z6 w+ jCode
0 e4 ^9 m5 m% @: {3 G$ e6 R$ b- |! Z. C
plugin: openstack
- A: z* f5 X" y) u
: a1 j3 o4 g4 q7 b6 I, `7 U
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 02:10 , Processed in 0.019991 second(s), 23 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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