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


( {( |$ m, F9 b! H+ syum install -y epel-release0 i  L) t# `8 H. G& Q+ ]) R) N
yum install -y  python-devel libffi-devel openssl-devel gcc ansible. L) D( N1 Z  y8 W6 I' c& `5 C
python get-pip.py
. y* v0 q1 t7 U% ?  h" g

3 ~: K- c- |! Z  J
pip install -U pip    ##当前python2支持pip-20.3.40版本6 q2 ~/ _* R# {5 Z
. M! O/ O3 t4 C/ B( Y* h, B
1 O) d# _2 j. D
pip install shade
' A/ |; O: h% r, V7 d) c9 ]' {9 ^$ s4 G! Z& [  M
# _  H5 g; H' i% A/ O  s0 [1 l( q

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

./openrc.sh

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


: [+ a; N8 j- n4 q6 {  dvi openstack_deploy.yaml
# X8 }2 u) ]5 W; |. _! |* @" \4 v+ u4 Z5 J! p* ~" m
  R% n/ s5 B0 e. L( w! H
--- " W" Q# C2 |. O0 r; E

' m5 ^6 _  `& S- R( X" h+ z1 W6 [1 c, M. t& P$ ?9 x
- # N# |- d/ t9 I  x7 o* R/ g1 X

. g2 c% L: z: a! ^' P3 g- X8 i$ h* Q2 f0 |
  gather_facts: false+ l# Y6 d) V3 ^2 A8 b# _
0 l' l# q# n# g3 m1 E& k
& v8 e2 h3 V5 X3 d  _+ r
  hosts: controller
5 B; h* \8 B1 x. Z. f8 A# x; }  i
, K; E" @# W" ?! ~$ E* R
) I% R) c. A4 |% W8 z  a6 U* P6 B5 P  name: "Deploy on OpenStack"! k* D9 ?# M4 X  Q7 G6 ]

6 e) L# U, ^4 p3 z
1 ]5 D% J2 }$ p% y  tasks: # n/ m% e. N6 R& B/ O5 ?- y: @

/ O% k1 ^2 j+ a) T$ }$ Q* M% m9 Q# O! V) |( Y! T
   -
% M9 K4 l: l; H! [* ?: B, g$ g! K7 @! Z  {5 W$ h/ t5 k

% {$ S  i. k, b4 H7 m. B; @     os_server:
: X' M7 j& f) O1 U/ K2 a; d! \$ @. w$ I( E& ~! f7 s' m' m+ l% K

3 M7 Q6 z5 E5 \. l       auto_floating_ip: yes2 ^2 U) T0 Z2 a) F9 E
7 S  F! h2 |& f! U1 L
. p& a6 Q3 r: G- M4 G
       flavor: 1C_1024M_50G
, S/ N% A8 |, f! ?( c, c; S3 s; j- L
4 C. N9 D  `5 ~$ u8 D+ c  d2 y4 K# e+ N) E
       image: 69e26018-2456-4f5b-aaeb-8821f23a4329. s/ q4 K) \3 i/ G0 k! b9 s6 N1 O
1 u( t) M" h# d1 T" |

* [6 G6 S; p. V       key_name: ansible_key5 P9 L5 u" W) N, [! [0 o* o
1 @( e* Q, R& J* s# e

1 I" h7 u; Q5 O" S4 K- q' v       name: testopenstack
( G; @9 t& u! g$ v9 ]% [6 @8 [& F. S9 K, s6 Y  Q

  g# N* T9 i9 o       network: linuxbridge
' L% j9 Q# |9 n/ t* W) O! [! _' n2 w5 W, J$ g
' Q" O1 t% y+ n4 `8 ?' i" f
       security_groups: default6 f/ H6 k7 v2 [; |: i2 X
) D& C* M4 I$ T# V
" _- l" K4 m' Q' ^  V
       state: present
* H& @% c1 V! K( }. z) n7 x) P- b$ c( ?! @$ |9 V% q
5 |9 ~: }1 K0 x7 @  u" ?
       wait: true
- G6 x0 ?, N% \& J- _2 P- k9 O, M6 f+ [- v) i/ o, x
; A0 b' ~3 g1 G' z

% d- [- P$ ]6 }3 J% O# D

运行测试

# . admin-openrc.sh3 P/ E' o+ S1 N) B& b

# ansible-playbook -vv openstack_deploy.yaml
- C/ \* Y  J, l7 s

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


1 ~0 R% n& S6 MUsing /etc/ansible/ansible.cfg as config file) \; K# l* ~! |1 c4 v% B
% p/ v6 @3 w4 E2 T% z: Z
5 u9 b' s* C4 k: v8 X0 G+ k

' X& _1 o* B: e% @" ^; _4 _, Z
' S) i0 Q! H% i8 }: tPLAYBOOK: openstack_deploy.yaml *******************************************************
. q9 @0 Z8 N" M
, A% i8 W4 H, A: x( Y* v& G8 c' D7 r! P1 V% [7 h) ~
1 plays in openstack_deploy.yaml1 p8 O: [3 [1 p4 ]  i( D7 I

2 d7 @$ v: t4 T& |" s% j4 s6 p; n1 u( s3 B+ U( J
PLAY [Deploy on OpenStack] *****************************************************
& D5 w  f- X0 u8 {5 O& j. U' a  w( A) \8 x. W6 d; p1 V
4 J8 o) }: c; s( X
TASK [os_server] ***************************************************************
0 [1 S6 n5 E9 z! X4 a5 S2 y& Q- y" k9 N8 i
6 ^' o1 F: R  @+ ~
task path: /root/openstack_deploy.yaml:8
% u; q7 G% x/ C' @, t; Y- L: F
* _8 v$ V7 T- S1 X( u
1 L4 E; u& S! @% t0 U/ X- ?. q, G! V; E8 f
... ...
# E+ l1 s& A" v  |5 I: ^: ]% w+ k
9 @' p9 N7 _# M. H' R! \1 p' g- V
$ q' Y" V3 D3 w. L1 ^$ f
PLAY RECAP ********************************************************************** e* C; P5 y, }4 c# ?' o0 R
( k0 |2 D- R! {

# L4 E- \, _9 U) M1 F7 {9 s) r  b* O
0 a, I$ _; ~: b& K+ Xcontroller                 : ok=1    changed=1    unreachable=0    failed=0  
  i" R6 @$ F7 i# F" v1 @4 s
7 D* O0 a& ^. i' s3 o% N% m0 I5 u: L6 Q, _' O" r  Q8 N, x3 }

+ N" p7 G' y$ v! N' w

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

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2021-8-2 10:51:52 | 显示全部楼层
1 Ansible管理docker1 k* B- j4 b2 V/ U
近年来Linux容器技术越来越受欢迎,通过容器技术,可以保持程序运行环境的一致性,快速启动并高效率运行,涉及到的开销也比较小,此外,在系统层次上完成容器级别的资源隔离非常快速。
1 a. j; v7 n) ^! Z4 j- yDocker是管理Linux容器最流行的工具,它为管理Linux容器提供了许多方便的工具,比如创建、销毁Linux容器,还提供了一些除管理Linux容器之外的工具,比如管理镜像、编排。通过它的易用性,Docker已经成为管理容器的最流行的方法之一。
$ f, ?% b; |0 ]- M# [  I题外话:关于容器和Docker* @/ K/ s) _; W" j: F* B* D
Linux容器是内核的几种功能组合在一起实现的。换句话说,Linux容器技术是内核层次的功能,Docker只是提供了一系列工具,包括从底层和内核交互到高层和用户交互的一条龙。除了Docker外,也还有其它操作Linux容器的工具,只是对大众来说,Docker是最流行的。- }8 l4 x$ q+ J: Y( s9 W
Ansible为Docker提供了一整套工具,包括相关模块、连接插件(ansible_connection: docker)和inventory脚本,因此Ansible可在许多方面与Docker进行交互。例如Ansible可构建Docker镜像、启动或停止容器、组合多个容器服务、连接到活动容器并与之交互,甚至可以从容器中获取inventory。
8 R- z( P, |+ B) ^( ~0 \6 E如下是Ansible官方目前提供的和Docker相关的模块:
- S5 t, w* G2 E; e) E2 |* O4 uCode
5 M' w9 H' N; z. p, U( i+ d6 `
% i3 X: W3 R7 c- E) l7 qdocker_compose – Manage multi-container Docker applications with Docker Compose
* ^( _5 n# l" n; }* m3 Ddocker_config – Manage docker configs
/ k- u8 V4 }- i2 v* |$ p9 Odocker_container – manage docker containers* E( Q8 O, I+ h+ W5 A4 ~+ M& N8 c
docker_container_info – Retrieves facts about docker container. H6 y$ @1 N1 e+ A7 u
docker_host_info – Retrieves facts about docker host and lists of objects of the services
1 x8 }# F7 T  k# j6 Bdocker_image – Manage docker images( q* f5 Q' C- ~
docker_image_info – Inspect docker images
5 L  S% F4 ^! k0 Edocker_login – Log into a Docker registry
# N/ y; C4 }' K5 F3 [$ z1 udocker_network – Manage Docker networks
/ {! j9 T) q! F- i+ m5 F! e" mdocker_network_info – Retrieves facts about docker network
- z: z4 d$ a" ~3 ^7 |docker_node – Manage Docker Swarm node
% @% V4 b$ A6 Ydocker_node_info – Retrieves facts about docker swarm node from Swarm Manager
! E4 j8 E6 b# {' l, K: zdocker_prune – Allows to prune various docker objects
0 B* n- `$ J! u$ g; Z! I5 mdocker_secret – Manage docker secrets
3 J6 B$ E5 f% x# fdocker_stack – docker stack module5 Q$ X) \$ z7 ^7 E) g& D: n; e5 ]
docker_swarm – Manage Swarm cluster2 v$ ^% G  g7 c  R: @* {- G
docker_swarm_info – Retrieves facts about Docker Swarm cluster
" l; T( ^2 {7 v& T$ m+ S. q5 W/ m' ^docker_swarm_service – docker swarm service
" \8 ^7 [& P3 L& Ydocker_swarm_service_info – Retrieves information about docker services from a Swarm Manager/ K; a- s$ b7 P& O# L& \1 y
docker_volume – Manage Docker volumes1 u# J) e2 L8 f  [
docker_volume_info – Retrieve facts about Docker volumes4 t, D6 d0 E8 x% \
要使用Ansible管理连接Docker,要求安装如下包(注意:Ansible端和docker端都安装,这一点和其它模块不一样,如报错,请自行在两端安装、卸载、升级调试):$ q" [& ]: ?) L( {0 i# w% {
Shell/ P& z) b) w5 ?: b- M; e! t7 H  C
" Q9 u% y, ^8 G9 U3 c. S
# 两端都安装,如果已经安装了,则在报错的情况下按需更新( p! I; q0 q! [0 d5 w
# 此外,根据Ansible使用的python解释器版本,按需决定使用pip还是pip3,% f& O2 ]8 s) Z9 H# \1 O
# 如果需要的是pip,则yum install python-pip* t9 j/ g- Y$ J
$ pip3 install docker requests
: i/ V, [, X% M' C如下是其中两次报错信息,注意其中的结尾:No module named ‘XXX’。
, s* Z- d2 s4 J2 K% hCode
+ H/ J2 \6 I. K1 x
/ ^/ t4 `/ P7 n& cfatal: [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'"}
1 J! K; U5 n4 Z& hfatal: [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'"}- {/ {1 T! Z' h$ w7 P
2 Ansible构建并运行Docker镜像
% j) _" E% c8 @0 o8 L; i2 M9 T( c通Ansible提供的docker_image模块可管理Docker镜像(比如构建、移除、pull镜像),使用docker_container模块可管理容器,比如将镜像运行起来成为容器。
+ k5 G+ ?$ O5 N7 D5 M1 h8 A, J对我们而言,一般都是在已有镜像的基础上通过Dockerfile来定义新的操作,然后构建出自己的Docker镜像。所以需要提供两个文件:一个基础镜像和一个Dockerfile文件(基础镜像不存在时会自动下载)。如果使用Ansible来构建镜像,那么这个Dockerfile文件需要能够被Ansible读取,比如可以放在Ansible playbook文件的同目录下。
. U# {$ V/ Z* r为了演示以下Ansible构建Docker镜像,此处已经写好了一个非常简单的Dockerfile,该Docker镜像是在CentOS 7镜像的基础上添加nginx,然后让nginx运行起来并提供cowsay页面。: O7 y7 M$ |9 P5 N
Dockerfile内容如下:
2 J' V6 }3 f* h% Q1 j% R1 hDockerfile, v) R! q# A5 p  Q$ d! d
+ @; Q/ L% f0 p9 z( r( H6 D
FROM centos:centos76 @4 X$ ?% L8 m# Y
LABEL maintainer="test.com"- W$ m3 X8 ?' _; M, I
RUN rm -rf /etc/yum.repos.d/*.repo && \0 s) m; l3 q' D5 n) B2 R
    echo -e ' \
# z4 E( K2 @" p8 {[base] \n\
! Y8 @  {% ?6 s: W" `name=os \n\
5 L; ~# S6 T5 K% {2 xbaseurl=https://mirrors.163.com/centos/$releasever/os/$basearch/ \n\5 |7 Z: u% V+ \( p& F
enable=1 \n\
* G' [5 Q* e& w. Ggpgcheck=0 \n\' Q. n: @4 d9 O0 P- Z: t9 y
[epel] \n\1 y) Y# e7 ^& Y; x
name=epel \n\
" x# k: X, K4 R8 E$ |baseurl=https://mirrors.163.com/epel/7Server/$basearch/ \n\) m2 ^& _* t, H
enable=1 \n\* M% c1 b9 b, p. J: p
gpgcheck=0 \n\
1 C5 @' r) }2 u3 K; {3 U- `' >/etc/yum.repos.d/base.repo && \
0 `& o' e( c% z2 w5 N% A    yum -y install cowsay nginx && \
6 v. P3 {1 C: z+ b& o1 A* E    rm -rf /usr/share/nginx/html/index.html && \- c7 h# c. i2 G3 y) e0 F) F( c" V
    cowsay test >/usr/share/nginx/html/index.html && \
! l. T  w5 g: O0 A    echo 'daemon off;' >>/etc/nginx/nginx.conf && \
9 A0 A5 J2 j2 E& s4 ~* E) t; \    yum clean all
+ S$ B0 h  L! b   
/ y8 m7 U0 L: M' d+ ~) S0 u) L0 ~EXPOSE 80* L* _/ \0 o& G
CMD /usr/sbin/nginx
% q- T7 h1 i/ X  v* h然后写一个Ansible任务文件,假设名为build_and_run_image.yaml,内容如下:
7 q2 A4 [; |4 n4 Q2 N5 ]3 HYaml, n8 |# C/ ~" y" l' _7 E

7 P8 s# B* w7 u- hosts: docker; k2 |8 ~' V8 U) ]
  gather_facts: no6 B6 S! ]# k! B0 R" d
  tasks:
" q- W8 o9 T3 s6 Q  S7 S2 R    - name: scp Dockerfile) W5 n+ }* Y" @7 {3 H1 p
      copy:
/ r# {" l) w% ?" |8 v        src: Dockerfile/ ~) [4 X! O! V1 ]
        dest: /tmp/Dockerfile
) ^% a" y! {* H2 b% G5 P: W    - name: build Docker image centos_nginx:v0.1.1
( u) Y& F+ o) r% `& t      docker_image:
' O8 j6 r- h, C( j  _4 O        name: centos_nginx
: v2 s4 S8 Z6 L1 B        source: build
4 r% c8 A8 B9 n4 y* Q        tag: v0.1.1
* m2 L( G% i) z9 J2 ?3 }        build:2 l" v+ F) ^" m2 ^4 v, _* i
          path: /tmp1 ^4 ^( U" V0 e1 v9 U8 k) {
          pull: yes( ]. \3 y" z: H
    - name: start centos_nginx
7 S# R5 m2 G2 F# o      docker_container:
9 f' j- Z* k; c% ?; _; U  W% A        name: cng
7 {+ y7 m* c9 Q. `" H- p& a' z, D        image: centos_nginx:v0.1.1
/ {; ?" [1 k+ N        ports: 8080:80" r% d* U! \9 u" }: o6 C8 B
        state: started, s& `' e# X* t& U" ?/ A3 L5 {
Ansible执行完成上述任务后,可直接在Ansible端使用curl来测试页面是否可获取:0 A0 [3 ^5 y( d& [' t8 ~* J/ \
Shell
- Y& M5 I. g: w. I9 s; a9 g1 J: `- M/ k+ S
$ curl 192.168.8.65:80807 L. Q# B0 r6 p' |
______________4 J" J3 `0 ~" v8 ^5 H" c  s, Z  [6 Y
< Junmajinlong >1 t' b- z0 n7 \8 H- {! b$ G5 D  D
--------------) m! n9 M2 e  R+ Q2 s# F3 ~8 B
        \   ^__^) @2 e( s# g' j% n1 J5 |
         \  (oo)\_______
5 M" s' l3 m6 z$ i- Z            (__)\       )\/\
- S% U4 Z, k6 v, j( T/ r( W                ||----w |5 p$ v7 }% ^6 k3 K. J! H9 _
                ||     ||
- M: ~1 z* W7 c6 g这里对上述两个模块稍作解释。
. B+ J& C4 Y: i6 s对于docker_image任务来说,通过sourec: build指令来表示这是一次镜像构建操作,source指令可包含如下值:- |2 W' n5 B( e  ]9 x. \% @; v
build:根据build指令的path参数指定的Dockerfile构建镜像& n4 s, i: g+ ?# _% @7 V1 a; T0 k; U4 Q
load:从镜像tar文件中提取镜像. R* {! l9 J# T) G; V. ]5 x, m* U
pull: 从registry中拉取镜像* E- Q$ u. y# G9 f: V
local:保证docker端已经具备指定的镜像
( B1 z3 y: C" d% h  L. [: C8 |对于build指令来说:
. m% E8 a6 F) v7 D- mpath:指定构建时的上下文目录,该目录要求包含Dockerfile文件
4 C  E) ]7 B+ m# _% I; Sdockerfile:明确指定使用哪个Dockerfile文件,而不是默认的上下文目录中的Dockerfile文件
8 u! I# Q8 i) h2 @8 G$ ipull:构建时是否从registry中拉取基础和中间镜像镜像
4 i2 R  R8 R4 B6 r& U* zcache_from:构建时使用缓存的中间镜像( a. S) s! L2 u  p
args:可按照key:value方式指定镜像的参数,对应于Dockerfile中的ARG指令,例如listen_port: 80800 \1 q  H- h5 x4 Y
其它指令应该都通俗易懂。
; c. h4 I: M6 f9 J) D7 x+ I构建镜像完成后,可使用docker_container模块启动该镜像。该模块指令非常非常多,几乎包含了docker container命令的所有选项功能,但是熟悉docker命令,这些指令的用法也通俗易懂。比如,指定卷和环境变量:
+ S' t: S; F5 Y- o+ K* N. T% h4 eYaml
: [9 r% [$ Z  W9 R  L( E5 v: u+ ?5 q7 V% d
0 \1 s& ^; m, s4 z2 O  ?" R
- name: Create a data container. n/ h( Z- g4 d: D0 R$ h1 i
  docker_container:- f6 E: O: z1 t
    name: mydata
9 f; E, ^+ h; Q# g/ ]    image: busybox7 _2 d$ l7 w  x8 _+ G
    volumes:
0 n& d" T$ H9 t      - /data
% C5 z  g# w. m' O7 K# ~' H& P& }$ g- name: Restart a container
+ O% i7 a1 F" y9 M  docker_container:$ [+ r( y$ x, p/ P5 a$ c. f
    name: myapplication
- N- U8 |4 x$ d! v, m    image: someuser/appimage
( N% `  \3 _- [' K# n$ d. K) \    state: started. r9 Q$ _4 y, m3 k  _! ~1 r
    restart: yes
( d) O1 y+ F' l; V. O, f  o+ h    devices:
9 s- j( o9 K# f# d( \     - "/dev/sda:/dev/xvda:rwm"8 b4 L/ a9 |. U9 L4 p
    ports:
" H2 _$ P% `# B, D8 u* {     - "8080:9000", {- i  \5 A2 w
     - "127.0.0.1:8081:9001/udp"
) _! U' C! Z% k! K" [1 M    env:+ k2 L6 C5 |0 U* ^
        SECRET_KEY: "ssssh"
- ]  k: J: m# ?/ x* I4 J        BOOLEAN_KEY: "yes"* N& w+ z6 M5 Z; W; Q
3 无Dockerfile启动镜像并连接容器3 \' q8 r% e& W6 k" G) I
在上面的playbook中明确使用了Dockerfile来构建镜像并启动镜像提供服务,但因为Dockerfile自身也是基于基础镜像构建的,所以可以省略这个构建过程,而是直接启动基础镜像并连接到启动的容器进行操作。
& Z! s8 \) i2 Q' S3 B下面实现与上述示例相同的效果,只是不使用Dockerfile构建。
: ?* H" h, X: d! g  Zplaybook文件内容如下:
' q) \: W, F' A7 }. KYaml
; `, O& f+ f2 Y3 I6 y& p. u+ w
+ k% A& P% _8 Z7 }% e/ q---
, T6 }$ ]  O, s- D& ]- name: start image ; P: ]6 M6 M, F# {
  hosts: docker0 z) F: P$ R# N
  gather_facts: no
& @! t2 V3 I1 U: s, y  vars: 5 R6 q( R: a( P3 I+ Z5 l! `
    container_name: "centos7"
$ g* j  F* |" S! p  tasks:
9 I' [; l; v: C: A    - name: start basic container "centos7") u5 L8 f* ^; `( r4 c
      docker_container:
% B4 R4 C# E, M. M5 F- S        name: "{{container_name}}"
0 u; H* g% n: d        hostname: "{{container_name}}"* R% E% q( g" B; W
        image: centos:centos7
- x2 [7 |' C7 w' A        ports: 8080:800 r4 d; N  B( ^4 c
        state: started8 a, N2 i6 z. E8 U
        auto_remove: yes
% L' e/ d! u# J        command: bash! p5 t( @2 m/ q# {( F, W
        tty: yes
7 F6 ~% q* H$ K& U+ F        + |) S! G; R! S+ w: i
    - name: add container to inventory) u) Y$ N8 o% D7 W
      add_host: 0 R# L5 d! {# l$ i
        name: "{{container_name}}"
  v5 H4 L: X3 s0 Y. ]- \' |4 V$ n        ansible_connection: docker
6 z+ y& d7 D) e* h& }0 v        ansible_host: "{{container_name}}"/ g$ M6 y# w2 ]9 @$ n% R  N
        ansible_user: root
$ A* T/ P6 ]5 F6 W4 @        groups: containers
( Y% |8 o* }2 n  X- P! Q. C        . Z+ c2 h: I1 y; Z/ [/ E
- name: do something in container
# G$ R: \8 L# R* W  hosts: containers
# Y, `# U' L, {/ ^4 i+ o. L  gather_facts: no1 ?& {9 K% d+ b5 d# }: i1 v
  tasks:# {1 @& O# x: L; E4 v. N. j5 ]
    - name: install python if needed
/ k$ j7 i! g* y, e+ a      raw: yum install -y python
# M$ b: g+ p2 r8 H, y8 L    - name: remove all repos exists+ r# t7 Q8 \- K+ g3 Q3 [! A9 {
      shell: rm -rf /etc/yum.repos.d/*
# t% n1 D5 R: h3 r! Z- k& h      
  k& C2 N; C1 C7 B) }6 B    - name: add os repo and epel repo
- c) d; o3 }9 E9 F' B" ]      yum_repository:
$ F+ _" w  C% |8 D: m; b" F! F- n# k        name: "{{item.name}}"
, s; ?; Z) Q+ ~( a' O( g7 C5 o        description: "{{item.name}} repo"
3 }* Z- v  D6 f7 p. v        baseurl: "{{item.baseurl}}"
- g* c. w  ~$ t7 j1 }; F' `' P( r        file: "{{item.name}}"
3 ~" i% k& }: c( v7 e7 s        enabled: 1
( w. r" _) o& [- z8 M; K; d) ^        gpgcheck: 0
, B0 y, _7 a) p0 N        reposdir: /etc/yum.repos.d
: x# o; D4 i% ^( U" r6 n. b      loop:
0 l( O  q9 i4 {4 m8 R7 Y9 j        - name: os
4 |. E* ]0 l+ }' @: g          baseurl: "https://mirrors.163.com/centos/$releasever/os/$basearch"6 |- n2 E6 q9 c8 f1 B1 i
        - name: epel
8 N3 B9 C/ @9 h; `# T          baseurl: "https://mirrors.163.com/epel/$releasever/$basearch"      # H) q% Q$ S6 a9 x
    - name: install nginx and cowsay  5 f* e4 `. K% U+ O# _2 v" G0 I3 z  W
      shell: yum -y install nginx cowsay' S$ x9 t* R" C1 g* [/ W
      
% B- o0 ?) _+ Y& C    - name: configure nginx
2 n7 N) O, D! n* Z5 Y      lineinfile: 4 d7 F! q7 {$ A( \6 y: P4 o
        line: "daemon off;"# F) L7 U% U6 m, n! C. c2 |1 i
        dest: /etc/nginx/nginx.conf
  f% K8 A! f8 ?" }        
# Q! X- B9 |4 q* q; Y    - name: change index page# Z. I/ c1 T! h/ n4 }9 e( v7 x
      block:
& M5 y/ n. g+ }( l        # 先移除index.html,因为它可能是一个软链接
3 `, s- k: ]( M' ?4 s7 t+ P) f        - name: remove old index.html page8 i- z5 u7 ?4 i4 f7 @
          shell: |
" ~' S. f9 W9 M9 p! b2 d) Q            rm -rf /usr/share/nginx/html/index.html
1 M) K4 D& @# d2 u+ E2 ?            cowsay test >/usr/share/nginx/html/index.html
9 h1 f) f3 I' f7 m    - name: run nginx
! j. l) z9 m5 |! C% {7 }      shell: nginx &
; c' c" P6 c3 b+ m/ @在执行上述playbook之前,需要先在Ansible端导出连接方式docker所在主机的环境变量,比如Ansible连接到远程docker时,使用tcp:
9 g* B0 c' V$ F' D8 g- g: Y- Z. TShell* m* J' k6 ?' _2 ^4 Y8 d. u& V
6 Y8 t' t( I& [* J# ~7 S) Q

3 S* x. H6 W6 e! p- p3 Q3 N" X$ export DOCKER_HOST=tcp://192.168.8.65:23767 H: `: B8 I% [% z; r  X
$ ansible-playbook -i inventoryname playbookname.yaml+ A, |8 j4 M8 Z% ?# f1 i4 L
上面的playbook任务中,首先启动docker容器,然后使用了connection: docker连接器添加该容器到containers主机组中,以便后续的连接。之后在第二个play中连接到containers组,安装Python(CentOS系统都会带有python),配置yum源,安装Nginx和cowsay,并启动nginx。任务流程比较简单。# {4 U& ?* ^0 J3 Q. `5 X
唯一需要关注的是add_hosts添加容器节点到inventory时指定的docker连接方式,这里不能使用默认的ssh连接方式,因为目标容器不一定开启了ssh服务,也不一定能和外界通信,而使用connection: docker连接方式,Ansible将会先ssh连接到docker服务所在主机,然后通过docker container exec的方式连接到容器内部。
1 U5 F  f6 e  o& y! t- L     docker inventory
& S/ C/ A  E- a4 x& w5 cAnsible为Docker提供了动态inventory的脚本。可下载该脚本:
: T8 r' b/ R: g9 K5 yShell
+ i- Q, J9 P% \5 ]6 u# {- Y8 W- q0 O+ g2 x5 H
: U/ s/ T( Y8 l$ Q3 R
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/docker.py1 r+ `0 z! W5 c( G
chmod +x docker.py
* S0 V$ Y& S( w执行该脚本测试:
% a. |$ |- N- nShell, @" \9 P. r8 r: U+ ], @) |

; i$ E% [1 X9 u/ S! X4 }; G# u- JDOCKER_HOST=tcp://192.168.8.65:2376 ./docker.py --pretty' ]% K. V# z1 L
或者直接在ansible命令或ansible-playbook命令中使用-i选项指定:
" U  {- P0 f: E$ E$ AShell
/ v) f3 W3 U) T" Q" E! N- c# B4 o- g+ V. b; i4 V. m+ y
ansible-playbook -i docker.py docker_containers.yml% S: T& v/ \' M, c
4 其它Ansible容器管理工具
/ t( S7 Z8 i; j# L# W; Q! B" pAnsible除了在官方提供了docker相关的模块外,还有一些第三方的工具可用来管理容器。9 i' s2 @  a, `
比如ansible-container、ansible-bender、Ansible Operator,它们需要单独安装,对于ansible-container来说,在之前几年比较知名,但是作者现在已经将该项目废弃,据作者本人所说,ansible-bender和Ansible Operator更好。
. i4 r% s- D4 r& l+ P' `0 Aansible-bender:1 f, k. T- j8 [2 C
简化Ansible Playbook构建容器(注:此容器是符合OCI标准的容器,docker所构建的底层容器也是OCI容器)1 V4 U0 r9 N( T( x9 c, _
地址:https://github.com/ansible-community/ansible-bender
) Y9 j1 d+ E4 u! r3 W7 j: }# b0 xAnsible Operator:# n6 z, I' z; y3 R" e3 p
是Red Hat Ansible Automation和Red Hat OpenShift团队联合开发的用来将容器部署到K8s上的工具
: g( Q+ ^3 s" r: }地址:https://learn.openshift.com/ansibleop
$ Z9 `) I3 K- ]( r; N1 @1 {) r5 Ansible管理OpenStack
* D7 V3 j1 q; `6 G  A# |OpenStack可整合一台或多台物理计算机的资源来按需创建、管理、配置、删除虚拟机(在OpenStack中,虚拟机对应的术语是”计算实例”,但后文都以虚拟机来描述),对OpenStack提供者来说,提高了硬件资源的利用率;对受益用户来说,可按自己的需求申请带有各种性能、各种资源配置的操作系统,比如公有云的模式,就像去网吧上网一样,想上多久、想体验什么配置的主机都按需付费来享用。: G; N# e/ k/ ^$ }% q# ~
对于OpenStack来说,Ansible几乎是全程参与其发展的,因为从OpenStack很早的版本开始,就已经逐步支持通过Ansible来配置管理OpenStack,而Ansible管理OpenStack相关的模块也随着OpenStack的版本迭代在不断更新。目前为止,Ansible官方提供的关于OpenStack的模块已经有五十多个,下面是Ansible官方目前提供的模块列表信息简介:# ^9 U0 @" z* O4 c; a# r% X
Code
* H2 h& K  W5 p- ]( v) N: k) a% C& |; i' Y; p9 }7 \: ~
os_auth – Retrieve an auth token1 A1 A# I6 ^: q. ^
os_client_config – Get OpenStack Client config
$ m+ U7 |1 E9 F, b# Bos_coe_cluster – Add/Remove COE cluster from OpenStack Cloud
! {8 _) {  p3 r6 p& Dos_coe_cluster_template – Add/Remove COE cluster template from OpenStack Cloud- ^" ~5 U' t0 ]" ^* J8 k% F
os_flavor_info – Retrieve information about one or more flavors8 g* c; H6 @, |! R
os_floating_ip – Add/Remove floating IP from an instance
8 `: l5 q  b; N5 D8 Aos_group – Manage OpenStack Identity Groups5 |2 y7 U" _2 G6 b/ C' s- t
os_group_info – Retrieve info about one or more OpenStack groups
  X: N6 m& X, m1 p: U) G. los_image – Add/Delete images from OpenStack Cloud
$ A1 E" v3 z% G- nos_image_info – Retrieve information about an image within OpenStack" ]6 b5 L1 J  @# C& R
os_ironic – Create/Delete Bare Metal Resources from OpenStack
+ ~- j- Q8 @8 K" g1 Tos_ironic_inspect – Explicitly triggers baremetal node introspection in ironic2 m  `) ]! `- V8 e1 z
os_ironic_node – Activate/Deactivate Bare Metal Resources from OpenStack
3 m/ _  J- Q& Tos_keypair – Add/Delete a keypair from OpenStack
$ S% V" [2 F) c0 Z6 Q. a9 J4 eos_keystone_domain – Manage OpenStack Identity Domains( h* r6 L$ n/ X8 H, c7 a
os_keystone_domain_info – Retrieve information about one or more OpenStack domains( z9 J1 k* y  Q9 @& M1 e
os_keystone_endpoint – Manage OpenStack Identity service endpoints
& t. p/ ]( H( N3 C+ A8 Y; ~os_keystone_role – Manage OpenStack Identity Roles
7 t; ~+ p$ {, V% K2 F* w. Los_keystone_service – Manage OpenStack Identity services- J$ {  Z3 `1 U% @$ Y! s. P
os_listener – Add/Delete a listener for a load balancer from OpenStack Cloud4 X3 _1 ^$ y" A9 g% l1 R- X( E; B
os_loadbalancer – Add/Delete load balancer from OpenStack Cloud( R/ g5 E: T% \7 D  i; b# W
os_member – Add/Delete a member for a pool in load balancer from OpenStack Cloud" I$ ~6 `8 w& }+ z# @" f
os_network – Creates/removes networks from OpenStack2 s+ q9 v* P: r  C- J6 L& D1 ^$ q7 R
os_networks_info – Retrieve information about one or more OpenStack networks" S" }! i3 I5 {- R
os_nova_flavor – Manage OpenStack compute flavors
! J' @, O; ?' X! {2 m* @os_nova_host_aggregate – Manage OpenStack host aggregates
# L# q" k- C+ D# u& _os_object – Create or Delete objects and containers from OpenStack
. Z- c% W; q) P/ ~os_pool – Add/Delete a pool in the load balancing service from OpenStack Cloud
) M9 B) u. \* g" N8 I. U+ R4 Ros_port – Add/Update/Delete ports from an OpenStack cloud
1 K# U$ v# A1 t0 [9 `os_port_info – Retrieve information about ports within OpenStack; x/ m( N3 a) ]- h, }* }8 p9 h
os_project – Manage OpenStack Projects& }; H! Q5 u- }4 i3 A& L
os_project_access – Manage OpenStack compute flavors access# f5 E/ [/ p+ X
os_project_info – Retrieve information about one or more OpenStack projects
& F' g! r. D( W6 I5 ~4 eos_quota – Manage OpenStack Quotas
! M6 u# k" y% ?$ e% A4 G/ Bos_recordset – Manage OpenStack DNS recordsets
' A8 x- r5 D- Q' g& jos_router – Create or delete routers from OpenStack! R$ e9 G' g" ]/ s# J3 u; x, s. f
os_security_group – Add/Delete security groups from an OpenStack cloud
# n" ]5 M" k% ~1 z; k# a& D! Nos_security_group_rule – Add/Delete rule from an existing security group+ b; J# }$ ~: x
os_server – Create/Delete Compute Instances from OpenStack
* _5 \9 A1 S- p9 a: q; xos_server_action – Perform actions on Compute Instances from OpenStack
) \6 U; D/ v) a/ Uos_server_group – Manage OpenStack server groups$ D  A# k5 F% W% d/ W
os_server_info – Retrieve information about one or more compute instances
. Y, [7 p1 Z: V: I/ \( u$ Zos_server_metadata – Add/Update/Delete Metadata in Compute Instances from OpenStack
2 ?6 ~) a0 i- |, \5 u/ Qos_server_volume – Attach/Detach Volumes from OpenStack VM’s
8 ?) w6 O# p1 ?0 E6 xos_stack – Add/Remove Heat Stack
4 G2 K  m& E1 M0 g  Z) Q/ Eos_subnet – Add/Remove subnet to an OpenStack network
# Z! `. ?! {( b7 u2 c" jos_subnets_info – Retrieve information about one or more OpenStack subnets
% A, D6 ^8 n, G$ h2 s+ dos_user – Manage OpenStack Identity Users
% D/ k% N/ M* `3 M6 `8 cos_user_group – Associate OpenStack Identity users and groups
9 i5 {; d" c6 v$ u: [os_user_info – Retrieve information about one or more OpenStack users
: h% s% r' }2 r7 D7 w% jos_user_role – Associate OpenStack Identity users and roles
. a! l- x7 {4 E5 j) uos_volume – Create/Delete Cinder Volumes
5 z8 m' i; M% `/ V9 A. N  Hos_volume_snapshot – Create/Delete Cinder Volume Snapshots$ O! F" g3 \9 a* I' ]/ Z/ J2 `
os_zone – Manage OpenStack DNS zones
/ D) n# a6 i5 w( V! V: x  B7 j, q$ U虽然看上去很多,但大致可总结为Ansible可对以下资源做管理:
  @4 k5 _& w. a(1).计算资源" x7 p) k" L/ s+ i% L0 B  w& q: H- P
(2).镜像管理
" i' P. f3 w' e2 d) e4 ~9 E(3).账户管理和账户认证2 c2 \! v3 f' G( c: X
(4).网络管理
/ Q+ ^& b6 l# ~; |) P9 s; r(5).对象存储管理
. k+ n/ r: W4 O) `' @5 e0 _6 ~7 C(6).块存储管理
! e' G/ e/ h0 v7 o5 U3 c  B对每种资源的管理可分为四类操作:$ D& u! D+ U# y2 y+ ~; o* _
(1).获取管理目标的信息  L7 c2 S$ S7 w5 p7 T
(2).添加管理目标' u# @) i+ d( I3 p5 b; z7 Q/ g7 ]) v: v
(3).修改管理目标的属性5 m2 }+ p" E$ e9 }  s: _" N; ~
(4).删除管理目标
& I* _, W: \, c8 S: H, b# j  K0 I即增、删、改、查。: s4 C' s: s& d; ?2 X' h& e2 @
此外,由于OpenStack自身已经跟踪了其创建的每个虚拟机的信息,所以Ansible还可以直接从OpenStack中获取这些虚拟机的信息,比如从OpenStack取得某些虚拟机信息来构建动态inventory,这样就免去了手动提供虚拟机inventory的麻烦。8 J3 d8 y- f0 L
本文不会介绍Ansible如何操作OpenStack自身(比如添加网络、上传镜像等),这和管理普通服务做的一些基本操作没任何区别,不同的仅仅只是做不同操作而已。本文会介绍Ansible管理OpenStack虚拟机时最常见的两种场景需求:$ }. F4 M" C# y$ m; }: d
(1).使用Ansible创建虚拟机,然后像平时管理远程主机一样管理这些虚拟机,最后删除这些虚拟机5 p0 o, t) g/ u
(2).从OpenStack生成动态inventory$ j, U8 R+ ^& |  u& J
14.2.1 创建虚拟机
& F* @% j  P$ r- hOpenStack管理虚拟机相关的模块都以os_server开头,目前包括如下6个模块:本文大概只会用到os_server模块
, q% O9 _1 P2 o7 j" U9 e* g7 [# BCode+ j& p: t$ ]& A" q3 [

0 }, P, M. N' c, r1 A& Y2 x, ]! ros_server – 创建或删除虚拟机# y2 R5 V+ V8 J
os_server_action – 对虚拟机做一些操作,比如虚拟机的关机、开机、重启、暂停、恢复等操作
8 v6 u/ |/ O& Los_server_group – 管理OpenStack虚拟机分组,比如测试环境的虚拟机可属于test组,生成环境的虚拟机可属于prod组  
: ]4 T6 c- ~5 K8 Nos_server_info – 检索一或多个虚拟机信息,在Ansible2.9之前,该模块名称为os_server_facts,用于检索虚拟机facts信息
: _% K) f) g' N: \. oos_server_metadata – 增、删、改虚拟机的元数据信息,比如设置虚拟机的主机名、虚拟机设备信息,如网卡配置、磁盘路径/dev/sda  " F2 ?1 {9 o5 M6 l9 r4 m
os_server_volume – 附加、剥离虚拟机的卷7 {: X7 L/ n( b3 Y2 I
这6个模块都要求先安装好版本高于0.12的openstacksdk包,在CentOS 7中只需执行如下命令即可:  b, M6 T" F6 E4 Y# f$ p3 f
Shell( a2 S, M* q- z: ^

4 a& x3 Z  n$ U* D$ pip3 install openstacksdk
! G$ K% I5 @9 W: U; {( z; l0 s  ^为了让Ansible连接到Controller进行管理,需要添加Controller的inventory信息。假如OpenStack的Controller的IP地址为192.168.8.65,可inventory文件openstack中添加如下内容:
8 C% s" j. ^& X& EUndefined7 C0 Z& t9 D, P# L1 ]5 u. I/ _7 e
2 \# u1 F3 W! o4 S
[openstack_controller]
+ ?6 Z4 e( P" T  c: U- F192.168.8.651 H6 L) K# x- n* Z% e' _; x$ T4 l
配置Ansible段和controller的ssh认证互信可自行配置,此处不赘述。
6 z5 i& D. L; s7 l0 N7 t6 }" l然后就可以编写playbook来创建虚拟机,假如playbook文件名为create_vm.yml,其内容如下:- f! m" p) o- y$ @, h
Yaml
  U+ v& f3 c4 a( G; |* [! |! r8 d) N2 e! {5 ]& d4 B1 U$ v
- name: create vm/ y! }6 e( C% ]% S! p" j# |+ P6 \
  hosts: openstack_controller0 o2 g0 ]3 a1 o4 {- x+ x
  gather_facts: no1 s  b& [! V0 A* O) M* q& c
  tasks:
7 {0 N$ Q% n; ^1 V. {    - name: Create a new instance
, a* w1 {& Z0 L8 y' B" ]- s( Q# \      os_server:' ^: Y- M6 [, V) G0 ~1 r* t; Y
        state: present
  e5 K3 ~3 |: T, g7 I        auth:& l# T- u2 V- r# X7 r9 p
          auth_url: http://192.168.8.65:5000/v3
2 e1 n+ q9 o! w# G' n$ E" K, h8 e9 Y          username: admin* e) `6 w- a- }& \
          password: admin123
; ]/ A" u2 k  B5 k* Y4 _8 @          project_name: admin3 I1 u4 y, D$ m9 I  e6 g/ Y
          project_domain_name: "Default"/ B8 N5 E8 O$ V* f
          user_domain_name: "Default"
" F. X, ~/ Q1 z" J        name: vm1. @. I4 [! ~2 ~6 i0 D' h
        image: "CentOS-7.9-x86_64"4 m+ z+ D+ a7 Z* C# f
        key_name: ansible_key! L$ }. t+ I7 P* Y2 s
        timeout: 200
* R: }& G1 i( N& R4 q7 Q        flavor: m1.small6 _5 B: C6 t5 Q: s
        network: 'ext_net'& E) u/ c: q) {& l4 a* I
        wait: yes
/ d# z7 [% o+ [; m( d9 I- d! w/ }        meta:, w* ~* r! c" t
          hostname: test1% d' q) S8 e& M/ c& H
          group: test_group
1 x( A3 p* U4 g3 H' Y          userdata: |
: u( s. l  }% C( @            {%- raw -%}#!/bin/bash. p& N: s& b/ S( b7 M5 b
            cp  /home/centos/.ssh/authorized_keys /root/.ssh/
# ]; F8 C. x: b+ f: Q            {% endraw %}' h- U7 @: j! C5 b  n
auth部分是认证相关信息,name1表示创建一个名为vm1的虚拟机,image、key_name、falvor、network都是OpenStack中已经配置好的。这里还同时设置了虚拟机创建出来后的主机名为test1,并加入到了test_group主机组。# l5 L1 n/ \3 d/ I/ b& ]! n
因为是CentOS镜像系统,该虚拟机创建出来后,默认登录用户名为”centos”,而且默认不支持root登录,为了后续可以使用root登录,上面使用userdata定义了该虚拟机创建后自定义的操作,即将保存的公钥信息拷贝到/root/.ssh目录下。
1 J2 W2 a  S- ^; Z注意os_server创建虚拟机任务中的一项wait: yes,它是默认选项,表示Ansible会等待虚拟机创建完成才会继续执行下面的任务。
$ O9 e$ c1 w. d6 Y1 Y/ a/ D因为所有的模块在连接OpenStack时都需要进行身份认证,为了简化playbook中的认证内容,将上面的auth选项段落的内容保存到OpenStack Controller的~/.config/openstack/clouds.yaml文件中。例如:
! q+ U, ]/ d' W7 j+ u' xYaml
: W5 [' b. [- e5 n% X. u
, N7 p: B' P: |2 l9 aclouds:1 w1 S& f, j5 o1 ~6 j( N
  mycloud:. V6 K% ~# {! n& z! D) b
    auth:
0 G. S- Y0 t( a7 ?: ]2 E( @" A     auth_url: http://192.168.8.65:5000/v3
+ ^9 A  d$ C+ G" L. K( n4 B     username: admin
) u# ^2 @! b" {% A  }7 }' n( \2 X     password: admin1234 i$ y) D5 [  ]$ F- c' P7 J, s6 t* A: V
     project_name: admin- l4 b/ \; x  F" Z; ~& l
     project_domain_name: "Default"( E2 J/ m. `1 Q) K/ Y/ e8 `
     user_domain_name: "Default"7 d# t# q. b, Y" Z
以后在模块选项中就可以省略auth,而使用一个cloud: CLOUDNAME即可:
; x) ]$ r, K0 p3 j- w* uYaml
7 [9 `; y* `5 P/ e9 i& }1 i4 s& e8 ]5 E* I
tasks: 8 X/ ~! [; t9 @% i! b6 W
  - name: Create a new instance7 j9 P) m; D+ Q
    os_server:
& x6 W# L5 t' \( U      clouds: mycloud
3 `7 \8 s8 H3 P) c5 z/ ^      state: present
$ @2 d3 d& G( V3 t1 b; ^      name: vm13 k& \4 J3 x% I* z2 T
      image: "CentOS-7-x86_64"
  h* s- a1 D4 u  {! [' o2 [% [      key_name: ansible_key. |3 j8 y. o7 s$ n! _% U7 L
      timeout: 200
! P, G! \/ x) v( N+ L- ]7 `      flavor: m1.small
  N! B; G# y, g( _% @9 }4 ?      network: 'ext_net'
  E2 R5 t; z0 ~# j- Q% R% a) |. \      wait: yes
7 Q2 U' V) {/ o      meta:! R0 I! F4 |3 ^: ~# z
        hostname: test1
7 z. S! D8 B1 q9 S        group: test_group
- o6 a5 w& z# b$ v' a但是要注意,将认证信息以明文方式写入文件是不安全的,可以使用Ansible的Valut加密。不过OpenStack的dashboard中也已经提供了一个环境配置文件,可以先按照如图所示的位置下载:
! p  q/ L" C0 C% V7 v* E! z5 H7 y0 R7 Q
然后以source的方式执行下载到的admin-openrc.sh脚本文件:3 P( t9 b! q. @
Shell% h+ f% k! j! b  e
: J- ]2 g7 f4 x/ T2 z" x4 x
source admin-openrc.sh
" d7 Y: T4 [0 H) [& q  X7 j执行完后,Ansible的OpenStack相关模块执行时,auth和cloud指令都可以省略。( [- ^9 l9 Y. v3 ]
上面只是创建一个虚拟机实例,但很多时候可能需要一次性创建多个虚拟机。可以将每个虚拟机相关信息定义到一个变量文件中,然后去遍历想要创建的虚拟机实例。例如:/ @4 C' s5 r6 N5 {: v
Code
' T, V* `* k' g* Q9 C9 E. ^; R3 T& [- X: O3 r% H6 B5 t$ u3 R0 J  h
---
+ x2 |2 k4 \5 q& \" {servers:
4 v" V, b4 V* \) t. [  - name: vm19 A" w& P: r1 h1 U
    image:   o$ b- O' `8 H' w$ a0 H  U, G
    flavor: 4 [# {2 F* A) g: @1 g4 S
    key: ) M" _# T8 Y. p; `% Z/ U
    nics:
1 U0 K# C" ]4 `8 C3 m    meta: 7 J( B& @9 G, I, J% B1 h" I5 C
      hostname: & w, C0 P. M' x1 _7 z
      group: 2 p% q6 [8 v' X; r
  - name: vm27 n% [) x/ t( U; h- `4 d
    image:
5 m" L" k4 g$ e: `    flavor:
; D# ?8 Y( V- R) c4 s; M    key: " V0 c/ l0 q2 d5 v( R/ x+ ]
    nics:
$ y* {, c& Y2 ~& E8 R3 b- k8 b    meta:
5 A# p3 a4 ]) c! b; |: D      hostname:
9 s+ G4 G# b4 Y8 c/ D+ R5 s      group:
; z; Z9 `$ F; Q. O4 |3 @有了前面的Ansible基础后,此处批量创建虚拟机应该毫无难度。
1 C- S- c7 s: G2 ~9 Z% ?创建虚拟机后,可以将os_server的任务注册到一个变量,从而可以获取该虚拟机的信息,包括该虚拟机的IP地址:
# _1 {% f6 Z+ N+ d) CYml
: o2 x+ f5 v# l/ |- Q& m
4 n; T  Z3 z8 W+ M/ ~# S' vtasks: 0 G' }2 e* V9 O2 E% |" V
  - name: Create a new instance. _3 Z' \/ E9 r
    os_server:
4 i  p8 Z" n& B, e      cloud: mycloud
" A/ `& j/ U) |) b+ M; e      state: present
8 P4 U; ]5 W( P1 \+ [" O  L. ?      name: vm1' \' Y* e( n# J8 r4 w4 W4 j6 \) K
      image: "CentOS-7.9-x86_64"
0 T& }! D$ _; F6 Y  i- X  C      key_name: ansible_key- z0 d) t( H' o) }8 }7 Z
      timeout: 200
# y9 i( |' L0 u9 V# _      flavor: m1.small: F6 o4 u# a8 C7 I* O
      network: 'ext_net') n! V! A! G4 T% F, t
      wait: yes( s3 t$ L0 y  O, H, E$ T* r
      meta:
; i  `$ W* s9 V8 a, X5 G        hostname: test18 L) w: ^5 `, T+ p$ P0 \' a9 \% S
        group: test_group
( [) Y0 L5 u9 p  n& g. |( p    register: newserver- S' U1 j7 |( q7 L( [" c. A. }% b
   
( D5 r: w$ I' H" \0 [0 Y* ?  - name: get instance ip
+ a" @. q2 v3 S" C3 j    debug: 0 H2 J  X0 D& ^
      var: newserver.openstack.accessIPv4' a3 J" e; ^0 i' v! @
有了IP地址,对Ansible来说就获得了最关键的信息,因为只要将新虚拟机添加到Ansible inventory中,新虚拟机便像普通节点一样可接受Ansible的控制。( Q2 d& A6 M' B& k
6、将新虚拟机动态添加到inventory
& Q; q& E; Q2 R6 \' o, p获取到IP地址后,可以将该节点通过add_host模块动态加入到inventory中:
  h9 j# }8 B- ~( c/ q0 p' b7 JYaml; s5 n1 b; M* Y8 \) F" J* _
5 x) k0 r" T0 C+ v# P
- name: add new vm to inventory
& c& w0 n0 Z& r/ Y  add_host:; F, L9 E4 K; ]: Z+ y, C5 _
    name: "{{ newserver.openstack.accessIPv4 }}"
) r( ~& C6 N, y    ansible_host: "{{ newserver.openstack.accessIPv4 }}"( ~# i8 L4 k& U4 w' D8 b% h
    ansible_user: "centos"
( q: r* {. w% H* Y8 W    ansible_port: 22
+ r8 k  P( p8 h8 Q    groups: ; z2 o* W6 x" S! T: {. K9 l
      - vm_hosts
7 n$ P; t0 P- e3 K' d' E9 ^6 n似乎这里的逻辑不太良好?如果虚拟机启动了但是不可连接呢?对于OpenStack创建的虚拟机来说,完全不用担心,因为os_server创建虚拟机成功后会等待该虚拟机可连接才真正返回。但对于非OpenStack的其它云主机实例则不一定,这时应当使用wait或wait_for_connection模块定义一个等待任务。尽管OpenStack中可以省略该步骤,但在脑海中应当要知道有这个步骤。8 g, R4 k: a" V$ @/ l3 o
此外,OpenStack安装的镜像系统可能是比较精简的系统,甚至没有安装Python,所以为了能管理这些虚拟主机,应先使用raw模块安装Python。' K/ j. q1 u2 J/ t% O
Yaml: ?2 y) {# `+ I/ ~
- name: for new vm host
/ B! N1 ^9 }; f$ q" U4 _4 s  hosts: vm_hosts/ }- `4 n. x& e' N& M  s5 V; W4 p5 W
  gather_facts: no
) O9 a  Z% Y% V1 |7 }  tasks:
5 z* G* K7 s( P! {; W/ H    - name: install python if needed
) U% C4 v9 {7 A* L+ L5 Y. {      raw: "sudo yum install -y python"
* ~# k6 p* b1 L如此,Ansible便可以像管理普通主机一样管理OpenStack虚拟机。  E$ J1 Y+ e6 k4 s4 ?2 U# z
7、收集OpenStack虚拟机的动态inventory0 j& `/ ~$ P# z' r# C
动态inventory一般需要写脚本(几乎是Python脚本)来收集,但即使不会Python也不用担心,因为对于OpenStack来说,官方已经提供了openstack插件,还提供了openstack_inventory.py脚本,该脚本位于Ansible官方github仓库的contrib/inventory目录下,查看文件时记得先选择对应Ansible版本的分支。
# q1 |0 h1 T6 e下载openstack_inventory.py并设置可执行权限:
5 q/ @3 `+ Z1 w7 ~. E, i* fShell
; }2 ?) t+ M: C3 y4 Q, [4 |( E. K+ m' T3 y% ]: d4 p7 ^1 A/ _
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/openstack_inventory.py
' V' M: [/ K& i  Cchmod +x openstack_inventory.py3 |, b. h# ~9 ?$ M& |: b0 O
然后source以下admin-openrc.sh脚本,再执行:
$ E9 |- n) U! HShell4 k" @4 Q7 M: P) x

: c+ E1 r, j4 E1 d7 j1 [source admin-openrc.sh: b6 |7 @! |6 u7 c3 S
./openstack_inventory.py --list
+ u$ I5 q+ |. `0 [7 H) j可查看inventory信息。
$ S+ v: t6 n' t  \9 u* C" X之后要将该脚本在ansible或ansible-playbook中使用,使用-i选项指定即可:
& W" ]3 |$ z' v' q- _2 sShell) E* i6 Z" `; c* `* }

, G9 N' G  W6 h2 X7 d& vansible-playbook -i openstack_inventory.py -m ping3 P( N# {5 O2 B' |3 p8 m
除了使用openstack_inventory.py脚本动态生成inventory外,还可以使用名为”openstack”的inventory插件。要使用openstack inventory插件,首先要在/etc/ansible.cfg中的[inventory]段的enable_plugins中开启script功能:
' X, _5 g" N7 p  x# Q5 R' E% D) ZShell
+ _2 r" z0 p1 O: d' L6 L7 T9 M0 I# s  _
$ grep 'enable_plugins' /etc/ansible/ansible.cfg
5 J$ v$ \* ^9 u7 `9 _#enable_plugins = host_list, virtualbox, yaml, constructed
5 W& W( L( ~' }6 o5 b$ C取消上面的注释,加上script:
8 X/ K5 j6 I- z9 h7 p$ bIni
8 j/ L( `  H6 ^$ k6 w) U  h9 ~' U( h( U  b- T+ r
[inventory]7 X, P8 e' \# v) v  l; q
enable_plugins = host_list, script, ini, virtualbox, yaml, constructed
( }( ~+ h* X4 X; D以后只需在yml文件中加上如下plugin指令即可:
- J" a0 K( u4 v, A* E2 wCode
! ]# V2 J4 r. |) z1 k+ ~
5 Z8 i# o! N) Y. X8 N* O0 Mplugin: openstack
9 b( I& F, C$ D% Y. e1 B* J
/ q$ N1 N9 P5 k, u5 e4 S7 K
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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